0

I'm migrating my C++ application build system to cmake. One dependency is gsoap++, which generates a SOAP service and client. To link against it, I specify

set(CMAKE_CXX_LINK_FLAGS "-lgsoap++ ... [other flags]")

in the root CMakeLists.txt. The generated sources are created with

file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src/generated/c++/ws)
set(GEN_WS_SOURCES ws/Bar.h ws/Bar_USCOREBinding.nsmap ws/soapBar_USCOREBindingProxy.h ws/soapBar_USCOREBindingProxy.cpp ws/soapBar_USCOREBindingService.h ws/soapBar_USCOREBindingService.cpp ws/soapH.h ws/soapC.cpp ws/soapStub.h)
add_custom_command(OUTPUT ${GEN_WS_SOURCES}
                   COMMAND wsdl2h -o ${CMAKE_BINARY_DIR}/src/generated/c++/ws/Bar.h -t wsdl/typemap.dat wsdl/bar.wsdl
                   COMMAND soapcpp2 -Lwxi -I/usr/include/gsoap ${CMAKE_BINARY_DIR}/src/generated/c++/ws/Bar.h -d ${CMAKE_BINARY_DIR}/src/generated/c++/ws
                   WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
add_library(GEN_WS ${GEN_WS_SOURCES})

Everything seems to work properly, the sources get created. But when linking the application, I get lots of errors like

undefined reference to `soap_end'
undefined reference to `soap_sender_fault'
more undefined references to `soap_sender_fault' follow

If I compile with make VERBOSE=1, I see that -lgsoap++ is passed to /usr/bin/c++ when linking. Other libraries I link against don't throw any errors, but for some reason, the linker does not seem to find gsoap's functions. The library is present and there is no error that the linker can't find it.

The old, custom build script worked as expected; it also just passed -lgsoap++ to the linker. The only real difference I see is that my cmake build groups the sources into static libraries before attempting to link everything together. But I don't see how this can lead to all the symbols from the library not being found.

What's the problem here? Why can't the linker find gsoap's symbols?

Host OS is debian.

Edit: This is the complete linker command executed by cmake:

/usr/bin/c++   -w -Wall -pedantic -fdata-sections -ffunction-sections -std=c++0x
-lgsoap++ -lsoci_core -lsoci_sqlite3 -lmicrohttpd -lfetcp -lfeisc -lFedmIscCore
-lboost_system -lboost_thread -lboost_program_options -lboost_date_time
-lboost_unit_test_framework  CMakeFiles/bar.dir/main.cpp.o
CMakeFiles/bar.dir/mainapp.cpp.o  -o bar -rdynamic ../../libs/c++/libLIB_JSONXX.a
../../libs/c++/libLIB_CONFIG.a ../../libs/c++/libLIB_DB.a ../../libs/c++/libLIB_OBID.a
../../libs/c++/libLIB_HELPER.a ../../generated/c++/libGEN_WS.a
../../generated/c++/libGEN_DB.a ../../generated/c++/libGEN_CONFIG.a
libMAIN_CONTROLLERS.a libMAIN_HARDWARE.a libMAIN_HELPER.a libMAIN_MODEL.a
libMAIN_NETWORK.a libMAIN_SYSTEM.a ../../generated/c++/libGEN_DB.a
../../libs/c++/libLIB_DB.a ../../generated/c++/libGEN_CONFIG.a
../../libs/c++/libLIB_JSONXX.a ../../libs/c++/libLIB_CONFIG.a
../../libs/c++/libLIB_HELPER.a ../../libs/c++/libLIB_OBID.a
../../generated/c++/libGEN_WS.a
flyx
  • 35,506
  • 7
  • 89
  • 126
  • Have you verified that the symbols it is missing are indeed present in the library that you are trying to link? – PlasmaHH Jan 16 '14 at 10:16
  • possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – PlasmaHH Jan 16 '14 at 10:16
  • @PlasmaHH Yes, I searched with `nm` in `libgsoap++.a` and the symbols are defined there. – flyx Jan 16 '14 at 10:18
  • See if there is any hint when you set LD_DEBUG. http://man7.org/linux/man-pages/man8/ld.so.8.html – mockinterface Jan 16 '14 at 10:22
  • @PlasmaHH I looked at the proposed solutions in the linked question, but none seems to apply here. – flyx Jan 16 '14 at 10:38
  • 1
    @flyx: You might want to provide the exact command line that you use to link. – PlasmaHH Jan 16 '14 at 10:51

1 Answers1

2

I'm not sure if it will directly solve your problem, but this:

set(CMAKE_CXX_LINK_FLAGS "-lgsoap++ ... [other flags]")

Should be:

set(CMAKE_CXX_LINK_FLAGS "[other flags]")
target_link_library(GEN_WS gsoap++) # after add_library of course
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    This actually fixes the problem. It moves `-lgsoap++` to the end of the linker command. I really wonder why the linker's behavior is different based on the order of the arguments passed. – flyx Jan 16 '14 at 13:23
  • Great, that's what I was hoping would happen. Yes, your linker is single-pass, meaning that order does matter, as is the case for many linkers. – John Zwinck Jan 16 '14 at 21:54