在我的项目中有一个简单的结构,其中包括几个子文件夹/子项目。结构如下:
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.h
#ifdef WITH_ADDS
class Adds
{
public:
void doSomething();
}
#endif
和*.cpp文件
相同但是现在我想在我的主项目中使用这些额外的类。
main.cpp
#include "adds.h"
Adds adds;
adds.doSomething();
所以我在主cmakeffiles .txt中打开了选项,但不幸的是,我得到了错误:
error: ‘Adds ’ does not name a type
经过研究,我发现add_definitions()
只在定义它的项目中工作。因此,尽管我已经在主文件中打开了定义WITH_ADDS
的选项,但仍然没有在主项目上定义,而是在子项目中定义。
所以我的问题-有没有一种方法来全局定义一个预处理器变量。所以一旦在子项目中定义,它将在所有其他项目/子项目中访问?或者有其他的解决方法?
现代cmake"方法是将所有标志封装在子项目中,当您使用target_link_library(MYEXE libsubproject)
链接到子项目时,所有必要的路径、标志和定义都将传播到主项目。
为此,在子项目中使用target_compile_definitions(library PUBLIC ADDS)
,它将把设置传播给此目标的任何用户。如果您的顶层正在为这个子项目手动添加一个包含路径,请删除它,并在子项目target_include_directories(library PUBLIC ./include)
中对包含路径使用相同的策略,以便目标的任何用户都将继承该路径。
PUBLIC
关键字是使传播工作的关键字:它意味着该设置既适用于构建库,也适用于用户。INTERFACE
表示仅供用户使用,PRIVATE
表示仅供构建库使用。