CMake:如何在目标之间重用源文件定义而不重复?

hbo*_*cio 4 cmake

在我的 CMake 项目中,我有 2 个共享相同源代码文件的目标(静态库和共享库),如下所示:

add_library("${PROJECT_NAME}" STATIC
    "${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h"
    "${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp"
    "${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h"
    "${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp"
)
add_library("${PROJECT_NAME}-shared" SHARED
    "${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h"
    "${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp"
    "${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h"
    "${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp"
)
Run Code Online (Sandbox Code Playgroud)

显然,这里存在一个问题:源定义是重复的。它很难维护并且也容易出错。

为了避免这种情况,我想创建一个 CMake 列表变量,以便源定义可以在两个目标中重用。

我已经尝试过这个但它不起作用:

set(CALCULATOR_CORE_SOURCES_LIST
    "${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h"
    "${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp"
    "${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h"
    "${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp"
)
string(REPLACE ";" " " CALCULATOR_CORE_SOURCES "${CALCULATOR_CORE_SOURCES_LIST}")

add_library("${PROJECT_NAME}" STATIC ${CALCULATOR_CORE_SOURCES})
add_library("${PROJECT_NAME}-shared" SHARED ${CALCULATOR_CORE_SOURCES})
Run Code Online (Sandbox Code Playgroud)

它失败并出现错误:Cannot find source file.

那么...如何在目标之间重用源文件定义而不进行这种重复?是否可以使用列表来做到这一点,或者是否有更好的方法来解决这个问题?

PS:我使用的是CMake 3.15

squ*_*les 5

你的代码很接近;您可以简单地使用该CALCULATOR_CORE_SOURCES_LIST变量将源/标头组添加到两个add_library()调用中:

set(CALCULATOR_CORE_SOURCES_LIST
    ${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h
    ${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp
    ${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h
    ${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp
)

add_library(${PROJECT_NAME} STATIC ${CALCULATOR_CORE_SOURCES_LIST})
add_library(${PROJECT_NAME}-shared SHARED ${CALCULATOR_CORE_SOURCES_LIST})
Run Code Online (Sandbox Code Playgroud)

如果两个库的源组相同,则您只需定义列表一次。从文档来看,该set命令将执行以下操作:

多个参数将作为分号分隔的列表连接起来,形成要设置的实际变量值。

因此,这个列表可以传递给add_library()调用。您也不应该需要在每个文件周围加上引号 ( ")。