Issue
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.
Minimal reproducible example:
Also on GitHub: https://github.com/bb1950328/CMakeBuildTwiceMinimalReproduce
$ tree
.
├── CMakeLists.txt
└── src
├── CMakeLists.txt
├── fibonacci.cpp
├── fibonacci.h
├── main.cpp
└── test.cpp
CMakeLists.txt
cmake_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.txt
target_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
- add the two
fibonacci.*
files directly when callingadd_library
- add the files using
target_sources
insidesrc/CMakeLists.txt
Both 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.
Solution
How can I use
target_sources
to 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.
Answered By - Tsyvarev