1

I have a project in CLion that uses CMake. I have added a list of directories using the include_directories command and although the IDE finds them properly and provides auto-complete and the includes seem to link properly, when I try to run the program I get errors of undefined references to all functions.

Updated CMake file:

cmake_minimum_required(VERSION 3.9)
project(Test C)

set(CMAKE_C_STANDARD 11)
set(C_LIBRARIES_DIR E:/Work\ Related\ General/C\ Projects/Libraries)

# set paths (only needed on windows)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
  # where is the SDL2 development package copied to?
  set(SDL2_PATH "${C_LIBRARIES_DIR}/SDL2-2.0.8/i686-w64-mingw32")

  # add path do search path (windows requires ";" instead of ":" )
  set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${C_LIBRARIES_DIR}/SDL2")
endif()

find_package(SDL2 REQUIRED)

include_directories(${SDL2_INCLUDE_DIR})

add_executable(Test src/main.c)

target_link_libraries(Test ${SDL2_LIBRARY})

And the error I'm getting is the following:

"C:\Program Files\JetBrains\CLion 2017.3\bin\cmake\bin\cmake.exe" --build "E:\Work Related General\C Projects\Test\cmake-build-debug" --target Test -- -j 2
[ 25%] Linking C executable Test.exe
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [Test.exe] Error 1
CMakeFiles\Test.dir\build.make:152: recipe for target 'Test.exe' failed
mingw32-make.exe[2]: *** [CMakeFiles/Test.dir/all] Error 2
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/Test.dir/all' failed
mingw32-make.exe[1]: *** [CMakeFiles/Test.dir/rule] Error 2
CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/Test.dir/rule' failed
mingw32-make.exe: *** [Test] Error 2
Makefile:117: recipe for target 'Test' failed

I can never find good help regarding CMake online and the fact that the IDE properly recognizes the libraries but fails to link baffles me since CLion and CMake should be taking care of that... What am I missing?

UPDATE Adding the following directive before the SDL include allowed gcc to properly link: #define SDL_MAIN_HANDLED

From what I read, SDL.h itself redefines the main function to SDL_main inside its header file. Adding this directive undefines it (sort of). The goal however is to make the program run without this (since this directive is for command line programs). Still no clue there...

PentaKon
  • 4,139
  • 5
  • 43
  • 80
  • Your title - `CMake fails to find library` - may imply that some of libraries listed in `target_link_libraries` hasn't been found. But actually all these libraries have been **found**. (Otherwise you would got different error message). Error message `undefined reference` means that none of these libraries contains required symbol. – Tsyvarev Apr 03 '18 at 07:51
  • Which means? I updated the question with new information but the issue remains... – PentaKon Apr 03 '18 at 08:02
  • I meant that your title is misleading - CMake **finds** the library, but cannot find a simbol in it. In updated question, only one "undefined reference" remains. And [that question](https://stackoverflow.com/questions/5259714/undefined-reference-to-winmain16) suggests that your haven't define `main()` function. If you expect SDL2 to define this function, make sure that you use `FindSDL2.cmake` script in a proper way. Documentation for the script you have is in the commentaries at the beginning of the script, like [here](https://github.com/brendan-w/collector/blob/master/cmake/FindSDL2.cmake). – Tsyvarev Apr 03 '18 at 08:32

2 Answers2

1

As I know when you want use SDL2 then you need link next libraries -lmingw32 -lSDL2main(libSDL2main) that hold WinMain function -lSDL2(libSDL2.dll.a) and apply the flag -mwindows. For the first I suggest you link this libraries and flags by you hands with full path to libraries. Also if you want to know what you variable store you can write message. You problem it's exactly linking.

Ansver
  • 94
  • 9
0

You may need to add a link_directories() directive

Also, you may be able to use pkg_check_modules() to reference SDL instead. The following may not be exactly what you need, but should give you the idea

include(FindPkgConfig)
pkg_check_modules(ALL REQUIRED sdl2)

include_directories(${ALL_INCLUDE_DIRS})
link_directories(${ALL_LIBRARY_DIRS})

add_executable(Test main.c)

target_link_libraries(Test ${ALL_LIBRARIES})
Abdul Ahad
  • 826
  • 8
  • 16
  • I updated the CMake file but still get the same problem. My CMake doesn't have the `FindPkgConfig` nor the `pkg_check_modules` command – PentaKon Apr 02 '18 at 22:32
  • @Konstantine yeah, if you don't have package config setup you can try specifying the library directories. Also try target_link_libraries() – Abdul Ahad Apr 02 '18 at 22:34
  • My libraries have a pkgconfig directory however with a sdl2.pc file inside. Should I try to use that? – PentaKon Apr 02 '18 at 22:38
  • @Konstantine I think pkgconfig is a better pattern to use but it's not necessary if this is a one-off thing. Did you try target_link_libraries()? It may just be target_link_libraries(Test sdl2) or target_link_libraries(Test libsdl2) – Abdul Ahad Apr 02 '18 at 22:40
  • View updated question. I added as relative path and it can't find them. If I add as absolute path I get same error... – PentaKon Apr 02 '18 at 22:42
  • @Konstantine if target_link_libraries() doesn't work then I don't know. You can try adding "set(CMAKE_VERBOSE_MAKEFILE ON)" and try to figure out what is wrong with the generated gcc instruction. good luck – Abdul Ahad Apr 02 '18 at 22:55