2010-07-21 152 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