Skip to content

Commit 5737a49

Browse files
committed
update to latest configure
1 parent a05665b commit 5737a49

File tree

10 files changed

+365
-398
lines changed

10 files changed

+365
-398
lines changed

‎RcppParallel.Rproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ RnwWeave: Sweave
1313
LaTeX: pdfLaTeX
1414

1515
BuildType: Package
16-
PackageInstallArgs: --with-keep.source
16+
PackageInstallArgs: --with-keep.source --clean
1717
PackageCheckArgs: --as-cran

‎cleanup‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/usr/bin/env sh
22
:${R_HOME=`R RHOME`}
3-
"${R_HOME}/bin/R" --vanilla --slave -f tools/config/cleanup.R
3+
"${R_HOME}/bin/Rscript"tools/config.R cleanup

‎cleanup.win‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/usr/bin/env sh
2-
"${R_HOME}/bin${R_ARCH_BIN}/R.exe"--vanilla --slave -f tools/config/cleanup.R
2+
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup

‎configure‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/usr/bin/env sh
22
:${R_HOME=`R RHOME`}
3-
"${R_HOME}/bin/R" --vanilla --slave -f tools/config/configure.R
3+
"${R_HOME}/bin/Rscript"tools/config.R configure

‎configure.win‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/usr/bin/env sh
2-
"${R_HOME}/bin${R_ARCH_BIN}/R.exe"--vanilla --slave -f tools/config/configure.R
2+
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R configure

‎tools/config.R‎

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
# configure-database.R ----
2+
3+
#' Retrieve the Global Configuration Database
4+
#'
5+
#' Retrieve the global configuration database (as an \R environment).
6+
#'
7+
#' @family configure-db
8+
#'
9+
#' @export
10+
configure_database<- local({
11+
database<- new.env(parent= emptyenv())
12+
function() database
13+
})
14+
15+
#' Define Variables for the Configuration Database
16+
#'
17+
#' Define variables to be used as part of the default configuration database.
18+
#' These will be used by [configure_file()] when no configuration database
19+
#' is explicitly supplied.
20+
#'
21+
#' @param ... A set of named arguments, mapping configuration names to values.
22+
#'
23+
#' @family configure-db
24+
#'
25+
#' @export
26+
configure_define<-function(...){
27+
envir<- configure_database()
28+
list2env(list(...), envir=envir)
29+
}
30+
31+
#' @export
32+
define<-configure_define
33+
34+
35+
# utils.R ----
36+
37+
#' Configure a File
38+
#'
39+
#' Configure a file, replacing any instances of `@`-delimited variables, e.g.
40+
#' `@VAR@`, with the value of the variable called `VAR` in the associated
41+
#' `config` environment.
42+
#'
43+
#' @param source The file to be configured.
44+
#' @param target The file to be generated.
45+
#' @param config The configuration database.
46+
#' @param verbose Boolean; report files as they are configured?
47+
#'
48+
#' @family configure
49+
#'
50+
#' @export
51+
configure_file<-function(
52+
source,
53+
target= sub("[.]in$", "", source),
54+
config= configure_database(),
55+
verbose= configure_verbose())
56+
{
57+
contents<- readLines(source, warn=FALSE)
58+
enumerate(config, function(key, val){
59+
needle<- paste("@", key, "@", sep="")
60+
replacement<-val
61+
contents<<- gsub(needle, replacement, contents)
62+
})
63+
64+
ensure_directory(dirname(target))
65+
writeLines(contents, con=target)
66+
67+
info<- file.info(source)
68+
Sys.chmod(target, mode=info$mode)
69+
70+
if (isTRUE(verbose)){
71+
fmt<-"** configured file: '%s' => '%s'"
72+
message(sprintf(fmt, source, target))
73+
}
74+
}
75+
76+
#' Configure Files in a Directory
77+
#'
78+
#' This companion function to [configure_file()] can be used to
79+
#' configure all `.in` files within a directory.
80+
#'
81+
#' @param path The path to a directory in which files should be configured.
82+
#' @param config The configuration database to be used.
83+
#' @param verbose Boolean; report files as they are configured?
84+
#'
85+
#' @family configure
86+
#'
87+
#' @export
88+
configure_directory<-function(
89+
path=".",
90+
config= configure_database(),
91+
verbose= configure_verbose())
92+
{
93+
files<- list.files(
94+
path=path,
95+
pattern="[.]in$",
96+
full.names=TRUE)
97+
98+
lapply(files, configure_file, config=config, verbose=verbose)
99+
}
100+
101+
configure_auto<-function(type){
102+
configure_common(type=type)
103+
}
104+
105+
configure_common<-function(type){
106+
107+
if (!isTRUE(getOption("configure.common", default=TRUE)))
108+
return(invisible(FALSE))
109+
110+
sources<- list.files(
111+
path= c("R", "src"),
112+
pattern="[.]in$",
113+
full.names=TRUE
114+
)
115+
116+
sources<- sub("[.]/", "", sources)
117+
118+
if (type=="configure"){
119+
lapply(sources, configure_file)
120+
} elseif (type=="cleanup"){
121+
targets<- sub("[.]in$", "", sources)
122+
lapply(targets, remove_file)
123+
}
124+
125+
invisible(TRUE)
126+
}
127+
128+
#' Read R Configuration for a Package
129+
#'
130+
#' Read the \R configuration, as through `R CMD config`.
131+
#'
132+
#' @param ... The \R configuration values to read (as a character vector).
133+
#' If empty, all values are read as through `R CMD config --all`).
134+
#' @param package The path to the \R package's sources.
135+
#' @param envir The environment in which the configuration information should
136+
#' be assigned. By default, the [configure_database()] is populated with the
137+
#' requested values.
138+
#' @param verbose Boolean; notify the user as \R configuration is read?
139+
#'
140+
#' @export
141+
read_r_config<-function(
142+
...,
143+
package= Sys.getenv("R_PACKAGE_DIR", unset="."),
144+
envir= configure_database(),
145+
verbose= configure_verbose())
146+
{
147+
# move to requested directory
148+
owd<- setwd(package)
149+
on.exit(setwd(owd), add=TRUE)
150+
R<- file.path(R.home("bin"), "R")
151+
152+
values<- unlist(list(...), recursive=TRUE)
153+
if (length(values) ==0){
154+
if (verbose)
155+
message("** executing 'R CMD config --all'")
156+
output<- system2(R, c("CMD", "config", "--all"), stdout=TRUE)
157+
equalsIndex<- regexpr("=", output, fixed=TRUE)
158+
keys<- trim_whitespace(substring(output, 1, equalsIndex-1))
159+
config<- as.list(trim_whitespace(substring(output, equalsIndex+1)))
160+
names(config) <-keys
161+
162+
} else{
163+
if (verbose)
164+
message("** executing 'R CMD config'")
165+
config<- lapply(values, function(value){
166+
system2(R, c("CMD", "config", value), stdout=TRUE)
167+
})
168+
names(config) <-values
169+
}
170+
171+
list2env(config, envir=envir)
172+
}
173+
174+
#' Concatenate the Contents of a Set of Files
175+
#'
176+
#' Given a set of files, concatenate their contents into
177+
#' a single file.
178+
#'
179+
#' @param sources An \R list of files
180+
#' @param target The file to use for generation.
181+
#' @param headers Headers to be used for each file copied.
182+
#' @param preamble Text to be included at the beginning of the document.
183+
#' @param postamble Text to be included at the end of the document.
184+
#' @param verbose Boolean; inform the user when the requested file is created?
185+
#'
186+
#' @export
187+
concatenate_files<-function(
188+
sources,
189+
target,
190+
headers= sprintf("# %s ----", basename(sources)),
191+
preamble=NULL,
192+
postamble=NULL,
193+
verbose= configure_verbose())
194+
{
195+
pieces<- vapply(seq_along(sources), function(i){
196+
source<-sources[[i]]
197+
header<-headers[[i]]
198+
contents<- trim_whitespace(read_file(source))
199+
paste(header, contents, "", sep="\n\n")
200+
}, character(1))
201+
202+
all<- c(preamble, pieces, postamble)
203+
204+
ensure_directory(dirname(target))
205+
writeLines(all, con=target)
206+
207+
if (verbose){
208+
fmt<-"** created file '%s'"
209+
message(sprintf(fmt, target))
210+
}
211+
212+
TRUE
213+
}
214+
215+
#' Add Configure Infrastructure to an R Package
216+
#'
217+
#' Add the infrastructure needed to configure an R package.
218+
#'
219+
#' @param package The path to the top-level directory of an \R package.
220+
#' @export
221+
use_configure<-function(package="."){
222+
223+
# preserve working directory
224+
owd<- getwd()
225+
on.exit(setwd(owd), add=TRUE)
226+
227+
# find resources
228+
package<- normalizePath(package, winslash="/")
229+
resources<- system.file("resources", package="configure")
230+
231+
# copy into temporary directory
232+
dir<- tempfile("configure-")
233+
on.exit(unlink(dir, recursive=TRUE), add=TRUE)
234+
235+
dir.create(dir)
236+
file.copy(resources, dir, recursive=TRUE)
237+
238+
# rename resources directory
239+
setwd(dir)
240+
file.rename(basename(resources), basename(package))
241+
242+
# now, copy these files back into the target directory
243+
file.copy(basename(package), dirname(package), recursive=TRUE)
244+
245+
# ensure DESCRIPTION contains 'Biarch: TRUE' for Windows
246+
setwd(package)
247+
DESCRIPTION<- read_file("DESCRIPTION")
248+
if (!grepl("(?:^|\n)Biarch:", DESCRIPTION)){
249+
DESCRIPTION<- paste(DESCRIPTION, "Biarch: TRUE", sep="\n")
250+
DESCRIPTION<- gsub("\n{2,}", "\n", DESCRIPTION)
251+
cat(DESCRIPTION, file="DESCRIPTION", sep="\n")
252+
}
253+
}
254+
255+
ensure_directory<-function(dir){
256+
info<- file.info(dir)
257+
258+
# no file exists at this location; try to make it
259+
if (is.na(info$isdir)){
260+
dir.create(info$isdir, recursive=TRUE, showWarnings=FALSE)
261+
if (!file.exists(dir))
262+
stop("failed to create directory '", dir, "'")
263+
return(TRUE)
264+
}
265+
266+
# a directory already exists
267+
if (isTRUE(info$isdir))
268+
return(TRUE)
269+
270+
# a file exists, but it's not a directory
271+
stop("file already exists at path '", dir, "'")
272+
}
273+
274+
enumerate<-function(x, f, ...){
275+
nms<-if (is.environment(x)) ls(envir=x) else names(x)
276+
lapply(nms, function(nm){
277+
f(nm, x[[nm]], ...)
278+
})
279+
}
280+
281+
read_file<-function(path){
282+
paste(readLines(path, warn=FALSE), collapse="\n")
283+
}
284+
285+
remove_file<-function(
286+
path,
287+
verbose= configure_verbose())
288+
{
289+
info<- file.info(path)
290+
if (!is.na(info$isdir)){
291+
unlink(path, recursive= isTRUE(info$isdir))
292+
if (verbose){
293+
fmt<-"** removed file '%s'"
294+
message(sprintf(fmt, path))
295+
}
296+
}
297+
298+
TRUE
299+
}
300+
301+
source_file<-function(
302+
path,
303+
envir= parent.frame())
304+
{
305+
contents<- read_file(path)
306+
invisible(eval(parse(text=contents), envir=envir))
307+
}
308+
309+
trim_whitespace<-function(x){
310+
gsub("^[[:space:]]*|[[:space:]]*$", "", x)
311+
}
312+
313+
configure_verbose<-function(){
314+
getOption("configure.verbose", !interactive())
315+
}
316+
317+
318+
# run.R ----
319+
320+
local({
321+
322+
# extract path to install script
323+
args<- commandArgs(TRUE)
324+
type<-args[[1]]
325+
326+
# report start of execution
327+
package<- Sys.getenv("R_PACKAGE_NAME", unset="<unknown>")
328+
fmt<-"* preparing to %s package '%s' ..."
329+
message(sprintf(fmt, type, package))
330+
331+
# execute the requested script
332+
path<- sprintf("tools/config/%s.R", type)
333+
if (file.exists(path)) source_file(path)
334+
335+
# perform automatic configuration
336+
configure_auto(type=type)
337+
338+
# report end of execution
339+
fmt<-"* finished %s for package '%s'"
340+
message(sprintf(fmt, type, package))
341+
})
342+
343+

0 commit comments

Comments
(0)