Project construction made easy with SCons
In the following lines you find tips help you start with building C++ programs using SCons project construction tool under Linux.
tip: SCons package can be installed with
sudo apt install sconscommand.
content
basics
SCons is super easy to start with you need to know only three thinks. The first one, scons command to start a building process (from project root directory), scons -c command for project clean-up and that SCons build file is called SConstruct. The most simplest SConstruct file can looks like this
Program('main.cpp')
Yes, that is all! I’ve told you it’s super easy. SCons will take main.cpp source file and create main executable from it. We are now ready to build something, go to basic/ directory and execute scons by
cd basic
scons
commands to see SCons in action. The main output should looks like this
$ ./main
done!
don’t forget to test
scons -ccommand to clean-up the sample directory
compiler settings
Let’s say we want to force building against C++17 standard and also turn on all compiler warnings. To do that, we can adjust compiler options with Environment variable this way
cpp17 = Environment(CCFLAGS=['-std=c++17', '-Wall'])
cpp17.Program('main.cpp')
go to
environment/directory and runsconsto buildmainexecutable to see SCons with modified environment in action
There is not only CCFLAGS construction variable there but many others like
CCFLAGSgeneral options passed to the c and c++ compilersCPPPATHthe list of directories that the c preprocessor will search for include directories.LIBSlist of libraries that will be linkedLIBPATHthe list of directories that will be searched for libraries (use#to indicate absolute pathLIBPATH='#/libs')CPPDEFINESc/c++ preprocessor definitions
full list of construction variables can be found there
tip: we don’t need to remember all that construction variable names, there is a shortcut there we can use
parse_flagsargument this wayEnvironment(parse_flags='-std=c++17 -Wall -g -O0')
advanced tip: building with clang instead of gcc can be done by setting
CXXconstruction variable toCXX='clang++'
more source files
In some cases there are more source files there like in 3dmath sample (we have main.cpp and vectors.cpp source files there) we can use Python’s list instead of single string in a Program() builder like this
Program(['main.cpp', 'vector.cpp'])
We can makes our lives even easier with Glob(PATTERN) helper function and build all cpp files in a directory with
Program('3dmath', Glob('*.cpp'))
'3dmath'is explicitly used there as a name for program executable, feel free to change it
tip: to speed up whole building process on multicore machines we can call SCons with
-jNoption like thisscons -j4, whereNrepresents number of parallel jobs
third party dependencies
Let’s render a triangle with OpenGL ES2 and GLFW libraries, like in triangle sample. We need to create SConstruct with OpenGL ES2 and GLFW library dependencies to get our sample working.
In Linux there is almighty pkg-config there to help us with the task.
before we can continue we need to install GLFW, OpenGL ES2 libraries and pkg-config itself with
sudo apt install libglfw3-dev libgles2 pkg-configcommand
Build environment can parse pkg-config output with ParseConfig() function this way
cpp17.ParseConfig('pkg-config --cflags --libs glfw3 glesv2')
tip: we can use
pkg-config --list-all | grep -i LIBRARYcommand to search for GLFW and OpenGL ES2 libraries, under Ubuntu 20.04 LTS they are there as glfw3 and glesv2
Now the last think needed to be done is to tell GLFW library we want render with OpenGL ES2 (not OpenGL). It can be done with GLFW_INCLUDE_ES2 define so we need to change CPPDEFINES construction variable for our environment. Final SConstruct file will looks like this
cpp17 = Environment(
CCFLAGS=['-std=c++17', '-Wall', '-O0', '-g'],
CPPDEFINES=['GLFW_INCLUDE_ES2'])
cpp17.ParseConfig('pkg-config --cflags --libs glfw3 glesv2')
cpp17.Program('triangle.cpp')
We are done, go to triangle/ directory and run scons from konsole to see it is working.
see OGRE starter or cube rain repositories for more SCons samples
static library
It is a good practise to group domain specific code into a library like in a physics sample. I’ve moved sample physics engine from great Game Physics Cookbook into a phys/ directory and want to use it from my project as a static library. In SCons it is super easy to do that with StaticLibrary() builder and Glob() function, like this
cpp17 = Environment(
CXX='clang++', CCFLAGS=['-std=c++17', '-Wall'])
cpp17.ParseConfig('pkg-config --cflags --libs glfw3 gl')
phys = cpp17.StaticLibrary('phys', Glob('phys/*.cpp'))
cpp17.Program('physics', ['main.cpp', phys])
note: We need to use clang there, because physics library use non-standard C++ language feature not supported by GCC. Install clang with
sudo apt install clangcommand.
tip: there are also builders for shared libraries
SharedLibrary()and object filesObject()
install command
Sometimes it can be handy to provide install command so project can be automatically installed to proper destination without too much effort from user side. In SCons install process can be done with Install() builder and Alias() function this way
target_dir = '/opt/foo'
cpp.Install(target_dir, main)
cpp.Alias('install', target_dir)
see full SConstruct file version
Now we can type scons install to install main executable to /opt/foo directory.
tip: in case you don’t have write access to
/optdirectory, use--install-sandboxoption to prefix target directory likescons --install-sandbox=/home/adam installto installmainexecutable to/home/adam/opt/fooinstead of/opt/foodirectory
Maybe, you are asking yourself whether uninstall is also possible? Yes, it is! We’ve got uninstall for free, we can type scons -c install which will uninstall main executable from /opt/foo directory.
reference
List of SCons comands can be found there.