Link error with SFML library in CMake project on Windows [duplicate] - cmake

This question already has answers here:
SFML: undefined reference to _imp_ [closed]
(2 answers)
Closed 2 years ago.
I'm trying to build a CMake project on Windows/MinGW and link it to SFML 2.5.1. CMake seems to find the libraries, and the program compiles fine, but I'm getting 'undefined reference' linker errors. I followed the SFML 2.5 CMake build instructions. What am I missing?
Errors:
[ 50%] Linking CXX executable pressure.exe
CMakeFiles\pressure.dir/objects.a(main.cpp.obj): In function `main':
C:/code/cpp/small/pressure/main.cpp:19: undefined reference to `_imp___ZN2sf6StringC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6locale'
C:/code/cpp/small/pressure/main.cpp:19: undefined reference to `_imp___ZN2sf9VideoModeC1Ejjj'
C:/code/cpp/small/pressure/main.cpp:19: undefined reference to `_imp___ZN2sf12RenderWindowC1ENS_9VideoModeERKNS_6StringEjRKNS_15ContextSettingsE'
C:/code/cpp/small/pressure/main.cpp:21: undefined reference to `_imp___ZNK2sf6Window6isOpenEv'
C:/code/cpp/small/pressure/main.cpp:24: undefined reference to `_imp___ZN2sf6Window9pollEventERNS_5EventE'
C:/code/cpp/small/pressure/main.cpp:26: undefined reference to `_imp___ZN2sf6Window5closeEv'
C:/code/cpp/small/pressure/main.cpp:30: undefined reference to `_imp___ZN2sf5ColorC1Ehhhh'
C:/code/cpp/small/pressure/main.cpp:30: undefined reference to `_imp___ZN2sf12RenderTarget5clearERKNS_5ColorE'
C:/code/cpp/small/pressure/main.cpp:32: undefined reference to `_imp___ZN2sf6Window7displayEv'
C:/code/cpp/small/pressure/main.cpp:19: undefined reference to `_imp___ZN2sf12RenderWindowD1Ev'
C:/code/cpp/small/pressure/main.cpp:19: undefined reference to `_imp___ZN2sf12RenderWindowD1Ev'
collect2.exe: error: ld returned 1 exit status
My project's CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(pressure)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_VERBOSE_MAKEFILE ON)
if(WIN32)
#set(SFML_STATIC_LIBRARIES TRUE)
set(SFML_DIR C:/lib/cpp/SFML-2.5.1/lib/cmake/SFML)
endif()
set(SFML_LIBRARIES sfml-graphics sfml-audio)
set(pressure_VERSION_MAJOR 0)
set(pressure_VERSION_MINOR 1)
configure_file(
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
include_directories("${PROJECT_BINARY_DIR}")
set(EXECUTABLE_NAME "pressure")
find_package(SFML 2.5 COMPONENTS system window graphics audio main network REQUIRED)
add_executable(pressure main.cpp)
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})

This error has been mentioned a few times on the Stack Overflow site:
SFML: undefined reference to _imp_
Cannot compile SFML project using cmake
CMake+SFML Linker error, even though library is specified in CMakeLists.txt
More often than not, this specific linker error appears to occur when there are incompatibilities between the SFML libraries and what they are linked to. From the SFML 2.5.1 downloads page, there are several versions of the SFML pre-built libraries available. Make sure you download and reference the version that matches your compiler (e.g. MinGW, Visual C++ 12, Visual C++ 15, etc.).
On Windows, several different compilers are supported; so for example, if you are building your project with Visual Studio 15, be sure you've downloaded and referenced the Visual C++ 15 SFML libraries. Also be sure the SFML libraries match the architecture of your compiler (i.e. 32-bit or 64-bit).
If you don't see the compiler you're using in the list offered on the SFML downloads page, you can download the SFML source and build it yourself using your compiler. This will help ensure the SFML libraries have binary compatibility with your project. Or, you can browse through older versions of SFML pre-built libraries to see if any of those match the compiler you're using for your project.

Related

Building a rust library through CMake and using it as imported library target

I'm restucturing the CMake based build of a cross platform (macOS/Windows, Linux should be added soon) C++ project that has a third party rust library as dependendcy. Until now the rust lib dependency was supplied as precompiled library but I want to make its compilation part of my CMake build.
I got it working on macOS using the CMake makefile exporter by referencing the compiled library as a static imported library target and setting up a custom target with the command to build the rust library through cargo like this
add_library (rustlib STATIC IMPORTED)
add_custom_target (rustlib_cargo
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/Ext/rustlib/c-api
COMMAND cargo rustc --release -- --crate-type staticlib)
# Note: RUSTLIB_OUTPUT is set above refering to the absolute path of the produced platform specific library
set_target_properties (rustlib PROPERTIES IMPORTED_LOCATION ${RUSTLIB_OUTPUT})
add_dependencies (rustlib rustlib_cargo)
On macOS the cargo rustc command is invoked before the targets that link against my rustlib target are built and in case the rust library has been built previously this is detected by cargo and it just skips that compilation steph. But on Windows this fails with the built-in ninja exporter of Microsoft Visual Studio 2019 with an error like this:
ninja : error : '../../../Ext/rustlib/target/release/deps/rustlib.lib', needed by 'SomeTargetLinkingAgainstRustlib', missing and no known rule to make it
If I remove the line set_target_properties (rustlib PROPERTIES IMPORTED_LOCATION ${RUSTLIB_OUTPUT}) the build starts correctly, the rust build gets triggered, but as expected I end up with a linker error as the library to link against is not found. So is there any way to refer to a file that is not existent at configuration time but is guranteed to be created during compilation?

Error using SDL2, SDL2_image with Cmake CLion on Windows [duplicate]

I'm trying to install SDL on MinGW.
I've downloaded SDL from here (the SDL2-devel-2.0.0-mingw.tar.gz link), then copied the contents of SDL2-2.0.0/x86_64-w64-mingw32/{bin,include,lib} into the matching directories in my MinGW installation.
When I try to compile any file that contains #include ‹SDL2/SDL.h› using gcc test.c -lmingw32 -lSDL2main -lSDL2 -mwindows, GCC complains about undefined reference to WinMain#16 and undefined reference to some SDL functions.
SDL2-devel-2.0.0-mingw.tar.gz contains both 32-bit libraries (i686-w64-mingw32 directory) and 64-bit libraries (x86_64-w64-mingw32 directory).
The error was caused by using a 64-bit version of the library with a 32-bit compiler.

Linking to libuv. Can't use vsbuild.bat version, own compilation links correctly

After sucessfully building libuv on windows in a mingw64 environment, I'm having a problems linking the libuv.dll/libuv.lib that are built as part of the vsbuild.bat build script.
When I build libuv by myself from the sources to produce either a .dll or .lib I can link without any issues.
The errors I get back when including the static or shared lib from the vsbuild.bat are related to undefined references e.g.:
[ 9%] Linking CXX shared library ..\buildcmake\bin\libuws.dll
CMakeFiles\uws.dir/objects.a(Group.cpp.obj): In function `uS::Async::start(void (*)(uS::Async*))':
D:/test/uWebSockets/git/src/Libuv.h:37: undefined reference to `uv_async_init'
CMakeFiles\uws.dir/objects.a(Group.cpp.obj): In function `uS::Async::close()':
D:/test/uWebSockets/git/src/Libuv.h:45: undefined reference to `uv_close'
...etc
The specific part of my cmake script that deals with the linking is:
find_library(LIBUV_STATIC_LIBRARY NAMES libuv.lib PATHS ${LIBUV_DEPS_DIR}/git/Debug ${LIBUV_DEPS_DIR}/git/Release PATH_SUFFIXES ${CMAKE_BUILD_TYPE}/lib NO_DEFAULT_PATH)
find_library(LIBUV_SHARED_LIBRARY NAMES libuv.dll PATHS ${LIBUV_DEPS_DIR}/git PATH_SUFFIXES .libs ${CMAKE_BUILD_TYPE} NO_DEFAULT_PATH)
MESSAGE(STATUS ".${LIBUV_STATIC_LIBRARY}")
MESSAGE(STATUS ".${LIBUV_SHARED_LIBRARY}")
include_directories(${UWS_DIR} ${LIBUVDIR_SRC} ${ZLIB_DIR_INCLUDE} ${LIBUVDIR_INCLUDE} ${OPENSSL_INCLUDE_DIR} )
add_library(uws SHARED ${UWS_SOURCES})
target_link_libraries(uws PUBLIC ${LIBUV_SHARED_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
add_definitions(-D_WIN32_WINNT=0x0A00)
cmake output shows the libraries are found ok...
-- .D:/test/deps/libuv/git/Debug/lib/libuv.lib
-- .D:/test/deps/libuv/git/Debug/libuv.dll
Version of CMake is 3.9.something and I'm using nu-mingw with g++.

Compiling a SFML project directly with the sources and CMake

I want to compile a SFML projet directly with the SFML sources.
I'm using CLion, it's an IDE who use CMakeLists as project proprety file
(he use CMake himself)
Here is my CMakeLists.txt :
cmake_minimum_required(VERSION 3.3)
include(${CMAKE_CURRENT_SOURCE_DIR}/SFML/CMakeLists.txt)
project(R-Type)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -static -static-libgcc -static-libgcc -static-libstdc++")
set(SOURCE_FILES
Client/src/main.cpp)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/Client/Include ")
add_executable(R-Type ${SOURCE_FILES})
As you can see , i'm trying to call the CMakeLists who is bundled with the SFML sources, but its doesnt work ..
Error log (after copying manually the header SFML file in my project )
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:9: undefined reference to `_imp___ZN2sf6StringC1EPKcRKSt6locale'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:9: undefined reference to `_imp___ZN2sf9VideoModeC1Ejjj'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:9: undefined reference to `_imp___ZN2sf6WindowC1ENS_9VideoModeERKNS_6StringEjRKNS_15ContextSettingsE'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:20: undefined reference to `_imp___ZN2sf6Window5closeEv'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:16: undefined reference to `_imp___ZN2sf6Window9pollEventERNS_5EventE'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:12: undefined reference to `_imp___ZNK2sf6Window6isOpenEv'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:24: undefined reference to `_imp___ZN2sf6WindowD1Ev'
C:/Users/roman/Documents/CLionProjects/R-Type/Client/src/main.cpp:24: undefined reference to `_imp___ZN2sf6WindowD1Ev'
collect2.exe: error: ld returned 1 exit status
As you can see the compilor can't link with SFML despite the call of SFML CMakeList
You should use CMake to build and install SFML onto your system. In your application that consumes SFML, you should use the appropriate cmake modules provided by SFML to locate the individual libraries that you need. (SFML is not a single library it is a group of libraries: EGL, FLAC, etc.)
The find modules provided with SFML set appropriate cmake variables that you use in target_link_libraries for your executable.
If you look at test_driven.pdf from my C++ Now! 2014 presentation on Test-Driven Development, I walk through an example of using cmake to locate Boost.Test with find_package. You would use find_package similarly to locate the SFML packages described by the SFML modules.
Of course, none of this is going to make sense to you without investing some time in learning how cmake works. In order to properly use your build system (cmake), you need to understand your build system and how it works.
What you have done in your example is to include the SFML CMakeLists.txt directly in your CMakeLists.txt for your project, which is not how this is intended to be used. I'm not even sure if you can get it to work that way.

Cmake - not creating the dynamic links

The project that I am compiling is not linking my shared object file to the main program. This can be confirmed by doing the ldd command on my executable and seeing it say libba.so => not found.
Inside my CMakeLists.txt file I have:
add_library(ba SHARED "/usr/local/include/libba.cpp" "/usr/local/include/libba.h")
target_link_libraries(ba (list of other libraries that link to ba))
set_target_properties(ba PROPERTIES LINK_INTERFACE_LIBRARIES "" LINK_FLAGS "${NO_UNDEFINED}")
add_executable(run "/usr/local/main/run.cpp")
target_link_libraries(run ba)
ldd reports what the run-time linker can find.
If you see libba.so in the output it means the binary is linked to the library.
The "not found" means the run-time linker can't find that library (i.e. you don't have it installed in a normal system location).
So you can either install your library to a system location, configure your run-time linker to know about your custom location, link your application statically, or use an rpath in your binary to have it give the run-time linker additional places to look for just itself.