c++ - tutorial - cmake add library example
Cmake target_link_libraries no vincula mi biblioteca (1)
Comenzaré a afirmar que estoy casi completo como tonto en este asunto.
Tengo el siguiente CMakeLists.txt
para un proyecto de 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})
Cuando intento construir mi proyecto veo:
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 ***
Todo lo que leo dice que add_executable
y target_link_libraries
deberían parecerse a las dos últimas líneas de mi archivo:
add_executable(uart ${uart_SRCS})
target_link_libraries(uart ${SERIALDEVICE_LIB})
Si cambio esas dos líneas de CMakeLists.txt
dejándolo como:
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})
Veo:
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 ***
Eso muestra claramente que target_link_libraries
no está enlazando mi qserialdeviced
.
qserialdeviced
está en qserialdeviced
, correctamente vinculado a /usr/lib/libqserialdeviced.so y se encuentra fácilmente si lo agrego manualmente en el Makefile.
Obviamente lo intenté
target_link_libraries(-lqserialdeviced)
sin cambio
También intenté:
if ("${SERIALDEVICE_LIB}" STREQUAL "SERIALDEVICE_LIB-NOTFOUND")
message(FATAL_ERROR "''qserialdeviced'' wasn''t found!")
else()
message("''qserialdeviced'' found: " ${SERIALDEVICE_LIB})
endif ()
Pero esta prueba tiene éxito. La biblioteca se encuentra:
''qserialdeviced'' found: /usr/lib/libqserialdeviced.so
¿Alguien por favor me puede ayudar a entender lo que pasa aquí?
Estoy usando Linux Fedora 13, cmake versión 2.8.0, gcc (GCC) 4.4.5 20101112 (Red Hat 4.4.5-2) y kdevelop-4.1.0-1.fc13.x86_64.
Gracias avanzo
EDITAR:
Como lo sugirió @DatChu, dividí mi CMakeLists.txt
en mis subdirectorios y ahora todo tiene sentido para mí.
Gracias a todos!
Para el archivo CMakeLists.txt original, el problema no es con target_link_libraries sino con add_executable
add_executable(uart ${uart_SRCS})
¿Dónde configuraste tu variable uart_SRCS? Tienes
set(uart_SRCS src/blahblah.cpp src/somethingblahblah.cpp)
Creo que podrías malinterpretar lo que hace add_subdirectory. No agrega los archivos de origen en el interior. Le dice a CMake que descienda a esa carpeta y busque otro CMakeLists.txt. Normalmente lo usa cuando tiene un subproyecto dentro de la carpeta de su proyecto.
Si tiene muchos archivos de origen que no desea configurar manualmente, también puede hacer
file(GLOB uart_SRCS src/*.cpp src/*.c)
El inconveniente es que necesita volver a ejecutar CMake manualmente para que pueda detectar nuevos archivos. Vea el comentario de Jack sobre por qué esto podría no ser lo que quiere usar.
Tus CMakeLists.txt probablemente serán
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})