[Tutorial] Using Irrlicht with CMake

A forum to store posts deemed exceptionally wise and useful
Post Reply
deteego
Posts: 2
Joined: Thu Jan 28, 2010 5:10 am

[Tutorial] Using Irrlicht with CMake

Post by deteego »

This basically a small howto on how to use CMake (http://www.cmake.org/). For those who don't know what CMake is, its basically like *nix's autotools/autoconf, but a lot better,nicer and has much better cross platform compatibility (especially with windows). It is also a LOT faster, since it uses native code (instead of scripting languages), this makes a big difference in larger products. We are going to go through building Irrlicht both statically and dynamically, and doing both debug and release builds (this is assuming you are using gcc or mingw for windows, with msvc extra stuff needs to be added, I will update this tut later when I manage to get Visual Studio installed or if someone shows how)

Ok some basics, you obviously need to install CMake. For *nix and mac, this should be straight forward since its basically a standard package now. Once installed all you basically need to do is to create a CMakeLists.txt file in your project folder, wherever you place CMakeLists is where the ${PROJECT_SOURCE_DIR} variable points to (explained later), so you almost always want to place it in the root of your project directory. For this tutorial we also assume you will have to separate folders for headers and src

Ok first up, create CMakeLists and add these lines to the file (we are going to do a simple project without debug/release and shared compilation of irrlicht just to get the basics). Also create the folder src and include in the project root folder (src will contain .cpp files and include your header files)

Code: Select all

cmake_minimum_required(VERSION 2.6)
PROJECT(example)
This shouldn't require explanation, you are basically stating the minimum version of cmake along with what your project is called (in this case example)

Code: Select all

INCLUDE_DIRECTORIES(
	"/usr/include/irrlicht"
	${PROJECT_SOURCE_DIR}/include
)
INCLUDE_DIRECTORIES basically designates the directories for the header files which the compiler needs to include in order to compile your executable. As mentioned before ${PROJECT_SOURCE_DIR} is the root of your project folder, and /usr/linux/irrlicht happens to be the location of the include files for irrlicht with my linux distribution

Code: Select all

FILE(GLOB SRCS src/*.cpp)
FILE(GLOB HDRS include/*.h)
Ok, so what FILE(GLOB ....) does is basically tell the compiler *add every file in this directory to the compiler*. SRCS/HDRS specifically tells the compiler which folders contain source/header files. So by doing FILE(GLOB SRCS src/*.cpp) we are basically saying set the variable SRCS to contain all the files in /src and similarly FILE(GLOB HDRS include/*.h) for headers. GLOB is a CMake command "GLOB will generate a list of all files that match the globbing expressions and store it into the variable". In our case the globbing expression is src/*cpp, which should be self explanatory

Code: Select all

ADD_EXECUTABLE(example
	${SRCS}
	${HDRS}
)
Since we have set SRCS and HDRS, we are now basically telling cmake to generate a binary out of those files. In our case the binary will be called "example"

Code: Select all

TARGET_LINK_LIBRARIES(example
	"/usr/lib/libIrrlicht.so"
)
TARGET_LINK_LIBRARIES works in a similar fashion to INCLUDE_DIRECTORIES, except we designate which libraries (shared or static) an executable needs (in this case example being the binary). The only shared object we need in this case is the irrlicht shared object.

Code: Select all

cmake_minimum_required(VERSION 2.6)
PROJECT(example)

INCLUDE_DIRECTORIES(
	"/usr/include/irrlicht"
	${PROJECT_SOURCE_DIR}/include

FILE(GLOB SRCS src/*.cpp)
FILE(GLOB HDRS include/*.h)

ADD_EXECUTABLE(example
	${SRCS}
	${HDRS}
)

TARGET_LINK_LIBRARIES(example
	"/usr/lib/libIrrlicht.so"
)
Ok thats it, this is the most basic build. It will create an executable in the root project folder called example. You can use cmake CMakeLists.txt to build this project. However as we know, most projects are more complicated then this one, so lets make a debug/release build (which will fit in most IDE's as well).

Ok so after PROJECT(example) lets add

Code: Select all

SET(CMAKE_CXX_FLAGS_RELEASE "-O3")
SET(CMAKE_CXX_FLAGS_DEBUG  "-g")
Similar to what we did with SRCS/HDRS we are now setting variables which CMake reads in order to build a project. In this case we are setting the flags which CMake uses to do debug/release builds. SET does what it implies, it sets the variable to the value. After the above, add this

Code: Select all

IF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
	SET(CMAKE_BUILD_TYPE Release)
ENDIF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
Ok so to make things clear, the IF statement structure in CMake is labelled by the expression. So when you do an ENDIF statement, you actually need to do ENDIF <EXPRESSION>, using the same expression that is used in the IF statement (in this case NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE).

In this case what we are saying, is if the user doesn't specify a build and configuration type (i.e. just runs CMake CMakeLists.txt) then we set the build type to Release. After the above add

Code: Select all

IF(CMAKE_CXX_FLAGS_DEBUG)
	SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/debug)
ELSE(CMAKE_CXX_FLAGS_DEBUG)
	SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/release)
ENDIF(CMAKE_CXX_FLAGS_DEBUG)
and create a debug and release folder in your project root

What this does is set the binary paths to the seperate folders. If we are a debug build the binary goes to debug folder (same story with release). By default, Project_Binary_Dir is the same as Project_Directory. Your complete CMakeLists.txt should look like this

Code: Select all

cmake_minimum_required(VERSION 2.6)
PROJECT(example)

SET(CMAKE_CXX_FLAGS_RELEASE "-O3")
SET(CMAKE_CXX_FLAGS_DEBUG  "-g")

IF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
	SET(CMAKE_BUILD_TYPE RelWithDebInfo)
ENDIF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)

IF(CMAKE_CXX_FLAGS_DEBUG)
	SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/debug)
ELSE(CMAKE_CXX_FLAGS_DEBUG)
	SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/release)
ENDIF(CMAKE_CXX_FLAGS_DEBUG)

INCLUDE_DIRECTORIES(
	"/usr/include/irrlicht"
	${PROJECT_SOURCE_DIR}/include

FILE(GLOB SRCS src/*.cpp)
FILE(GLOB HDRS include/*.h)

ADD_EXECUTABLE(example
	${SRCS}
	${HDRS}
)

TARGET_LINK_LIBRARIES(example
	"/usr/lib/libIrrlicht.so"
)
Now in order to specify different build types for CMake, we need to run CMake with different arguments. cmake -D CMAKE_BUILD_TYPE=CMAKE_CXX_FLAGS_DEBUG CMakeLists.txt is the command we would run if we want a debug build. The -D command is used to parse in variables to CMakeLists.txt which we use to determine how to build our project. Similarly we would use cmake -D CMAKE_BUILD_TYPE=CMAKE_CXX_FLAGS_RELEASE CMakeLists.txt for release.

Now the last part of the tutorial, what if we wan't to compile our irrlicht project statically? This is obviously slightly more complicated, since we actually need to add in the dependencies that irrlicht requires. When you install CMake, it creates a directory where CMake modules are found. CMake modules are used for finding packages which are dependencies of programs. On *nix systems, this CMake folder is usually in /usr/share/cmake-<version> or /usr/local/share/cmake-<version> and usually stored in a folder called modules. This is important, since the default value CMAKE_MODULE_PATH points to this path, but it can be changed using set to another folder. Since there is no module for locating the dependancies of irrlicht yet, we have to do it manually (which isn't such a big deal in this case). Place

Code: Select all

FIND_PACKAGE(X11)
FIND_PACKAGE(GLUT)
FIND_PACKAGE(ZLIB)
After ENDIF(CMAKE_CXX_FLAGS_DEBUG)

This makes sense, its basically telling CMake to find those packages. Now since these are standardised packages, there are Cmake package modules for them. However if package doesn't have a CMake module (in this case irrlicht, which is why we had to specificy a manual location to the irrlicht header files and shared objects) we need to specifiy where it is located. FIND_PACKAGE just locates the packages, now we need to actually add them to the include folders and library folders. Change INCLUDE_DIRECTORIES to this

Code: Select all

INCLUDE_DIRECTORIES(
	"/usr/include/irrlicht"
	${X11_INCLUDE_DIR}
	${GLUT_INCLUDE_DIR}
	${ZLIB_INCLUDE_DIR}
	${PROJECT_SOURCE_DIR}/include
)
This again is self explanatory, since we have found directories with the FIND_PACKAGE command, we can refer to the packages with the variables. Likewise we do the same with TARGET_LINK_LIBRARIES, changing it to this

Code: Select all

TARGET_LINK_LIBRARIES(example
	${X11_LIBRARIES}
	${GLUT_LIBRARIES}
	${ZLIB_LIBRARIES}
	"/usr/lib/libIrrlicht.a"
)
In my case /usr/lib/libIrrLicht.a is the location of the static library for Irrlicht. The complete CMakeLists.txt should look like this

Code: Select all

cmake_minimum_required(VERSION 2.6)
PROJECT(example)

SET(CMAKE_CXX_FLAGS_RELEASE "-O3")
SET(CMAKE_CXX_FLAGS_DEBUG  "g")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g")

IF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
	SET(CMAKE_BUILD_TYPE RelWithDebInfo)
ENDIF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)

IF(CMAKE_CXX_FLAGS_DEBUG)
	SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/debug)
ELSE(CMAKE_CXX_FLAGS_DEBUG)
	SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/release)
ENDIF(CMAKE_CXX_FLAGS_DEBUG)

FIND_PACKAGE(X11)
FIND_PACKAGE(GLUT)
FIND_PACKAGE(ZLIB)

INCLUDE_DIRECTORIES(
	"/usr/include/irrlicht"
	${X11_INCLUDE_DIR}
	${GLUT_INCLUDE_DIR}
	${ZLIB_INCLUDE_DIR}
	${PROJECT_SOURCE_DIR}/include
)

FILE(GLOB SRCS src/*.cpp)
FILE(GLOB HDRS include/*.h)
 
ADD_EXECUTABLE(example 
	${SRCS}
	${HDRS}
)
 
TARGET_LINK_LIBRARIES(example
	${X11_LIBRARIES}
	${GLUT_LIBRARIES}
	${ZLIB_LIBRARIES}
	"/usr/lib/libIrrlicht.a"
)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Hi, and thanks for the nice explanation. However, it seems to lack certain things. First of all, GLUT is not needed, we only need GL. More problematic seem to be the missing libraries, though, which reside in jpeglib and libpng. Also, it should be user configurable whether system zlib/jpeglib/libpng are used, or those from the Irrlicht directories. Also, static and dynamic library building should be kept in one file, and both be created (or dpending on user choice).
Other options and flags could be added as well, but that's another thing.
deteego
Posts: 2
Joined: Thu Jan 28, 2010 5:10 am

Post by deteego »

hybrid wrote:Hi, and thanks for the nice explanation. However, it seems to lack certain things. First of all, GLUT is not needed, we only need GL. More problematic seem to be the missing libraries, though, which reside in jpeglib and libpng. Also, it should be user configurable whether system zlib/jpeglib/libpng are used, or those from the Irrlicht directories. Also, static and dynamic library building should be kept in one file, and both be created (or dpending on user choice).
Other options and flags could be added as well, but that's another thing.
I read somewhere else that GLUT was needed (also there was only the GLUT cmake module on my system, no GL).

I forgot to mention the other missing libraries, because currently there is an issue on my linux distro where our libjpeg is a higher version then yours (and isn't completely backwards compatible).

As I said, this tutorial was meant to be basic. There shouldn't be a need to configure the libraries your irrlicht project (since you know if you are going to use jpeg or png or whatnot). One the other hand if you were making the build system for irrlicht in cmake, then yes that would be another story
X3liF
Posts: 1
Joined: Sat Feb 13, 2010 11:32 am

Post by X3liF »

hi

nice tutorial ^^ thanks for this

but i've a question, this tutorial is only working for Linux and only if the include/ and lib/ directory are placed at /usr/ directory isn't it?

is someone knowing enough in cmake to build a findIRRLICHT.cmake file?

for the moment i don't really understand the cmake syntax, i'm trying without result :(

if someone don't have the time to make the file anyone can give some advices?

thanks

X3liF
oet
Posts: 1
Joined: Tue Jun 17, 2008 6:15 pm

Post by oet »

Hi all,

I am using this FindIrrlicht.cmake in my project and I have put it in a folder in the root of my project called cmake,

Code: Select all

FIND_PATH(IRRLICHT_INCLUDE_DIR irrlicht/irrlicht.h
	PATHS $ENV{IRRDIR}/include
	PATH_SUFFIXES irrlicht
)

MESSAGE(STATUS "IRRLICHT_INCLUDE_DIR = ${IRRLICHT_INCLUDE_DIR}")

FIND_LIBRARY(IRRLICHT_LIBRARY NAMES Irrlicht
	PATHS $ENV{IRRDIR}/lib
)

MESSAGE(STATUS "IRRLICHT_LIBRARY = ${IRRLICHT_LIBRARY}")

# handle the QUIETLY and REQUIRED arguments and set IRRLICHT_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(IRRLICHT DEFAULT_MSG IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR)

IF(IRRLICHT_FOUND)
  SET(IRRLICHT_LIBRARIES ${IRRLICHT_LIBRARY})
ELSE(IRRLICHT_FOUND)
  SET(IRRLICHT_LIBRARIES)
ENDIF(IRRLICHT_FOUND)

MARK_AS_ADVANCED(IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR)
it is looking in the normal placed for libs and includes or in a directory specified by the environment variable IRRDIR.

and using it in my main CMakeLists.txt like this (change Example to match your project):

Code: Select all

PROJECT(Example)
SET(CMAKE_MODULE_PATH ${Example_SOURCE_DIR}/cmake)
FIND_PACKAGE(Irrlicht)
and the just set the include with

Code: Select all

INCLUDE_DIRECTORIES(${IRRLICHT_INCLUDE_DIR}
and link with

Code: Select all

TARGET_LINK_LIBRARIES(Example ${IRRLICHT_LIBRARY})
Cheers
Oet
AzP
Posts: 16
Joined: Fri Jun 09, 2006 8:47 pm
Location: Stockholm, Sweden

Post by AzP »

That's a great FindIrrlicht that can help other people using CMake. I configured my own project for it a while ago, and that file would have been nice at that time.

Have you supplied it upstream to the CMake developers?
wishmaster
Posts: 3
Joined: Sun Sep 29, 2013 2:59 am

Re:

Post by wishmaster »

oet wrote:Hi all,

I am using this FindIrrlicht.cmake in my project and I have put it in a folder in the root of my project called cmake,

Code: Select all

 
FIND_PATH(IRRLICHT_INCLUDE_DIR irrlicht/irrlicht.h
    PATHS $ENV{IRRDIR}/include
    PATH_SUFFIXES irrlicht
)
 
MESSAGE(STATUS "IRRLICHT_INCLUDE_DIR = ${IRRLICHT_INCLUDE_DIR}")
 
FIND_LIBRARY(IRRLICHT_LIBRARY NAMES Irrlicht
    PATHS $ENV{IRRDIR}/lib
)
 
MESSAGE(STATUS "IRRLICHT_LIBRARY = ${IRRLICHT_LIBRARY}")
 
# handle the QUIETLY and REQUIRED arguments and set IRRLICHT_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(IRRLICHT DEFAULT_MSG IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR)
 
IF(IRRLICHT_FOUND)
  SET(IRRLICHT_LIBRARIES ${IRRLICHT_LIBRARY})
ELSE(IRRLICHT_FOUND)
  SET(IRRLICHT_LIBRARIES)
ENDIF(IRRLICHT_FOUND)
 
MARK_AS_ADVANCED(IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR)
 
it is looking in the normal placed for libs and includes or in a directory specified by the environment variable IRRDIR.

and using it in my main CMakeLists.txt like this (change Example to match your project):

Code: Select all

 
PROJECT(Example)
SET(CMAKE_MODULE_PATH ${Example_SOURCE_DIR}/cmake)
FIND_PACKAGE(Irrlicht)
 
and the just set the include with

Code: Select all

 
INCLUDE_DIRECTORIES(${IRRLICHT_INCLUDE_DIR}
 
and link with

Code: Select all

 
TARGET_LINK_LIBRARIES(Example ${IRRLICHT_LIBRARY})
 
Cheers
Oet
I'm interested on using this "search irrlicht". Someone claim some copyright of it? Can I use on my zlib/libpng licensed software package?
shybovycha
Posts: 13
Joined: Wed Jul 27, 2011 8:36 am
Contact:

Re: [Tutorial] Using Irrlicht with CMake

Post by shybovycha »

Necromancy mode on!

Hi, peeps! I was trying to build Irrlicht under my OSX these days and I successfully failed. The build process was not quite straightforward and there are a few tricks to do with CIrrDeviceMacOSX.mm in order to get window show, etc. So I tried my best to build Irrlicht and (at least) HelloWorld example with CMake.

There was a lot of playing with 3rd party libs like zlib and libpng, which did not want to be compiled with their out-of-the-box CMakeLists.txt files, but I ended up (up until now) with Irrlicht itself and the HelloWorld example compiled successfully under OSX and HelloWorld was able to start (yet the window did not show up, most likely because I did not wrap the binary file in bundle-like dir structure).

I was thinking whether it is worth making a commit to trunk with all those CMakeLists.txt changes?

My changelist so far contains mostly changes to CMakeLists.txt files for zlib and libpng (removing the clutter, inexistent targets, moving towards CMake 3.10, etc.) and two line changes to CIrrDeviceMacOSX.mm to fix the problems with window not being shown or being hidden beneath the currently active window. Though I still lack the CMakeLists for (almost all) examples and I need to dig deeper into bundling the example application as an OSX... well, bundle. And I did not manage to force libpng to pick zlib version provided with Irrlicht, but I think I can figure that out (or I could have used CMake experts' advice if there are any reading this thread).

The change to the CIrrDeviceMacOSX.mm can easily go as a fix to 1.8 branch, I reckon.

Wanted to hear others' thoughts on this.
shybovycha
Posts: 13
Joined: Wed Jul 27, 2011 8:36 am
Contact:

Re: [Tutorial] Using Irrlicht with CMake

Post by shybovycha »

Created a patch for some basic CMake support. Any constructive feedback is welcomed!
Post Reply