How to use CMake's pkg_search_module() when compiling under Windows? - c++

I'm programming a game which uses SDL2 and CMake.
In order to link and include SDL2 I use the following CMake code:
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
target_link_libraries(MYLIB SDL2)
When compiling under Linux (Fedora) this works perfectly.
But what about Windows? There I don't have standard system locations for DLL/a files and include folders. There isn't even pkg-config.
This is the error I get:
Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
checking for one of the modules 'sdl2'
CMake Error at C:/Program Files (x86)/CMake/share/cmake-3.0/Modules/FindPkgConfig.cmake:425 (message):
None of the required 'sdl2' found
Call Stack (most recent call first):
.../CMakeLists.txt:4 (pkg_search_module)
I used the VS 2013 generator.

As you may already know, pkg_search_module() relies on the pkg-config program in order to locate dependencies. As you point out, Windows doesn't come with pkg-config. You might be able to install it and get things working that way, but probably a better alternative for crossplatform builds is to use CMake's find_package() function instead. This way you can eliminate the dependency on having pkg-config installed on the developer's machine.
cmake_minimum_required(VERSION 3.1)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
find_package(SDL2 REQUIRED)
add_executable(sdl2demo sdl2demo.cpp)
target_include_directories(sdl2demo SYSTEM PRIVATE "${SDL2_INCLUDE_DIR}")
target_link_libraries(sdl2demo "${SDL2_LIBRARY}")
CMake doesn't come with a module for finding SDL2 so you'll need to add that to your source directory. That's why the above sets the CMAKE_MODULE_PATH; you add a cmake script that works cross platform for finding SDL2 to ${CMAKE_SOURCE_DIR}/cmake/Modules and then you can deliver that script with your source code.
The FindSDL2.cmake module I've used is: http://freerct.googlecode.com/svn/trunk/CMake/FindSDL2.cmake
This script should be able to locate SDL2 if it's installed in a standard location. If SDL2 isn't installed in a standard location or otherwise can't be located by this script, the developer has to configure the appropriate CMake variables to tell CMake the appropriate location, after which the configure and build will be able to procede normally.
cmake <source dir> -G "Visual Studio 12 2013 Win64" -DSDL2_INCLUDE_DIR=<sdl dir>/include -DSDL2MAIN_LIBRARY=<sdl dir>/lib/x64/SDL2main.lib -DSDL2_LIBRARY=<sdl dir>/lib/x64/SDL2.lib

Related

Build uWebSockets on Windows 10 with CMake

I want to use uWebSockets(UWS) in my C++ project to transfer images over the network. The setup will be running on multiple operating systems, so the best way of creating the build files seemed like using CMake.
However, I am new to CMake and having a hard time building UWS. I don't understand how to start working with the official repository on Windows 10, so I found another repository that includes a CMakeFiles.txt file and some of the dependencies (openssl, zlib, libuv, but it doesn't include uSockets for some reason). The root CMakeFiles.txt includes:
[...]
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
find_path(LIBUV_INCLUDE_DIR uv.h)
find_library(LIBUV_LIBRARY NAMES uv uv1)
[...]
It looks straightforward, but when I try to run mkdir build && cd build; cmake .., it cannot find OpenSSL. Here is the error message it spits out:
[...]
[cmake] Could not find a package configuration file provided by "OpenSSL" with any
[cmake] of the following names:
[cmake]
[cmake] OpenSSLConfig.cmake
[cmake] openssl-config.cmake
[...]
The above error message suggests that I need to set up a config file for each of these libraries. Yet, if I understand the find_package docs correctly, the command itself searches the library in various locations under the root folder. What kind of a folder structure does the find_package need in order to work?
More generally, am I wasting my time with this alternative repo? Is there a better way of using UWS with Windows 10? The official repo has a question about how to use it on Windows but I don't understand how that's an answer to the question. It only points to this page where it says any specific build systems will not officially be supported.
Any help would be appreciated.
Importing dependencies with add_subdirectory seems like a good way around this. When I ran cmake, I was receiving LNK2019 Error. I realized the following code snippet I found online was causing the problem, and the system works when I delete it.
if(MSVC)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS")
endif()

How do I use cmake to build external libraries as well as my own application?

I am trying to build a cross platform OpenGL application, which means building and including multiple libraries (glfw, glbinding, glm, etc.) Because my application is cross platform, it makes sense to use cmake to generate all the build scripts and not have to muck about with them myself. I am attempting to target Windows and Linux specifically.
A main feature that I need is that the libraries I need are not installed on the host system. Furthermore, they cannot be installed (due to administrative reasons). What I need is to build these libraries and then build my application.
I am mostly working on Windows using Visual Studio 2017, which has cmake support included. Currently, I have attempted to build these libraries myself, however I am having many issues getting find_package to do the right thing.
My directory structure looks like this:
project/
|-src/
|- my sources for my application
|-include/
|- my header files
|-external/
|-glfw-3.2.1/
|-glbinding-2.1.4/
|-glfw-build/
|-glbinidng-build/
So I am attempting to build the external libraries and use them in my application. I am also attempting to follow cmake best practices. My CMakeLists.txt currently looks like this:
cmake_minimum_required(VERSION 3.5)
project(glTestProj)
set(CMAKE_PREFIX_PATH "external/")
find_package(glfw3 3.2 REQUIRED)
find_package(glbinding REQUIRED)
add_executable(glTest src/main.cpp)
target_compile_features(glTest PRIVATE cxx_std_17)
target_compile_options(glTest PRIVATE -Wall -Wextra)
target_link_libraries(
glTest
glfw
glbinding::glbinding
)
The libraries in question (glfw and glbinding) both have instructions on including them via cmake, however I am running into this issue:
CMake Error at CMakeLists.txt:6 (find_package):
By not providing "Findglfw3.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "glfw3", but
CMake did not find one.
Could not find a package configuration file provided by "glfw3" (requested
version 3.2) with any of the following names:
glfw3Config.cmake
glfw3-config.cmake
Add the installation prefix of "glfw3" to CMAKE_PREFIX_PATH or set
"glfw3_DIR" to a directory containing one of the above files. If "glfw3"
provides a separate development package or SDK, be sure it has been
installed.

How to know variable such as 'OpenCV' in CMake

I am using OpenCV with gcc and cmake. And I found a tutorial https://docs.opencv.org/3.4.0/db/df5/tutorial_linux_gcc_cmake.html .In the file CMakeLists.txt, there are some variables such as OpenCV and OpenCV_INCLUDE_DIRS.
cmake_minimum_required(VERSION 3.9)
project(VideoRecord)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(VideoRecord main.cpp)
target_link_libraries(VideoRecord ${OpenCV_LIBS})
I want to know where to find these variables definition.
EDIT
Thanks #qbranchmaster's answer. I tried to search FindOpenCV.cmake but failed.
First try.
➜ ~ cmake --help-module-list | grep "FindOpen"
FindOpenACC
FindOpenAL
FindOpenCL
FindOpenGL
FindOpenMP
FindOpenSSL
FindOpenSceneGraph
FindOpenThreads
Another try.
➜ / find . "FindOpenCV.cmake"
In addition, my os is osx and I install cmake with brew. I comiple and install OpenCV manually.
These variables are part of the package config script shipping with OpenCV.
Note that find_package is a two-headed beast. The classic mode of operation is finding libraries through find-scripts. This is still the approach being used today for third-party libraries that are not aware of CMake. However, if your dependency is itself being built with CMake, it can provide a package config file instead, which allows for a more powerful mode of operation.
The idea here is that instead of you telling CMake how to find a dependency, the dependency itself tells CMake how clients can find it. This is the approach that is taken by libraries like OpenCV and Qt.
To answer your question, those variables are being set by the package config file in your local OpenCV installation, the template of which can be found in the OpenCV source code under cmake/templates/OpenCVConfig.cmake.in.
They are defined in CMake OpenCV module. CMake has numerous modules that aid in finding various libraries like OpenCV (FindOpenCV.cmake module).
Using this command you can get a list of modules that your CMake supports:
cmake --help-module-list
Some libraries come with their own *.cmake modules which should be installed in some system path. If you are using Ubuntu, your cmake modules should be localised in:
/usr/share/cmake/Modules/
If not, just search system for file FindOpenCV.cmake. In that file you will find these variables.
In general, you get variable names from the documentation or source code of the package you want to find.
Often you can derive the name to put into find_package from the provided FindFoo.cmake module file name, because "Foo" would be the name. The find module is either part of CMake or comes with the third-party library.
If there is no find module, some modules provide FooConfig.cmake files, where "Foo" is again the string to put into find_package.
If you have neither a find nor a config file, you need to find the library by other means, e.g., FindPkgConfig or find_library / find_file.

Missing sfml libraries for cmake

C++ newbie here, I'm trying to implement SFML library for CLion (Win 10).
I followed this http://www.sfml-dev.org/tutorials/2.0/compile-with-cmake.php guidelines and installed sfml using cmake gui and mingw.
Now when I try to include SMF libraries to project in CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(untitled2)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(untitled2 ${SOURCE_FILES})
set(CMAKE_MODULE_PATH "C:/Program Files (x86)/SFML/cmake/Modules"${CMAKE_MODULE_PATH})
set(SFML_STATIC_LIBRARIES TRUE)
find_package(SFML COMPONENTS graphics window system REQUIRED)
include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(First ${SFML_Libraries})
Howewer, i'm getting an error
CMake Error at C:/Program Files (x86)/SFML/cmake/Modules/FindSFML.cmake:355 (message):
SFML found but some of its dependencies are missing ( FreeType libjpeg)
Call Stack (most recent call first):
CMakeLists.txt:13 (find_package)
But I thought those libs are included in Windows. I am doing something wrong? Where should I place FreeType and libjpeg files if I were to download them?
You shouldn't set any local system specific things (like paths) in your CMakeLists.txt. This defeats the whole purpose of a build system.
First, I'd suggest you create a sub directory "cmake" in your project and copy SFML's FindSFML.cmake module in there.
Then update your CMAKE_MODULE_PATH accordingly:
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
This will ensure the module is found. CMake's default modules are always found, you don't have to preserve the previous value of the variable (should typically be empty anyway).
Next, when creating your actual project files, you'll just have to pass SFML_ROOT to CMake, for example:
cmake "-DSFML_ROOT=C:/Program Files (x86)/SFML" path/to/source
In a similar way, you shouldn't set SFML_STATIC_LIBRARIES in your CMakeLists.txt unless you're somehow forced to use static libraries. So I'd actually add that to the command line as well:
cmake "-DSFML_ROOT=C:/Program Files (x86)/SFML" -DSFML_STATIC_LIBRARIES=TRUE path/to/source
You only have to set these once, they're stored in your CMakeCache.txt file later.
Last but not least, if you'd like to support static linking with SFML, you'll have to link SFML's dependencies as well:
target_link_libraries(First ${SFML_LIBRARIES} ${SFML_DEPENDENCIES})
Note that all these won't fix the error message you're getting. For some reason SFML's prebuilt dependencies aren't in C:\Program Files (x86)\SFML\lib. Are you sure you've got the correct prebuilt package?

Building PoDoFo library using CMake and MinGW

I am trying to build PoDoFo Library on my Windows Platform (for use as an API). It is done using CMake. The ReadMe file says the following. Unfortunately I am new to CMake and I can't make out much from it.
Building PoDoFo on Windows
CMake 2.6.x is required for Windows. You can download it from
cmake.org .
On Windows, PoDoFo may be built as either a shared or static library.
Building both is not supported. By default only the shared library
will be built. If you want a static library, just disable generation
of the shared library with the extra argument to cmake:
-DPODOFO_BUILD_SHARED=FALSE
Handling library naming on win32
Especially on Windows it is also common for custom built libraries to
have different names to those you might download as pre-built copies.
CMake won't be able to find them if they're called something else
unless you tell it. Use these variables to tell CMake what names to
look for a library under:
•FREETYPE_LIBRARY_NAMES_DEBUG, FREETYPE_LIBRARY_NAMES_RELEASE and FREETYPE_LIBRARY_NAMES
•TIFF_LIBRARY_NAMES_DEBUG, TIFF_LIBRARY_NAMES_RELEASE and TIFF_LIBRARY_NAMES
•LIBJPEG_LIBRARY_NAMES_DEBUG, LIBJPEG_LIBRARY_NAMES_RELEASE and LIBJPEG_LIBRARY_NAMES
•ZLIB_LIBRARY_NAMES_DEBUG, ZLIB_LIBRARY_NAMES_RELEASE,ZLIB_LIBRARY_NAMES
CMake builds on Windows with MinGW
Once MinGW is set up, make sure that the MinGW "bin" directory is on
your PATH, and be sure to set CMAKE_INCLUDE_PATH and
CMAKE_LIBRARY_PATH such that CMake can find the headers and .lib files
for the libraries PoDoFo requires. The GnuWin32 library packages from
http://gnuwin32.sf.net/ are known to work with PoDoFo, so installing
zlib, freetype, and libjpeg from there should do the trick.
To configure and build PoDoFo with a default GnuWin32 install and with
MinGW already on your PATH:
md ..\podofo-debug
cd ..\podofo-debug
cmake -G "MinGW Makefiles" ..\podofo-src -DCMAKE_INCLUDE_PATH=c:\progra~1\gnuwin32\include -DCMAKE_LIBRARY_PATH=c:\progra~1\gnuwin32\lib -DPODOFO_BUILD_SHARED:BOOL=FALSE mingw32-make
I have installed CMake and downloaded the other libraries mentioned like freetype, zlib, libjpeg. Their header and binary files are in their respective folders.
Now what should DCMAKE_INCLUDE_PATH and DCMAKE_LIBRARY_PATH be? Also what is "MinGW Makefiles"? Do I have to supply any extra parameters?
I'll be grateful if someone can explain in simple steps how I can go about it.
EDIT: error while executing CMAKE:
-- Ensure you cppunit installed version is at least 1.12.0
Cppunit not found. No unit tests will be built.
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPack
ageHandleStandardArgs.cmake:97 (message):
Could NOT find FREETYPE (missing: FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR)
Call Stack (most recent call first):
C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStan
dardArgs.cmake:291 (_FPHSA_FAILURE_MESSAGE)
cmake/modules/FindFREETYPE.cmake:75 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:372 (FIND_PACKAGE)
To build PoDoFo you need installed GnuWin32, CMake, MinGW32 and PoDoFo sources
download GetGnuWin32
install to c:\getgnuwin32
open cmd.exe
cd c:\getgnuwin32
download.bat
install.bat
Then as suggested in #ibizaman answer
cmake -G "MinGW Makefiles" -DCMAKE_INCLUDE_PATH="C:\gnuwin32\include" -DCMAKE_LIBRARY_PATH="C:\gnuwin32\lib" -DPODOFO_BUILD_STATIC=TRUE ..
FreeType should be installed with GnuWin32 packages
If you followed all the instructions, to compile it should normally be enough to do:
cd <podofo root directory (where CMakeLists.txt is)>
mkdir build
cd build
cmake -G "MinGW Makefiles" -DCMAKE_INCLUDE_PATH=<path to headers> -DCMAKE_LIBRARY_PATH=<path to libraries> -DPODOFO_BUILD_SHARED:BOOL=FALSE ..
mingw32-make
Step by step:
First, go to the directory where your podofo sources are. You should see a CMakeLists.txt file lying around.
Second (and third), create (and go into) a directory where the compilation will be done. I call it build but it can be any name. This is a best practice since you can simply delete the build directory and come back to a clean state.
Fourth, ask cmake to create the makefile(s) for mingw:
Specify the PODOFO_BUILD_SHARED like advertised in the manual: build shared or static version.
CMAKE_INCLUDE_PATH and CMAKE_LIBRAY_PATH are used to reference to the packages needed to build podofo. If you downloaded the precompiled packages like you did since you have de headers and the binaries, then you need to give to cmake the path to those headers and binaries. You can specify the variables multiple times if needed, e.g.:
cmake -G "MinGW Makefiles" -DCMAKE_INCLUDE_PATH=/path/to/freetype/include -DCMAKE_LIBRARY_PATH=/path/to/freetype/lib -DCMAKE_INCLUDE_PATH=/path/to/zlib/include -DCMAKE_LIBRARY_PATH=/path/to/zlib/lib -DPODOFO_BUILD_SHARED:BOOL=FALSE ..
The "MinGW Makefiles" tells cmake to create makefiles specific to mingw. Else, by default on windows, it creates makefiles specific to Microsoft Visual Studio.
Finaly reference the CMakeLists.txt in the parent directory with .. at the end.
Last, but not least, compile with the mingw version of make.