Экспорт сообщений об ошибках компиляции g ++ из библиотеки TMB в текстовый файл

Я пытаюсь скомпилировать модель с gcc (c ++) в R (используя пакет TMB). Ошибки настолько многочисленны, что в Rstudio я даже не могу прокрутить вверх, чтобы увидеть их начало. Поэтому я хотел бы распечатать все в консоли (сообщения, ошибки и предупреждения) в текстовый файл. Таким образом, я мог бы также сравнить различные результаты модели (или, в частности, их ошибки).

Я пробовал следующие вещи:

fileConn<-file("Fail.txt")
writeLines(compile("Mymodel.cpp"), fileConn)
close(fileConn)

=> Дает мне пустой файл (который я более или менее ожидал)

zz <- file("Fail.txt", open = "wt")
sink(zz, type = "message")
compile("Mymodel.cpp")
sink()

=> печатает только последнюю ошибку

Что я упустил?

1

Решение

Вы не предоставили свой compile() функция, но я предполагаю, что она запускает системную команду, которая вызывает g++ Скомпилировать Mymodel.cpp,

В этом случае g++ процесс выведет свой вывод ошибок в stderr. Единственный способ захватить этот вывод, используя R, это вызвать system2() с stderr=T, Обратите внимание, что system() не может напрямую захватывать stderr (хотя он может захватывать stdout через intern=Tи вы могли бы добавить 2>&1 в команду оболочки для захвата stderr вместе с ним, так что это еще один жизнеспособный вариант). sink() не захватывает вывод системных команд; он только захватывает вывод R

Я рекомендую передать аргументы compile() функция к system2() вызов, таким образом, параметризация ли ваш вызов compile() результаты в g++sderder собирается в терминал или на возвращаемое значение вашего compile() функция. Вот как это будет сделано:

write('error!','test1.cpp'); ## generate a test file with invalid C++
compile <- function(file,...) system2('g++',file,...);
compile('test1.cpp'); ## output lost to the terminal
## test1.cpp:1:1: error: ‘error’ does not name a type
##  error!
##  ^
output <- compile('test1.cpp',stdout=T,stderr=T); ## capture output
## Warning message:
## running command ''g++' 'test1.cpp' 2>&1' had status 1
output;
## [1] "test1.cpp:1:1: error: ‘error’ does not name a type"## [2] " error!"## [3] " ^"## attr(,"status")
## [1] 1
write(output,'output.txt'); ## write output to a text file
cat(readLines('output.txt'),sep='\n'); ## show it
## test1.cpp:1:1: error: ‘error’ does not name a type
##  error!
##  ^

Если вы действительно хотите захватить все вывод генерируется в вашем compile() функции, то вы можете объединить вышеуказанное решение с sink() как показано здесь: Как сохранить весь вывод консоли в файл в R?.

В этом случае я бы порекомендовал отказаться от идеи аргументов с переменным аргументом и добавить один дополнительный аргумент в compile(), который будет принимать имя выходного файла, в который будут записаны все выходные данные.

Это потребует нескольких предположений об отсутствии дополнительного аргумента:

write('error!','test1.cpp'); ## generate a test file with invalid C++
compile <- function(file,outputFile) {
if (!missing(outputFile)) {
outputCon <- file(outputFile,'wt'); ## require file name
sink(outputCon);
sink(outputCon,type='message'); ## must sink messages separately
warn.old <- options(warn=1)$warn; ## necessary to capture warnings as they occur
}; ## end if
cat('some random output 1\n');
if (!missing(outputFile)) {
output <- system2('g++',file,stdout=T,stderr=T); ## before flush to get warnings
sink(); ## force flush before appending system command output
sink(type='message');
outputCon <- file(outputFile,'at'); ## must reopen connection for appending
write(output,outputCon);
sink(outputCon);
sink(outputCon,type='message');
} else {
system2('g++',file);
}; ## end if
cat('some random output 2\n');
if (!missing(outputFile)) {
sink();
sink(type='message');
options(warn=warn.old);
}; ## end if
}; ## end compile()
compile('test1.cpp'); ## output lost to the terminal
## some random output 1
## test1.cpp:1:1: error: ‘error’ does not name a type
##  error!
##  ^
## some random output 2
compile('test1.cpp','output.txt'); ## internally capture all output
cat(readLines('output.txt'),sep='\n'); ## show it
## some random output 1
## Warning: running command ''g++' test1.cpp 2>&1' had status 1
## test1.cpp:1:1: error: ‘error’ does not name a type
##  error!
##  ^
## some random output 2
2

Другие решения

Это старый вопрос, но я нашел простое решение, чтобы получить вывод файла журнала для TMB::compile, которого я больше нигде не нашел.
Как указано выше, sink () не фиксирует вывод системных команд; он только захватывает вывод R
Однако любой аргумент, не указанный в функции compile из библиотеки TMB передаются как переменные Makeconf. Таким образом, вам нужно только передать классическую команду вывода с путем к целевому лог-файлу в строковом формате:

TMB::compile(file = "Mymodel.cpp", "&> /tmp/logfile.log")
0

По вопросам рекламы [email protected]