Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake building files twice when using `target_sources` on common library

Tags:

c++

cmake

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

  1. add the two fibonacci.* files directly when calling add_library
  2. add the files using target_sources inside src/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.

like image 214
bb1950328 Avatar asked Nov 01 '25 20:11

bb1950328


1 Answers

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.

like image 167
Tsyvarev Avatar answered Nov 03 '25 10:11

Tsyvarev