BuildSystem

Naming conventions

Software revision follow the <major>.<minor>.<patch> scheme :

  • the major number changes when major changes are included since the previous version,
  • the minor number changes when important (but not major) changes are included since the previous version,
  • the patch number changes when only bug fixes (no real new feature) have been completed since the previous version.

We may use "Alpha", "beta" and "release candidate" version (not always) ; in such cases, we use the following naming scheme :

  • Alpha : <major>.<minor>.<patch>-a<alpha number> (example: "2.0.0-a1", "2.0.0-a2", ...),
  • Beta : <major>.<minor>.<patch>-b<beta number> (example: "1.4.0-b1", ...),
  • Release candidate : <major>.<minor>.<patch>-rc<release candidate number> (example: "1.4.0-rc1", ...).

Finally, as a last precaution, we may include the corresponding SVN revision in the version name, as in :

  • the binary and source package files we releases (example: speed-dreams-1.4.0-r2307-win32-setup.exe),
  • the in-game version indicators in the splash screen and in every menu help screen (ex: 2.0.0-a1-r2720)

In the SVN repository, we define 3 main folders in order to cope with releases :

  1. trunk : the root folder of source tree for the main stream developments
  2. branches : the folder where "branch" source trees are stored ;
    • maintenance branches are the place where we fix bugs in officially released versions ; they are named "<major>.<minor>.x" (example: "branches/1.4.x"),
    • development branches are the place where we develop new big things that would prevent the other developers from working on the trunk for the next release, or for which we don't know yet if we'll release them one day (experimental).
  3. tags : the folder where "tagged" source trees are stored ; tagged source trees are frozen snapshots (copies) of the trunk or some branch corresponding to officially released versions; the name of their root folder is simply the name of the version example: "tags/1.4.0", "tags/2.0.0-a1").

How to build from sources

See source:trunk/INSTALL.txt for the 2.x series (source:tags/1.4.0/INSTALL for the 1.4.0).

Build times examples for trunk@3276 (elapsed time for the 'make' command, or equivalent ; not considered the 'cmake' or 'make install' build steps, which may also take a long time, especially under Windows).

CPU Disk OS Compiler Build configuration Parallel jobs Elapsed time (mm:ss)
AMD 64 x 2 4600+ (2.4 GHz) DDR2 800 Western Digital Raptor 74 Gb (10000 rpm, cache 8 Mb) Linux Mandriva 2010.0 64 bits GCC 4.4.1 Debug, full contents 1 02:11
2 01:09
Western Digital Caviar Black 500 Gb (7200 rpm, cache 32 Mb) Windows XP SP2 32 bits MSVC 2005 Pro
Debug, full contents 1 03:18
2 01:38
Intel Core2 Duo E8400 (3 GHz) DDR3 1066 Hitashi Deskstar 160 Gb (7200 rpm, cache 8 Mb) Windows XP SP2 32 bits MSVC 2005 Pro Debug, Official contents 1 01:54
2 01:08
Intel Xeon 3250 (2.66 GHz) DDR3 1066 Western Digital Caviar Blue 250 Gb (7200 rpm, cache 8 Mb) Windows XP SP3 32 bits MSVC 2005 Pro Debug, Official contents 2 01:04
4 01:00
6 00:54
8 00:50

Same for trunk@4791m (MinGW port pre-release)

CPU Disk OS Compiler Build configuration Parallel jobs Elapsed time (mm:ss)
Intel Xeon 3250 (2.66 GHz) DDR3 1066 Western Digital Caviar Blue 250 Gb (7200 rpm, cache 8 Mb) Windows XP SP3 32 bits MSVC 2005 Pro Debug, Official contents 1 01:46
2 01:05
4 00:48
8 00:55
MinGW Gcc 4.7.0 Release, Official contents 1 04:25
2 01:56
4 01:26
Debug, Official contents 1 03:25
2 01:45
4 01:06
AMD 64 x 2 4600+ (2.4 GHz) DDR2 800 Western Digital Veloci-raptor 150 Gb (10000 rpm, cache 16 Mb) Linux Mint Debian Edition April 2012 GCC 4.6.0 Release, official contents 1 TODO
2 TODO
Western Digital Caviar Black 500 Gb (7200 rpm, cache 32 Mb) Windows XP SP2 32 bits MinGW 201204 Gcc 4.7.0 Debug, full contents 1 TODO
2 02:15
Release, official contents 1 05:10
2 02:33

How to make a release

Note:

  • In below examples, we assume that we are freezing 'trunk' into 'tags/2.0.0-b1' for a 2.0.0 Beta 1 release.
  • This applies only to the 2.x series (the 1.4 does is not built with CMake).

Linux

  1. update the release notes files (source:trunk/CHANGES.txt, source:trunk/doc/2.0.0.txt) : 'svn log' is your friend
  2. build your up-to-date trunk sandbox using the Release configuration
  3. test everything needed (no more detail about testing here, but very important and quite difficult to reach 100% coverage ...)
  4. freeze the source tree into a tag, inside the remote SVN server

    svn copy https://speed-dreams.svn.sourceforge.net/svnroot/speed-dreams/trunk@3935 
             https://speed-dreams.svn.sourceforge.net/svnroot/speed-dreams/tags/2.0.0-b1
    
  5. checkout the tag or switch your trunk/branch sandbox to the tag

    1. alternative 1 : switch your trunk/branch sandbox to the tag (very quick, some seconds, few downloads)

      cd mysandbox/trunk
      ./clobber.sh # if not there, cmake && make should generate it
      svn status -q # MANDATORY : make sure nothing is uncommitted ; fix it first if not !
      rm CMakeLists.txt # will force SVN keyword substitution, to auto-generate the exact version name
      svn switch https://speed-dreams.svn.sourceforge.net/svnroot/speed-dreams/tags/2.0.0-b1
      
    2. alternative 2 : checkout the tag (from far longer, as it downloads about 2 Gb)

      cd mysandbox
      mkdir tags
      cd tags
      svn checkout https://speed-dreams.svn.sourceforge.net/svnroot/speed-dreams/tags/2.0.0-b1 2.0.0-b1
      cd 2.0.0-b1
      
  6. configure the build for the official contents and the Release (optimized) configuration (see above for more details, especially about external dependencies)

    cmake -D OPTION_OFFICIAL_ONLY:BOOL=ON -D CMAKE_BUILT_TYPE:STRING=Release .
    # Note: Depending on your configuration, you migh also use '-D CMAKE_PREFIX_PATH:STRING=/usr/local'
    
  7. build and install

    make
    sudo make install
    
  8. test the release (check cars, tracks, robots and modules-related contents ; check all race mode ; ...)

    /usr/local/games/speed-dreams-2
    
  9. make the needed changes to the code / artwork in your 2.0.0-b1 sandbox

  10. loop back to 5 or 6 if any change was done
  11. commit any change to the tags (and don't forget to merge these back to the trunk later !)

Now, it's time for release package(s) ...

Windows

All the same as for Linux, but rather than the command line, you generally use graphical tools for dealing with SVN (ex: Tortoise SVN), compiling (MS Visual C++ 2005), ... etc ...

See the Windows chapter for more details about each build step in source:trunk/INSTALL.txt.


How to build release packages

If you didn't "make the release" yet, please do it, as explained above in "How to make a release".

Below, we assume you did it, and so that you enjoy a 2.0.0-b1 SVN sandbox where CMake was run at least once as explained above (step 5 : configure the build ...).

Source packages

These packages are the "reference" ones for any release, as all the binary packages can be rebuilt / must be "rebuildable" from them.

They contain only official contents (not the whole SVN repo. contents).

Linux

Alternative 1 (our preferred) : Multiple source packages

For official releases, we use the following multi-package scheme :

  1. base = game core sources and data + 1 1st class car set + 1 1st class track
  2. other official 1st class cars and tracks
  3. other official 1st class cars and tracks
  4. more official but lower quality / WIP / no AI - cars and tracks
  5. unmaintained contents (old physics engines)

The small base package is designed to become at the end a quick-download-and-try one, a kind of demo one.

But for the moment, you need to download and extract all of these source packages before starting to build (due to the limitations of our current CMake build system).

To build these packages, things are simple :

  1. cd to the top of your SVN source tree
  2. well, for the moment, not that simple : you have to hack the root CMakeLists.txt in order the in-game version name is generated correctly building outside of a SVN local copy, as it will be the case for the packages we are generating :
    • before "IF(NEED_SVN_REV)" at line 66, add this line : "SET(NEED_SVN_REV FALSE)"
    • replace line 98 : SET(VERSION_LONG "${VERSION}) by SET(VERSION_LONG "${VERSION}-r3937") (if r3937 is the target SVN revision)
  3. run the packaging/sources/build.sh script, and give it the version of your packages

    ./packaging/sources/build.sh 2.0.0-b1-r3937
    

That's all : after some minutes, you've got all of the .tar.xz packages

To extract these packages :

mkdir sd-2.0.0-b1-r3937-src
cd sd-2.0.0-b1-r3937-src
for file in <packages folder>/*.xz; do tar xvfa $file; done

Alternative 2 : All-in-one source package

  1. automatically generate the full-contents source package (unfortunately, the (our?) CMake source packager does not do any filtering) (as a .tar.bz2 file)

    make package_source
    
  2. extract it (we need to clean it up) :

    tar xvfj speed-dreams-2.0.0-b1-r3937-src.tar.bz2
    
  3. cleanup the resulting source tree from unofficial contents

    cd speed-dreams-2.0.0-b1-r3937-src
    
    # Docs you can find online
    rm -fr doc/tutorials
    
    # Race modes
    rm src/raceman/networkrace.xml
    rm src/raceman/championship-mpa1.xml
    
    # Robots
    rm -fr src/drivers/bt
    rm -fr src/drivers/networkhuman
    rm -fr src/drivers/hymie
    rm -fr src/drivers/K1999
    rm -fr src/drivers/simplix/simplix_mpa1
    
    # Tracks
    rm -fr data/tracks/development
    rm -fr data/tracks/dirt/dirt-5
    rm -fr data/tracks/circuit/bueno
    rm -fr data/tracks/gprix
    rm -fr data/tracks/karting
    rm -fr data/tracks/road/Salty
    rm -fr data/tracks/road/longday
    
    # Cars
    rm -fr data/cars/models/gtc-aichi-aidoru
    rm -fr data/cars/models/ls1-cavallo-570s1
    rm -fr data/cars/models/ls1-marisatech-gt4r
    rm -fr data/cars/models/lancer09-wr
    rm -fr data/cars/models/lp1-*
    rm -fr data/cars/models/lp2-*
    rm -fr data/cars/models/mp1*
    rm -fr data/cars/models/mp10-*
    rm -fr data/cars/models/mpa1*
    rm -fr data/cars/models/nascar-*
    rm -fr data/cars/models/ref-boxer-gt3-rs-2010
    
    rm data/tracks/dirt/garguree/garguree.ac                     
    rm data/tracks/dirt/dirt-2/dirt-2.ac                         
    rm data/tracks/dirt/dirt-1/dirt-1.ac                         
    rm data/tracks/dirt/mixed-1/mixed-1.ac                       
    rm data/tracks/speedway/manton/manton.acc                    
    rm data/tracks/speedway/newton/newton.acc                    
    rm data/tracks/road/alpine-2/alpine-2.ac                     
    rm data/tracks/road/e-track-2/e-track-2.ac                   
    rm data/tracks/road/charmey/charmey.ac                       
    rm data/tracks/road/prenzlau/prenzlau.ac                     
    rm data/tracks/road/street-1/street-1.ac                     
    rm data/tracks/road/e-track-1/e-track-1.ac                   
    rm data/tracks/circuit/chemisay/chemisay.ac
    rm data/tracks/circuit/forza/forza.ac
    rm data/tracks/circuit/aalborg/aalborg.ac
    rm data/tracks/circuit/karwada/karwada.ac
    rm data/tracks/circuit/corkscrew/corkscrew.ac
    rm data/tracks/circuit/migrants/migrants.ac
    rm data/tracks/circuit/ruudskogen/ruudskogen.ac
    

4. archive and compress (lzma) the resulting source tree

cd ..
tar -c -v -f - speed-dreams-2.0.0-b1-r3937-src | 7zr a -m0=lzma -mx=9 -mfb=64 -md=32m xxx.tar.7z speed-dreams-2.0.0-b1-r3937-src.tar.7z

That's all :-)

To extract this package under Linux :

7zr x -so speed-dreams-2.0.0-b1-r3937-src.tar.7z | tar xvf -

Under Windows, you can use the excellent 7-Zip.

Windows

We don't build source packages under Windows, but if it is needed, here's how to.

Alternative 1 (our preferred) : Multiple source packages

You can use the Linux method, after installing MSYS or CygWin? (gives your a Linux shell and tool set under Windows).

Alternative 2 : All-in-one source package

Basically, you'll use the same procedure as for Linux, but through different tools :

  • to "automatically build the full-contents all-in-one source package" (as a ZIP archive), you'll use MS Visual Studio, and "build" the "PACKAGE_SRC" project,
  • to "extract this full-contents all-in-one source package", you'll use any ZIP archiver (7-Zip is an excellent one),
  • to "cleanup the resulting source tree from unofficial contents", you'll probably simply use your Windows explorer, but will surely remove the same file/folders,
  • to "archive and compress (lzma) the resulting source tree", you'll use 7-Zip in order to get the best possible compression ratio. Note however that the resulting source package will not be a compressed "tarball" (a .tar.7z file), but a compressed tree (a .7z file) ... meaning that one will have to use a different command in order to extract it under Linux :

    7zr x -so speed-dreams-2.0.0-b1-r3937-src.7z
    

Binary package(s)

Here's how to build packages that suit for direct and automatic installation on various OSes : the kind that the end-users prefer (and the developers don't like to make ;-).

Whatever the target OS, you start from the "all-in-one" source package, or from the SVN release tag ... as you like.

Let's assume that you've got such a source tree, already built it with "official contents only" and as a "Release" configuration (optimized compilation).

Windows

Multi-installers scheme

We use this one for official releases :

  • multiple NSIS packages
    1. base = demo = game core binaries and data + 1 1st class car set + 1 1st class track
    2. other official 1st class cars and tracks
    3. other official 1st class cars and tracks
    4. more official but lower quality / WIP / no AI - cars and tracks
  • the small base package is designed as a quick download and try one, a kind of demo one
  • it also enables the user to download and install the other packages in a few simple clicks

After the "make a release" loop (build, install, test, change, loop until OK), you enter here a "make the packages" loop if it was not achieved earlier : at the end, you must be happy with your packages (official contents, the game works, ...).

Once OK about the contents of the packages, you have to tweak the last detail : the release name. As it is automatically built in the game binaries (splash screen, help screens, console log) and package file names from the actual SVN version of the tree, you have to commit your last changes (to the .nsi / .nsh files in the tags/2.0.0-b1/installer/windows folder) and generate the packages one last time.

Wait a minute : for the moment, this is not fully automatic, as you need to manually tweak the SVN revision in source:tags/2.0.0-b1/installer/windows/speed-dreams.nsh :

  • look at the current revision, add 1 to it (you'll have to commit) and then set the "VER_REVISION" define (in the first lines of speed-dreams.nsh)
  • then commit these changes to tags/2.0.0-b1
  • remove the top CMakeLists.txt
  • svn update to get it back, but with updated SVN keywords inside, useful for you to get the right SVN revision in the splash screen, help screens, console log

Then, you'll be done after :

  • a full rebuild and install, as explained above in "make the release"
  • generating all of the multiple NSIS packages (through NSIS's "compile NSI script" tool)
  • a last test of these package in order to see if all's right (especially the SVN revision number ;-)

All-in-one (monolithic) NSIS binary package

We don't use it, for now, but in case it is useful to anyone, it is simple and automatically generates an executable package suitable for Windows XP, Vista and 7.

Simply build the "PACKAGE" project with MS Visual Studio.

Note: You can get different binary packages : run cmake GUI and check the PACKAGERS_BINARY variables.

Linux

Our CMake build system has some support for building Linux binary packages, based on what is configured to be built and installed (see above cmake command line options, especially the "official-only" stuff).

You can get different binary packages : run ccmake and check the PACKAGERS_BINARY variables.

To build the chosen package :

make package

Note: In order to get .deb binary packages for other platforms than Ubuntu 9.10, you'll need to change source:trunk/cmake/packagemaker.cmake

TO BE COMPLETED for each distro. ... volunteers are welcome :-)

Ubuntu

To be completed, made more step-by-step precise.

  1. build the targeted release, as explain above,
  2. 'make package' for a Ubuntu 9.10 .deb binary package.

...

Fedora

...

Mageia

...


CMake configuration

Here's the description of this configuration.

You'll find also some hints about :

  • how the whole thing works,
  • how to add a new dependency, and how to enhance an existing one,
  • how to create a new SD library or module,
  • ...

Overview

The whole game (executable, libraries, modules, and also tools) is built through a single "speed-dreams-2" CMake project, defined in the "master" (root) CMakeLists.txt (the directory of which is the target of the cmake command).

Basically, this master CMakeLists.txt :

  • includes some .cmake files for defining our specific macros and build options,
  • checks the compilation environment (mostly external dependencies),
  • does some more preparation stuff,
  • and finally tells CMake to go down the "src" and "data" sub-folder, in order to go on with the building work (more precisely "the build configuration work").

The .cmake files are located in the "cmake" sub-folder :

  • macros.cmake : the "master" macro-definition file, the only one to care with when writing a SD module or library CMakeLists.txt ; every CMakeLists.txt should include it (includes most of the other .cmake files) ;
  • options.cmake : the place where configuration / build options are defined,
  • checks.cmake : macros for checking the build environment, mostly if 3rd party libraries are there, and where ; also about some specific C-API functions (includes customthirdparty.cmake),
  • internaldeps.cmake : macros for adding internal includes dirs, link dirs and link libraries, when configuring a SD library or module (through its CMakeLists.txt),
  • thirdpartydeps.cmake : macros for adding 3rd party includes dirs, link dirs and link libraries, when configuring a SD library or module (through its CMakeLists.txt),
  • customthirdparty.cmake : macros for dealing with custom 3rd party packages, only used under Windows (detection, compilation and link against, installation of run-time binaries ... for the pre-built 3rd party packages for MSVC and MinGW : see http://sourceforge.net/projects/speed-dreams/files/3rd%20party/),
  • robot.cmake : robot modules and data management macros
  • install.cmake : install-related macros,
  • uninstall.cmake : macros for generating the "uninstall" target,
  • packagemaker.cmake : macros for dealing with CPack-generated binary and source packages (no more used, see the packaging sub-dir, and see above),
  • FindENET.cmake, FindOGG.cmake, FindPLIB.cmake, FindSOLID.cmake, FindVORBIS.cmake, FindVORBISFILE.cmake : specific FindXXX macros for detecting some 3rd party includes dirs, link dirs and link libraries (might become one day part of CMake itself, but seems they are not yet, that's why we wrote them :-)
  • FindSpeedDreams.cmake : macros installed with SD API, intended for when developing a robot without building SD from source (SD binaries as a robot development platform) ; not sure it is still working,
  • robot.def.in.cmake, config.h.in.cmake, doxygenconfig.in.cmake : template files for auto-tools-like configuration file generation (MSVC .def files for robots linking, config.h and DOxygen config. file),
  • splitargn.cmake : utility macros for writing macros with a rich argument scheme.

Writing a CMakeLists.txt

Let's not talk here about the master one, but about the others (the ones you are the most likely to update or add).

There are 3 big types :

  • for producing and installing a binary product (library, module, executable), optionally with some attached data files to install,
  • for installing only data files (no real compilation),
  • for navigating through the source tree.

As already told, you nearly always must first include macros.cmake, through the INCLUDE command, using always a relative path.

Binary product

You should normally always find the following overall scheme :

  • define the source files (often separating source and headers) needed for building the binary product,
    for this, you use simple CMake lists ; example :

    SET(TGF_HEADERS os.h tgf.h tgf.hpp modinfo.h osspec.h)
    SET(TGF_SOURCES application.cpp eventloop.cpp directory.cpp file.cpp filesetup.cpp 
                    formula.cpp hash.cpp module.cpp legacymodule.cpp modinfo.cpp os.cpp
                    params.cpp profiler.cpp schedulespy.cpp tgf.cpp trace.cpp)
    SET(TGF_OTHER_SOURCES params.dtd)
    
  • define the name and type of the binary product to build from these sources (static or shared library, executable, ...),
    for this, you use the ADD_LIBRARY or ADD_EXECUTABLE CMake command ; example :

    # Note: Other sources needed for having them available in IDEs (no use for building).
    ADD_LIBRARY(tgf SHARED ${TGF_HEADERS} ${TGF_SOURCES} ${TGF_OTHER_SOURCES})
    
  • define the internal compile-time dependencies of the binary products,
    for this, you use the ADD_SDLIB_INCLUDEDIR and/or ADD_INTERFACE_INCLUDEDIR macros (defined in trunk/cmake/internaldeps.cmake) ; example :

    ADD_INTERFACE_INCLUDEDIR()
    ADD_SDLIB_INCLUDEDIR(portability math)
    
  • list the external (3rd party) compile-time dependencies of the binary products,
    for this, you use the ADD_XX_INCLUDEDIR macros (one exists for each dependency, see trunk/cmake/thirdpartydeps.cmake) ; example :

    ADD_PLIB_INCLUDEDIR()
    ADD_SDL_INCLUDEDIR()
    
  • list the internal link-time dependencies of the binary products,
    for this, you use the ADD_SDLIB_LIBRARY macro (defined in trunk/cmake/internaldeps.cmake) ; example :

    ADD_SDLIB_LIBRARY(tgf portability txml)
    
  • list the external (3rd party) link-time dependencies of the binary products,
    for this, you use the ADD_XX_LIBRARY macros (one exists for each dependency, see trunk/cmake/thirdpartydeps.cmake) ; example :

    ADD_DL_LIBRARY(tgf)
    ADD_SDL_LIBRARY(tgf)
    ADD_EXPAT_LIBRARY(tgf) # Ignored if not OPTION_3RDPARTY_EXPAT
    
  • explain where to install the binary product,
    for this, you use the SD_INSTALL_FILES macro ; example :

    SD_INSTALL_FILES(BIN TARGETS tgf) # Install CMake target "tgf" in the binary folder.
    
  • optionally, explain what data files to install, and where,
    for this, you also use the SD_INSTALL_FILES macro ; example :

    SD_INSTALL_FILES(INCLUDE FILES ${TGF_HEADERS})
    SD_INSTALL_FILES(DATA config FILES params.dtd)
    

Notes:

  • a CMakeLists.txt sometimes "produces" more than 1 binary.
  • you sometimes need more that the above scheme :
    • some specific pre-processor definitions (ex: -DXXX_exports under Windows for DLLs) or compilation options,
    • some CMake commands to disable warnings,
    • some compiler / plate-form-specific stuff.

Simple library

No specific configuration, the above overall scheme perfectly fits.

Simple shared and static libraries are to be installed in the $SD_BINDIR folder, as specified by the "BIN" argument of the SD_INSTALL_FILES macro (a CMake cache variable / advanced option you can check / change at configure time).

See src/libs/tgf or tgfclient or portability for working examples.

Executable

The game main executable (src/main) has one specific configuration trick : it takes care of installing the 3rd party and MS CRT DLLs along with its binary file under Windows (this is done through the SD_INSTALL_CUSTOM_3RDPARTY macro, defined in trunk/cmake/customthirdparty.cmake).

Other executable (src/tools) don't care about that (assuming the main executable has been installed, and thus that their (same) 3rd party dependencies have been installed already).

Just like shared and static libraries, executables are to be installed in the $SD_BINDIR folder, as specified by the "BIN" argument of the SD_INSTALL_FILES macro.

Non-robot module

Works just like a simple (but "shared") library, except that the shared library binary file name must not have the standard "lib" prefix under Linux / MinGW ;
that's why, as an example for modules/graphic/ssggraph :

IF(UNIX OR MINGW)
    SET_TARGET_PROPERTIES(ssggraph PROPERTIES PREFIX "")
ENDIF()

Note also that the module binary has to be installed in $SD_LIBDIR/modules/<category>, as specified by the "LIB" argument of the SD_INSTALL_FILES macro ;
example :

SD_INSTALL_FILES(LIB modules/graphic TARGETS ssggraph)

See src/modules/<category>/* for working examples.

Robot module

Robot modules are a bit more complicated, and their CMakeLists.txt does not follow the above detailed scheme.

A couple of macros actually make it simpler for the robot developer ; hence the following scheme :

  • define the source files needed for building the robot library,
    for this, you use simple CMake lists ; example :

    SET(ROBOT_SOURCES 
        src/unitcarparam.cpp
        src/unitcarparam.h
        src/unitcharacteristic.cpp
        src/unitcharacteristic.h
        src/unitclothoid.cpp
        src/unitclothoid.h
        ...)
    
  • define the robot library interface to SD,
    for this, you use simple CMake lists ; example :

    # Simplix library displays at the same time a "legacy" (TORCS) and the modern "welcome" (SD) one ;
    # and it takes care of multiple sets of drivers (SC A, SC B, 36GP, LS1, MP5, ...)
    SET(ROBOT_INTERFACE LEGACY WELCOME
                        simplix_sca simplix_scb 
                        simplix_36GP 
                        simplix_ls1 
                        simplix_mp5 
                        ...)
    
  • define the file names of the robot module DLL clones
    for this, you use simple CMake lists ; example (1 clone for each car category here) :

    SET(ROBOT_CLONES simplix_36GP simplix_sc simplix_trb1 simplix_ls1 simplix_ls2 simplix_mp5 simplix_lp1)
    
  • define the robot module (1 DLL, cloned as many times as needed),
    for this, you use the ROBOT_MODULE macro (defined in trunk/cmake/robot.cmake) ; example :

    # The ubiquitous robot module and its clones.
    ROBOT_MODULE(NAME simplix VERSION 3.3.0 SOVERSION 1.0.0
                 INTERFACE ${ROBOT_INTERFACE}
                 SOURCES ${ROBOT_SOURCES}
                 CLONENAMES ${ROBOT_CLONES})
    
  • then, for each DLL clone, define the data files to install and where,
    for this, you use the ROBOT_DATA macro (defined in trunk/cmake/robot.cmake) ; example :

    SET(ROBOT_SUBDIRS 0 1 2 3 4 5 6 7 8 9
                      36gp-ettore-t59 36gp-milano-12c36 36gp-silber-w25b 
                      36gp-tridenti-6c34 36gp-tridenti-v8ri
                      tracks)
    
    ROBOT_DATA(NAME simplix_36GP PREFIX simplix_36GP 
               FILES simplix_36GP.xml default.xml logo.rgb readme.txt
               SUBDIRS ${ROBOT_SUBDIRS} PATTERNS *.xml logo.rgb *.png *.jpg)
    

Note: A robot module also has to be installed in $SD_LIBDIR/drivers/<robot>, but that's transparent in the CMakeLists.txt, thanks to the ROBOT_MODULE macro.

See src/drivers/simplix, or usr or kilo2008 for working examples.

Data

We are dealing here with the CMakeLists.txt of the "data" tree under trunk.

Car data files

The "sources" for a car are located in a dedicated folder (data/cars/models/<model name>) ; the CMakeLists.txt is very simple, as it only use 1 macro for installing everything needed : SD_INSTALL_CAR (defined in install.cmake).

Example:

SD_INSTALL_CAR(36gp-century-r11b readme.txt)

These car data files are actually installed in $SD_DATADIR/cars/models/<model name>.

Track data files

The "sources" for a track are also located in a dedicated folder (data/tracks/<category>/<track name>) ; the CMakeLists.txt is very simple, as it only use 1 macro for installing everything needed : SD_INSTALL_TRACK (defined in install.cmake).

Example:

SD_INSTALL_TRACK(karwada circuit readme.txt)

These track data files are actually installed in $SD_DATADIR/tracks/<category>/<track name>.

Other data files

For any other data source folder, we use the generic SD_INSTALL_FILE macro (defined in trunk/cmake/install.cmake).

Example (for the data/data/img folder) :

FILE(GLOB _PNG_FILES *.png)
FILE(GLOB _JPG_FILES *.jpg)

# Work-in-progress / unofficial contents (network menus background images).
IF(OPTION_OFFICIAL_ONLY)
    FILE(GLOB _REMOVE_FILES splash-network*.jpg)
    LIST(REMOVE_ITEM _JPG_FILES ${_REMOVE_FILES} )
ENDIF(OPTION_OFFICIAL_ONLY)

SD_INSTALL_FILES(DATA data/img FILES ${_PNG_FILES} ${_JPG_FILES})

Note that the files are to be installed in the specified sub-folder (after the "DATA" argument) of the $SD_DATADIR folder.

You basically only use the ADD_SUBDIRECTORY CMake command or the SD_ADD_SUBDIRECTORY macro, for each sub-directory to configure.

Example:

SD_ADD_SUBDIRECTORY(aalborg)
SD_ADD_SUBDIRECTORY(brondehach)
SD_ADD_SUBDIRECTORY(chemisay)

SD_ADD_SUBDIRECTORY prevents the configuration to fail if the target folder doesn't exists (and if OPTION_CHECK_CONTENTS CMake option if Off), so you should use it everywhere unless the target folder is really really a mandatory one (data ones are generally not, while most libraries and executables are).

How to …

Add a new 3rd party dependency

Basically, a 3rd party dependency is a set / package of external libraries coming with their header files, in order you can compile and link a SD library or executable with them.

Here are the steps to complete :

  1. Find<dependency name>.cmake : the new 3rd party dependency may or may not be automatically detected by CMake ; look in the CMake installation folders, in the "Modules" sub-folder, for a Find<dependency name>.cmake file ; if it is there, you're a lucky SD developer, you only need to use it ; if not, you'll have to write it yourself, and put it in SD's cmake folder, aside the others ; look at the existing ones and use as a template the one you consider the closest of your needs ; please note that this FindXXX.cmake will hardly be used under Windows when building with MSVC or QtCreator?, but that it must be interface-level consistent with the alternative detection code in the _FIND_3RDPARTY_DEPENDENCIES macro defined in customthirdparty.cmake.
  2. checks.cmake : you have to add a block of code in the CHECK_LIBRARIES for detecting the new dependency ; a simple copy of the OpenAL one should be enough most of the time :

    # OpenAL
    Find_Package(OpenAL)
    IF(OPENAL_FOUND)
      SET(HAVE_LIBOPENAL 1)
      MESSAGE(STATUS "Looking for library OpenAL - found")
    ELSE(OPENAL_FOUND)
      MESSAGE(STATUS "Looking for library OpenAL - NOT found")
    ENDIF(OPENAL_FOUND)
    
  3. thirdpartydeps.cmake : now you have to create 2 macros for making it easy to compile and link a SD library or executable against the new libraries : ADD_<new dependency>INCLUDEDIR for the include directories, and ADD<new dependency>_LIBRARY for the target link libraries ; example, for the OpenAL library :

    MACRO(ADD_OPENAL_INCLUDEDIR)
    
      FIND_PACKAGE(OpenAL)
    
      IF(OPENAL_FOUND)
        INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIR})
      ELSE(OPENAL_FOUND)
        MESSAGE(FATAL_ERROR "Cannot find OpenAL header files")
      ENDIF(OPENAL_FOUND)
    
    ENDMACRO(ADD_OPENAL_INCLUDEDIR)
    
    MACRO(ADD_OPENAL_LIBRARY TARGET)
    
      FIND_PACKAGE(OpenAL)
    
      IF(OPENAL_FOUND)
        TARGET_LINK_LIBRARIES(${TARGET} ${OPENAL_LIBRARIES})
      ELSE(OPENAL_FOUND)
        MESSAGE(FATAL_ERROR "Cannot find OpenAL libraries")
      ENDIF(OPENAL_FOUND)
    
    ENDMACRO(ADD_OPENAL_LIBRARY TARGET)
    
  4. customthirdparty.cmake : only useful under Windows, but, as SD must build also under these plate-forms, you'll need to do something here even if you're working under Linux ;

    • detection : you'll generally need to add 1 _FIND_3RDPARTY_DEPENDENCY line in the _FIND_3RDPARTY_DEPENDENCIES macro for each target link library of the new package
    • run-time installation : you'll generally need to add 1 _FIND_3RDPARTY_DLL line in the SD_INSTALL_CUSTOM_3RDPARTY macro for each DLL needed at run-time due to the new package (beware that some such DLLs may not appear in the link-time dependencies, like plugin DLLs, or simply 2nd level dependencies) ; example (for the PNG dependency) :

      _FIND_3RDPARTY_DLL("${PNG_LIBRARY}" "png" "lib" _DLL_PATHNAME)
      LIST(APPEND _THIRDPARTY_DLL_PATHNAMES "${_DLL_PATHNAME}")
      
  5. 3rd party binary package : of course, you'll have to find a way to enable the developers to get the header and binary files for their build chain ; under Linux, it's mostly a question of dev package installation (easy) ; under Windows, it's more complicated : you'll probably have to enhance the 3rd party binary package(s) shipped here by compiling from source the new dependency ! Then, don't forget to update the source package, and the installation instructions.

  6. CMakeLists.txt : finally, you of course need to tell CMake :
    • where to find the new header files (through the newly added ADD_XXX_INCLUDEDIRS macro in thirdpartydeps.cmake),
    • where to find the new libraries, and how they are named (through the newly added ADD_XXX_LIBRARY macro in thirdpartydeps.cmake).

Enhance an existing dependency

Some dependencies feature multiple libraries, or even plug-ins.

When you need to add a new target link library / include dir. to an existing dependency, you have to :

  1. detection for compile and link-time :

    1. possibly enhance the SD-specific (if any) Find<dependency>.cmake in order it also finds this new library,
    2. sometimes, add the new library to the calls to FindPackage(<dependency>), in macro. CHECK_LIBRARIES defined in check.cmake, and in macros ADD_<dependency>INCLUDEDIR and ADD<dependency>_LIBRARY in thirdpartydeps.cmake),
      example (for OpenSceneGraph):

      Find_Package(OpenSceneGraph REQUIRED osgDB osgViewer osgGA osgUtil osgFX)
      
    3. always, add a call to _FIND_3RDPARTY_DEPENDENCY in the _FIND_3RDPARTY_DEPENDENCIES macro. defined in customthrirdparty.cmake
      example (for OpenSceneGraph):

      _FIND_3RDPARTY_DEPENDENCY(OSGFX osgFX/version "" osgFX ${ROOT_DIR} "")
      
  2. installation for run-time :

    1. DLLs associated with target link libraries : always, add the new library / include dir. to the call to the _FIND_3RDPARTY_DLL macro in the SD_INSTALL_CUSTOM_3RDPARTY macro. defined in customthrirdparty.cmake
      example (for OpenSceneGraph):

      # DLLs whose libs we link with.
      SET(_OSG_DLLS_NAME_HINTS "OpenThreads;osgDB;osgFX;osgGA;osgViewer;osgUtil;osg") # <===== sure here (new DLL name, without a pre- or suf-fix)
      FOREACH(_LIB_NAME ${OPENSCENEGRAPH_LIBRARIES})
        FOREACH(_NAME_HINT ${_OSG_DLLS_NAME_HINTS})
          IF("${_LIB_NAME}" MATCHES "${_NAME_HINT}\\.")
            _FIND_3RDPARTY_DLL("${_LIB_NAME}" "${_NAME_HINT}" "lib;ot12-;osg80-" _DLL_PATHNAME) # <==== May be here (possibly another DLL prefix)
            SET(_NAME_HINT_ "${_NAME_HINT}") # For later (see below DLLs we don't link with).
            SET(_LIB_NAME_ "${_LIB_NAME}") # For later (see below DLLs we don't link with).
            SET(_DLL_PATHNAME_ "${_DLL_PATHNAME}") # For later (see below plugins).
            BREAK()
          ENDIF()
        ENDFOREACH()
        LIST(APPEND _THIRDPARTY_DLL_PATHNAMES "${_DLL_PATHNAME}")
      ENDFOREACH()
      Find_Package(OpenSceneGraph REQUIRED osgDB osgViewer osgGA osgUtil osgFX)
      
    2. DLLs associated with non-target link libraries (2nd level dependencies, plug-ins, ...) : always, add the new library to the call to the _FIND_3RDPARTY_DLL macro in the SD_INSTALL_CUSTOM_3RDPARTY macro. defined in customthrirdparty.cmake
      example, for OpenSceneGraph osgText, a DLL we need at run-time but don't link with):

      # Other needed DLLs we don't link with.
      # We use _LIB_NAME_ as a template, and _NAME_HINT_ as the string to replace inside. 
      SET(_EXTRA_OSG_DLLS_NAME_HINTS "osgText") # ';'-separated list   <===== sure here (new DLL name, without a pre- or suf-fix)
      FOREACH(_NAME_HINT ${_EXTRA_OSG_DLLS_NAME_HINTS})
        STRING(REPLACE "${_NAME_HINT_}" "${_NAME_HINT}" _LIB_NAME "${_LIB_NAME_}")
        _FIND_3RDPARTY_DLL("${_LIB_NAME}" "${_NAME_HINT}" ";lib;ot12-;osg80-" _DLL_PATHNAME) # <==== May be here (possibly another DLL prefix)
        LIST(APPEND _THIRDPARTY_DLL_PATHNAMES "${_DLL_PATHNAME}")
      ENDFOREACH()
      

example, for OpenSceneGraph plug-ins :

        # Plugins : Complete the list right below according to the actual needs.
        # TODO: Find a way to install them in the osgPlugins-xxx subdir (works as is, but ...)
        SET(_OSG_PLUGIN_NAME_HINTS "glsl;jpeg;png;rgb") # ';'-separated list  <===== sure here (new plug-in name, without a pre- or suf-fix)
        GET_FILENAME_COMPONENT(_OSG_PLUGINS_DIR "${_DLL_PATHNAME_}" PATH)
        FILE(GLOB_RECURSE _OSG_PLUGIN_NAMES "${_OSG_PLUGINS_DIR}/*${CMAKE_SHARED_LIBRARY_SUFFIX}")
        FOREACH(_NAME_HINT ${_OSG_PLUGIN_NAME_HINTS})
          FOREACH(_PLUGIN_NAME ${_OSG_PLUGIN_NAMES})
            IF("${_PLUGIN_NAME}" MATCHES "osgPlugins.*/.*${_NAME_HINT}\\.")
              LIST(APPEND _THIRDPARTY_DLL_PATHNAMES "${_PLUGIN_NAME}")
              MESSAGE(STATUS "Will install 3rdParty plugin ${_PLUGIN_NAME}")
              BREAK()
            ENDIF()
          ENDFOREACH()
        ENDFOREACH()

Related

Wiki: Home
Wiki: Index

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.