CMake在.o和.a文件之间添加了不必要的依赖关系 [英] CMake adds unnecessary dependencies between .o and .a files

查看:1969
本文介绍了CMake在.o和.a文件之间添加了不必要的依赖关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由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%]构建CXX对象CMakeFiles / lib1。 dir / lib1.cpp.o 
链接CXX静态库liblib1.a
[25%]内部目标lib1
[50%]构建CXX对象CMakeFiles / lib2.dir / lib2.cpp。 o
链接CXX静态库liblib2.a
[50%]构建目标lib2
[75%]构建CXX对象CMakeFiles / lib3.dir / lib3.cpp.o
链接CXX静态库liblib3.a
[75%]构建目标lib3
[100%]构建CXX对象CMakeFiles / main.dir / main.cpp.o
链接CXX可执行文件main
[100%]建立目标主要

即使我已指定 j4 并且编译每个.cpp文件应该从不依赖于任何.a文件,它等待上一次编译和链接完成下一个。我宁愿看到像:

 构建CXX对象CMakeFiles / lib1.dir / lib1.cpp.o 
编译CXX对象CMakeFiles / lib2.dir / lib2.cpp.o
构建CXX对象CMakeFiles / lib3.dir / lib3.cpp.o
构建CXX对象CMakeFiles / main.dir / main.cpp.o
链接CXX静态库liblib1.a
构建目标lib1
链接CXX静态库liblib2.a
构建目标lib2
链接CXX静态库liblib3.a
构建目标lib3
链接CXX可执行文件main
构建目标main

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



在现实中,我在一个百万线项目中使用大约20个CPU内核

解决方案

顺序执行可能是一个后果的静态库之间建立的链接相关性 lib1 lib2 lib3



一种解决方法是摆脱这些静态库链接依赖。由于您仍然构建静态库,删除依赖关系不会阻止它们成功链接。可执行文件 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)



如果摆脱链接依赖不是一个选项,您可以应用原则计算机科学中的任何问题都可以通过另一层间接解决

  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源文件。


I've got a project managed by CMake with multiple libraries that have link time dependencies between them, but each of the libraries can be compiled independently of each other. How do I express this to CMake so that I can build all the libraries concurrently?

For example, I tried this 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)

Each file just defines a different empty function like:

void f1() {}

When I type cmake . && make -j4, I see this:

[ 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

Even though I've specified -j4 and compiling each .cpp file should never depend on any .a files, it's waiting on the previous compile and link to finish begin the next one. I'd rather see something like:

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

Is it possible to tell CMake that it can build all the .o files concurrently?

In reality, I'm doing this in a million-line project with about 20 CPU cores at my disposal (with distcc), so this is a huge bottleneck on my build times.

解决方案

The sequential execution is probably a consequence of the link dependencies established between the static libraries lib1, lib2 and lib3.

One work-around is to get rid of these static library link dependencies. Since you are building static libraries anyway, removing the dependencies will not prevent them from being linked successfully. The executable main needs to depend on all libraries then:

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)

Organized this way make -j builds the libraries in parallel.

If getting rid of the link dependencies is not an option, you can apply the principle "Any problem in computer science can be solved with another layer of indirection":

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)

This sets up helper libraries (e.g., lib1_objects), which have no dependencies and can thus be built in parallel. The original libraries link to these helper libraries and also have the required link dependencies set up. empty.cpp is just an empty dummy CPP source file.

这篇关于CMake在.o和.a文件之间添加了不必要的依赖关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆