Cmake target_link_libraries не связывает мою библиотеку - PullRequest
18 голосов
/ 22 марта 2011

Я начну утверждать, что я почти полностью туп в вопросе Cmake.

У меня есть следующее CMakeLists.txt для проекта 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})

Когда я пытаюсь построить свой проект, я вижу:

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

Все, что я читаю, говорит о том, что add_executable и target_link_libraries должны выглядеть как две последние строки моего файла:

add_executable(uart ${uart_SRCS})
target_link_libraries(uart ${SERIALDEVICE_LIB})

Если я изменю эти две строки CMakeLists.txt, оставив это как:

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

Понятно:

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

Это ясно показывает, что target_link_libraries не связывает мои qserialdeviced.

qserialdeviced находится на /usr/lib/libqserialdeviced.so.1.0.0, правильно сопоставлена ​​с /usr/lib/libqserialdeviced.so и может быть легко найдена, если я добавлю его вручную в Makefile.

Я явно пытался:

target_link_libraries(-lqserialdeviced)

без изменений.

Я тоже пробовал:

if ("${SERIALDEVICE_LIB}" STREQUAL "SERIALDEVICE_LIB-NOTFOUND")
    message(FATAL_ERROR "'qserialdeviced' wasn't found!")
else()
    message("'qserialdeviced' found: " ${SERIALDEVICE_LIB})
endif ()

Но этот тест успешен. Библиотека найдена:

'qserialdeviced' found: /usr/lib/libqserialdeviced.so

Кто-нибудь может помочь мне понять, что здесь происходит?

Я использую Linux Fedora 13, cmake версии 2.8.0, gcc (GCC) 4.4.5 20101112 (Red Hat 4.4.5-2) и kdevelop-4.1.0-1.fc13.x86_64.

Спасибо, я заранее.


EDIT:

Как подсказывает @DatChu, я разделил свой CMakeLists.txt по своим подкаталогам, и теперь все для меня имеет смысл.

Спасибо всем!

1 Ответ

13 голосов
/ 22 марта 2011

Для исходного файла CMakeLists.txt проблема не в target_link_libraries, а в add_executable

add_executable(uart ${uart_SRCS})

где вы установили переменную uart_SRCS? У вас есть

set(uart_SRCS src/blahblah.cpp src/somethingblahblah.cpp)

Я думаю, вы можете неправильно понять, что делает add_subdirectory. Он не добавляет исходные файлы внутри. Он говорит CMake, чтобы спуститься в эту папку и искать другой CMakeLists.txt. Обычно вы используете его, когда у вас есть подпроект внутри папки вашего проекта.

Если у вас много исходных файлов, которые вы не хотите устанавливать вручную, вы также можете сделать

file(GLOB uart_SRCS src/*.cpp src/*.c)

Недостатком является то, что вам нужно вручную запустить CMake, чтобы он обнаруживал новые файлы. См. Комментарий Джека о том, почему это может быть не то, что вы хотите использовать.

Ваш CMakeLists.txt, скорее всего, будет

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