web-dev-qa-db-fra.com

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!

18
j4x

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})
13
Dat Chu