Reputation: 13
I am trying to build a C++ module that contains multiple libraries and executable programs.
The basic (directory) structure is as follows:
module
module/lib1
module/lib2
module/prog1
module/prog2
Let us assume that prog1 uses lib1 only, and prog2 uses both lib1 and lib2. Both libs require certain additions to construction variables like include and library paths, preprocessor defines etc.
I am looking for a way where the SConscript files in the lib* directories can specify what has to be added to the construction environments of the programs using these libraries.
Here is what I have now, following chapter 14.5 of the scons documentation (for simplicity, using CPPDEFINES only):
module/SConstruct:
env = Environment();
env.Append(CPPDEFINES = 'GLOBAL_DEFINE')
Export('env')
use_lib1 = SConscript(['lib1/SConscript'])
use_lib2 = SConscript(['lib2/SConscript'])
Export('use_lib1', 'use_lib2')
SConscript(['prog1/SConscript'])
SConscript(['prog2/SConscript'])
module/lib1/SConscript:
Import ('*')
def use_lib1(i_environment):
i_environment.Append(CPPDEFINES = 'DEFINE_FOR_LIB1')
Return('use_lib1')
module/lib2/SConscript:
Import ('*')
def use_lib2(i_environment):
i_environment.Append(CPPDEFINES = ['DEFINE_FOR_LIB2'])
Return('use_lib2')
module/prog1/SConscript:
Import ('*')
prog1_env = env.Clone()
use_lib1(prog1_env)
print "PROG1: CPPDEFINES = " + str(prog1_env['CPPDEFINES'])
module/prog2/SConscript:
Import ('*')
prog2_env = env.Clone()
use_lib1(prog2_env)
use_lib2(prog2_env)
print "PROG2: CPPDEFINES = " + str(prog2_env['CPPDEFINES'])
This setup seems to work correctly, but also a bit cumbersome.
Question: Is there any more straightforward way to achieve the desired goal?
Upvotes: 1
Views: 180
Reputation: 3509
You can use a PseudoBuilder to add use_lib1 to your Environment.
See: https://scons.org/doc/production/HTML/scons-user/ch20.html
This would removed the need to pass use_lib1, etc around.
You could do something like:
Import ('*')
env.Program('myprogram',['source1.c','source2.c'],CPPDEFINES=env['CPPDEFINES']+env.lib1_cppdefines()+env.lib2_cppdefines())
You could define a PseudoMethod to do more where each lib would add to env:
env['LIB1_CPPDEFINES']=['LIB1','LIB1_AWESOME']
env['LIB1_LIBS']=['LIB1','LIB1_AWESOME']
And then the PseudoBuilder (in your SConstruct, or logic in site_scons/site_init.py):
def LibProgram(env, target, sources, libs=None):
LIBS=env.get('LIBS',[])
CPPDEFINES=env.get('CPPDEFINES',[])
for lib in libs:
LIBS.extend(env.get('%s_LIBS'%lib,[])
CPPDEFINES.extend(env.get('%s_CPPDEFINES'%lib,[])
return env.Program(target,sources, CPPDEFINES=CPPDEFINES, LIBS=LIBS)
env.AddMethod(LibProgram, "LibProgram")
Then your prog2/SConscript would be:
Import ('*')
env.LibProgram('prog2',prog2_sources,libs=['lib1','lib2'])
Lots of different ways to do this with less verbose SConscripts.
Upvotes: 1