Build 在您构建的库上使用--CMake中的整个存档

Build 在您构建的库上使用--CMake中的整个存档,build,cmake,ld,build-dependencies,Build,Cmake,Ld,Build Dependencies,我有一个CMake项目,同时构建一个静态库,并将其与其他代码链接到一个可执行文件中。出于我不想讨论的原因,我希望此链接使用--whole archive链接器标志进行 现在,这个标志很棘手,因为你不能只在任何地方添加它-你必须切换它,然后列出你想应用它的库,然后取消它 我在某个地方读到(我想不出URL),如果您有一个预先存在的库,您可以通过执行以下操作有效地添加此链接器标志: # Just an example, find_library calls should really be isola

我有一个CMake项目,同时构建一个静态库,并将其与其他代码链接到一个可执行文件中。出于我不想讨论的原因,我希望此链接使用
--whole archive
链接器标志进行

现在,这个标志很棘手,因为你不能只在任何地方添加它-你必须切换它,然后列出你想应用它的库,然后取消它

我在某个地方读到(我想不出URL),如果您有一个预先存在的库,您可以通过执行以下操作有效地添加此链接器标志:

# Just an example, find_library calls should really be isolated to separate find modules
find_library(FOO_LIBRARY foo)
set(FOO_LIBRARY "-Wl,--whole-archive ${FOO_LIBRARY} -Wl,--no-whole-archive")

add_executable(hello main.c)
target_link_libraries(hello ${FOO_LIBRARY})
那很好。但是,如果您正在构建的是一个静态库,而您没有预先存在的变量(即,您有
add\u library()
CMake命令的对象),该怎么办?是否必须手动指示其路径而不是${FOO_LIBRARY}?或者,您是否可以使用其他技巧来获取CMake在命令行上为其设置的路径


此外,如果我使用某种类似
${FOO_LIBRARY}
-的字符串而不是静态库目标标识符,我相信CMake可能会丢失依赖项,即它可能不会与修改后的库重新链接(甚至不会构建它)因为target_link_libraries命令将看到一个奇怪的字符串,而不是另一个目标的标识符。

这可以通过以下方法完成:

add_dependencies(the_exe the_static_lib)
set_target_properties(the_exe LINK_FLAGS
    "-L/path/to/the_static_lib -Wl,--whole-archive,-lthe_static_lib,--no-whole-archive")
-L/path/to/The_static_lib
的值透明地遵循您指定的输出目录 要设置的目标,如果不设置,则为目标的默认输出目录。例如,如果
静态库
为 只需在build目录中输出,
-L/path/to/the_static_lib
将是
-L.

这里是一个项目,以合理的一般方式说明,我们 具有结构化的源和头子目录以及不同的常规 输出目录,
bin
lib

$ ls -R
.:
app  build  CMakeLists.txt  foobar  inc

./app:
main.c

./build:

./foobar:
bar.c  foo.c

./inc:
foobar.h
使用文件:

app/main.c

#include <foobar.h>

int main(void)
{
    foo();
    bar();
    return 0;
}
#include <foobar.h>
#include <stdio.h>

void foo(void)
{
    puts(__func__);
}
#include <foobar.h>
#include <stdio.h>

void bar(void)
{
    puts(__func__);
}
CMakeLists.txt(1)

我们想从
/foobar/foo.c
/foobar/bar.c
制作
/build/lib/libfoobar.a
。 我们想从
/app/main.c
创建
/build/bin/app
,链接整个归档文件
/build/lib/libfoobar.a

生成、构建和运行:

$ cd build; cmake ..; make; ./bin/app
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/imk/develop/so/cmake_prob/build
Scanning dependencies of target foobar
[ 20%] Building C object CMakeFiles/foobar.dir/foobar/foo.c.o
[ 40%] Building C object CMakeFiles/foobar.dir/foobar/bar.c.o
[ 60%] Linking C static library lib/libfoobar.a
[ 60%] Built target foobar
Scanning dependencies of target app
[ 80%] Building C object CMakeFiles/app.dir/app/main.c.o
[100%] Linking C executable bin/app
[100%] Built target app
foo
bar
类似地,如果我们没有使用
CMakeLists.txt
,而是:

CMakeLists.txt(2)

另外:

foobar/CMakeLists.txt(1)

使用相同的分隔,但默认的输出目录,我们有:

CMakeLists.txt(3)

foobar/CMakeLists.txt(2)

那会是这样的:

$ cd build; cmake ..; make; ./app
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/imk/develop/so/cmake_prob/build
Scanning dependencies of target foobar
[ 20%] Building C object foobar/CMakeFiles/foobar.dir/foo.c.o
[ 40%] Building C object foobar/CMakeFiles/foobar.dir/bar.c.o
[ 60%] Linking C static library libfoobar.a
[ 60%] Built target foobar
Scanning dependencies of target app
[ 80%] Building C object CMakeFiles/app.dir/app/main.c.o
[100%] Linking C executable app
[100%] Built target app
foo
bar

这有点骇人,但是,好吧,它似乎是有效的。这不是100%有效的
add\u dependencies(app foobar)
说,在
foobar
之后构建
app
。但不是:如果
foobar
需要重建,
app
也需要重建!看见最好还添加
target\u link\u库(app foobar)
,即使此链接没有任何内容或仅包含部分内容。
$ cd build; cmake ..; make; ./bin/app
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/imk/develop/so/cmake_prob/build
Scanning dependencies of target foobar
[ 20%] Building C object CMakeFiles/foobar.dir/foobar/foo.c.o
[ 40%] Building C object CMakeFiles/foobar.dir/foobar/bar.c.o
[ 60%] Linking C static library lib/libfoobar.a
[ 60%] Built target foobar
Scanning dependencies of target app
[ 80%] Building C object CMakeFiles/app.dir/app/main.c.o
[100%] Linking C executable bin/app
[100%] Built target app
foo
bar
cmake_minimum_required(VERSION 3.0)
project(app)
include_directories(inc)
add_subdirectory(foobar)
add_executable(app app/main.c)
add_dependencies(app foobar)
set_target_properties(app PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
    LINK_FLAGS "-Llib -Wl,--whole-archive,-lfoobar,--no-whole-archive")
add_library(foobar STATIC foo.c bar.c)
set_target_properties(foobar
    PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
cmake_minimum_required(VERSION 3.0)
project(app)
include_directories(inc)
add_subdirectory(foobar)
add_executable(app app/main.c)
add_dependencies(app foobar)
set_target_properties(app PROPERTIES
    LINK_FLAGS "-Lfoobar -Wl,--whole-archive,-lfoobar,--no-whole-archive")
add_library(foobar STATIC foo.c bar.c)
$ cd build; cmake ..; make; ./app
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/imk/develop/so/cmake_prob/build
Scanning dependencies of target foobar
[ 20%] Building C object foobar/CMakeFiles/foobar.dir/foo.c.o
[ 40%] Building C object foobar/CMakeFiles/foobar.dir/bar.c.o
[ 60%] Linking C static library libfoobar.a
[ 60%] Built target foobar
Scanning dependencies of target app
[ 80%] Building C object CMakeFiles/app.dir/app/main.c.o
[100%] Linking C executable app
[100%] Built target app
foo
bar