I am writing something like an interactive tutorial for C++. The tutorial will consist of two parts: one is compiled into a library (I’m using Scons to build that), and the other (the lessons) is shipped with the tutorial to be compiled by the end user. I’m currently looking for a good, easy way for people to build these lessons.
Basically, the second part is a directory with all the lessons in it, each in its own directory. Each lesson will have at least a lesson.cpp and a main.cpp file, there may be also other files, the existence of which I will not know until after it is shipped — the end user will create these. It will look something like this:
all_lessons/
helloworld/
lesson.cpp
main.cpp
even_or_odd/
lesson.cpp
main.cpp
calculator/
lesson.cpp
main.cpp
user_created_add.cpp
Each of these will need to be compiled according to almost the same rules, and the command for compiling should be possible to run from one of the lesson directories (helloworld/, etc.).
Seeing as the rest of the project is built with Scons, it would make sense to use it for this part, too. However, Scons searches for the SConstruct file in the directory it is run from: would it be acceptable to put a SConstruct file in each lesson directory, plus a SConscript in the all_lessons/ directory that gives the general rules? This seems to go against the typical way Scons expects projects to be organised: what are the potential pitfalls of this approach? Could I put a SConstruct file instead of the SConscript one, and thereby make it possible to build from either directory (using exports to avoid endless recursion, I’m guessing)?
Also, I may at some point want to replace the lesson.cpp with a lesson.py that generates the necessary files; will Scons allow me to do this easily with builders, or is there a framework that would be more convenient?
In the end, I want to end up with the following (or equivalent with different build systems):
all_lessons/
SConstruct
helloworld/
SConstruct
lesson.cpp
main.cpp
even_or_odd/
SConstruct
lesson.py
main.cpp
calculator/
SConstruct
lesson.cpp
main.cpp
user_created_add.cpp
Running scons all in the all_lessons directory would need to:
- Run
even_or_odd/lesson.pyto generateeven_or_odd/lesson.cpp. - Realise that
user_created_add.cppalso needs to be compiled. - Produce an executable for each lesson.
Running scons in even_or_odd/, or scons even_or_odd in all_lessons/ should produce an executable identical to the one above (same compile flags).
Summary:
- Is Scons suitable for/capable of this?
- Does Scons work well when
SConscriptfiles are aboveSConstructfiles? - Does Scons work well with multiple
SConstrcutfiles for one project, SConscripting each other? - Is the Scons builder system suitable for using Python scripts to generate C++ files?
- Is there any advantage of using a different build system/writing my own build framework that I’m missing?
Any further comments are, of course, welcome.
Thanks.
You can actually do this with a few lines of GNU Make.
Below are two makefiles that allow building and cleaning from
all_lessonsdirectory and individual project directories. It assumes that all C++ sources in that directory comprise an executable file which gets named after its directory. When building and cleaning from the top level source directory (all_lessons) it builds and cleans all the projects. When building and cleaning from a project’s directory it only builds and cleans the project’s binaries.These makefiles also automatically generate dependencies and are fully parallelizable (
make -jfriendly).For the following example I used the same source file structure as you have:
To be able to build from individial project directories
project.mkmust be symlinked asproject/MakefilefirstLet’s build one project:
Now build all projects:
Clean one project:
Clean all projects:
The makefiles: