Cmake target_link_libraries ne lie pas ma bibliothèque
Je vais commencer à dire que je suis presque complètement stupide dans l'affaire Cmake.
J'ai les éléments suivants CMakeLists.txt
pour un projet Kdevelop 4.1:
project(uart)
find_package(KDE4 REQUIRED)
include (KDE4Defaults)
include_directories( ${KDE4_INCLUDES} ${QT_INCLUDES} src/include src/include/QSerialDevce )
add_subdirectory(doc)
add_subdirectory(src)
add_subdirectory(icons)
link_directories(/usr/lib)
find_library(SERIALDEVICE_LIB qserialdeviced)
add_executable(uart ${uart_SRCS})
target_link_libraries(uart ${SERIALDEVICE_LIB})
Lorsque j'essaie de construire mon projet, je vois:
uart/build> make -j2
-- Found Qt-Version 4.6.3 (using /usr/bin/qmake-qt4)
-- Found X11: /usr/lib64/libX11.so
-- Found KDE 4.5 include dir: /usr/include/kde4
-- Found KDE 4.5 library dir: /usr/lib64/kde4/devel
-- Found the KDE4 kconfig_compiler4 preprocessor: /usr/bin/kconfig_compiler4
-- Found automoc4: /usr/bin/automoc4
CMake Error at CMakeLists.txt:16 (add_executable):
add_executable called with incorrect number of arguments
CMake Error: Attempt to add link library "/usr/lib/libqserialdeviced.so" to target "uart" which is not built by this project.
-- Configuring incomplete, errors occurred!
make: *** [cmake_check_build_system] Error 1
*** Failed ***
Tout ce que je lis dit que add_executable
et target_link_libraries
devrait ressembler aux deux dernières lignes de mon fichier:
add_executable(uart ${uart_SRCS})
target_link_libraries(uart ${SERIALDEVICE_LIB})
Si je change ces deux lignes de CMakeLists.txt
en le laissant comme:
project(uart)
find_package(KDE4 REQUIRED)
include (KDE4Defaults)
include_directories( ${KDE4_INCLUDES} ${QT_INCLUDES} src/include src/include/QSerialDevce )
add_subdirectory(doc)
add_subdirectory(src)
add_subdirectory(icons)
link_directories(/usr/lib)
find_library(SERIALDEVICE_LIB qserialdeviced)
target_link_libraries(${SERIALDEVICE_LIB})
Je vois:
uart/build> make -j2
-- Found Qt-Version 4.6.3 (using /usr/bin/qmake-qt4)
-- Found X11: /usr/lib64/libX11.so
-- Found KDE 4.5 include dir: /usr/include/kde4
-- Found KDE 4.5 library dir: /usr/lib64/kde4/devel
-- Found the KDE4 kconfig_compiler4 preprocessor: /usr/bin/kconfig_compiler4
-- Found automoc4: /usr/bin/automoc4
-- Configuring done
-- Generating done
-- Build files have been written to: uart/build
[ 11%] Built target doc-handbook
[ 11%] Built target uart_automoc
Linking CXX executable uart
CMakeFiles/uart.dir/uart.o: In function `uart::setupSerial()':
uart/src/uart.cpp:126: undefined reference to `AbstractSerial::AbstractSerial(QObject*)'
CMakeFiles/uart.dir/uart.o: In function `uart::setupEnumerator()':
uart/src/uart.cpp:108: undefined reference to `SerialDeviceEnumerator::SerialDeviceEnumerator(QObject*)'
CMakeFiles/uart.dir/uart.o: In function `uart::setupSerial()':
uart_/uart/src/uart.cpp:136: undefined reference to `AbstractSerial::enableEmitStatus(bool)'
CMakeFiles/uart.dir/uart.o: In function `uart::setupEnumerator()':
uart_/uart/src/uart.cpp:112: undefined reference to `SerialDeviceEnumerator::setEnabled(bool)'
collect2: ld returned 1 exit status
make[2]: *** [src/uart] Error 1
make[1]: *** [src/CMakeFiles/uart.dir/all] Error 2
make: *** [all] Error 2
*** Failed ***
Cela montre clairement que target_link_libraries
ne lie pas mon qserialdeviced
.
qserialdeviced
est à /usr/lib/libqserialdeviced.so.1.0.0
, correctement lié à /usr/lib/libqserialdeviced.so
et facilement trouvé si je l'ajoute manuellement dans le Makefile.
J'ai évidemment essayé:
target_link_libraries(-lqserialdeviced)
sans changement.
J'ai aussi essayé:
if ("${SERIALDEVICE_LIB}" STREQUAL "SERIALDEVICE_LIB-NOTFOUND")
message(FATAL_ERROR "'qserialdeviced' wasn't found!")
else()
message("'qserialdeviced' found: " ${SERIALDEVICE_LIB})
endif ()
Mais ce test réussit. La bibliothèque se trouve:
'qserialdeviced' found: /usr/lib/libqserialdeviced.so
Quelqu'un peut-il m'aider à comprendre ce qui se passe ici?
J'utilise Linux Fedora 13, cmake version 2.8.0, gcc (GCC) 4.4.5 20101112 (Red Hat 4.4.5-2) et kdevelop-4.1.0-1.fc13.x86_64.
Merci j'avance.
ÉDITER:
Comme suggéré par @DatChu, j'ai divisé mon CMakeLists.txt
dans mes sous-répertoires et tout me semble logique maintenant.
Merci à tous!
Pour le fichier CMakeLists.txt d'origine, le problème n'est pas avec target_link_libraries mais avec add_executable
add_executable(uart ${uart_SRCS})
où avez-vous défini votre variable uart_SRCS? As-tu
set(uart_SRCS src/blahblah.cpp src/somethingblahblah.cpp)
Je pense que vous pourriez mal comprendre ce que fait add_subdirectory. Il n'ajoute pas les fichiers source à l'intérieur. Il indique à CMake de descendre dans ce dossier et de rechercher un autre CMakeLists.txt. Vous l'utilisez généralement lorsque vous avez un sous-projet à l'intérieur de votre dossier de projet.
Si vous avez de nombreux fichiers source que vous ne souhaitez pas définir manuellement, vous pouvez également
file(GLOB uart_SRCS src/*.cpp src/*.c)
L'inconvénient est que vous devez réexécuter manuellement CMake afin qu'il détecte les nouveaux fichiers. Voir le commentaire de Jack sur pourquoi ce n'est peut-être pas ce que vous souhaitez utiliser.
Votre CMakeLists.txt sera très probablement
project(uart)
find_package(Qt4 REQUIRED)
include (${QT_USE_FILE})
find_package(KDE4 REQUIRED)
include (KDE4Defaults)
include_directories( ${KDE4_INCLUDES} ${QT_INCLUDES} src/include src/include/QSerialDevice )
link_directories(/usr/lib)
file(GLOB uart_SRCS src/*.cpp src/*.h)
file(GLOB uart_HDRS include/*.h include/QSerialDevice/*.h)
find_library(SERIALDEVICE_LIB qserialdeviced)
add_executable(uart ${uart_SRCS} ${uart_HDRS})
target_link_libraries(uart ${SERIALDEVICE_LIB} ${QT_LIBRARIES})