Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: How to reuse source file definitions between targets without duplication?

Tags:

cmake

In my CMake project, I have 2 targets (a static library and a shared library) that share the same source code files, like this:

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"
)

Obviously, there is a problem here: the sources definition is duplicated. It's hard to maintain and it's also error prone.

In order to avoid that, I'd like to create a CMake list variable so that the sources definition could be reused in both targets.

I've tried this but it doesn't work:

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})

It fails with the error: Cannot find source file.

So... how could I reuse source file definitions between targets without this duplication? Is it possible to do this using lists or is there a better approach to solve this issue?

PS: I'm using CMake 3.15

like image 992
hbobenicio Avatar asked Sep 06 '25 22:09

hbobenicio


1 Answers

Your code is close; you can simply use the CALCULATOR_CORE_SOURCES_LIST variable to add the group of sources/headers to both add_library() calls:

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})

If the group of sources is the same for both libraries, you should only need to define the list once. From the documentation, the set command will do the following:

Multiple arguments will be joined as a semicolon-separated list to form the actual variable value to be set.

Thus, this list can be passed to the add_library() calls. You also shouldn't need the quotes (") around each file.

like image 152
Kevin Avatar answered Sep 09 '25 08:09

Kevin