[CMake] Weird linking error while cross compiling

Michael Hertling mhertling at online.de
Wed Oct 26 09:43:29 EDT 2011


On 10/26/2011 10:28 AM, Andreas Pakulat wrote:
> On 26.10.11 03:54:02, Jose wrote:
>> Sorry for not being very specific.
>>
>> This is the command that Cmake is running while linking :
>>
>> /usr/bin/i686-pc-mingw32-g++  -O3 -O3    -Wl,-Bstatic -static-libgcc
>> -Wl,--whole-archive CMakeFiles/sqt2pin.dir/objects.a -Wl,--no-whole-archive
>> -o sqt2pin.exe -Wl,--out-implib,libsqt2pin.dll.a
>> -Wl,--major-image-version,0,--minor-image-version,0
>> -L/home/fedora/percolator/percolator/src/converters/../../src
>> libconverters.a libperclibrary_part.a MSToolkit/libMSToolkit.a
>> MSToolkit/RAMP/libRAMP.a -lxerces-c -lportablexdr
>> /home/fedora/percolator/percolator/src/converters/libs/dll/libtokyocabinet.a
>> -lz -lsqlite3 -Wl,-Bstatic -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32
>> -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
>> /usr/lib/gcc/i686-pc-mingw32/4.5.3/../../../../i686-pc-mingw32/bin/ld:
>> cannot find -lxerces-c
>> /usr/lib/gcc/i686-pc-mingw32/4.5.3/../../../../i686-pc-mingw32/bin/ld:
>> cannot find -lportablexdr
>> /usr/lib/gcc/i686-pc-mingw32/4.5.3/../../../../i686-pc-mingw32/bin/ld:
>> cannot find -lz
>> /usr/lib/gcc/i686-pc-mingw32/4.5.3/../../../../i686-pc-mingw32/bin/ld:
>> cannot find -lsqlite3
>>
>> That is weird cos I "load" all the libraries in the same way and they all
>> the variables content the right paths to the libraries : (for example)
>>
>> Xercesc : /usr/i686-pc-mingw32/sys-root/mingw/lib/libxerces-c.dll.a , XDR :
>> /usr/i686-pc-mingw32/sys-root/mingw/lib/libportablexdr.dll.a
>>
>> This is how I link :
>>
>> #COMPILING SQT2PIN
>> include_directories(. MSToolkit/RAMP MSToolkit )
>> add_executable(sqt2pin Sqt2Pin.cpp )
>> IF(STATIC AND MINGW)
>>   set_property(TARGET sqt2pin PROPERTY LINK_SEARCH_END_STATIC ON)
>>   set_target_properties(sqt2pin PROPERTIES LINK_FLAGS "-Wl,-Bstatic
>> -static-libgcc")
>> ENDIF()
>> message(STATUS "Xercesc : ${XERCESC_LIBRARIES} , XDR :
>> ${PORTABLEXDR_LIBRARIES}")
>> target_link_libraries(sqt2pin converters perclibrary_part  MSToolkit RAMP
>> ${XERCESC_LIBRARIES} ${PORTABLEXDR_LIBRARIES} ${TOKYOCABINET_LIBRARIES} )
>>
>> I might  be missing something very stupid because I use the same prodecure
>> to search for the librarys....the FindXXX.cmake macros that are tested and
>> working with other programs.
>>
>> Could it be the include_directories("library include dir") which is messing
>> this up? it looks like the linker disregard the path of the library that Im
>> pasinng and looks for -lxerces-c instead. Is that xerces-c defined somehow
>> before?
> 
> This happens if the library is considered to be in a 'system path' since
> in that case specifying the path is not necessary for the linker to find
> it. However in your specific case it seems like cmake does this even for
> static libraries, which is of course wrong. I'd suggest to file a
> bugreport for this with a small self-contained example.
> 
> Andreas

The -l switch of ld is not related to the library's type, i.e.
shared or static; see ld's manpage and the following example:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(STATIC C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "int f(void){return 0;}\n")
EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} -c f.c)
EXECUTE_PROCESS(COMMAND ${CMAKE_AR} cr libf.a f.o)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return f();}\n")
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main -L${CMAKE_BINARY_DIR} f /usr/lib/libz.a)

The executable "main" is linked against the static libf.a via the -l
switch. Usually, in particular on ELF systems, ld just prefers shared
libraries with -l unless it is told to not do so, e.g. using -Bstatic.
However, MinGW's ld behaves differently in this regard; IIRC, it even
prefers static and import libraries to shared ones with the -l switch.

BTW, /usr/lib/libz.a is converted into -Wl,-Bstatic -lz -Wl,-Bdynamic
due to /usr/lib being a system directory, i.e. CMake performs this -l
conversion of full paths in system directories for static libraries,
too; why should it be called wrong?

Jose, could you find out which directories CMake considers as system
directories and if these are actually searched implicitly by ld? If
CMake takes /usr/i686-pc-mingw32/sys-root/mingw/lib as system dir,
thus libxerces-c.dll.a --> -lxerces-c, but ld does not search it
without a proper -L switch, the issue would be quite clear. As
a quick workaround, you might use imported targets for the
concerned libraries to avoid the -l conversion, i.e.:

ADD_LIBRARY(xerces-c STATIC IMPORTED)
SET_TARGET_PROPERTIES(xerces-c PROPERTIES IMPORTED_LOCATION
    /usr/i686-pc-mingw32/sys-root/mingw/lib/libxerces-c.dll.a)
TARGET_LINK_LIBRARIES(... xerces-c ...)

'hope that helps.

Regards,

Michael


More information about the CMake mailing list