Понимание содержимого файла Makevars в R (макросы, переменные, ~/.R/Makevars и pkg/src/Makevars)

Я пытаюсь понять роль и соотношение макросов/переменных, установленных в ~/.R/Makevars и package_directory/src/Makevars при установке/создании собственных пакетов R. Предположим, что эти файлы выглядят как

~/.R/Makevars

CXX = g++
CXXSTD = -std=c++11
CXXFLAGS = -fsanitize=undefined,address -fno-omit-frame-pointer

CXX98 = g++
CXX98STD = -std=c++98

CXX11 = g++
CXX11STD = -std=c++11

CXX14 = g++
CXX14STD = -std=c++14

package_directory/SRC/Makevars

PKG_CPPFLAGS = -I../inst/include
CXX_STD = CXX11

Как я понимаю, с CXX мы можем выбрать компилятор для С++ при создании пакетов R, а CXXSTD мы выбрали стандарт, а с CXXFLAGS добавим флаги компилятора. С PKG_CPPFLAGS мы добавляем флаги для препроцессора С++ и CXX_STD говорим, что наши пакеты используют С++ 11.

У меня есть следующие вопросы:

  • Какова связь между CXX и CXX98, CXX11 и CXX14?
  • В чем смысл, например, CXX11STD = -std=c++11, если С++ 11 уже подразумевается? Это между выбором -std=c++11 и -std=gnu++11? Следует ли избегать -std=gnu++11 по причинам мобильности?
  • Невозможно добавить флаги для CXXSTD и CXXFLAGS в CXX, чтобы первые три строки уменьшались до CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer. В чем заключается преимущество в объяснении CXXSTD и CXXFLAGS?
  • Как работает CXX_STD = CXX11? Как CXX11 здесь связано с CXX11 в ~/.R/Makevars?
  • Какая связь между CXXFLAGS и PKG_CXXFLAGS (не включена в мой пример)?

Я знаю информацию, содержащуюся в Написание R-расширений и R Установка и администрирование, но я не могу извлечь больше информации за пределы моего нынешнего уровня понимания, чтобы ответить на вышеуказанные вопросы.

Я добавляю тег Rcpp, потому что я полагаю, что ответы на эти вопросы будут наиболее важны для пользователей Rcpp, но я знаю, что это, вероятно, напрямую не связано с Rcpp, поэтому тег может удаляться, если сочтет это целесообразным.

Ответ 1

Файл Makevars, указанный в Написание R-расширений: 1.2.1 Использование Makevars, является вариантом Make, который является уникальным для R. Многие из перечисленных вами переменных называются неявные переменные. Значение задается как:

Неявные правила говорят о том, как использовать обычные методы, чтобы вам не нужно было подробно их указывать, когда вы хотите их использовать.

Эти неявные переменные диктуйте, какой компилятор должен использоваться и какие варианты доступны.

Внутри R мы заботимся о следующих параметрах компилятора по умолчанию:

CC Программа для компиляции программ на C; default 'cc.

CXX Программа для компиляции программ на C++; default 'g++.

CPP Программа для запуска препроцессора C с результатами для стандартного вывода; default '$ (CC) -E.

FC Программа для компиляции или предварительной обработки программ Fortran и Ratfor; default 'f77.

Следующий набор значений указывает, какие параметры должны использоваться компилятором. В общем случае значения по умолчанию для всех этих параметров представляют собой пустую строку.

CFLAGS Дополнительные флаги для компилятора C.

CXXFLAGS Дополнительные флаги для компилятора С++.

CPPFLAGS Дополнительные флаги для предоставления препроцессору C и программам, которые его используют (компиляторы C и Fortran).

FFLAGS Дополнительные флаги для компилятора Fortran.

LDFLAGS Дополнительные флаги для компиляторов, когда они должны вызывать компоновщик ld, например -L. Библиотеки (-lfoo) следует добавить вместо переменной LDLIBS.

LDLIBS Флаги библиотеки или имена, присваиваемые компиляторам, когда они должны вызывать компоновщик, 'ld. LOADLIBES является устаревшим (но все еще поддерживается), альтернативной LDLIBS. Небиблиотечные флаги компоновки, такие как как -L, должен идти в переменной LDFLAGS.

Теперь R определяет "дополнительные" варианты в терминах различных стандартов С++ ISO. Эти варианты приведены в R Administration: Раздел 2.7.2 Поддержка С++ и R Администрирование: Раздел B.7 Компилировать и загружать флаги

CXX98 CXX98STD CXX98FLAGS CXX98PICFLAGS

CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS

CXX14 CXX14STD CXX14FLAGS CXX14PICFLAGS

CXX17 CXX17STD CXX17FLAGS CXX17PICFLAGS


Сказав это, давайте рассмотрим первый вопрос:

Какова связь между CXX и CXX98, CXX11 и CXX14?

CXX - это общая опция компилятора. Между тем, R определяет дополнительные опции CXX для использования в зависимости от установленного стандарта компиляции. То есть, если -std=c++98 (CXX98 спецификация языка), заданная CXX_STD, тогда используется компилятор, связанный с CXX98. Аналогично, для CXX11 и CXX14 следует следующая логика. Подробнее см. Галерея Rcpp: Использование Rcpp с С++ 11, С++ 14 и С++ 17.


В чем смысл, например, CXX11STD = -std=c++11, если С++ 11 уже подразумевается? Это между выбором -std=c++11 и -std=gnu++11? Следует ли избегать -std=gnu++11 по причинам мобильности?

Значение CXX11STD заключается в определении соответствующего языка для компиляции С++ 11. Этот параметр существует просто потому, что если версия R для выбора соответствующей компиляции С++ 11 неверна для компилятора, вы можете ее изменить. Причина этого заключается в том, что каждый компилятор может определить поддержку С++ 11 несколько иначе, чем следующую, как указано в R Установка и администрирование: 2.7.2 Поддержка С++:

Может быть [Сноска 13], что для поддержки С++ 11 нет подходящего флага, и в этом случае для CXX11 и соответствующих флагов может быть выбран другой компилятор.

Сноска 13:

Это справедливо для более ранних версий g++, таких как 4.2.1, а также для часто используемых версий компилятора Solaris CC.

Подробнее о языковых стандартах, одобренных gcc, см. Руководство GCC: 3.4 Опции Управление диалектом C. Кроме того, для получения подробной информации об использовании С++ 11 с R в пакете см. Написание R-расширений: Раздел 1.2.4 Использование кода С++ 11.

Как правило, я бы не стал явно устанавливать эту переменную. Если вы должны явно установить эту переменную, я бы рекомендовал перейти с -std=c++11, поскольку большинство компиляторов поддерживают это объявление.


Могут ли флаги для CXXSTD и CXXFLAGS не просто добавляться в CXX, так что первые три строки уменьшаются до CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer. В чем преимущество явного указания CXXSTD и CXXFLAGS?

Возможно ли это? Да. Это правильно? Нет.

Почему есть три переменные, каждая из которых имеет свою собственную цель, когда мы просто можем ее использовать?

Преимущества трех переменных рабочего процесса предоставляют разные строки, каждая из которых имеет определенную роль. Это позволяет быстро понять вариант компиляции. Таким образом, гораздо более прямолинейно смотреть, сравнивая, что он переполнен одной переменной на одной линии (с шириной терминала 80).

например.

CXX = g++ -std=c++11 -fsanitize=undefined,address -fno-omit-frame-pointer

против

CXX = g++ 
CXX11STD = -std=c++11
CXXFLAGS = -fsanitize=undefined,address -fno-omit-frame-pointer

Кроме того, вы должны выбрать CXX_STD над CXXSTD при упаковке, как показано в Написание расширений R: Раздел 1.2.4 Использование кода С++ 11. Это просто, чтобы гарантировать, что R зарегистрировал пакет как требующий С++ xy. Альтернативой является запись в файле DESCRIPTION атрибута SystemRequirements: C++xy, где xy обозначает год.


Как работает CXX_STD= CXX11? Как CXX11 здесь связано с CXX11 в ~/.R/Makevars?

Это устанавливает компиляцию и привязку для языка, который должен быть выполнен с помощью компилятора С++ 11, установленного CXX11. Задав CXX11, вы указываете переменную в Make, которая будет использоваться для компиляции файла по рецепту:

$(OBJCXX) $(ALL_CPPFLAGS) $(ALL_OBJCXXFLAGS) -c $< -o [email protected]

где $(OBJCXX) CXX, $(ALL_CPPFLAGS) задается $(R_XTRA_CPPFLAGS) $(PKG_CPPFLAGS) $(CLINK_CPPFLAGS) $(CPPFLAGS), а $(ALL_OBJCXXFLAGS) имеет $(PKG_OBJCXXFLAGS) $(CXXPICFLAGS) $(SHLIB_CXXFLAGS) $(OBJCXXFLAGS) .

Вышеизложенное следует /R/Makeconf.in. Однако процедура может быть /m4/R.


Какова связь между CXXFLAGS и PKG_CXXFLAGS (не включена в мой пример)?

Оба они задают флаги компиляции компилятора. Порядок, в котором они записаны в Makevars, отличается. В частности, мы имеем CXXFLAGS размещен после PKG_CXXFLAGS. Всегда используется самый правильный вариант. Итак, CXXFLAGS имеет приоритет над PKG_CXXFLAGS.

В в Написание расширений R: раздел 5.5 Создание общих объектов.

Добавление

Ниже приведены вопросы, заданные @Dominik в разделе комментариев этого ответа.


Правильно ли, что переменные, определенные в ~/.R/Makevars, применимы глобально к установке всех пакетов, а переменные в /src/Makevars применимы только к данному пакету?

Да. Это точно. Переменные внутри ~/.R/Makevars будут применяться ко всем пакетам, тогда как /src/Makevars, который поставляется с каждым пакетом, будет влиять только на настройки для этого пакета. Значения в /src/Makevars будут иметь приоритет над ~/.R/Makevars.

Некоторые пакеты могут поставляться с /src/Makevars.win, который предоставляет файл Makevars специально для среды Windows.


Является ли стандарт компиляции для пакетов в настоящее время установленным только через CXX_STD и не более чем на PKG_CXXFLAGS, как показано в gallery.rcpp.org/articles/simple-lambda-func-c++11?

Существует небольшое различие между этими двумя флагами. В частности, CXX_STD работает только в среде пакета. Между тем, вопреки его имени, PKG_CXXFLAGS, влияет на все параметры компиляции. Таким образом, при цитировании вышеупомянутого сообщения галереи Rcpp вы выполняете автономный запуск script. Чтобы быстро включить правильный режим, для которого требуется PKG_CXXFLAGS, а не определение CXX_STD.

Теперь, простите меня за краткое касание истории автономных вариантов компиляции использования. Использование PKG_CXXFLAGS - это немного старая школа. На самом деле предпочтительным подходом в R 3.4 является установка переменной окружения USE_CXX11 = "yes". Между R 3.1 и R 3.3 стандартом было установить переменную среды USE_CXX1X = "yes". До этих случаев предпочтение отдается использованию PKG_CXXFLAGS ="-std=c++11". (За исключением Windows, для которого требуется PKG_CXXFLAGS ="-std=c++0x".)


Используется ли CXX_STD=CXX11 для использования всех настроек, заданных CXX, CXXSTD, CXXFLAGS и CXX11PICFLAGS?

Нет. Это означает использование опций, установленных:

CXX11 CXX11STD CXX11FLAGS CXX11PICFLAGS