0

We are working on the Project which contains thousands of the cmake files. Code is develop on the Linux platform. Now we are porting this project for Windows CE platform.

We are facing lots of linking error when change some of the functionality to project in Linux platform.

We are resolving this linking error by adding respective library in target_link_library of cmake file.

I am surprised how it worked for Linux? And it is failing for Windows CE.

Difference between the platform additional library :

Linux Platform

[A.Common]
[B]
[C]
[C]
[C]
[TLV]
[D]
[Boost.Filesystem]
[Boost.System]
[Boost.Thread]
[Boost.Atomic]
[Boost.DateTime]
[Boost.Chrono]
[Platform.Socket]
[D]
[C]
[C]
[Debug]
[SQLite]
[C]
[C]
[C]
[Meta]
[E]

WinCE

[A.Common]
[B]
[E]
[E]
[E]
[TLV]
[D]
[Boost.Filesystem]
[Boost.System]
[Boost.Thread]
[Boost.Atomic]
[Boost.DateTime]
[Boost.Chrono]
[Platform.Socket]
[D]
[C]
[C]
[Debug]
[SQLite]
[ZLib]
[C]
[C]
[C]
[Meta]
[E]

Any help will be appreciated.

Swapnil
  • 1,424
  • 2
  • 19
  • 30
  • The linking order is also important, not only that the library is named somewhere on the linker command line. So the difference could be how many paths over the command line your linker does to find the dependencies. CMake does sort the libraries according to the dependencies. If you have something line `--start-group`/`--end-group` for GCC, but your Windows CE linker does only one path you get those linker errors (see e.g. [here](http://stackoverflow.com/questions/5651869) or [here](http://stackoverflow.com/questions/45135)) – Florian Nov 03 '15 at 10:14
  • @Florian I can see the order is not issue. How to check "how many paths over the command line your linker does to find the dependencies." ? As I am using visual studio 8. – Swapnil Nov 03 '15 at 12:23
  • Because I couldn't find any documentation if linkage order does matter in Visual Studio, I've written a small CMake test program. I don't have Visual Studio 2008 Windows CE to give it a try, but for Visual Studio 2013 it seems not to matter (I'm assuming it will increase link time, but at least it doesn't come up with errors). I've added an answer describing the details and a second approach with `GLOBAL_DEPENDS_DEBUG_MODE`. If both don't help you in finding the root cause, please add an example of the error messages you get and how you have fixed it. – Florian Nov 03 '15 at 20:33
  • Just one other thought/possibility: If we are talking about `SHARED` libraries see [cmake link shared library on Windows](http://stackoverflow.com/questions/33062728/cmake-link-shared-library-on-windows) – Florian Nov 04 '15 at 08:33

1 Answers1

0

From my experience I can confirm that moving with a CMake project to a new platform is also a check if you have setup your library dependencies correctly.

If we are talking about SHARED libraries, please first confirm that you have correctly exported your function declarations:

If you are using STATIC libraries, I see two possible approaches (not taking linker errors about missing symbols from system libraries into account):

  1. You may have some if statements checking for this or that platform in your CMake code. So first check that your library dependencies are truly the same by activating GLOBAL_DEPENDS_DEBUG_MODE:

    set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_DEBUG_MODE 1)
    

    Put it in your main CMakeList.txt file and compare the output on both platforms.

  2. The linking order is also important, not only that the library is named somewhere on the linker command line. I like to quote from the Beginner's Guide to Linkers:

    Another important detail to note is the order of events; the libraries are consulted only when then the normal linking is done, and they are processed in order, left to right. This means that if an object pulled in from a library late in the link line needs a symbol from a library earlier in the link line, the linker won't automatically find it.

    Use the following CMake test program to see if your linker does a multi-path scan for open symbols. I've tested it with GCC 4.8.1 (doesn't work) and Visual Studio 2013 (does work). So I don't have your environments, so please do the test yourself.

    The program is deliberately setup to have a wrong library linkage order by not using normal library dependencies like target_link_libraries(lib1 lib2) (a rule of thumb is to add as dependecies all libraries you directly include a header file from), but by giving the order in a global list to main:

    cmake_minimum_required(VERSION 2.8)
    
    project(WrongLinkOrderTest CXX)
    
    set(_idx 1)
    while (_idx LESS 10)
        math(EXPR _next_idx "${_idx} + 1")
    
        file(WRITE lib${_idx}.h  "int lib${_idx}_func();")
        file(WRITE lib${_idx}.cc "#include \"lib${_next_idx}.h\"\nint lib${_idx}_func() { return lib${_next_idx}_func(); }")
        add_library(lib${_idx} lib${_idx}.cc)
    
        # NOTE: This would fix it
        #target_link_libraries(lib${_idx} lib${_next_idx})
    
        set(_idx "${_next_idx}")
    endwhile()
    
    file(WRITE lib${_idx}.h  "int lib${_idx}_func();")
    file(WRITE lib${_idx}.cc "int lib${_idx}_func() { return 0; }")
    add_library(lib${_idx} lib${_idx}.cc)
    
    file(WRITE main.cc "#include \"lib1.h\"\nint main() { return lib1_func(); }")
    add_executable(main main.cc)
    
    if (CMAKE_COMPILER_IS_GNUCXX)
        #target_link_libraries(main "-Wl,--start-group")
    endif()
    
    while (_idx GREATER 0)
        math(EXPR _next_idx "${_idx} - 1")
    
        # NOTE: Here it's done wrong
        target_link_libraries(main lib${_idx})
    
        set(_idx "${_next_idx}")
    endwhile()
    
    if (CMAKE_COMPILER_IS_GNUCXX)
        #target_link_libraries(main "-Wl,--end-group")
    endif()
    

    By default, it will show the following error with GCC:

    liblib1.a(lib1.cc.obj):lib1.cc:(.text+0x7): undefined reference to `lib2_func()'
    

    Uncomment the target_link_libraries(lib${_idx} lib${_next_idx}) or --start-group/--end-group lines to fix it.

Additional References

Community
  • 1
  • 1
Florian
  • 39,996
  • 9
  • 133
  • 149
  • we have tried the set_property option suggested by you. We can see the include library difference between Windows CE and Linux platform. – Swapnil Nov 04 '15 at 10:48
  • Ok, but did it help to find the root cause of your problem? Generally speaking: If you are using the same CMake environment and you don't have any `if` statements to check for a certain platform in it, there should be no differences in the library dependencies listed (with the exception of the CMake's own global targets like `ZERO_CHECK`). Can you give an example of how the differences look like? – Florian Nov 04 '15 at 11:52
  • We are trying to understand what is wrong with this... Linux Platform [A.Common] [B] [C] [C] [C] [TLV] [D] [Boost.Filesystem] [Boost.System] [Boost.Thread] [Boost.Atomic] [Boost.DateTime] [Boost.Chrono] [Platform.Socket] [D] [C] [C] [Debug] [SQLite] [C] [C] [C] [Meta] [E] WinCE [A.Common] [B] [E] [E] [E] [TLV] [D] [Boost.Filesystem] [Boost.System] [Boost.Thread] [Boost.Atomic] [Boost.DateTime] [Boost.Chrono] [Platform.Socket] [D] [C] [C] [Debug] [SQLite] [ZLib] [C] [C] [C] [Meta] [E] – Swapnil Nov 04 '15 at 12:30
  • The difference example is added int question as well. – Swapnil Nov 04 '15 at 12:39
  • Thanks. If I do this on my current project I get also lines with `depends on target ...`. Those would also be interesting, so please don't remove those in the output you've added to the question. If I assume some of the `C` and `E` lines are the dependencies, those are where you have to look at. If you don't get `depends on target ...` lines, then you may not correctly using the `target_link_libraries()` command (the first parameter is the name of the `` which needs the libraries listed after that for linking). – Florian Nov 04 '15 at 13:40
  • @swapnil Just wanted to check if you found the root cause of your problem. I - and maybe others searching for help in a similar case - would be interested to hear what has caused your linking erros. Thanks in advance for any details. – Florian Nov 23 '15 at 19:50
  • sorry for late reply... Yes we did find the root cause, we have link the shared and static library in case of wince which has same name and because of that we are facing the problem. We are now linking with static library only. – Swapnil Dec 01 '15 at 14:31