Learn R Programming

mvbutils (version 2.2.0)

pre.install: Create a simple formal package from an informal package

Description

pre.install creates a "source package" from a "source task", ready for installation using R CMD INSTALL/BUILD/CHECK. patch.installed can be called after a pre.install; it makes a quick modification to your already-installed version of a package, and there is then no subsequent need to re-build and re-install via RCMD. It also updates HTML and pager-help, with immediate effect (i.e. during the current R session).

Usage

pre.install( pkg, character.only=FALSE, force.all.docs=FALSE, ...)
 # Your own hook: pre.install.hook<>( default.list, <>, ...)
 patch.installed( pkg, character.only=FALSE, force.all.docs=FALSE, help.patch=TRUE)

Arguments

pkg
package name. Either quoted or unquoted is OK; unquoted will be treated as quoted unless...
character.only
...is TRUE
force.all.docs
normally just create help files for objects whose documentation has changed; if TRUE, then recreate help for all documented objects.
help.patch
if TRUE, patch the html and pager-style help of the installed package
default.list
list of various things-- see under "Overriding..." below
...
arguments to pass to your pre.install.hook.XXX function, usually if you want to be able to build different versions of a package.

Package structure

The "task directory" means the working directory when you call pre.install; cd will look after this for you. The "package directory" is the subdirectory "<>" below that, which will be created if needs be. The default behaviour of pre.install is as follows-- to change it, see Overriding defaults. A basic source package is created (no C code etc.) in a subdirectory "<>" of the current task. The package will have a DESCRIPTION file, a single R source file with name "<>.R" in the "R" subdirectory, possibly a "sysdata.rda" file in the same place to contain non-functions, possibly a NAMESPACE file, and a set of Rd files in the "man" subdirectory. Rd files will be auto-created from flatdoc style documentation, although precedence will be given to any pre-existing Rd files that in an "Rd" subdirectory of your task, which get copied directly into the package. Any "demo", "src", and "data" subdirectories will be copied straight to the package. An "inst" subdirectory will also be copied, but recursively (i.e. including any of its subdirectories). There is no recompilation of source code. For handling of DLLs, see below. Most objects in the task will go into the package, but there are usually a few you wouldn't want there: objects that are concerned only with how to create the package in the first place, and ephemeral system clutter such as .Random.seed. The default exceptions are: functions pre.install.hook.<> and .First.task; data forced!exports, .required, tasks, .Traceback, .packageName, last.warning, .Random.seed, .SavedPlots, and any character vector of the form ***.doc. All pre-existing files in the "man", "inst", and "R" subdirectories of the package directory will be removed (unless you have some mlazy objects; see below). If an .Rbuildignore file is present in the task directory, it's copied to the package directory (NB I should include a facility in the pre-install hook for this). If there is a "changes.txt" file in the task directory, it will be copied to the "inst" subdirectory of the package, as will any files in the task's own "inst" subdirectory. Similarly, any DESCRIPTION file in the task directory will be copied to the package directory, after removing the "Built:" line. If there is no DESCRIPTION file in the task directory, a default DESCRIPTION file will be created in the package directory, but you'll certainly want to edit it before CRAN release; you can also generate the DESCRIPTION file via the pre.install.hook override. No other files or subdirectories in the package directory will be created or removed, but some essential files will be modified. The package is assumed to be namespaced if any of the following apply: there is a NAMESPACE file in the task directory; there is a .onLoad function in the task; there is an "Imports" directive in the DESCRIPTION file. If a NAMESPACE file is present in the task, then it is copied directly to the package. If not but the package still looks like a namespace candidate, then pre.install will generate a NAMESPACE file by calling make.NAMESPACE, which makes reasonable guesses about what to import, export, and S3methodize. What is & isn't an S3 method is generally deduced OK (based on function name, and name of first argument-- if it's not a method, I'd suggest giving the first arg a different name to that in the generic), but if you want to force a plausible S3 method not to be listed as a method, then give the function an attribute export.me=TRUE, or override with the pre-install hook. By default, any DLLs found in either the task directory or its "libs" subdirectory (if any) are copied to the "inst/libs" package directory. This will ensure that the DLLs ultimately get copied to the "libs" subdirectory of the installed package, which is where R expects to see DLLs. This works fine for RCMD BUILD & INSTALL, but horrifies RCMD CHECK; you could use the ... argument and a pre-install hook to pre-install different versions of the package, depending on whether you are distributing it informally or putting it onto CRAN. To change the behaviour in the pre-install hook, you can modify or remove elements from the dll.paths character vector, whose elements are the original paths of the DLLs and whose names are the names of the DLLs. By default, the R source file will only contain functions, but you can include other objects too by naming them in the funs argument. For functions, only source code will be included; in other words, any attributes except source are removed before printing. In particular, any export.me attribute (see make.NAMESPACE) and any flat-format documentation in the doc attribute do not go into the R file. However, the doc attribute is used to create the Rd files, by doc2Rd. If any of the Rd files starts with a period (e.g. ".dotty.name"), it will be renamed to "01.dotty.name.Rd" (to avoid some problems with rcmd). If the package is not namespaced (and namespacing is definitely a Good Thing-- ), then any undocumented functions (i.e. functions not in find.documented( doctype="any")) will receive skeletal documentation in a my.proto.package-internals.Rd file. The doco is OK for RCMD CHECK, but says little more than "don't use these functions yourself". To speed up conversion of documentation, a list of raw & converted documentation is stored in the file "doc2Rd.info.rda" in the task directory, and conversion is only done for objects whose raw documentation has changed. pre.install creates a file "funs.rda" in the package's "R" subdirectory, which is subsequently used by patch.installed. RCMD BUILD will omit this file (currently with a complaint, though I'm trying to fix this) but it does not cause trouble.

Package documentation

If there is a text object called "<>.package.doc", then it will be passed through doc2Rd with an extra "docType{{}package}{}" field. The first line should start "<>-package" and the corresponding ".Rd" file will be put first into the index. This is the recommended way of providing package overviews-- and, speaking as a frequently bewildered would-be user of others' packages, I beg you to make use of it!

Data objects

Most data objects in the task will get stored in the "system.rda" file in the "R" package subdirectory. This is loaded when the package is, but in a NAMESPACEd package the contents only go into the namespace and are not directly visible to the user. You can make them visible (i.e. exported) by providing documentation for individual objects; doco for data object xx needs to go in a separate text object xx.doc in the source task.

Big data objects

Lazy-loading objects cached with mlazy are handled specially, to speed up pre.install. Such objects (apart from .Random.seed) get their cache-files copied to "inst/mlazy", and the .onLoad is prepended with code that will load them on demand. They are exported (unless overriden in the pre-install hook), and are not locked; users don't need to use data() to access them, and actually can't. If they are exported, you should really provide formal doco for them, at least if you're planning to submit to CRAN, so perhaps pre.install shouldn't just export them by default.

Overriding defaults

If a function pre.install.hook.<> exists in the task "pkgname", it will be called during pre.install. It will be passed one list-mode argument, containing default values for various installation things that can be adjusted; it should return a list with the same names. It will also be passed any ... arguments to pre.install, which can be used e.g. to set "production mode" vs "informal mode" of the end product. The hook can do two things: sort out any file issues not adequately handled by pre.install, and/or change the following elements in the list that is passed in: copies: files to copy directly dll.paths: DLLs to copy directly extra.docs: names of character-mode objects that constitute flat-format documentation description: named elements of DESCRIPTION file task.path: path of task (ready-to-install package will be created as a subdirectory in this) has.namespace: should a namespace be used? use.existing.NAMESPACE: ignore default and just copy the existing NAMESPACE file? nsinfo: default namespace information, to be written iff has.namespace==TRUE and use.existing.NAMESPACE==FALSE exclude.funs: any functions not to include exclude.data: non-functions to exclude from system.rda There are two reasons for using a hook rather than directly setting parameters in pre.install. The first is that pre.install will calculate sensible but non-obvious default values for most things, and it is easier to change the defaults than to . The second is that once you have written a hook, you can forget about it-- you don't have to remember special argument values each time you call pre.install for that task. The pre-install hook is probably the best way to tailor the package construction, but there are some other "legacy" ways to include/export specific objects. If a character vector forced!exports is present in the task, then the objects it names will be exported. If any function has an attributed export.me, it is also exported (which can be used to prevent something being seen as an S3 method).

Details

The minimal ingredient for pre.install is a "source task"-- basically a directory with a ".Rdata" file in it. [The term "task" is used because there is an expectation that this directory will be linked into the "task hierarchy" maintained by cd; this might not be essential, but I haven't tested it any other way.] pre.install is useful in two circumstances: when you have a set of functions that you want to make into a formal package for the first time, and also when you are ready to update a "maintained package" that you have just changed (see maintain.packages). It creates a source package with R source, Rd documentation, optionally a NAMESPACE, and other things, ready for RCMD CHECK, RCMD BUILD, and/or patch.installed; see Package structure. You can override some of the defaults by providing your own hook function pre.install.hook.<> in the task-- see Overriding defaults. If you have already built your package and are just using pre.install to update it, you can follow up with a call to patch.installed. This patches up your already-installed R package to reflect changes in the "source task", so that the modifications will be incorporated the next time R loads it (NB that if the package is already loaded and you are using maintain.packages, then code changes to the loaded version are immediate-- but will be lost the next time the package is loaded, unless you call patch.installed. However, changes to the documentation are currently only triggered by patch.installed.). Using patch.installed means that you don't need to repeatedly rebuild and re-install the package via RCMD while developing it; those steps are only necessary when giving the package to others, or to CRAN. patch.installed updates the HTML and pager-style help files, but not CHM help nor the help.search database (not yet, anyway)-- for that, you need to re-build and re-install. It does not compile C/Fortran code for you, but it does update your DLLs, and re-loads them if they've changed. The DLLs present in the installed "libs" subdirectory will be kept in synch with any DLLs in your task directory or a subdirectory "libs" thereof. patch.installed also copies new and/or changed files out of the "demo" and "inst" subdirectories of the source package, respectively into the "demo" subdirectory and the installed directory itself; copying of "inst" is recursive. For safety's sake, though, no files are deleted from the installed version. The recommended way to use pre.install to create the package for the first time, is to have your collection of functions as a task called e.g. "protopack", use cd(protopack) to bring it to the top workspace, and then call pre.install(protopack). This will create the formal skeleton in the "protopack" subdirectory of the task directory. Once you get the package built, use maintain.packages to live-edit it and make future changes-- it's better to do that than to keep using cd to access the original task.

See Also

cd, doc2Rd, maintain.packages