13 EnsureSConsVersion(0, 96)
20 # Command-line options
23 opts = Options('scache.conf')
25 BoolOption('ALTIVEC', 'Compile using Altivec instructions', 0),
26 ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
27 BoolOption('SYSLIBS', 'USE AT YOUR OWN RISK: CANCELS ALL SUPPORT FROM ARDOUR AUTHORS: Use existing system versions of various libraries instead of internal ones', 0),
28 BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
29 PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
30 BoolOption('DEVBUILD', 'Use shared libardour (developers only)', 0),
31 BoolOption('SIGCCVSBUILD', 'Use if building sigc++ with a new configure.ac (developers only)', 0),
32 BoolOption('NLS', 'Set to turn on i18n support', 1),
33 BoolOption('NOARCH', 'Do not use architecture-specific compilation flags', 0),
34 PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
35 BoolOption('VST', 'Compile with support for VST', 0),
36 BoolOption('VERSIONED', 'Add version information to ardour/gtk executable name inside the build directory', 0),
37 BoolOption('USE_SSE_EVERYWHERE', 'Ask the compiler to use x86/SSE instructions and also our hand-written x86/SSE optimizations when possible (off by default)', 0),
38 BoolOption('BUILD_SSE_OPTIMIZATIONS', 'Use our hand-written x86/SSE optimizations when possible (off by default)', 0)
41 #----------------------------------------------------------------------
42 # a handy helper that provides a way to merge compile/link information
43 # from multiple different "environments"
44 #----------------------------------------------------------------------
46 class LibraryInfo(Environment):
47 def __init__(self,*args,**kw):
48 Environment.__init__ (self,*args,**kw)
50 def Merge (self,others):
52 self.Append (LIBS = other.get ('LIBS',[]))
53 self.Append (LIBPATH = other.get ('LIBPATH', []))
54 self.Append (CPPPATH = other.get('CPPPATH', []))
55 self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
58 env = LibraryInfo (options = opts,
61 TARBALL='ardour-' + version + '.tar.bz2',
63 DISTTREE = '#ardour-' + version,
64 DISTCHECKDIR = '#ardour-' + version + '/check'
68 #----------------------------------------------------------------------
70 #----------------------------------------------------------------------
72 # Handy subst-in-file builder
75 def do_subst_in_file(targetfile, sourcefile, dict):
76 """Replace all instances of the keys of dict with their values.
77 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
78 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
81 f = open(sourcefile, 'rb')
85 raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
86 for (k,v) in dict.items():
87 contents = re.sub(k, v, contents)
89 f = open(targetfile, 'wb')
93 raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
96 def subst_in_file(target, source, env):
97 if not env.has_key('SUBST_DICT'):
98 raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
99 d = dict(env['SUBST_DICT']) # copy it
100 for (k,v) in d.items():
102 d[k] = env.subst(v())
103 elif SCons.Util.is_String(v):
106 raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
107 for (t,s) in zip(target, source):
108 return do_subst_in_file(str(t), str(s), d)
110 def subst_in_file_string(target, source, env):
111 """This is what gets printed on the console."""
112 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
113 for (t,s) in zip(target, source)])
115 def subst_emitter(target, source, env):
116 """Add dependency from substituted SUBST_DICT to target.
117 Returns original target, source tuple unchanged.
119 d = env['SUBST_DICT'].copy() # copy it
120 for (k,v) in d.items():
122 d[k] = env.subst(v())
123 elif SCons.Util.is_String(v):
125 Depends(target, SCons.Node.Python.Value(d))
126 # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
127 return target, source
129 subst_action = Action (subst_in_file, subst_in_file_string)
130 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
133 # internationalization
138 # this is not a builder. we can't list the .po files as a target,
139 # because then scons -c will remove them (even Precious doesn't alter
140 # this). this function is called whenever a .mo file is being
141 # built, and will conditionally update the .po file if necessary.
144 def po_helper(po,pot):
150 print 'Updating ' + po
151 return os.spawnvp (os.P_WAIT, 'msgmerge', args)
153 # mo_builder: builder function for (binary) message catalogs (.mo)
155 # first source: .po file
156 # second source: .pot file
159 def mo_builder(target,source,env):
160 po_helper (source[0].get_path(), source[1].get_path())
164 target[0].get_path(),
167 return os.spawnvp (os.P_WAIT, 'msgfmt', args)
169 mo_bld = Builder (action = mo_builder)
170 env.Append(BUILDERS = {'MoBuild' : mo_bld})
172 # pot_builder: builder function for message templates (.pot)
174 # source: list of C/C++ etc. files to extract messages from
177 def pot_builder(target,source,env):
182 '-o', target[0].get_path(),
183 "--default-domain=" + env['PACKAGE'],
184 '--copyright-holder="Paul Davis"' ]
185 args += [ src.get_path() for src in source ]
187 return os.spawnvp (os.P_WAIT, 'xgettext', args)
189 pot_bld = Builder (action = pot_builder)
190 env.Append(BUILDERS = {'PotBuild' : pot_bld})
193 # utility function, not a builder
196 def i18n (buildenv, sources, installenv):
197 domain = buildenv['PACKAGE']
198 potfile = buildenv['POTFILE']
200 installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
202 p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
203 languages = [ po.replace ('.po', '') for po in p_oze ]
204 m_oze = [ po.replace (".po", ".mo") for po in p_oze ]
207 po = 'po/' + mo.replace (".mo", ".po")
208 installenv.Alias ('install', buildenv.MoBuild (mo, [ po, potfile ]))
210 for lang in languages[:]:
211 modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
212 moname = domain + '.mo'
213 installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
216 # A generic builder for version.cc files
218 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
219 # note: assumes one source files, the header that declares the version variables
221 def version_builder (target, source, env):
222 text = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
223 text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
224 text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
227 o = file (target[0].get_path(), 'w')
231 print "Could not open", target[0].get_path(), " for writing\n"
234 text = "#ifndef __" + env['DOMAIN'] + "_version_h__\n";
235 text += "#define __" + env['DOMAIN'] + "_version_h__\n";
236 text += "extern int " + env['DOMAIN'] + "_major_version;\n"
237 text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
238 text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
239 text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n";
242 o = file (target[1].get_path(), 'w')
246 print "Could not open", target[1].get_path(), " for writing\n"
251 version_bld = Builder (action = version_builder)
252 env.Append (BUILDERS = {'VersionBuild' : version_bld})
255 # a builder that makes a hard link from the 'source' executable to a name with
256 # a "build ID" based on the most recent CVS activity that might be reasonably
257 # related to version activity. this relies on the idea that the SConscript
258 # file that builds the executable is updated with new version info and committed
259 # to the source code repository whenever things change.
262 def versioned_builder(target,source,env):
263 # build ID is composed of a representation of the date of the last CVS transaction
264 # for this (SConscript) file
267 o = file (source[0].get_dir().get_path() + '/CVS/Entries', "r")
269 print "Could not CVS/Entries for reading"
273 lines = o.readlines()
275 if line[0:12] == '/SConscript/':
276 parts = line.split ("/")
282 print "No SConscript CVS update info found - versioned executable cannot be built"
285 tag = time.strftime ('%Y%M%d%H%m', time.strptime (last_date));
286 print "The current build ID is " + tag
288 tagged_executable = source[0].get_path() + '-' + tag
290 if os.path.exists (tagged_executable):
291 print "Replacing existing executable with the same build tag."
292 os.unlink (tagged_executable)
294 return os.link (source[0].get_path(), tagged_executable)
296 verbuild = Builder (action = versioned_builder)
297 env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
300 # source tar file builder
303 def distcopy (target, source, env):
304 treedir = str (target[0])
308 except OSError, (errnum, strerror):
309 if errnum != errno.EEXIST:
310 print 'mkdir ', treedir, ':', strerror
314 # we don't know what characters might be in the file names
315 # so quote them all before passing them to the shell
317 all_files = ([ str(s) for s in source ])
318 cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
319 cmd += ' | (cd ' + treedir + ' && tar xf -)'
323 def tarballer (target, source, env):
324 cmd = 'tar -jcf ' + str (target[0]) + ' ' + str(source[0]) + " --exclude '*~'"
325 print 'running ', cmd, ' ... '
329 dist_bld = Builder (action = distcopy,
330 target_factory = SCons.Node.FS.default_fs.Entry,
331 source_factory = SCons.Node.FS.default_fs.Entry,
334 tarball_bld = Builder (action = tarballer,
335 target_factory = SCons.Node.FS.default_fs.Entry,
336 source_factory = SCons.Node.FS.default_fs.Entry)
338 env.Append (BUILDERS = {'Distribute' : dist_bld})
339 env.Append (BUILDERS = {'Tarball' : tarball_bld})
341 # ----------------------------------------------------------------------
342 # Construction environment setup
343 # ----------------------------------------------------------------------
347 libraries['core'] = LibraryInfo (CPPPATH = [ '#libs'])
349 libraries['sndfile'] = LibraryInfo()
350 libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
352 libraries['lrdf'] = LibraryInfo()
353 libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
355 libraries['raptor'] = LibraryInfo()
356 libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
358 libraries['samplerate'] = LibraryInfo()
359 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
361 libraries['jack'] = LibraryInfo()
362 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
364 libraries['xml'] = LibraryInfo()
365 libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
367 libraries['glib2'] = LibraryInfo()
368 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
369 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
370 libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
372 libraries['gtk2'] = LibraryInfo()
373 libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
375 libraries['pango'] = LibraryInfo()
376 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
378 libraries['libgnomecanvas2'] = LibraryInfo()
379 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
381 libraries['glade2'] = LibraryInfo()
382 libraries['glade2'].ParseConfig ('pkg-config --cflags --libs libglade-2.0')
384 libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
386 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
387 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
388 libraries['pbd3'] = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
389 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
390 #libraries['cassowary'] = LibraryInfo(LIBS='cassowary', LIBPATH='#libs/cassowary', CPPPATH='#libs/cassowary')
392 libraries['fst'] = LibraryInfo()
394 libraries['fst'].ParseConfig('pkg-config --cflags --libs libfst')
397 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
400 conf = Configure(env)
402 if conf.CheckCHeader('alsa/asoundlib.h'):
403 libraries['sysmidi'] = LibraryInfo (LIBS='asound')
404 env['SYSMIDI'] = 'ALSA Sequencer'
405 subst_dict['%MIDITAG%'] = "seq"
406 subst_dict['%MIDITYPE%'] = "alsa/sequencer"
407 elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
408 # this line is needed because scons can't handle -framework in ParseConfig() yet.
409 libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -bind_at_load')
410 env['SYSMIDI'] = 'CoreMIDI'
411 subst_dict['%MIDITAG%'] = "ardour"
412 subst_dict['%MIDITYPE%'] = "coremidi"
418 libraries['sigc2'] = LibraryInfo()
419 libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
421 libraries['gtkmm2'] = LibraryInfo()
422 libraries['gtkmm2'].ParseConfig ('pkg-config --cflags --libs gtkmm-2.0')
424 libraries['libglademm'] = LibraryInfo()
425 libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
427 libraries['soundtouch'] = LibraryInfo(LIBS='SoundTouch')
447 libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
448 LIBPATH='#libs/sigc++2',
449 CPPPATH='#libs/sigc++2')
450 libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
451 LIBPATH='#libs/glibmm2',
452 CPPPATH='#libs/glibmm2')
453 libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
454 LIBPATH='#libs/gtkmm2/pango',
455 CPPPATH='#libs/gtkmm2/pango')
456 libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
457 LIBPATH='#libs/gtkmm2/atk',
458 CPPPATH='#libs/gtkmm2/atk')
459 libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
460 LIBPATH='#libs/gtkmm2/gdk',
461 CPPPATH='#libs/gtkmm2/gdk')
462 libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
463 LIBPATH="#libs/gtkmm2/gtk",
464 CPPPATH='#libs/gtkmm2/gtk/')
465 libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
466 LIBPATH='#libs/libgnomecanvasmm',
467 CPPPATH='#libs/libgnomecanvasmm')
469 libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
470 LIBPATH='#libs/soundtouch',
471 CPPPATH=['#libs', '#libs/soundtouch'])
472 libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
473 LIBPATH='#libs/libglademm',
474 CPPPATH='#libs/libglademm')
496 'libs/libgnomecanvasmm',
502 opts.Save('scache.conf', env)
503 Help(opts.GenerateHelpText(env))
505 if os.environ.has_key('PATH'):
506 env.Append(PATH = os.environ['PATH'])
508 if os.environ.has_key('PKG_CONFIG_PATH'):
509 env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
511 if os.environ.has_key('CC'):
512 env['CC'] = os.environ['CC']
514 if os.environ.has_key('CXX'):
515 env['CXX'] = os.environ['CXX']
517 if os.environ.has_key('DISTCC_HOSTS'):
518 env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
519 env['ENV']['HOME'] = os.environ['HOME']
521 final_prefix = '$PREFIX'
522 install_prefix = '$DESTDIR/$PREFIX'
524 if env['PREFIX'] == '/usr':
525 final_config_prefix = '/etc'
527 final_config_prefix = env['PREFIX'] + '/etc'
529 config_prefix = '$DESTDIR' + final_config_prefix
532 # SCons should really do this for us
534 conf = Configure (env)
536 have_cxx = conf.TryAction (Action (env['CXX'] + ' --version'));
538 print "This system has no functional C++ compiler. You cannot build Ardour from source without one."
541 print "Congratulations, you have a functioning C++ compiler."
546 # Compiler flags and other system-dependent stuff
550 debug_flags = [ '-g' ]
552 # guess at the platform, used to define compiler flags
554 config_guess = os.popen("tools/config.guess").read()[:-1]
560 config = config_guess.split ("-")
563 # on OS X darwinports puts things in /opt/local by default
565 if config[config_arch] == 'apple':
566 if os.path.isdir('/opt/local/lib'):
567 libraries['core'].Append (LIBPATH = [ '/opt/local/lib' ])
568 if os.path.isdir('/opt/local/include'):
569 libraries['core'].Append (CPPPATH = [ '/opt/local/include' ])
570 if config[config_cpu] == 'powerpc':
572 # Apple/PowerPC optimization options
574 # -mcpu=7450 does not reliably work with gcc 3.*
576 if env['NOARCH'] == 0:
577 if env['ALTIVEC'] == 1:
578 if config[config_arch] == 'apple':
579 opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
581 opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
583 opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
584 opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
586 elif ((re.search ("i[0-9]86", config[config_cpu]) != None) or (re.search ("x86_64", config[config_cpu]) != None)):
588 build_host_supports_sse = 0
590 if env['NOARCH'] == 0:
592 debug_flags.append ("-DARCH_X86")
593 opt_flags.append ("-DARCH_X86")
595 if config[config_kernel] == 'linux' :
597 flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
598 x86_flags = flag_line.split (": ")[1:][0].split (' ')
600 if "mmx" in x86_flags:
601 opt_flags.append ("-mmmx")
602 if "sse" in x86_flags:
603 build_host_supports_sse = 1
604 if "3dnow" in x86_flags:
605 opt_flags.append ("-m3dnow")
607 if config[config_cpu] == "i586":
608 opt_flags.append ("-march=i586")
609 elif config[config_cpu] == "i686":
610 opt_flags.append ("-march=i686")
612 if env['USE_SSE_EVERYWHERE'] == 1:
613 opt_flags.extend (["-msse", "-mfpmath=sse"])
614 debug_flags.extend (["-msse", "-mfpmath=sse"])
615 if build_host_supports_sse != 1:
616 print "\nWarning: you are building Ardour with SSE support even though your system does not support these instructions. (This may not be an error, especially if you are a package maintainer)"
618 if env['BUILD_SSE_OPTIMIZATIONS'] == 1:
619 opt_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
620 debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
621 if build_host_supports_sse != 1:
622 print "\nWarning: you are building Ardour with SSE support even though your system does not support these instructions. (This may not be an error, especially if you are a package maintainer)"
624 # end of processor-specific section
627 # ARCH="..." overrides all
630 if env['ARCH'] != '':
631 opt_flags = env['ARCH'].split()
634 # prepend boiler plate optimization flags
639 "-fomit-frame-pointer",
644 if env['DEBUG'] == 1:
645 env.Append(CCFLAGS=" ".join (debug_flags))
647 env.Append(CCFLAGS=" ".join (opt_flags))
649 env.Append(CCFLAGS="-Wall")
652 env.Append(CCFLAGS="-DVST_SUPPORT")
656 # everybody needs this
659 env.Merge ([ libraries['core'] ])
665 conf = Configure (env)
668 print 'Checking for internationalization support ...'
669 have_gettext = conf.TryAction(Action('xgettext --version'))
670 if have_gettext[0] != 1:
671 print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
674 if conf.CheckCHeader('libintl.h') == None:
675 print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
682 env.Append(CCFLAGS="-DENABLE_NLS")
685 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
688 # the configuration file may be system dependent
691 conf = env.Configure ()
693 if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
694 subst_dict['%JACK_BACKEND%'] = "coreaudio:Built-in Audio:in"
696 subst_dict['%JACK_BACKEND%'] = "alsa_pcm:playback_"
698 # posix_memalign available
699 if not conf.CheckFunc('posix_memalign'):
700 print 'Did not find posix_memalign(), using malloc'
701 env.Append(CCFLAGS='-DNO_POSIX_MEMALIGN')
706 rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
708 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour_system.rc'))
709 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.rc'))
715 Precious (env['DISTTREE'])
718 # note the special "cleanfirst" source name. this triggers removal
719 # of the existing disttree
722 env.Distribute (env['DISTTREE'],
724 'COPYING', 'PACKAGER_README', 'README',
729 glob.glob ('DOCUMENTATION/AUTHORS*') +
730 glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
731 glob.glob ('DOCUMENTATION/TRANSLATORS*') +
732 glob.glob ('DOCUMENTATION/BUILD*') +
733 glob.glob ('DOCUMENTATION/FAQ*') +
734 glob.glob ('DOCUMENTATION/README*')
737 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
738 env.Alias ('srctar', srcdist)
740 # don't leave the distree around
742 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
743 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
749 for subdir in coredirs:
750 SConscript (subdir + '/SConscript')
752 for sublistdir in [subdirs, gtk_subdirs]:
753 for subdir in sublistdir:
754 SConscript (subdir + '/SConscript')
757 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])