Cmake target_link_libraries没有链接我的库

j4x*_*j4x 18 c++ linux linker kdevelop cmake

我会开始说我在Cmake问题上几乎完全愚蠢.

我有以下CMakeLists.txtKdevelop 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})
Run Code Online (Sandbox Code Playgroud)

当我尝试构建我的项目时,我看到:

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 ***
Run Code Online (Sandbox Code Playgroud)

我读到的所有内容都说明了add_executable,target_link_libraries应该看起来像我文件的最后两行:

add_executable(uart ${uart_SRCS})
target_link_libraries(uart ${SERIALDEVICE_LIB})
Run Code Online (Sandbox Code Playgroud)

如果我将这两行改为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})
Run Code Online (Sandbox Code Playgroud)

我知道了:

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 ***
Run Code Online (Sandbox Code Playgroud)

这清楚地表明,这target_link_libraries并不是我的联系qserialdeviced.

qserialdeviced/usr/lib/libqserialdeviced.so.1.0.0,正确simlinked到/usr/lib/libqserialdeviced.so并很容易找到,如果我手动添加在Makefile.

我显然试过了:

target_link_libraries(-lqserialdeviced)
Run Code Online (Sandbox Code Playgroud)

没有变化.

我也尝试过:

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

但是这个测试成功了.找到图书馆:

'qserialdeviced' found: /usr/lib/libqserialdeviced.so
Run Code Online (Sandbox Code Playgroud)

有人可以帮我理解这里发生了什么吗?

我使用的是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.

谢谢我提前.


编辑:

正如@DatChu建议的那样,我将我的CMakeLists.txt子目录分开,现在一切对我都有意义.

谢谢大家!

Dat*_*Chu 13

对于原始的CMakeLists.txt文件,问题不在于target_link_libraries,而在于add_executable

add_executable(uart ${uart_SRCS})
Run Code Online (Sandbox Code Playgroud)

你在哪里设置你的uart_SRCS变量?你有没有

set(uart_SRCS src/blahblah.cpp src/somethingblahblah.cpp)
Run Code Online (Sandbox Code Playgroud)

我想你可能会误解add_subdirectory的作用.它不会在里面添加源文件.它告诉CMake进入该文件夹并查找另一个CMakeLists.txt.当项目文件夹中有子项目时,通常使用它.

如果您有许多源文件,您不想手动设置,您也可以这样做

file(GLOB uart_SRCS src/*.cpp src/*.c)
Run Code Online (Sandbox Code Playgroud)

缺点是您需要手动重新运行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})
Run Code Online (Sandbox Code Playgroud)

  • 请不要建议使用`file(GLOB ...)`:http://www.cmake.org/pipermail/cmake/2010-July/037984.html和http://www.cmake.org/ pipermail/cmake的/ 2010年9/039562.html (7认同)
  • 我开始明白你们所说的话.它让我想起了辛普森的狗开始理解人们所说的一集.不幸的是,我必须等到明天才能重新尝试.谢谢大家! (3认同)
  • @Jack Kelly:谢谢.我构建项目的方式在每个文件夹中没有额外的文件.此外,当项目成熟时,缺乏文件更改的论点是双向的.我已经更新了我的回答,请注意这一点. (2认同)