代码之家  ›  专栏  ›  技术社区  ›  Asher postmodern

CMake链接失败

  •  2
  • Asher postmodern  · 技术社区  · 14 年前

    我正在为CMake配置我的项目,并且出现了链接问题-项目文件都编译成功,然后它说它正在链接,并报告各种未找到的符号。

    这些符号大部分是由我自己的代码提供的,而其中一些是由BerkeleyDB提供的,它被正确地定位和包含。

    以下是我的顶级CMakeLists.txt:

    cmake_minimum_required(VERSION 2.6)
    
    project( rpdb C )
    
    #   add local modules path for project
    set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/" )
    
    #   where to look for source files (headers and source)
    include_directories( include src )
    
    #   define sub-directories of source that cmake knows about as well a where their output will be put
    add_subdirectory( src bin )
    
    #   compiler-dependent flags:
    if( CMAKE_COMPILER_IS_GNUCC )
        #   gcc
        add_definitions( -ggdb -fsigned-char -freg-struct-return -Wall -W -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Winline -Werror )
    else( CMAKE_COMPILER_IS_GNUCC )
        #   non-gcc (intended for clang)
        add_definitions( -ggdb -fsigned-char -Wall -W -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Winline -Werror )
    endif( CMAKE_COMPILER_IS_GNUCC )
    
    
    #   distribution configuration
    set(CMAKE_C_FLAGS_DISTRIBUTION "-O3")
    set(CMAKE_CXX_FLAGS_DISTRIBUTION "-O3")
    

    #   make sure we have libdb
    find_package( BerkeleyDB REQUIRED )
    include_directories( ${libdb_INCLUDE_DIRS} )
    target_link_libraries( rpdb ${libdb_LIBRARIES} )
    
    #   define variable specifying included source files - all .c files below this directory
    file( GLOB rpdb_src "**/*.c" )
    
    #   define shared library with sources
    add_library( rpdb SHARED ${rpdb_src} )
    

    输出(部分):

    ...
    [100%] Building C object bin/CMakeFiles/rpdb.dir/RPDB_TransactionController/RPDB_TransactionController.c.o
    Linking C shared library librpdb.dylib
    Undefined symbols:
      "_RPDB_ReplicationVerbositySettingsController_displayMessageProcessingInformation", referenced from:
          _RPDB_SettingsController_internal_setVerbosity in RPDB_SettingsController.c.o
    ...
    

    所有的符号 确实存在。结果似乎发生在对象文件中的符号,而不是它当前正在查看的符号。

    “cmake../”的输出(来自install,顶级目录):

    => cmake ..
    -- Found BerkeleyDB: /usr/local/lib/libdb.dylib
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /Users/ahaig/Projects/RPDB/RPDB_C/install
    

    非常感谢您的帮助。

    3 回复  |  直到 13 年前
        1
  •  2
  •   user568493 user568493    14 年前

    而不是 GLOB GLOB_RECURSE ( CMake 2.8.3 docs, file command ),可以这样使用: file ( GLOB_RECURSE rpdb_src "*.c" )

    function (add_test_files)
        set ( src_files "" )
    
        ####################################################
        # Find all C/C++ files recursively from current dir
        ####################################################
        foreach ( ext IN ITEMS "cpp" "cxx" "cc" "c" )
            file ( GLOB_RECURSE _files "*.${ext}" )
            set ( src_files ${src_files} ${_files} )
        endforeach ()
    
        message ( STATUS "Found: ${src_files}" )
    
        add_executable ( test ${src_files} )
    endfunction ()
    
    add_test_files ()
    
        2
  •  0
  •   Bill Hoffman    14 年前

    使详细=1

    另外,请查看CMakeCache.txt

        3
  •  0
  •   Asher postmodern    14 年前

    我的问题归结为文件包含的问题。我是通过glob使用**/*.c包含文件的,它显然被视为*/*.c。也许我在这里误解了glob模式——我只在Ruby的文件globbing中很少使用它们。

    不管怎样,我想到的解决办法是:

    #   function processes each sub-directory and then adds each source file in directory
    #   each function should cascade back upward in setting variables so that the bottom directory
    #   adds its source first, and then the level above it adds its source and passes both up, and so on...
    function( recursively_include_source which_directory )
    
        #   get list of source from this directory
        file( GLOB this_directory_src "${which_directory}/*.c" )
    
        #   get list of all files for this directory
        file( GLOB this_directory_all_files "${which_directory}/*" )
    
        if( this_directory_all_files AND this_directory_src )
    
            #   remove source from list of files to get list of directories
            list( REMOVE_ITEM this_directory_all_files ${this_directory_src} )
            set( this_directory_directories ${this_directory_all_files} )
    
            #   for each sub-directory, call self with sub-directory as arg
            foreach( this_sub_directory ${this_directory_directories} )
                recursively_include_source( ${this_sub_directory} )
            endforeach( this_sub_directory ${this_directory_directories} )
    
        endif( this_directory_all_files AND this_directory_src )
    
        #   add source files to ${rpdb_src} in PARENT_SCOPE
        set( rpdb_src ${rpdb_src} ${this_directory_src} PARENT_SCOPE )
    
    endfunction( recursively_include_source which_directory )
    

    这包括当前目录中及其下的所有.c文件。

    recursively_include_source( ${CMAKE_CURRENT_SOURCE_DIR} )
    

    最后的src dir CMakeLists.txt如下所示:

    #   make sure we have libdb
    find_package( BerkeleyDB REQUIRED )
    include_directories( ${DB_INCLUDE_DIRS} )
    set(LIBS ${LIBS} ${DB_LIBRARIES})
    
    recursively_include_source( ${CMAKE_CURRENT_SOURCE_DIR} )
    
    #   define shared library with sources
    add_library( rpdb SHARED ${rpdb_src} )
    target_link_libraries( rpdb ${LIBS} )
    

    一切似乎都在运转。