-
Notifications
You must be signed in to change notification settings - Fork 117
Setup Guide
This guide describes how to setup cmake-init based projects, and cmake-based projects in general. It is aimed at larger projects with many sub-projects which depend on each other, and shows a way to configure such projects so that all dependencies are met at build-time as well as run-time, without the need to install projects into the local system or copy files around. As an example, the CG Internals computer graphics middleware is used, but the guide can also be used for any cmake-based projects.
- C++ compiler
- CMake
First, you need to checkout the projects you want to build. As an example for a large group of interdependent projects, we use the CG Internals middleware stack.
-
Choose a directory for your projects, e.g.,
/projects
, orC:/projects
. -
Checkout git repositories there, e.g.:
/projects/cpplocate
/projects/cppassist
/projects/cppexpose
/projects/glbinding
/projects/globjects
/projects/gloperate
- Download 3rd-party dependencies, e.g.:
/projects/glm
/projects/glfw
/projects/assimp
- Build 3rd-party dependencies using their provided build system, e.g.
./configure
orcmake
. Copy the resulting libraries into subdirectorylib
, as most of the find scripts assume libraries to be located there.
To configure the project, cmake needs to be called. This can be accomplished in three ways:
All cmake-init-based projects include a shell script named configure
.
This script is nothing more than a wrapper around cmake, and it can be used
for any cmake-based project. Its purpose is to persist all cmake options
needed to successfully configure the project, so that nothing needs to be
passed to cmake on the commandline or via the cmake-gui any more. This makes
it possible to reconfigure the project at any time without worrying about
losing important configuration values.
The script needs a UNIX shell, such as bash, to be executed. On Windows,
we recommend to use git-bash
, which is bundled with the installation
of git
.
Run the script by changing into the directory of the project you want to
build, and enter ./configure
on the terminal. On the first run,
the configure script creates a hidden subdirectory named .localconfig
,
containing three files: default
, debug
, and pack
. These
files contain the configuration parameters needed to configure the project,
i.e., cmake options or environment variables.
When running ./configure
, the script reads the files in .localconfig
,
applies the options specified in the file, and then calls cmake. The file
default
is always processed, the other files are only processed if
specified on the command line. For example, running ./configure debug
will first apply default
, then debug
. This way, you can define
several configurations and even mix configurations, e.g., have one for each
compiler, one for debug instead of release, one for cross compilation,
and mix them like this: ./configure gcc48 debug arm
.
Inside the configuration files, you can define all options for cmake.
The cmake generator, build type (release, debug, ...) and build directory can
be specified via CMAKE_GENERATOR
, BUILD_TYPE
, and BUILD_DIR
,
respectively. Search paths for dependencies should be exported to the
environment variable CMAKE_PREFIX_PATH
. General cmake options can be
specified in the variable CMAKE_OPTIONS
.
You can also configure the project via the cmake-gui, entering all necessary options, like search paths of dependend projects, into the GUI. This is not recommended, because it needs to be repeated every time you recreate the build directory, which makes it hard to reconfigure projects. Please consider using option a), you can then still use the cmake-gui to explore and set the available project options.
- Start cmake-gui
- Choose compiler and generator, e.g., "Unix Makefiles", or "Microsoft Visual Studio ..."
- Choose source directory:
/projects/cpplocate
- Choose build directory:
/projects/cpplocate/build
- Enter all necessary build options and paths to dependend libraries
- Configure
- Generate
You can also configure the project by running cmake manually. In that case, you have
to pass all project options and search paths via the command line and environment
build, and enter CMAKE_PREFIX_PATH
. This is not recommend because the options
are not persisted when recreating the project. Please consider using method a).
- Open a terminal
- Change into the project directory:
cd /projects/cpplocate
- Create build directory:
mkdir build
- Specify all necessary build options and paths to dependend libraries via -D arguments
- Configure project:
cd build
- Configure project:
cmake ..
Most importantly, cmake needs to find the dependencies of your project. For
this to work, the project has either to be installed in a global system path,
or the path to the project must be made available to cmake by adding it to
the CMAKE_PREFIX_PATH
. All cmake-init
-based projects supply a
cmake file <project>-config.cmake
in their root directory, which enables
cmake to use that project from its development directory, so it is not
necessary to install projects into the system, only the project directory
needs to be added to CMAKE_PREFIX_PATH
.
To find the project dependencies, add the following lines to .localconfig/default
:
# cpplocate
export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:/projects/cginternals/cpplocate"
# cppassist
export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:/projects/cginternals/cppassist"
# cppexpose
export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:/projects/cginternals/cppexpose"
# glm
export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:/projects/glm"
# glfw
export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:/projects/glfw"
In the case of the CG Internals middleware, lot of projects depend on one another,
so the paths for the dependencies are similar for all projects. It that case,
it can me more convenient to write the above lines into a single file,
e.g., /projects/dependencies
, and include that from ./localconfig/default
:
# Import dependencies
source /projects/dependencies
You can also persist the search paths by storing them in an environment variable. This has the disadvantage that environment variables are global to the system, so you cannot for example use different version of the same library for different projects.
Windows:
- Open an environment variable editor
- Add project directories to
CMAKE_PREFIX_PATH
variable CMAKE_PREFIX_PATH="C:/projects/cpplocate;C:/projects/cppassist;..."
- Save
- Restart all programs and explorer windows, otherwise the environment variables are not reloaded. If nothing else helps, restart Windows.
Linux:
- Set
CMAKE_PREFIX_PATH
to include all paths and persist it in the system. This can be done in several ways depending on your distribution, e.g.,/etc/environment
,/etc/profile
,.profile
,.bashrc
. - export
CMAKE_PREFIX_PATH="/projects/cpplocate:/projects/cppassist:..."
See StackExchange for details.
You can of course use your own scripts, or batch files, to set all necessary cmake options and environment variables before calling cmake. This option is in general equal to a), but can be preferable if you want to optimize the setup for your specific system.
In order to run the compiled applications, the system must be able to find the dynamic libraries the application depends on. For example, gloperate depends on globjects and glbinding, so the respective dynamic libraries (.so or .dll) must be available to run gloperate-viewer.
The compiled binaries already contain the paths of the dependend libraries
in their RPATH. Therefore, they can be executed in place and all libraries will
be found automatically. Note however that the binaries are only setup to work
in the build environment, they cannot be copied around and are not intended to
be used directly for packaging or deployment. If you want to install a project into
the local system or create an installation package, use the make pack
or
make install
directives.
The DLLs of the dependend projects need to be found, therefore it is necessary
to add their directories to the environment variable PATH
.
- Open an environment variable editor
- Add project directories to PATH variable
PATH="C:/projects/cpplocate/build/Debug;C:/projects/cpplocate/build/Release;..."
- Save
- Restart all programs and explorer windows, otherwise the environment variables are not reloaded. If nothing else helps, restart Windows.
You should now be able to build and run projects from their development
location. However, the programs and libraries must also be able to find
their data files at runtime. Since the projects are distributed over many
directories, this is not a trivial task. Therefore, we use cpplocate
to help us locate data files at runtime.
This is accomplished by providing .modinfo
files for each program or
library, which are searched for at runtime. The module files for the currently
executed program will be found relative to the program executable. However,
to find data files for dependent libraries, cpplocate
must be provided
with search paths. This can be accomplished by adding the build directories
of those libraries to the environment variable CPPLOCATE_PATH
.
Windows:
- Open an environment variable editor
- Add project build directories to
CPPLOCATE_PATH
variable CPPLOCATE_PATH="C:/projects/gloperate/build/Debug;C:/projects/gloperate/build/Release;..."
- Save
- Restart all programs and explorer windows, otherwise the environment variables are not reloaded. If nothing else helps, restart Windows.
Linux:
- Set
CPPLOCATE_PATH
to include all paths and persist it in the system. This can be done in several ways depending on your distribution, e.g.,/etc/environment
,/etc/profile
,.profile
,.bashrc
. export CPPLOCATE_PATH="/projects/gloperate/build:/projects/gloperate/build-debug:..."
TODO ...
TODO ...
Module files of dependent projects could be copied into the using project automatically, so CPPLOCATE_PATH would not be needed any more.
TODO ...