2010-07-21 2 views
2

Je configure mon projet pour CMake et j'ai des problèmes de liaison - les fichiers du projet se compilent tous avec succès, puis il dit qu'il relie et signale toutes sortes de symboles non trouvés.CMake Liaison échoue

Ces symboles sont principalement fournis par mon propre code, alors que certains d'entre eux sont fournis par BerkeleyDB, qui est correctement localisés et inclus.

Voici mon CMakeLists.txt haut niveau:

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") 

Et voici mon niveau 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}) 

La sortie (partielle):

... 
[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 
... 

Tous les symboles existent réellement. Le résultat semble se produire pour les symboles dans les fichiers objets autres que celui actuellement en cours de visualisation.

La sortie de "cmake ../" (à partir de l'installation, un répertoire dans le haut niveau):

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

Toute aide très appréciée.

+0

je me suis rendu $ {libdb_INCLUDE_DIRS} et $ {libdb_INCLUDE_LIBRARIES} eu tort et que J'avais besoin de $ {BerkeleyDB_INCLUDE_DIRS} et de $ {BerkeleyDB_LIBRARIES} à la place, mais après avoir résolu que j'avais toujours le même problème. – Asher

+0

Basé sur un autre post (http://stackoverflow.com/questions/1962453/cmake-finds-boost-but-nmake-fails-to-link) J'ai ajouté une ligne: MESSAGE (STATUS "libs: $ {BerkeleyDB_LIBRARIES} "); $ {BerkeleyDB_LIBRARIES} et $ {LIBS} n'impriment rien. Cela me semble être le problème - mais pourquoi? – Asher

+0

Les commentaires précédents étaient en fait incorrects; J'avais besoin d'utiliser $ {DB_LIBRARIES}; maintenant je reçois la sortie pour $ {LIBS}, mais j'ai toujours le même problème de lien. J'ai commencé avec un nouveau répertoire d'installation pour le tester. Essayé VERBOSE = 1 et ne vois rien de différent; Maintenant, je vais examiner le CMakeCache.txt de plus près. – Asher

Répondre

2

Au lieu de GLOB, essayez GLOB_RECURSE (CMake 2.8.3 docs, file command), que vous pouvez utiliser comme ceci: file (GLOB_RECURSE rpdb_src "*.c")

Un exemple:

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

faire verbose = 1

Aussi, regardez CMakeCache.txt

+0

VERBOSE ne sort rien d'inhabituel; voici le bit autour du début de la liaison: Lier la bibliothèque partagée C librpdb.dylib cd/Users/ahaig/Projets/RPDB/RPDB_C/install/bin && "/ Applications/CMake 2.8-2.app/Contents/bin/cmake "-E cmake_link_script CMakeFiles/rpdb.dir/lien.txt --verbose = 1 /Développeur/usr/bin/clang -march = x86-64 -dynamiclib -headerpad_max_install_names -o librpdb.dylib -install_name Asher

+0

Problème avec l'inclusion de tous les fichiers .c via glob - seul le premier niveau descendant est inclus. Voir le commentaire sur le message original. – Asher

0

Mon problème est descendu à un problème avec l'inclusion de fichiers. J'inclus les fichiers via glob en utilisant **/*. C, qui était apparemment traité comme */*. C. Peut-être que je ne comprends pas les schémas globaux ici - je les ai utilisés seulement minimalement autrement dans le globbing de dossier de Ruby.

Dans tous les cas, voici la solution que je suis venu avec:

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

Cela inclut tous les fichiers .c et sous le répertoire courant.

J'appelle la fonction comme ceci:

recursively_include_source(${CMAKE_CURRENT_SOURCE_DIR}) 

donc la finale CMakeLists.txt src-dir ressemble à ceci:

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

Et tout semble fonctionner.

+0

target_link_libraries devrait être: target_link_libraries (rpdb db) – Asher