My project has a main executable and a test executable. All files from the main executable except the one with the int main() definition are used in the test executable too. So I put these files in a library which is linked to main and test executable.
Also on GitHub: https://github.com/bb1950328/CMakeBuildTwiceMinimalReproduce
$ tree
.
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── fibonacci.cpp
    ├── fibonacci.h
    ├── main.cpp
    └── test.cpp
CMakeLists.txtcmake_minimum_required(VERSION 3.19)
project(CMakeBuildTwiceMinimalReproduce)
set(CMAKE_CXX_STANDARD 14)
# uncomment the next line to add the files directly (without using target_sources)
# add_library(Lib src/fibonacci.h src/fibonacci.cpp)
# uncoment the next two lines to add the files using target_sources (inside src/CMakeLists.txt)
add_library(Lib)
add_subdirectory(src)
add_executable(MainExecutable src/main.cpp)
add_executable(TestExecutable src/test.cpp)
target_link_libraries(MainExecutable Lib)
target_link_libraries(TestExecutable Lib)
src/CMakeLists.txttarget_sources(Lib PUBLIC fibonacci.cpp fibonacci.h)
src/fibonacci.cpp#include "fibonacci.h"
int fibonacci(int nth) {
    int a = 1, b = 1;
    for (int i = 0; i < nth; ++i) {
        int res = a + b;
        a = b;
        b = res;
    }
    return b;
}
src/fibonacci.h#ifndef FIBONACCI_H
#define FIBONACCI_H
int fibonacci(int nth);
#endif //FIBONACCI_H
src/main.cpp#include <iostream>
#include "fibonacci.h"
int main() {
    std::cout << "Main" << fibonacci(5) << std::endl;
    return 0;
}
src/test.cpp#include <iostream>
#include "fibonacci.h"
int main() {
    std::cout << "Testing" << fibonacci(6) << std::endl;
    return 0;
}
In the root CMakeLists.txt there are two variants
fibonacci.* files directly when calling add_librarytarget_sources inside src/CMakeLists.txtBoth variants work fine, but when using variant 2, the fibonacci.cpp.o object is built twice:
[ 20%] Building CXX object CMakeFiles/Lib.dir/src/fibonacci.cpp.o
[ 40%] Linking CXX static library libLib.a
[ 40%] Built target Lib
Scanning dependencies of target MainExecutable
[ 60%] Building CXX object CMakeFiles/MainExecutable.dir/src/main.cpp.o
[ 80%] Building CXX object CMakeFiles/MainExecutable.dir/src/fibonacci.cpp.o
[100%] Linking CXX executable MainExecutable
[100%] Built target MainExecutable
Build finished
The above log is from Ubuntu 21.04, ${CMAKE_VERSION}=3.19.2, -G"Unix Makefiles"
The log for variant 1 is the same, except that the line [ 80%] Building CXX object CMakeFiles/MainExecutable.dir/src/fibonacci.cpp.o isn't there, so the file is only built once.
The reason why I want to use variant 2 is that I can keep the list of source files in the same directory as the files itself. Otherwise the root CMakeLists.txt would be huge.
So my question is: How can I use target_sources to add files to the library without building them twice?
This question is NOT a duplicate of this or this.
How can I use
target_sourcesto add files to the library without building them twice?
Normally, target_sources command is used only with PRIVATE keyword:
target_sources(Lib PRIVATE fibonacci.cpp fibonacci.h)
With that keyword sources will be used only when compile the library itself, and won't be used when compile a library/executable which is linked with your library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With