   [solved] SCons dependencies
  Hi,I'm trying to convert a project currently using make to SCons, since I've gotten tired of the current make-systems extreme brittleness. However, I'm a bit stuck on one part that someone here perhaps might be able to help me with.The project consists of a large amount of source files in various languages, and part of it is written in Modelica. Modelica-files are not compiled directly, but instead translated to C-code. The problem I have is that some C++-code depends on header-files that are created when translating the Modelica code. However, I want to be able to do a parallel build to speed up the build, and this breaks if the C++-code is compiled before or at the same time as the Modelica-code. I've tried to make the C++-code dependent on the Modelica-code, but I can't figure out how. Here is my current SConscript-file:import reimport os.pathImport('env')# A scanner for Modelica-filesinclude_re = re.compile(r'^protected\s+import\s+(\S+);$', re.M)def add_suffix_mo(filename):return filename + '.mo'def mo_file_scan(node, env, path):contents = node.get_contents()includes = include_re.findall(contents)return map(add_suffix_mo, includes)mo_scan = Scanner(function = mo_file_scan,skeys = ['.mo'])# A builder for Modelica filesrml_home = env['RMLHOME']def mo_build_function(target, source, env):for src in source:Execute('cd ' + str(src.get_dir()) + '; ' + rml_home + '/bin/rml -Eplain -ftrace ' + os.path.basename(str(src)))return 0mo_builder = Builder(action = mo_build_function,suffix = '.c',src_suffix = '.mo',source_scanner = mo_scan)# Create a new environment with the scanner and buildermo_env = Environment(BUILDERS = {'RML' : mo_builder})mo_env.Append(SCANNERS = mo_scan)# Create a list of files to be builtdont_include = map(File, Split('DAEEXT.mo Print.mo RTOpts.mo System.mo Parser.mo TaskGraphExt.mo Corba.mo Socket.mo ErrorExt.mo Settings.mo'))objs = [node for node in Glob('*.mo') if node not in dont_include];# Build the Modelica-files, and create an alias.mo_env.Decider('MD5')mo2c = mo_env.RML(objs)env.Alias('mo2c', mo2c)# Call the runtime-script, which compiles the C++-files. This should not be called until # after mo_env.RML(objs) is finished.runtime = mo_env.SConscript(['runtime/SConscript'])# Use Depends to try and make runtime dependent on mo2c. Doesn't work.Depends(runtime, env.Alias('mo2c'))It seems like SCons simply ignores the Depends-statement. I've tried every variation with and without aliases and depends I could think of, but can't get it to work. The SCons manual isn't very helpful in this matter either. I'm no expert on SCons, so I've probably misunderstood something about dependencies.EDIT: Ok, got it to work now. Emitter was indeed the way to go. I'm posting the working code below, since I hate it when someone claim to have solved a problem without showing the actual solution [smile]import reimport SCons.UtilImport('env')# A scanner for modelica filesinclude_re = re.compile(r'^protected\s+import\s+(\S+);$', re.M)def add_suffix_mo(filename):return filename + '.mo'def mo_file_scan(node, env, path):contents = node.get_contents()includes = include_re.findall(contents)return map(add_suffix_mo, includes)# An emitter for Modelica files. Compilation of a Modelica-file produces a .h and .c file as a side effect, so we need to inform SCons about that.def mo_emitter(target, source, env):base,ext = SCons.Util.splitext(str(source[0]))env.SideEffect(base + ".h", target)env.SideEffect(base + ".c", target)return (target, source)# A scanner for Modelica filesmo_scan = Scanner(function = mo_file_scan,skeys = ['.mo'])# A builder for Modelica files. Takes a list of .mo-files and produces # .o-files, using the previously defined emitter and scanner.mo_builder = Builder(action = "cd ${SOURCE.dir} && $RMLHOME/bin/rmlc -Wr,-ftrace -c ${SOURCE.file}",src_suffix = ".mo",suffix = ".o",single_source = True,emitter = mo_emitter,source_scanner = mo_scan)env.Append(BUILDERS = { "RML" : mo_builder })dont_include = map(File, Split('DAEEXT.mo Print.mo RTOpts.mo System.mo Parser.mo TaskGraphExt.mo Corba.mo Socket.mo ErrorExt.mo Settings.mo'))objs = [node for node in Glob('*.mo') if node not in dont_include];env.RML(objs)# Call the SConscript for runtime. No need to explicitly state dependencies, # since SCons figures them out automagically!env.SConscript(['runtime/SConscript'])[Edited by - Perost on June 27, 2009 11:30:14 AM]
  Agreed that the docs are not great.Depends() takes two filenames or targets as arguments. I don't think you can pass entire environments in. SCons doesn't think of environments as separate build steps. So you'd have to do a Depends call for every involved filename.So you say that the Modelica tool produces header files? The Builder definition you have only says that it produces ".c" files.. are those the same thing or does it make other files? If it makes other files, then you need to tell SCons about how those other files are created. I think you can do that with an Emitter.One good debugging method, is that you can call SCons with just a filename of something you want to build. So if you call it like this:scons <path to a Modelica-produced header file>then you can find out if SCons knows how those files are produced.   ;Quote:Original post by pinacoladaAgreed that the docs are not great.Yeah, the docs could use some work. A pity, since SCons is a nice tool (at least compared to make [rolleyes]).Quote:Original post by pinacoladaSo you say that the Modelica tool produces header files? The Builder definition you have only says that it produces ".c" files.. are those the same thing or does it make other files? If it makes other files, then you need to tell SCons about how those other files are created. I think you can do that with an Emitter.Modelica produces both a .c and .h file, but I didn't know how to tell SCons that. Perhaps Emitter is what is needed, I'll check it out.Quote:Original post by pinacoladaOne good debugging method, is that you can call SCons with just a filename of something you want to build. So if you call it like this:scons <path to a Modelica-produced header file>then you can find out if SCons knows how those files are produced.Ok, good to know. Thank you for your help!