Can't use protobuf in cmakelists.txt - c++

I am trying to run the example given in protobuf repo here, the c++ version. I have successfully installed the library and am able to run the Makefile. But on running the CMakeLists.txt, I get this error:
CMake Error at CMakeLists.txt:9 (find_package):
Could not find a package configuration file provided by "protobuf" with any
of the following names:
protobufConfig.cmake
protobuf-config.cmake
Add the installation prefix of "protobuf" to CMAKE_PREFIX_PATH or set
"protobuf_DIR" to a directory containing one of the above files. If
"protobuf" provides a separate development package or SDK, be sure it has
been installed.
-- Configuring incomplete, errors occurred!
See also "/home/cortana/Projects/CppProjects/proto/build/CMakeFiles/CMakeOutput.log".
See also "/home/cortana/Projects/CppProjects/proto/build/CMakeFiles/CMakeError.log".
I have updated my LD_LIBRARY_PATH but this error is still there. How do I remove this error?
EDIT:
CMakeLists.txt:
# Minimum CMake required
cmake_minimum_required(VERSION 2.8.12)
# Project
project(protobuf-examples)
include(FindProtobuf)
# Find required protobuf package
find_package(protobuf CONFIG REQUIRED)
if(protobuf_VERBOSE)
message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
endif()
set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
${THIRDPARTY_DIR}/protobuf-3.1.0
)
include_directories(${ProtobufIncludePath})
# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
if(MSVC AND protobuf_MSVC_STATIC_RUNTIME)
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach()
endif()
foreach(example add_person list_people)
set(${example}_SRCS ${example}.cc)
set(${example}_PROTOS addressbook.proto)
#Code Generation
if(protobuf_MODULE_COMPATIBLE) #Legacy Support
protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
else()
foreach(proto_file ${${example}_PROTOS})
get_filename_component(proto_file_abs ${proto_file} ABSOLUTE)
get_filename_component(basename ${proto_file} NAME_WE)
set(generated_files ${basename}.pb.cc ${basename}.pb.h)
list(APPEND ${example}_SRCS ${generated_files})
add_custom_command(
OUTPUT ${generated_files}
COMMAND protobuf::protoc
ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs}
COMMENT "Generating ${generated_files} from ${proto_file}"
VERBATIM
)
endforeach()
endif()
#Executable setup
set(executable_name ${example}_cpp)
add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS})
if(protobuf_MODULE_COMPATIBLE) #Legacy mode
target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
else()
target_link_libraries(${executable_name} protobuf::libprotobuf)
endif()
endforeach()
EDIT 2:
After trying for 2 hours, I couldn't fix the CMakeLists.txt provided by google examples. I wrote this basic one and it works for me:
PROJECT(protopuff)
CMAKE_MINIMUM_REQUIRED (VERSION 3.5)
SET(CMAKE_CXX_FLAGS "-g -Wall -Werror -std=c++11")
INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER addressbook.proto)
ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}_add add_person.cc)
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}_list list_people.cc)
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME}_add proto ${PROTOBUF_LIBRARY})
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME}_list proto ${PROTOBUF_LIBRARY})

Your problem is here:
find_package(protobuf CONFIG REQUIRED)
The name should start with uppercase: Protobuf. And that is the reason why your version is working; because in there, you have used correct case (last code snippet line 6):
find_package(Protobuf REQUIRED)
Here cmake documentation for find_package
The command searches for a file called <name>Config.cmake or <lower-case-name>-config.cmake for each name specified.

in this thread fraser solved the problem but if you need to develop according to protobuf CMake config and find_package command in CMake for finding protobuf libraries. your protobuf library must be compiled with CMake and do not use configure routine .
after compile protobuf with CMake , a config file named protobuf-config.cmake will be generated into the prefix/lib/CMake/protobuf directory.

The CmakeList.txt that is provided by the OP works on Linux but it does NOT work on Windows.
There is a way to make the actual CMakeList.txt work without any changes. The problem is that it requires the CONFIG parameter and that part is not documented anywhere. We need to provide the path to that config using -Dprotobuf_DIR parameter while generating the project.
On Windows, wherever you have installed protobuf, it will have bin, cmake, include, lib folders. We need to give the path of this cmake folder as an argument, like following:
cmake -G "Visual Studio 16 2019" -A x64 -B _build2 -Dprotobuf_DIR=C:/protobuf/install/cmake
This will build a solution file in the current directory.

Related

CMake Errors including IXWebSocket in Ubuntu 22 (works on MacOS 12.6)

Context:
I have a cpp program built on MacOS 12.6 with the following CMakeLists.txt file.
cmake_minimum_required(VERSION 3.19.0)
project(cpp-test VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(cpp-test main.cpp)
add_library(test-helpers main.cpp ${PROJECT_SOURCE_DIR}/helpers.hpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
# this is super important in order for cmake to include the vcpkg search/lib paths!
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
# find library and its headers
find_path(IXWEBSOCKET_INCLUDE_DIR ixwebsocket/IXWebSocket.h)
find_library(IXWEBSOCKET_LIBRARY ixwebsocket)
find_package(OpenSSL REQUIRED)
find_package(CURL REQUIRED)
# include headers
include_directories(${IXWEBSOCKET_INCLUDE_DIR} ${CURL_INCLUDE_DIR})
# Cmake will automatically fail the generation if the lib was not found, i.e is set to NOTFOUND
target_link_libraries(
${PROJECT_NAME} PRIVATE
${IXWEBSOCKET_LIBRARY}
OpenSSL::SSL
OpenSSL::Crypto
${CURL_LIBRARIES}
"-framework Foundation"
"-framework Security"
"-lz"
)
This compiles just fine. However, when I try to pull it into my Ubuntu VM and try to build it /build> cmake .., I get the following errors
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of "cpp-test":
"IXWEBSOCKET_INCLUDE_DIR-NOTFOUND"
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of
"test-helpers":
"IXWEBSOCKET_INCLUDE_DIR-NOTFOUND"
-- Generating done
What I have tried...
I have installed vcpkg and created my symlink ln -s /path/to/vcpkg /usr/local/bin/vcpkg.
I have installed ixwebsocket via vcpkg install ixwebsocket, but it seems that the CMAKE_TOOLCHAIN_FILE is not being parsed correctly.
I'm a bit lost, any help would be appreciated
This is not a great answer to the issue, but I ended up resolving it by building ixwebsocket via CMake instead.
It seems that vcpkg was not compatible with the linux distro in my VM.

Encounter issue with `find_package` command in Visual Studio CMake

I'm operating under a new learning curve here with c++ and using CMake in Visual Studio. Here is the partial code up until the point where I receive the error:
project(libfranka
VERSION 0.8.0
LANGUAGES CXX
)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(MSVC)
add_compile_options(/W0)
else()
add_compile_options(-Wall -Wextra)
endif()
set(THIRDPARTY_SOURCES_DIR "${CMAKE_SOURCE_DIR}/3rdparty" CACHE PATH
"Directory for third-party sources")
## Dependencies
find_package(Poco REQUIRED COMPONENTS Net Foundation)
find_package(Eigen3 REQUIRED)
Once it hits the first find_package is where I encounter the error:
Here is the code within FindPoco.cmake.
find_package(Poco COMPONENTS ${Poco_FIND_COMPONENTS} CONFIG QUIET)
if(Poco_FOUND)
return()
endif()
find_path(Poco_INCLUDE_DIR Poco/Poco.h)
mark_as_advanced(FORCE Poco_INCLUDE_DIR)
foreach(component ${Poco_FIND_COMPONENTS})
set(component_var "Poco_${component}_LIBRARY")
find_library(${component_var} Poco${component})
mark_as_advanced(FORCE ${component_var})
if(${component_var})
set(Poco_${component}_FOUND TRUE)
list(APPEND Poco_LIBRARIES ${component})
if(NOT TARGET Poco::${component})
add_library(Poco::${component} SHARED IMPORTED)
set_target_properties(Poco::${component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${Poco_INCLUDE_DIR}
IMPORTED_LOCATION ${${component_var}}
)
endif()
endif()
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Poco
FOUND_VAR Poco_FOUND
REQUIRED_VARS Poco_INCLUDE_DIR Poco_LIBRARIES
VERSION_VAR Poco_VERSION
HANDLE_COMPONENTS
)
I installed poco using vcpkg in a directory titled vcpkg. Within the vcpkg directory is the libfranka directory, which houses the CMakeLists.txt file that I compile in Visual Studio. Here is an image of that directory:
Finally, here is the tutorial that I am using: https://frankaemika.github.io/docs/installation_windows.html#building-from-source
EDIT:
Per the link I followed the instructions for solving the build dependencies and here is an image of that:
Then I ran the CMakeLists.txt again and in the CMake Settings this is what I see:
Note also that I ran through the install of poco again and I noticed this and am unsure if it could be the source of the problem or if it means nothing (again, this was the out put after running vcpkg install poco):
After this I still receive the same error.
Does anyone see what it is that I am doing incorrectly?
Thank you!

How to use Caffe library in C++ project with CMakeLists.txt

I'm trying to use Caffe in my C++ project which I compile with CMakeLists.txt, but it doesn't want to work. My only line in the code is
#include <caffe/caffe.hpp>
I compiled Caffe myself, it is installed in the directory "/home/tamas/caffe". My CMakeLists.txt looks like this so far:
cmake_minimum_required (VERSION 3.5)
include(FindPkgConfig)
project (main)
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED TRUE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++11 -pthread")
set (source_dir "${PROJECT_SOURCE_DIR}/src/")
set (OpenCV_DIR "/home/tamas/opencv/include/opencv2")
set (Caffe_DIR "/home/tamas/caffe")
file (GLOB source_files "${source_dir}/ssd_video.cpp")
find_package(OpenCV 4.4.0 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
find_package(Caffe REQUIRED)
include_directories(${Caffe_INCLUDE_DIRS})
add_executable (main ${source_files})
target_link_libraries(main ${OpenCV_LIBS})
target_link_libraries(main ${Caffe_LIBRARIES})
The error is the following:
CMake Error at CMakeLists.txt:24 (find_package):
By not providing "FindCaffe.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Caffe", but
CMake did not find one.
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake
Add the installation prefix of "Caffe" to CMAKE_PREFIX_PATH or set
"Caffe_DIR" to a directory containing one of the above files. If "Caffe"
provides a separate development package or SDK, be sure it has been
installed.
-- Configuring incomplete, errors occurred!
The problem is that I have searched and I don't have a FindCaffe.cmake file on my computer. I found an example for CaffeConfig.cmake, but I tried it and it doesn't work either.
Is there a way I can link Caffe with my C++ project? Thanks!
To fix this issue you may do the following:
Download this FindCAFFE.cmake file
Create cmake dir in your repo root directory and put the downloaded file there.
Modify your CMake file:
add set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
change set (Caffe_DIR "/home/tamas/caffe") to set (CAFFE_ROOT_DIR "/home/tamas/caffe")
change find_package(Caffe REQUIRED) to find_package(CAFFE REQUIRED)
use CAFFE_INCLUDE_DIRS and CAFFE_LIBRARIES for include directories and link libraries respectively
Clean up your build dir and run cmake command again
<library>_DIR should not be set manually in CMake code usually. There are better alternatives that should be used as setting these variable won't necessarily do what you want. It won't change where find_package finds its libraries.
The CaffeConfig.cmake file is generated when building Caffe. You should never download another one, these files are compatible only with a specific build configuration.
The Caffe library supports to be used with CMake, so FindCaffe.cmake is unnecessary.
For find_package to work, either set the <package>_ROOT variable (require CMake 3.12 minimum) or you must append the install path in CMAKE_PREFIX_PATH. Here's a CMake example that uses the prefix path:
# If you only built the library
list (APPEND CMAKE_PREFIX_PATH "/home/tamas/caffe/build-dir")
# If you installed the library there
list (APPEND CMAKE_PREFIX_PATH "/home/tamas/caffe/")
find_package(Caffe REQUIRED)
Note that the Caffe_LIBRARIES and Caffe_INCLUDE_DIRS won't be set. This is old CMake style and the Caffe library uses the new style. This is what you should do:
target_link_libraries(main PUBLIC caffe caffeproto)
This line add both include directory and adds linking to the libraries too.

Create CMake for NetCDF C++

I am trying to create a CMake file for my project which uses NetCDF. I am very new at CMake (this is my first try), so I apologize if some of this stuff is evident.
To install NetCDF I followed the steps in the git guide shown here
I believe I did the steps correctly. I am trying to use the NetCDF C++ library, but I also had to install the C library for compilation purposes. I did this by using:
sudo apt install libnetcdf-dev
When I run the following command, I receive appropriate output (according to the git guide):
nc-config --has-nc4
So far so good... I hope. Here is my CMakeLists.Txt:
cmake_minimum_required(VERSION 3.16)
project(orbit LANGUAGES CXX)
# ##############################################################################
# Conan Packages
# ##############################################################################
set(CONAN_EXTRA_REQUIRES "") set(CONAN_EXTRA_OPTIONS "")
list(APPEND CONAN_EXTRA_REQUIRES boost/1.73.0) list(APPEND CONAN_EXTRA_REQUIRES eigen/3.3.7)
if(BUILD_SHARED_LIBS) list(APPEND CONAN_EXTRA_OPTIONS "Pkg:shared=True") endif()
include(cmake/Conan.cmake) run_conan()
# ##############################################################################
find_file(CMAKE_PREFIX_PATH netCDFCxxConfig.cmake)
find_package (NetCDF REQUIRED) include_directories(${NETCDF_INCLUDES})
# set(SOURCE test.cpp player.cpp player.hpp)
# include_directories(include)
# Search all .cpp files
file(GLOB_RECURSE SOURCE_FILES "*.cpp")
add_executable(test ${SOURCE_FILES})
target_link_libraries(test
PRIVATE
CONAN_PKG::boost
CONAN_PKG::eigen
${NETCDF_LIBRARIES_CXX})
And here is the error output:
CMake Error at CMakeLists.txt:24 (find_package):
By not providing "FindNetCDF.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "NetCDF", but
CMake did not find one.
Could not find a package configuration file provided by "NetCDF" with any
of the following names:
NetCDFConfig.cmake
netcdf-config.cmake
Add the installation prefix of "NetCDF" to CMAKE_PREFIX_PATH or set
"NetCDF_DIR" to a directory containing one of the above files. If "NetCDF"
provides a separate development package or SDK, be sure it has been
installed.
My understanding is that this error comes from me not doing the following line from the git guide correctly:
Make sure that either nc-config is in your PATH, or that the location of netCDFConfig.cmake is in CMAKE_PREFIX_PATH.
I have tried adding the nc-config to my PATH, by running:
export PATH="nc-config:$PATH"
But this does not resolve the issue...
Additionally, I have tried to find a netCDFConfig.cmake file in my computer, however it does not seem to exist. I do have a netCDFCxxConfig.cmake, but I am not sure if this is the same, or how I could go about using it here.
Does anyone have any experience with this issue, and know how to resolve it? Any help would be greatly appreciated, and I do apologize if such a solution has been provided in the past.
Edit:
I was able to get CMake to finally find the file, but now it gets lost looking for another one... Here is the file it was not finding in my original post:
# NetCDF CXX Configuration Summary
####### Expanded from #PACKAGE_INIT# by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was netCDFCxxConfig.cmake.in ########
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
macro(set_and_check _var _file)
set(${_var} "${_file}")
if(NOT EXISTS "${_file}")
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
endif()
endmacro()
macro(check_required_components _NAME)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(NOT ${_NAME}_${comp}_FOUND)
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
endif()
endif()
endforeach()
endmacro()
####################################################################################
include(CMakeFindDependencyMacro)
if (1)
if(EXISTS "")
set(netCDF_ROOT "")
endif()
if(EXISTS "/usr/lib/x86_64-linux-gnu/cmake/netCDF")
set(netCDF_DIR "/usr/lib/x86_64-linux-gnu/cmake/netCDF")
endif()
find_dependency(netCDF)
set(NETCDF_C_LIBRARY ${netCDF_LIBRARIES})
set(NETCDF_C_INCLUDE_DIR ${netCDF_INCLUDE_DIR})
else()
set(NETCDF_C_LIBRARY "netcdf")
set(NETCDF_C_INCLUDE_DIR "/usr/include")
endif()
if (NOT TARGET netCDF::netcdf)
add_library(netCDF::netcdf UNKNOWN IMPORTED)
set_target_properties(netCDF::netcdf PROPERTIES
IMPORTED_LOCATION "${NETCDF_C_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${NETCDF_C_INCLUDE_DIR}"
)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/netcdf-cxx4Targets.cmake")
This last line is where it all sort of goes wrong. Here is where it has issues finding the netcdf-cxx4Targets.cmake.
The file I have just posted is in the directory: netcd-cxx4/build
netcdf-cxx4Targets.cmake is in the directory:
netcd-cxx4/build/CMakeFiles/Export/lib/cmake/netCDF
So the first should be able to find the other?
The netCDFCxxConfig.cmake file is what you want to use. From quickly looking at the GitHub repository, there is a template for this file (netCDFCxxConfig.cmake.in), but not one for netCDFConfig.cmake.in. Therefore, my conclusion is the maintainers probably changed the config file name at some point, and forgot to update their README documentation to netCDFCxxConfig.cmake.
You can add the location of the netCDFCxxConfig.cmake file to the CMAKE_PREFIX_PATH list variable in your CMake file. Then, link to the imported target netCDF::netcdf defined in the netCDFCxxConfig.cmake file.
...
# ##############################################################################
# Don't do this.
find_file(CMAKE_PREFIX_PATH netCDFCxxConfig.cmake)
# Instead, append the path to the config file using the 'list' command.
list(APPEND CMAKE_PREFIX_PATH "/path/to/installed/netcdf")
# Look for the 'netCDFCxx' package, since that is what the config file is called.
find_package (netCDFCxx REQUIRED)
# Probably don't need this if we use the imported target below.
include_directories(${NETCDF_INCLUDES})
# set(SOURCE test.cpp player.cpp player.hpp)
# include_directories(include)
# Search all .cpp files
file(GLOB_RECURSE SOURCE_FILES "*.cpp")
add_executable(test ${SOURCE_FILES})
# Link to the imported target 'netCDF::netcdf' here instead.
target_link_libraries(test
PRIVATE
CONAN_PKG::boost
CONAN_PKG::eigen
netCDF::netcdf)

what is the proper way of configuring visual studio code to use sdl2 over mingw32 and cmake [duplicate]

I'm trying to use CLion to create a SDL2 project.
The problem is that the SDL headers can't be found when using #include's.
My CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.4)
project(ChickenShooter)
set(SDL2_INCLUDE_DIR C:/SDL/SDL2-2.0.3/include)
set(SDL2_LIBRARY C:/SDL/SDL2-2.0.3/lib/x64)
include_directories(${SDL2_INCLUDE_DIR})
set(SOURCE_FILES main.cpp)
add_executable(ChickenShooter ${SOURCE_FILES})
target_link_libraries(ChickenShooter ${SDL2_LIBRARY})
My test main.cpp:
#include <iostream>
#include "SDL.h" /* This one can't be found */
int main(){
if (SDL_Init(SDL_INIT_VIDEO) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Quit();
return 0;
}
Thank you for any help you could give me.
Edit:
I'm using Windows and CLion is configured to use cygwin64.
This blog post shows how you can do it: Using SDL2 with CMake
On Linux you can use a recent CMake (e.g. version 3.7) and using SDL2 works out of the box.
cmake_minimum_required(VERSION 3.7)
project(SDL2Test)
find_package(SDL2 REQUIRED)
include_directories(SDL2Test ${SDL2_INCLUDE_DIRS})
add_executable(SDL2Test Main.cpp)
target_link_libraries(SDL2Test ${SDL2_LIBRARIES})
Under Windows you can download the SDL2 development package, extract it somewhere and then create a sdl-config.cmake file in the extracted location with the following content:
set(SDL2_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include")
# Support both 32 and 64 bit builds
if (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
set(SDL2_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2main.lib")
else ()
set(SDL2_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2main.lib")
endif ()
string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES)
When you now configure inside the CMake-GUI application there will be a SDL2_DIR variable. You have to point it to the SDL2 directory where you extracted the dev package and reconfigure then everything should work.
You can then include SDL2 headers by just writing #include "SDL.h".
Don't set the path to SDL2 by hand. Use the proper find command which uses FindSDL. Should look like:
find_file(SDL2_INCLUDE_DIR NAME SDL.h HINTS SDL2)
find_library(SDL2_LIBRARY NAME SDL2)
add_executable(ChickenShooter main.cpp)
target_include_directories(ChickenShooter ${SDL2_INCLUDE_DIR})
target_link_libraries(ChickenShooter ${SDL2_LIBRARY})
If SDL2 is not found, you have to add the path to SDL2 to CMAKE_PREFIX_PATH, that's the place where CMake looks for installed software.
If you can use Pkg-config, its use might be easier, see How to use SDL2 and SDL_image with cmake
If you feel more comfortable to use a FindSDL2.cmake file similar to FindSDL.cmake provided by CMake, see https://brendanwhitfield.wordpress.com/2015/02/26/using-cmake-with-sdl2/
You can also pull in the SDL source repository as a submodule and build/link it statically along with your main program via add_subdirectory() and target_link_libraries():
cmake_minimum_required( VERSION 3.18.0 )
project( sdl2-demo )
set( SDL_STATIC ON CACHE BOOL "" FORCE )
set( SDL_SHARED OFF CACHE BOOL "" FORCE )
# 'external/sdl' should point at a SDL
# repo clone or extracted release tarball
add_subdirectory( external/sdl )
add_executable(
${CMAKE_PROJECT_NAME}
"src/main.cpp"
)
target_link_libraries( ${CMAKE_PROJECT_NAME} SDL2main SDL2-static )
(At least as of the release-2.0.9 tag, possibly earlier.)
I recently discovered the latest version of SDL2 (version 2.0.12) now comes with all the required CMake config/install scripts, so there's no need to use FindSDL anymore.
I downloaded the SDL source from https://www.libsdl.org/download-2.0.php then from the root folder ran...
cmake -S . -B build/debug -G Ninja -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_BUILD_TYPE=Debug
cmake --build build/debug --target install
This will build and install the debug version of the library, you can then also run...
cmake -S . -B build/release -G Ninja -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_BUILD_TYPE=Release
cmake --build build/release --target install
Which will build and install the release version of the library (and because the SDL CMake script uses DEBUG_POSTFIX the release version of the library won't overwrite the debug one as the debug versions all have 'd' appended to their name).
In your CMakeLists.txt file you can then simply do this:
find_package(SDL2 REQUIRED)
add_executable(${PROJECT_NAME} ...)
target_link_libraries(
${PROJECT_NAME} PRIVATE
SDL2::SDL2
SDL2::SDL2main
You'll need to tell your application where to find the SDL install folder if you used a custom location as I've done in the example. To do this from the root folder of your app run:
cmake -S . -B build/debug -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=</absolute/path/to/install/dir>
cmake --build build/debug
Note: You can use $(pwd) (*nix/macOS) or %cd% (Windows) to create a hybrid relative path which can be very useful.
You can omit both DCMAKE_INSTALL_PREFIX and DCMAKE_PREFIX_PATH if you want to install SDL to the default system location.
In the examples I've opted to use the Ninja generator as it is consistent across macOS/Windows - it can be used with MSVC/Visual Studio, just make sure you run this (path may differ slightly depending on year/version) to add Ninja to your path.
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
Update:
One other thing I remembered which is useful on Windows is the ability to copy the SDL .dll file into the application binary directory, this can be achieved like so:
if (WIN32)
# copy the .dll file to the same folder as the executable
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:SDL2::SDL2>
$<TARGET_FILE_DIR:${PROJECT_NAME}>
VERBATIM)
endif()
Using the SDL2 CMake module that I developed, you can integrate the SDL2 library easily in a modern and portable approach.
You should just copy the module in cmake/sdl2 (Or just clone the modules repo) in your project:
git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2
Then add the following lines in your 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.
The SDL2 CMake modules support other related libraries : SDL2_image, SDL2_ttf, SDL2_mixer, SDL2_net and SDL2_gfx.
You can find a list of examples/samples and projects that uses these modules here : https://github.com/aminosbh/sdl-samples-and-projects
With the compiled version of SDL2-2.0.9 with MinGW-w64 in Windows, the following configuration works for me:
find_package(SDL2 REQUIRED)
add_executable(sdl-test ${SOURCES})
target_link_libraries(sdl-test
mingw32
SDL2::SDL2main
SDL2::SDL2
)
A longer explanation
By reading SDL2Targets.cmake file, I've learned that SDL2 is providing several targets:
SDL2::SDL2main (lib/libSDL2main.a)
SDL2::SDL2 (lib/libSDL2.dll.a)
SDL2::SDL2-static (lib/libSDL2-static.a)
Each of them has INTERFACE_INCLUDE_DIRECTORIES defined, which means we don't need to manually specify include_directories for SDL2.
But by only adding SDL2::SDL2main and SDL2::SDL2 as target_link_libraries is not enough. The g++ compiler might be complaining about "undefined reference to `WinMain'".
By inspecting the compiler options, I found that the SDL2 libraries are added before -lmingw32 option. In order to make the -lmingw32 option comes before SDL2 libraries, we have to also specify mingw32 as the first target_link_libraries. Which will make this configuration working.
The command that I have used for building it is:
$ mkdir build && cd build && cmake .. -G"MinGW Makefiles" && cmake --build .
The only small problem here is in the finally generated compiler options, the -lmingw32 option is duplicated. But since it doesn't affect the linking process, I've ignored it for now.
On Linux, in Clion, this works:
cmake_minimum_required(VERSION 3.20)
project(first_game)
set(CMAKE_CXX_STANDARD 14)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})
You don't seems to have a CMake error whike generating your make file. But I think your problem is, the SDL Header are located in a subfolder named "SDL2".
Change your CMakeLists.txt to include
C:/SDL/SDL2-2.0.3/include/SDL2
Instead of
C:/SDL/SDL2-2.0.3/include
I had the same problem and none of the other solutions worked.
But I finally got it working by following this solution : How to properly link libraries with cmake?
In a nutshell, the problem was that the SDL2 library was not linked properly in my CMakeLists.txt. And by writing this into the file, it worked (more explainations in the other thread) :
project (MyProgramExecBlaBla) #not sure whether this should be the same name of the executable, but I always see that "convention"
cmake_minimum_required(VERSION 2.8)
ADD_LIBRARY(LibsModule
file1.cpp
file2.cpp
)
target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule liblapack.a)
target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)
ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)
target_link_libraries(MyProgramExecBlaBla LibsModule)
Highlighting the steps of how I was able to eventually accomplish this using the FindSDL2.cmake module:
Download SDL2-devel-2.0.9-VC.zip (or whatever version is out after this answer is posted) under the Development Libraries section of the downloads page.
Extract the zip folder and you should see a folder similar to "SDL2-2.0.9". Paste this folder in your C:\Program Files(x86)\ directory.
Copy the FindSDL2.cmake module and place it in a new "cmake" directory within your project. I found a FindSDL2.cmake file in the answer referenced in the Accepted Answer: https://brendanwhitfield.wordpress.com/2015/02/26/using-cmake-with-sdl2/
Find the SET(SDL2_SEARCH_PATHS line in the FindSDL2.cmake and add your copied development directory for SDL2 as a new line: "/Program Files (x86)/SDL2-2.0.9" # Windows
Within my CMakeLists.txt, add this line: set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
After this, running CMake worked for me. I'm including the rest of my CMakeLists just in case it further clarifies anything I may have left out:
cmake_minimum_required(VERSION 2.8.4)
project(Test_Project)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# includes cmake/FindSDL2.cmake
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(SOURCE_FILES src/main.cpp src/test.cpp)
add_executable(test ${SOURCE_FILES})
# The two lines below have been removed to run on my Windows machine
#INCLUDE(FindPkgConfig)
#PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
find_package(SDL2 REQUIRED)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(chip8 ${SDL2_LIBRARY})
Hope this helps somebody in the near future.
by the time of my answer, SDL2 is provided with sdl2-config executable (as I understand, developers call him "experimental").
After "make install" of SDL2 you can try calling it from terminal with
sdl2-config --cflags --libs to see what it outputs.
And then you can add call to it in your makefile:
set(PROJECT_NAME SomeProject)
project(${PROJECT_NAME})
execute_process(COMMAND /usr/local/bin/sdl2-config --libs RESULT_VARIABLE CMD_RES OUTPUT_VARIABLE SDL2_CFLAGS_LIBS ERROR_VARIABLE ERR_VAR OUTPUT_STRIP_TRAILING_WHITESPACE)
message("SDL2_CFLAGS_LIBS=${SDL2_CFLAGS_LIBS}; CMD_RES=${CMD_RES}; ERR_VAR=${ERR_VAR}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${SDL2_CFLAGS_LIBS}")
set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
Here I have a problem - if I only put an executable name without path like
execute_process(COMMAND sdl2-config --libs <...>
I get error "No such file", i.e. cmake does not search in current path and I don't know how to write it properly by now.
One more notice: in my makefile I do not user --cflags option, because cmake finds includes correctly and I do not need to specify them explicitly.
For your information, I was able to successfully cmake and compile SDL2_ttf while linking to SDL2 source code.
At first I was getting errors due to cmake not being able to locate SDL2, even though it was specified in cmake using the SLD2_DIR variable in cmake.
It seems that for some reason cmaking SDL2 fails to create the SDL2Targets.cmake file which is searched for by SDL2_ttf
If this is the case for you, get the SDL2Targets.cmake file from https://bugs.archlinux.org/task/57972 and modify the file like so:
You can remove the following lines:
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
if(_IMPORT_PREFIX STREQUAL "/")
set(_IMPORT_PREFIX "")
endif()
and add this one:
set(_IMPORT_PREFIX "C:/SDL2-2.0.12")
Obviously change the filepath to the place you unpacked the SDL2 source code
I'm not sure if this is exactly your issue, but there it is.