I'm trying to compile a project into a statically linked library with 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. 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.

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?

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.

The way you solve this instead is by building dependency hierarchies using target_link_libraries. In your case, it looks like backtrace_symbols depends on iberty and bfd, while simplog in turn depends on 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. 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. If you want to ship only a single file, you have to make simplog a dynamic library instead.

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归因
不隶属于 StackOverflow
scroll top