CMake在.o和.a文件之间添加了不必要的依赖项



我有一个由CMake管理的项目,其中有多个库,它们之间具有链接时间依赖关系,但每个库都可以独立编译。如何向CMake表达这一点,以便同时构建所有库?

例如,我尝试了这个CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)
project (test)
add_library(lib1 STATIC lib1.cpp)
add_library(lib2 STATIC lib2.cpp)
add_library(lib3 STATIC lib3.cpp)
add_executable(main main.cpp)
target_link_libraries(lib2 lib1)
target_link_libraries(lib3 lib2)
target_link_libraries(main lib3)

每个文件只定义了一个不同的空函数,如:

void f1() {}

当我键入cmake . && make -j4时,我看到的是:

[ 25%] Building CXX object CMakeFiles/lib1.dir/lib1.cpp.o
Linking CXX static library liblib1.a
[ 25%] Built target lib1
[ 50%] Building CXX object CMakeFiles/lib2.dir/lib2.cpp.o
Linking CXX static library liblib2.a
[ 50%] Built target lib2
[ 75%] Building CXX object CMakeFiles/lib3.dir/lib3.cpp.o
Linking CXX static library liblib3.a
[ 75%] Built target lib3
[100%] Building CXX object CMakeFiles/main.dir/main.cpp.o
Linking CXX executable main
[100%] Built target main

尽管我已经指定了-j4,并且编译每个.cpp文件永远不应该依赖于任何.a文件,但它正在等待上一个编译和链接完成并开始下一个。我宁愿看到这样的东西:

Building CXX object CMakeFiles/lib1.dir/lib1.cpp.o
Building CXX object CMakeFiles/lib2.dir/lib2.cpp.o
Building CXX object CMakeFiles/lib3.dir/lib3.cpp.o
Building CXX object CMakeFiles/main.dir/main.cpp.o
Linking CXX static library liblib1.a
Built target lib1
Linking CXX static library liblib2.a
Built target lib2
Linking CXX static library liblib3.a
Built target lib3
Linking CXX executable main
Built target main

有可能告诉CMake它可以同时构建所有的.o文件吗?

事实上,我在一个百万线的项目中做这件事,我可以使用大约20个CPU核心(使用distcc),所以这是我构建时间的一个巨大瓶颈。

顺序执行可能是静态库lib1lib2lib3之间建立的链接依赖关系的结果。

一个解决办法是消除这些静态库链接依赖关系。由于您无论如何都在构建静态库,因此删除依赖项不会阻止它们成功链接。可执行文件main需要依赖于所有库,然后:

cmake_minimum_required(VERSION 2.6)
project (test)
add_library(lib1 STATIC lib1.cpp)
add_library(lib2 STATIC lib2.cpp)
add_library(lib3 STATIC lib3.cpp)
add_executable(main main.cpp)
target_link_libraries(main lib1 lib2 lib3)

以这种方式组织make -j并行构建库。

如果摆脱链接依赖性不是一种选择,你可以应用"计算机科学中的任何问题都可以用另一层间接方法来解决"的原则:

cmake_minimum_required(VERSION 2.6)
project (test)
add_library(lib1_objects STATIC lib1.cpp)
add_library(lib2_objects STATIC lib2.cpp)
add_library(lib3_objects STATIC lib3.cpp)
add_executable(main main.cpp)
add_library(lib1 STATIC empty.cpp)
add_library(lib2 STATIC empty.cpp)
add_library(lib3 STATIC empty.cpp)
target_link_libraries(lib1 lib1_objects)
target_link_libraries(lib2 lib2_objects lib1)
target_link_libraries(lib3 lib3_objects lib2)
target_link_libraries(main lib3)

这设置了辅助库(例如lib1_objects),这些辅助库没有依赖关系,因此可以并行构建。原始库链接到这些辅助库,还设置了所需的链接依赖项。empty.cpp只是一个空的伪CPP源文件。

最新更新