Определение препроцессора в современном CMake - PullRequest
2 голосов
/ 05 апреля 2019

В настоящее время я изучаю CMake и не хочу получать вредных привычек, поскольку в CMake всегда есть 2 способа сделать что-то (старый и современный способ из того, что я видел)

После прочтения некоторой документации о препроцессоре в CMake и проверки этого поста: Определение макроса препроцессора с помощью cmake

Я пришел к выводу, что я мог бы определить препроцессор как:

  • add_compile_definitions(FOO)
  • target_compile_definitions(myTarget PRIVATE FOO)
  • add_definitions(-DFOO)

и после некоторого теста они фактически все работают как задумано и определяют FOO

Но теперь мой вопрос заключается в том, какой самый «современный» способ я должен использовать, и в чем разница между каждой функцией, единственное различие, которое я заметил, заключается в том, что если я использую target_compile_definitions(myTarget PUBLIC FOO), тогда он определяет FOO в родительском цель.

Ответы [ 2 ]

3 голосов
/ 05 апреля 2019

Общая тенденция в современном CMake - перейти от глобальных настроек к настройкам, ориентированным на цель. Исходя только из этого правила, target_compile_definitions() - самый современный подход. Это также позволяет контролировать, используются ли настройки только в цели (PRIVATE), в других целях, использующих эту цель (INTERFACE), или в обеих (PUBLIC). Внутренне это работает, изменяя свойства цели COMPILE_DEFINITIONS и INTERFACE_COMPILE_DEFINITIONS.

Следующим по уровню современности является add_compile_definitions(). Он добавляет определения макросов ко всем целям, определенным в текущем каталоге и подкаталогах; в этом отношении его объем аналогичен include_directories(). Внутренне это работает путем изменения свойства COMPILE_DEFINITIONS текущего каталога. Итак: он по-прежнему использует правильные «современные» механизмы, но ориентирован на каталог, а не на целевой.

В нижней части списка у нас есть очень старая функция add_definitions(). Это действительно лучше избегать в современном CMake. Хотя он предназначен для указания определений препроцессора (отсюда и его имя), он на самом деле позволяет передавать произвольные параметры компилятора (именно поэтому вам необходимо указать -DFOO вместо просто FOO в качестве аргумента). Он пытается выяснить, являются ли передаваемые вещи на самом деле определениями макросов препроцессора, и в этом случае они перемещаются в свойство каталога COMPILE_DEFINTIIONS. Если они не определены как таковые (что может произойти для макросов со сложными замещающими строками), они остаются в списке флагов.

2 голосов
/ 05 апреля 2019

Действительно, target_compile_definitions является наиболее адекватным способом добавления макросов предварительной обработки.

Причина, по которой target_compile_definitions(myTarget PUBLIC FOO) распространяет FOO на зависимости, также является одной из причин, по которой вы должны использовать ее, поскольку вы можете правильно определить их для каждой цели, а не для каждой папки. Теперь вы можете прикрепить эти определения к цели, чтобы зависимости также объявляли их. Если вы попытаетесь создать цели из разных папок, вы увидите это поведение более точно и увидите, что оно на самом деле имеет гораздо больший смысл, чем предыдущий, очень ненадежный.

Например, в Windows все обычные макросы «export» должны быть объявлены таким образом и PRIVATE, чтобы они не распространялись, так как это действительно частные определения.

...