Compiling a SFML project directly with the sources and CMake - 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.

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?

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

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.

What happened to FindSDL2 in CMake?

I use SDL2 in my game. I always was using custom FindSDL2.cmake, because there is no one in standard CMake set. However, some time ago posts about FindSDL2 did appeared. Example: Reddit post.
If your cmake is new enough and it has FindSDL2.cmake file, you can do this:
find_package(SDL2 REQUIRED)
But when I download latest CMake (3.13.2), it doesn't include FindSDL2.cmake.
What happened to it?
FindSDL2 has never appeared in CMake.
Following the reject reason in pull request #149, SDL2 ships with a SDL2Config.cmake, which provides a cmake package.
The documentation for find_package states that find_package(SDL2) will behave as follows:
Look for FindSDL2.cmake, use that if it exists. (module mode)
Otherwise, use the information in SDL2Config.cmake or sdl2-config.cmake. (config mode)
In short, make sure that your SDL2 package has installed the SDL2Config.cmake file and that is on your CMAKE_PREFIX_PATH. The documentation lists the exact paths and prefixes it looks under.
To easily integrate the SDL2 library, I developed cross-platform modern CMake modules for finding and using the SDL2 library as well as other related libraries:
SDL2: example, game example
SDL2_image: example
SDL2_ttf: example
SDL2_mixer: example
SDL2_net
SDL2_gfx: animation example
So the only things that you should do in order to integrate the SDL2 library are:
Clone SDL2 CMake modules inside your project:
git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2
Add the following lines in your main CMakeLists.txt
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main)
Note: If CMake didn't find the SDL2 library (in Windows), we can specify the CMake option SDL2_PATH as follows:
cmake .. -DSDL2_PATH="/path/to/sdl2"
For more details, please read the README.md file.
This is a list of SDL2 samples and projects: https://github.com/aminosbh/sdl-samples-and-projects

How would I build and link an external library using CMake?

To start off, I should say that I've seen the answers on questions that were similar to mine, yet none of them seem to make sense to me. Here goes:
Say I have the following simple CMakeLists:
cmake_minimum_required (VERSION 2.8)
project (Example)
add_executable (Example Main.cpp)
I would then like to link a library that already has its own CMakeLists (for example, glfw) against Example. Of course, this brings into question how to properly set up the build order.
How would I go about doing this?
First let me describe what to do for GLFW. See the notes below for variations.
Build GLFW. As the official GLFW head's CMake support is currently broken, use this shaxbee fork:
git clone https://github.com/shaxbee/glfw.git
cmake -Hglfw -Bbuild/glfw -DCMAKE_INSTALL_PREFIX=inst -DCMAKE_BUILD_TYPE=Release
cmake --build build/glfw --target install --config Release
This install step installs inst/lib/cmake/glfw3/glfw3Config.cmake, the glfw3 config-module which will be used by client projects to find GLFW.
Your project should look like this:
cmake_minimum_required(VERSION 2.8)
project(Example)
find_package(glfw3 REQUIRED)
add_executable(Example Main.cpp)
target_link_libraries(Example glfw3)
The find_package command finds the glfw3Config.cmake which creates an IMPORTED library, a CMake target, which incorporates all the information needed to use GLFW in your project.
The target_link_libraries command tells CMake not only to link to GLFW but to use its include directories and compile flags, too.
Configure your project with -DCMAKE_PREFIX_PATH=inst (use full path if necessary)
Note: Other config-modules or find-modules may not provide IMPORTED targets. See the actual config or find-module for help. They usually provide <PACKAGE>_INCLUDE_DIRS and <PACKAGE>_LIBRARIES variables which should be added to the appropriate settings of your target:
target_include_directories(mytarget ${ZLIB_INCLUDE_DIRS})
or
include_directories(${ZLIB_INCLUDE_DIRS})
Same for target_link_libraries / link_libraries.
Build the external dependency first.
add a function call to find your external library. That can either be FindGLFW.cmake with find_package if you can find that or write it yourself using find_library et al. More information about including external libraries can be found in the CMake wiki
Add the includes and libraries to your Example executable.
This is how CMake should be used, I don't see why is not answered in the sources in the Internet.

Linking GLEW with CMake

How can you link GLEW to a project with CMake?
We've been trying to link GLEW to our project using CMake for at least 3 hours without any success so any help is accepted.
I'm using the FindGLEW.cmake which comes with CMake 3.1.0
CMakeLists.txt
find_package(GLEW REQUIRED)
if (GLEW_FOUND)
include_directories($(GLEW_INCLUDE_DIRS))
endif()
Environment Variables
I'm using MinGW w64 to compile the sources and we successfully linked GLFW and GLM just by copying the includes and libs to their respective folders, but after doing the same with GLEW, CMake still couldn't find it.
Sorry if I wasn't clear enough while formulating the question. I will provide any additional information required.
Edit: I've managed to link the header files by specifying their location in the CMake Cache file, though I'm getting undefined reference to glew functions like glewInit().
Typical CMake scripts like FindGLEW will define variables that specify the paths and files that your project needs. If the script can't automatically identify the correct paths (usually because of nonstandard install location, which is fine), then it leaves these variables up to you to fill in.
With command line CMake, you use the -D flag to define and set the value of a given variable. Other CMake interfaces, like CMake-gui or an IDE integration, give you this ability some other way.
However you do it, you can also modify the cache directly (CMakeCache.txt) and see what CMake is using in there or just clear the cache altogether. You'll have to rerun CMake for it to pick up your changes.
When it comes to linking, that's when you need to tell CMake which libs to link. Use the link_libraries command with what the automated script gives you.
find_package(GLEW REQUIRED)
include_directories(${GLEW_INCLUDE_DIRS})
link_libraries(${GLEW_LIBRARIES})
Other answers do obviously work, but the target based style of cmake makes it even easier since the GLEW find module defines the imported target GLEW::GLEW. All you need is:
find_package(GLEW REQUIRED)
target_link_libraries(YourTarget GLEW::GLEW)
YourTarget is the target that you created with add_executable or add_library. No need to explicitly add include directories, they are added automatically by linking the targets.
The secret of find_package(GLEW) is in FindGLEW.cmake file with cmake install.
find_path(GLEW_INCLUDE_DIR GL/glew.h)
find_library(GLEW_LIBRARY NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64)
The find_path and find_library commands find paths in standard system paths. If you want them to find paths in user defined directories, you should tell them.
For example:
set(CMAKE_PREFIX_PATH "d:/libs/glew-1.10.0")
set(CMAKE_LIBRARY_PATH "d:/libs/glew-1.10.0/lib/Release/Win32/")
find_package(GLEW REQUIRED)
Reference:
http://www.cmake.org/cmake/help/v3.0/command/find_path.html
http://www.cmake.org/cmake/help/v3.0/command/find_library.html
I was struggling hard to link glew to cmake through command line on mac. This might be helpful but I am not sure :) I will walk you through step by step of what I have done.
I installed Cmake source from the web.
Then I went inside the cmake folder in terminal and typed
./bootstrap && make && make install
(this will install cmake command line tools on our OS platform)
I have some exercise files. I want cmake to generate xcode files for me for all those exercise files (ex. triangles.cpp, shader.cpp etc) So i made a directory inside exercise files folder.
$ mkdir xcode
$ cd xcode
$ cmake -G "Xcode" ..
At this point, Cmake suppose to install all xcode files that included correct libraries. But there was an error :
$ cmake -G "Xcode" ..
CMake Warning (dev) at CMakeLists.txt:3 (cmake_minimum_required):
Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.
This warning is for project developers. Use -Wno-dev to suppress it.
system name is: Darwin-14.1.0
system processor is: x86_64
-- Could NOT find GLEW (missing: GLEW_INCLUDE_DIR GLEW_LIBRARY)
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Using Cocoa for window creation
-- Using NSGL for context creation
-- Building GLFW only for the native architecture
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GLEW_LIBRARY
linked by target "TextureLoader" in directory /Users/Mydir/Desktop/Exercise/Exercise Files
-- Configuring incomplete, errors occurred!
Then to make sure I have installed GLEW and all its libraries correctly, I ran
$brew install glew
Yes, I have installed glew already but it was NOT linked. See the Warning below:
Warning: glew-1.12.0 already installed, it's just not linked
Then I ran the following commands:
$ brew unlink glew
$ brew link glew
And I have solved the error. So just make sure that you have linked glew. Hope this helps.
Happy Coding :)
Finally I found a simple and short CMakeLists which works if you have installed everything in default paths.(openGL, glfw and glew)
cmake_minimum_required(VERSION 3.3)
project(openGL_tutorial)
find_package(OpenGL REQUIRED)
if(NOT OPENGL_FOUND)
message("ERROR: OpenGL not found")
endif(NOT OPENGL_FOUND)
set(GL_LIBRARY GL GLU X11)
add_executable(openGL_tutorial main.cpp)
target_link_libraries(openGL_tutorial glfw GLEW libGLEW.so libGLU.so libGL.so)
For what it is worth, in 2023, this works for me, on macOS, with GLEW, GLFW, and CMake installed using Homebrew:
cmake_minimum_required(VERSION 3.10)
project(Project)
add_executable(Project main.cpp)
find_package(glfw3 REQUIRED)
find_package(GLEW REQUIRED)
target_link_libraries(Project glfw GLEW::glew)