Is it possible to force CMake to reorder arguments when calling the linker?

Viewed 1100

I have a strange behavior where CMake is not able to link any executable if dynamic linking is required. g++ is not able to find any of the symbols defined in the libraries.

I found out it might have to do with the order of the arguments CMake passes to g++ when linking.

Here is the verbose output of the build process (which fails linking):

[ 50%] Building CXX object CMakeFiles/chargen.dir/test.cpp.obj
g++ -std=c++11   -o CMakeFiles/test.dir/test.cpp.obj -c /f/test/test.cpp
[100%] Linking CXX executable mytest

/usr/bin/cmake -E cmake_link_script CMakeFiles/test.dir/link.txt --verbose=1
g++   -std=c++11   -lSDL2 CMakeFiles/test.dir/test.cpp.obj  -o mytest

Indeed if I try to link using that command I get undefined references, however if I compile with the library flags at the end:

g++   -std=c++11 CMakeFiles/test.dir/test.cpp.obj  -o mytest -lSDL2 

it runs just fine. How can I force CMake to use that order of arguments instead?

The contents of the CMakeLists.txt:

cmake_minimum_required(VERSION 3.6)

project(mytest)

set(COMPILER_PATH "/usr/bin/")
set(CMAKE_MAKE_PROGRAM "make")
set(CMAKE_C_COMPILER   "gcc")
set(CMAKE_CXX_COMPILER "g++")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lSDL2")
set(SOURCE_FILES test.cpp)
add_executable(mytest ${SOURCE_FILES})
1 Answers

You have probably added -lSDL2 into CMAKE_CXX_FLAGS. In that case it will appear withn compile/link flags, in front of source file name in actual link command, as you showed. Don't do that.

You should use _target_link_libraries_ cmake command in order to define libraries to link against. In brief, the skeleton of your CMakeLists.txt should look like this:

project (project_name)

add_executable (mytest test.cpp)
target_link_libraries( mytest SDL2)

In this case, cmake will put libraries on correct place. Note that you may use target_link_libraries after adding target mytest

[EDIT]

After seeing your CMakeLists it is obvious that your problem is in wrong CMAKE_EXE_LINKER_FLAGS. Simply delete the line where you are setting it, and add target_link_libraries after add_executable.

Regarding your question about handling circular dependencies among static libs, you handle it the sam way as you would if you didn't use cmake: mention it twice:

target_link_libraries( 
    mytest 
    circular_dep1
    circular_dep2
    circular_dep1
    circular_dep2
)

regarding your question about specific linker flags, just place them into target_link_libraries command, it accepts linker flags as well. You can find documentation on following link:

https://cmake.org/cmake/help/latest/command/target_link_libraries.html

Related