用CMake编译到静态库的问题

时间:2014-01-06 23:09:48

标签: c linker cmake static-linking

我正在尝试使用CMake将项目编译为静态链接库。在这里,我正在检查BFDIberty是否可用,如果是,我将修改后的backtrace-symbols.c编译到OBJECT库中,并将该对象静态链接到项目中以及它所依赖的BFDIbertyDL库。当我尝试在项目中使用生成的静态库时,我在BFD中使用backtrace-symbols.c函数时会出现错误,表示它们未定义。

如何确保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()

1 个答案:

答案 0 :(得分:1)

正如评论中所指出的,您无法将多个静态库合并为一个。这是因为大多数C ++编译器不支持此功能,因此CMake也不能在不破坏其一半生成器的情况下支持它。

您解决此问题的方法是使用target_link_libraries构建依赖关系层次结构。在您的情况下,看起来backtrace_symbols取决于ibertybfd,而simplog又取决于backtrace-symbols。您可以像这样建模这些依赖项:

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 )

现在任何链接到simplog的可执行文件都会自动以正确的顺序提取所有依赖项,包括传递顺序。另一方面,如果您要将库的二进制文件发送给其他开发人员,则不仅要包含.a的{​​{1}}文件,还要包含simplog的文件{ {1}}和backtracesymbols。如果您只想发送单个文件,则必须使iberty成为动态库。

确保始终在首次使用它们的层次结构中指定库依赖项!尽管链接器在链接最终可执行文件时实际上只需要它们,但以这种方式指定它们可确保链接器以正确的顺序将它们拉入。 如果不这样做,可能会导致未定义的符号错误,如您所遇到的那样。