cmake如何设置全局定义?
Cmake how to set a global definition?
我的项目中有一个简单的结构,其中包括几个 subfolders/subprojects。结构如下:
main
|- CmakeLists.txt
|- include
|- src
|- library
|- CmakeLists.txt
|- include
|- src
主要CmakeLists.txt
project(main)
file(GLOB SRC . src/*.cpp)
file(GLOB INC . include/*.h)
add_executable(${PROJECT_NAME} ${SRC} ${INC})
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
option(ADDS, "", ON)
add_subdirectory(library)
target_link_libraries(${PROJECT_NAME} PRIVATE library)
和图书馆的 CmakeLists.txt
project(library)
file(GLOB SRC . src/*.cpp)
file(GLOB INC . include/*.h)
add_library(${PROJECT_NAME} SHARED ${SRC} ${INC})
option(ADDS, "Some additional classes", OFF)
if(ADDS)
message(STATUS "Configure with some extra classes")
add_definitions(-DWITH_ADDS)
endif()
实际上我需要 option
来选择性地 add/compile 几个额外的 类,通常我不打算 use/compile。在这些额外的 类 中,我做了这样的事情:
library/add.h
#ifdef WITH_ADDS
class Adds
{
public:
void doSomething();
}
#endif
与*.cpp文件相同
但现在我想在我的主项目中使用这些额外的 类。
main.cpp
#include "adds.h"
Adds adds;
adds.doSomething();
所以我在主要 CMakeFiles.txt 中打开了选项,但不幸的是我得到了错误:
error: ‘Adds ’ does not name a type
经过研究,我发现 add_definitions()
仅在定义它的项目中有效。因此,尽管我已经在我的主文件中打开了该选项,但定义 WITH_ADDS
仍然没有在主项目中定义,但仅在子项目中定义。
所以我的问题 - 有没有办法全局定义预处理器变量。因此,一旦在子项目中定义,它就可以在所有其他 projects/subprojects 中访问?或者也许还有其他解决方案?
“现代 cmake”方法是所有标志都封装在子项目中,当您 link 使用 target_link_library(MYEXE libsubproject)
到子项目时,所有必要的路径、标志和定义都会传播到主要项目。
为此,请在子项目中使用 target_compile_definitions(library PUBLIC ADDS)
,这会将设置传播给该目标的所有用户。如果您的顶层手动添加此子项目的包含路径,请将其删除并使用相同的包含路径策略:在子项目中,target_include_directories(library PUBLIC ./include)
,以便目标的任何用户都将继承此路径。
PUBLIC
关键字使传播起作用:这意味着该设置既适用于构建库,也适用于用户。 INTERFACE
表示仅供用户使用,PRIVATE
表示仅用于构建库。
我的项目中有一个简单的结构,其中包括几个 subfolders/subprojects。结构如下:
main
|- CmakeLists.txt
|- include
|- src
|- library
|- CmakeLists.txt
|- include
|- src
主要CmakeLists.txt
project(main)
file(GLOB SRC . src/*.cpp)
file(GLOB INC . include/*.h)
add_executable(${PROJECT_NAME} ${SRC} ${INC})
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
option(ADDS, "", ON)
add_subdirectory(library)
target_link_libraries(${PROJECT_NAME} PRIVATE library)
和图书馆的 CmakeLists.txt
project(library)
file(GLOB SRC . src/*.cpp)
file(GLOB INC . include/*.h)
add_library(${PROJECT_NAME} SHARED ${SRC} ${INC})
option(ADDS, "Some additional classes", OFF)
if(ADDS)
message(STATUS "Configure with some extra classes")
add_definitions(-DWITH_ADDS)
endif()
实际上我需要 option
来选择性地 add/compile 几个额外的 类,通常我不打算 use/compile。在这些额外的 类 中,我做了这样的事情:
library/add.h
#ifdef WITH_ADDS
class Adds
{
public:
void doSomething();
}
#endif
与*.cpp文件相同
但现在我想在我的主项目中使用这些额外的 类。
main.cpp
#include "adds.h"
Adds adds;
adds.doSomething();
所以我在主要 CMakeFiles.txt 中打开了选项,但不幸的是我得到了错误:
error: ‘Adds ’ does not name a type
经过研究,我发现 add_definitions()
仅在定义它的项目中有效。因此,尽管我已经在我的主文件中打开了该选项,但定义 WITH_ADDS
仍然没有在主项目中定义,但仅在子项目中定义。
所以我的问题 - 有没有办法全局定义预处理器变量。因此,一旦在子项目中定义,它就可以在所有其他 projects/subprojects 中访问?或者也许还有其他解决方案?
“现代 cmake”方法是所有标志都封装在子项目中,当您 link 使用 target_link_library(MYEXE libsubproject)
到子项目时,所有必要的路径、标志和定义都会传播到主要项目。
为此,请在子项目中使用 target_compile_definitions(library PUBLIC ADDS)
,这会将设置传播给该目标的所有用户。如果您的顶层手动添加此子项目的包含路径,请将其删除并使用相同的包含路径策略:在子项目中,target_include_directories(library PUBLIC ./include)
,以便目标的任何用户都将继承此路径。
PUBLIC
关键字使传播起作用:这意味着该设置既适用于构建库,也适用于用户。 INTERFACE
表示仅供用户使用,PRIVATE
表示仅用于构建库。