Если в файле .mk
есть что-то, кроме прямого расширения переменных (например, более сложные make
-rules / tricks / functions), может быть лучше доверять make
, чтобы выполнить расширение за вас, а затемпрочитайте его. Есть сообщение здесь , которое, как я обнаружил, сбрасывает все переменные (после обработки).
TL; DR
expand_mkvars <- function(path, aslist = FALSE) {
stopifnot(file.exists(mk <- Sys.which("make")))
tf <- tempfile(fileext = ".mk")
# needed on my windows system
tf <- normalizePath(tf, winslash = "/", mustWork = FALSE) # tempfile should suffice
on.exit(suppressWarnings(file.remove(tf)), add = TRUE)
writeLines(c(".PHONY: printvars",
"printvars:",
"\t@$(foreach V,$(sort $(.VARIABLES)), \\",
"\t $(if $(filter-out environment% default automatic, \\",
"\t $(origin $V)),$(warning $V=$($V))))"), con = tf)
out <- system2(mk, c("-f", shQuote(path), "-f", shQuote(tf), "-n", "printvars"),
stdout = TRUE, stderr = TRUE)
out <- out[grepl(paste0("^", tf), out)]
out <- gsub(paste0("^", tf, ":[0-9]+:\\s*"), "", out)
known_noneed <- c(".DEFAULT_GOAL", "CURDIR", "GNUMAKEFLAGS", "MAKEFILE_LIST", "MAKEFLAGS")
out <- out[!grepl(paste0("^(", paste(known_noneed, collapse = "|"), ")="), out)]
if (aslist) {
spl <- strsplit(out, "=")
nms <- sapply(spl, `[[`, 1)
rest <- lapply(spl, function(a) paste(a[-1], collapse = "="))
setNames(rest, nms)
} else out
}
В действии:
expand_mkvars("~/StackOverflow/karthikt.mk")
# [1] "file=./here/is/a/path/file.csv" "num=100"
# [3] "path=./here/is/a/path"
expand_mkvars("~/StackOverflow/karthikt.mk", aslist = TRUE)
# $file
# [1] "./here/is/a/path/file.csv"
# $num
# [1] "100"
# $path
# [1] "./here/is/a/path"
Я не тестировал другие системы, поэтому вам может потребоваться настроить known_noneed
для добавления всплывающих дополнительных переменных.В зависимости от ваших потребностей, вы могли бы фильтровать более интеллектуально (например, ни одна из ваших переменных не должна начинаться с заглавной буквы), но для этого примера я сохранил ее для переменных, которые нам неизвестны, которые нам дает make
.
В блоге предлагается использовать фальшивую цель
.PHONY: printvars
printvars:
@$(foreach V,$(sort $(.VARIABLES)), \
$(if $(filter-out environment% default automatic, \
$(origin $V)),$(warning $V=$($V))))
(некоторые из них - табуляции, а не все пробелы, очень важны для make
)
К сожалению, он производит больше выходных данных, чем вам технически необходимо:
$ /c/Rtools/bin/make.exe -f ~/StackOverflow/karthikt.mk printvars
C:/Users/r2/StackOverflow/karthikt.mk:10: .DEFAULT_GOAL=all
C:/Users/r2/StackOverflow/karthikt.mk:10: CURDIR=/Users/r2/Projects/Ford/shiny/shinyobjects/inst
C:/Users/r2/StackOverflow/karthikt.mk:10: GNUMAKEFLAGS=
C:/Users/r2/StackOverflow/karthikt.mk:10: MAKEFILE_LIST= C:/Users/r2/StackOverflow/karthikt.mk
C:/Users/r2/StackOverflow/karthikt.mk:10: MAKEFLAGS=
C:/Users/r2/StackOverflow/karthikt.mk:10: SHELL=sh
C:/Users/r2/StackOverflow/karthikt.mk:10: file=./here/is/a/path/file.csv
C:/Users/r2/StackOverflow/karthikt.mk:10: num=100
C:/Users/r2/StackOverflow/karthikt.mk:10: path=./here/is/a/path
make: Nothing to be done for 'printvars'.
, поэтому нам нужна небольшая фильтрация, поэтому большая часть кода в функции.
Редактировать : если readRenviron
-to-envvar - лучший способ для вас, нетрудно перенаправить вывод этого вызова make
в другой файл, разобрать соответствующие строки,и затем сделайте readRenviron
для этого нового файла.Это кажется более косвенным из-за использования двух временных файлов, но они очищены, поэтому не о чем беспокоиться.