2010-07-21 156 views
2

我正在为CMake配置我的项目,并且有链接问题 - 项目文件全部编译成功,然后它说它正在链接并报告找不到的各种符号。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") 

这里是我的SRC级的CMakeLists.txt:

# 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 ../”(从安装,在顶级目录):

=> 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 

任何帮助非常赞赏。

+0

我意识到$ {libdb_INCLUDE_DIRS}和$ {libdb_INCLUDE_LIBRARIES}是错误的,我需要$ {BerkeleyDB_INCLUDE_DIRS}和$ {BerkeleyDB_LIBRARIES},但是修正了我仍然存在的问题。 – Asher 2010-07-22 05:44:15

+0

基于另一篇文章(http://stackoverflow.com/questions/1962453/cmake-finds-boost-but-nmake-fails-to-link)我添加了一行:MESSAGE(STATUS“libs:$ {BerkeleyDB_LIBRARIES} “); $ {BerkeleyDB_LIBRARIES}和$ {LIBS}都不会打印任何内容。这似乎是我的问题 - 但为什么? – Asher 2010-07-22 05:45:33

+0

之前的评论其实是不正确的;我需要使用$ {DB_LIBRARIES};现在我得到的输出为$ {LIBS},但我仍然有相同的链接问题。我已经开始使用全新的安装目录来测试它。尝试了VERBOSE = 1并没有看到任何不同;现在我将更仔细地检查CMakeCache.txt。 – Asher 2010-07-22 18:06:18

回答

2

相反的GLOB,尝试GLOB_RECURSECMake 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() 
0

使VERBOSE = 1

而且,看CMakeCache.txt

+0

VERBOSE不输出任何异常;这里是围绕链接的起始位: 连接C共享库librpdb.dylib CD /用户/ ahaig /项目/ RPDB/RPDB_C /安装/ bin中&&“/应用/ CMake的2.8-2.app/Contents/bin/cmake“-E cmake_link_script CMakeFiles/rpdb.dir/link.txt --verbose = 1 /Developer/usr/bin/clang -march = x86-64 -dynamiclib -headerpad_max_install_names -o librpdb.dylib -install_name 通读CMakeCache.txt,但对我来说没有什么不寻常的。不确定是否有特别的东西我应该寻找? – Asher 2010-07-22 18:48:28

+0

问题是通过glob包含所有.c文件 - 只有第一级下来包含在内。查看原帖的评论。 – Asher 2010-07-22 18:53:42

0

我的问题归结为与文件包含的问题。我使用**/*。c通过glob来包含文件,这显然被当作*/*。c来处理。也许我在这里误解了全局模式 - 我只是最低限度地使用它们,否则在Ruby的文件通配中。

在任何情况下,这里是我想出了解决方案:

# 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}) 

,一切似乎是工作。

+0

target_link_libraries应该是:target_link_libraries(rpdb db) – Asher 2010-07-25 03:17:49