在您构建的库中使用CMake中的–whole-archive

我有一个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_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的值与您指定输出目录的内容透明地相关
目标是,或者目标的默认输出目录,如果不这样做.例如.如果the_static_lib是
只需在构建目录中输出,然后-L / path /到/ 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

有文件:

应用程序/ main.c中

#include <foobar.h>

int main(void)
{
    foo();
    bar();
    return 0;
}

foob​​ar的/ foo.c的

#include <foobar.h>
#include <stdio.h>

void foo(void)
{
    puts(__func__);
}

foob​​ar的/ bar.c

#include <foobar.h>
#include <stdio.h>

void bar(void)
{
    puts(__func__);
}

INC / foobar.h中

#ifndef FOOBAR_H
#define FOOBAR_H

void foo(void);
void bar(void);

#endif

CMakeLists.txt(1)

cmake_minimum_required(VERSION 3.0)
project(app)
include_directories(inc)
add_library(foobar STATIC foobar/foo.c foobar/bar.c)
set_target_properties(foobar
    PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
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")

我们想从./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)

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")

并单独:

foob​​ar / CMakeLists.txt(1)

add_library(foobar STATIC foo.c bar.c)
set_target_properties(foobar
    PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

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

CMakeLists.txt(3)

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")

foob​​ar / CMakeLists.txt(2)

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
点赞