Basic Path Setup
If we restructure our project thus:
.
├── SConstruct
├── src
│ └── main.c
└── support
├── message.c
└── message.h
We need to change two build parameters:
Source files
Changing our SConstruct
to find the files is simply a matter of adding the directory path, e.g.
sources=['src/main.c', 'support/message.c']
Program(target = exe, source = sources)
But the build will fail, e.g.:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o src/main.o -c src/main.c
src/main.c:1:10: fatal error: 'message.h' file not found
#include "message.h"
^~~~~~~~~~~
1 error generated.
scons: *** [src/main.o] Error 1
as the build system cannot message.h
in the default search path.
Search path Include
The construction variable CPPPATH
is a list of directories that the C preprocessor will search for include directories. We can simple add our required directory to the variable.
However, to do this, it is best to create an Environment variable (the benefit of this will become more obvious later, but for now just accept this).
We do this by adding the line:
env = Environment()
to the head of the SConstruct
file.
Next we can append the required search path for our needed header file:
env.Append(CPPPATH = ["support"])
Finally, we modify the build step to use the context of the environment:
env.Program(target = exe, source = sources)
So our complete SConstruct
looks thus:
env = Environment()
env.Append(CPPPATH = ["support"])
exe = 'hello'
sources = ['src/main.c', 'support/message.c']
env.Program(target = exe, source = sources)
When we build:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o src/main.o -c -Isupport src/main.c
gcc -o support/message.o -c -Isupport support/message.c
gcc -o hello src/main.o support/message.o
scons: done building targets.
we can see the -Isupport
added to the compilation step.
When more than one include directory is needed, simply create a comma separated list, e.g.
env.Append(CPPPATH = ["support", "dir1", "dir2", ])
or:
project_includes = ["support", "dir1", "dir2"]
env.Append(CPPPATH = project_includes)
or even:
project_includes = [
"support",
"dir1",
"dir2"
]
env.Append(CPPPATH = project_includes)
depending on your persuasion!
Relative vs Absolute paths
A worthwhile practice is to force scons
to look-up a directory relative to the root of the source tree by using #
at the start of the path, e.g.
project_includes = [
"#/support",
"#/dir1",
"#/dir2"
]
env.Append(CPPPATH = project_includes)
Again, the benefit of this approach will become apparent later.
Source file lookup alternative
earlier we discussed using with the Glob
pattern matching or the explicit list model. Of course we could combine the two, e.g.
sources = ['src/main.c']
sources += Glob('support/*.c')
env.Program(target = exe, source = sources)