[CMake] linking libraries at many levels

Michael Wild themiwi at gmail.com
Tue Aug 25 09:27:10 EDT 2009


On 25. Aug, 2009, at 15:06, Pol Monsó IRI wrote:

> Hello cmake users!
>
> I'm quite new to cmake as well as makefiles, and i've bumped the same
> trouble twice. I'm trying to break a source code into several  
> libraries and
> a main program. The scenario has one main executable called  
> calClient which
> uses functions from three libraries, let's say 1A 1B and 2C.  
> Everybody uses
> library 2C, that is calClient, 1A and 1B. I've stored the source  
> codes of 1A
> 1C and 2C in a subdirectory called lib/ toghether with a  
> CMakeLists.txt :
>
> FIND_PACKAGE(YARP REQUIRED)
>>
>> SET(PROJECT_LIBS
>>   2C.cpp
>>   2C.h
>>   1B.cpp
>>   1B.h
>>   1A.cpp
>>   1A.hpp
>> )
>>
>> add_library(callibs ${PROJECT_LIBS})
>
>
> In the upper directory, toghether with the source code of the main  
> program,
> I have:
>
> project(calibration)
>>
>> cmake_minimum_required(VERSION 2.6)
>>
>> set(CMAKE_CXX_FLAGS "-g -Wall")

DON'T EVER do something like this unless you really know what you're  
doing. The proper way of doing this is to use the Debug configuration  
at configure-time:

cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-Wall /path/to/source

>>
>> set(PROJECT_SRC
>>   calClient.cpp
>>   calClient.hpp
>>   chaser.cpp
>>   chaser.hpp
>> )
>>
>> FIND_PACKAGE(YARP REQUIRED)
>> FIND_PACKAGE(OpenCV REQUIRED)
>>
>> add_subdirectory(lib)
>>
>> INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/lib)
>> link_directories(lib)
>>
>> INCLUDE_DIRECTORIES(${OPENCV_INCLUDE_DIR})
>>
>> ADD_EXECUTABLE(calClient ${PROJECT_SRC})
>> TARGET_LINK_LIBRARIES( calClient ${OPENCV_LIBRARIES} )
>> TARGET_LINK_LIBRARIES( calClient callibs )

This should be:

TARGET_LINK_LIBRARIES( calClient
  ${OPENCV_LIBRARIES}
  callibs
  )

>
> Every header includes the headers of the files which contains the  
> functions
> that it needs. So, calClient.hpp actually includes 1A, 1B and 2C.
>
> The output of the make command is then:
>
>> [ 60%] Built target callibs
>> Linking CXX executable calClient
>> CMakeFiles/calClient.dir/calClient.cpp.o: In function
>> `incrementalCalibrate(yarp::dev::IPositionControl*,  
>> yarp::dev::IEncoders*)':
>> /home/pmonso/YARP/Calclient/calClient.cpp:276: undefined reference to
>> `print_double_array(double const*, int)'
>> /home/pmonso/YARP/Calclient/calClient.cpp:277: undefined reference to
>> `print_double_array(double const*, int)'
>> /home/pmonso/YARP/Calclient/calClient.cpp:295: undefined reference to
>> `print_double_array(double const*, int)'
>> CMakeFiles/calClient.dir/calClient.cpp.o: In function
>> `calibrate(yarp::dev::IPositionControl*, yarp::dev::IEncoders*)':
>> /home/pmonso/YARP/Calclient/calClient.cpp:155: undefined reference to
>> `print_double_array(double const*, int)'
>> CMakeFiles/calClient.dir/calClient.cpp.o: In function
>> `randomCalibrate(yarp::dev::IPositionControl*,  
>> yarp::dev::IEncoders*)':
>> /home/pmonso/YARP/Calclient/calClient.cpp:207: undefined reference to
>> `print_double_array(double const*, int)'
>> CMakeFiles/calClient.dir/calClient.cpp.o:/home/pmonso/YARP/ 
>> Calclient/calClient.cpp:208:
>> more undefined references to `print_double_array(double const*,  
>> int)' follow
>> collect2: ld returned 1 exit status
>> make[2]: *** [calClient] Error 1
>> make[1]: *** [CMakeFiles/calClient.dir/all] Error 2
>> make: *** [all] Error 2
>>
>

In order for this output to be useful, we'd need to see the link-line,  
which you can get by invoking

make VERBOSE=1


>
> The function print_double_array is located in the 2C source and  
> header files
> which, as I said, is included in calClient header as well as in  
> headers of
> 1A and 1B.
>
> Does somebody know why linking fails? What I am doing wrong? It's  
> driving me
> nuts!

It's probably that you invoke TARGET_LINK_LIBRARIES twice on the same  
target, as pointed out above.

>
> Thanks alot for your help!
>
> pol
>

HTH

Michael


More information about the CMake mailing list