简体   繁体   English

使用CMake编译到静态库时出现问题

[英]Problems compiling to a static library with CMake

I'm trying to compile a project into a statically linked library with CMake. 我正在尝试使用CMake将项目编译为静态链接库。 Here I'm checking if BFD and Iberty are availabe, and if they are I compile a modified backtrace-symbols.c into an OBJECT Library, and statically link that object into the project along with the BFD , Iberty , and DL libraries it depends on. 在这里,我正在检查BFDIberty是否Iberty ,是否将它们修改后的backtrace-symbols.c Iberty编译到OBJECT库中,并将该对象与BFDIbertyDL库一起静态链接到项目中上。 When I try to use the resultant static library in a project, I get errors on BFD functions that are used in backtrace-symbols.c saying they are undefined. 当我尝试在项目中使用生成的静态库时,在backtrace-symbols.c中使用的BFD函数出现错误,提示它们未定义。

How can I ensure that BFD , Iberty , and DL are also statically linked into this library so that the user won't have to worry about linking against them in their project? 如何确保BFDIbertyDL也静态链接到该库中,以便用户不必担心在他们的项目中与它们链接?

cmake_minimum_required(VERSION 2.8)
project(simplog)

configure_file (
    "SimpLogConfig.h.in"
    "SimpLogConfig.h"
    @ONLY
)

set( CMAKE_C_COMPILER "clang" )

find_library( BFD_LIBRARY bfd )
find_library( IBERTY_LIBRARY iberty )

find_path(
    IBERTY_HEADER_PATH libiberty.h
    PATHS
        /usr/include/libiberty
        /usr/local/include/libiberty.h
)

include_directories(
    ${IBERTY_HEADER_PATH}
    ${PROJECT_BINARY_DIR}
)

set( PACKAGE "SimpLog" )
set( PACKAGE_VERSION "0.0.1" )
if( BFD_LIBRARY AND IBERTY_LIBRARY )
    option( BETTER_BACKTRACE "" ON )
    add_library( backtrace-symbols OBJECT backtrace-symbols.c )
    add_library( simplog STATIC simplog.c $<TARGET_OBJECTS:backtrace-symbols> )
    target_link_libraries( simplog ${BFD_LIBRARY} ${IBERTY_LIBRARY} ${CMAKE_DL_LIBS} )
else()
    option( BETTER_BACKTRACE "" OFF )
    add_library( simplog STATIC simplog.c )
endif()

As pointed out in the comments, you cannot merge multiple static libraries into one. 如注释中所指出的,您不能将多个静态库合并为一个。 This is because most C++ compilers do not support this feature, so CMake also cannot support it without breaking half of its generators. 这是因为大多数C ++编译器不支持此功能,因此CMake在不破坏其一半生成器的情况下也无法支持该功能。

The way you solve this instead is by building dependency hierarchies using target_link_libraries . 相反,解决此问题的方法是使用target_link_libraries构建依赖关系层次结构。 In your case, it looks like backtrace_symbols depends on iberty and bfd , while simplog in turn depends on backtrace-symbols . 在您的情况下, backtrace_symbols取决于ibertybfd ,而simplog则取决于backtrace-symbols You can model those dependencies like this: 您可以像这样对那些依赖进行建模:

add_library( backtrace-symbols backtrace-symbols.c )
target_link_libraries( backtracesymbols ${IBERTY_LIBRARY} ${BFD_LIBRARY} )
add_library( simplog STATIC simplog.c )
target_link_libraries( simplog backtracesymbols )

Now any executable that links to simplog will automatically pull in all dependencies in the correct order, including transitive ones. 现在,链接到simplog任何可执行文件simplog将以正确的顺序自动提取所有依赖项,包括传递性依赖项。 On the other hand, if you want to ship binaries of your library to other developers, you need to include not only the .a file for simplog , but also the ones for backtracesymbols , iberty and bfd . 另一方面,如果要将库的二进制文件运送给其他开发人员,则不仅需要包括.a文件用于simplog ,还需要包括用于backtracesymbolsibertybfd If you want to ship only a single file, you have to make simplog a dynamic library instead. 如果只想发送一个文件,则必须使simplog成为动态库。

Ensure that you always specify library dependencies at the level in the hierarchy where they are first used! 确保始终在首次使用它们的层次结构中指定库依赖项! Even though the linker will only actually need them when linking the final executable, specifying them in this way ensures that the linker pulls them in in the right order. 即使链接器仅在链接最终的可执行文件时才真正需要它们,以这种方式指定它们也可以确保链接器以正确的顺序将它们拉出。 Failing to do so can lead to undefined symbol errors like those you experienced. 否则,可能会导致未定义的符号错误,如您遇到的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM