[Scons-users] Source paths across external projects

Bill Deegan bill at baddogconsulting.com
Fri Sep 9 12:08:46 EDT 2016


Most welcome!

On Fri, Sep 9, 2016 at 8:46 AM, Bobby Casey <beecee808 at gmail.com> wrote:

> Wow, I feel awfully foolish right now. The first suggestion ( `src =
> [File("src/foo.c")]' ) is a perfect solution.
>
> For some reason it didn't occur to me that File would preserve the file
> path based upon the file loaded, unlike when using strings.
>
> Thanks for the help!
>
>
> On Thu, Sep 8, 2016 at 9:27 PM Bill Deegan <bill at baddogconsulting.com>
> wrote:
>
>> Bobby,
>>
>> How about:
>>
>> In the example above, `top_project/SConscript' would look like this:
>>     src = SConscript('sources.scons')
>>     foo =SConscript('extern/foo/sources.scons')
>>     src.extend(foo)
>>     prog = Program('test', src)
>>
>> and `extern/foo/sources.scons' would look like this:
>>     src = [File('src/foo.c')]
>>     Return('src')
>>
>> Or:
>>     src = [SharedObject('src/foo.c')]
>>     Return('src')
>>
>>
>>
>> On Thu, Sep 8, 2016 at 11:15 AM, Bobby Casey <beecee808 at gmail.com> wrote:
>>
>>> Hello,
>>>
>>> I'm going to start by apologizing for the length of this email.  I
>>> started off trying to explain what I'm looking for and what I have done and
>>> ended up trying other ideas as I went along.
>>>
>>> So here's what I'm trying to do - I have a project that depends on
>>> several external source repositories. The structure looks something like
>>> this:
>>>
>>> top_project/
>>> ---> SConstruct
>>> ---> SConscript
>>> ---> sources.scons
>>> ---> extern/foo
>>> ------> SConstruct
>>> ------> SConscript
>>> ------> sources.scons
>>> ------> src/
>>> ---------> foo.c
>>> ---> extern/bar
>>> ......
>>>
>>> Where each of the "extern" projects (there are several) is a separate
>>> repository that is capable of building itself (generally for testing
>>> purposes) and contains a sources.scons file that top_project's SConscript
>>> file pulls in to grab the list of source files that the sub-project
>>> provides. The problem, however, is that when `top_project/SConscript' calls
>>> `SConscript("extern/foo/sources.scons")', all the paths are relative to
>>> top_project (rather than extern/foo).
>>>
>>> This is a bit hard to explain, let me give a visual.
>>>
>>> In the example above, `top_project/SConscript' would look like this:
>>>     src = SConscript('sources.scons')
>>>     foo =SConscript('extern/foo/sources.scons')
>>>     src.extend(foo)
>>>     prog = Program('test', src)
>>>
>>> and `extern/foo/sources.scons' would look like this:
>>>     src = ['src/foo.c']
>>>     Return('src')
>>>
>>> This will fail with the following error:
>>>     scons: *** [build/src/foo.o] Source `build/src/foo.c' not found,
>>> needed by target `build/src/foo.o'.
>>>
>>> That is, of course, the correct behavior - just not the behavior what I
>>> wanted!  I could prepend os.path.abspath before each file, but that leaves
>>> the object files next to the sources, ignoring any variant_dir that was
>>> specified in top_project/SConstruct.
>>>
>>> I worked around this by modifying top_project/SConscript to look like
>>> this instead:
>>>     def add_scons_source(proj_dir):
>>>         src = SConscript('%s/sources.scons' % proj_dir)
>>>         src = ['%s/%s' % (proj_dir, s) for s in src]
>>>         return src
>>>
>>>     src = SConscript('sources.scons')
>>>     src.extend( add_scons_source('extern/foo') )
>>>     prog = Program('test', src)
>>>
>>> This prepends the appropriate path to each source file and works just
>>> fine but feels decidedly "unsconsy".  I then considered having each
>>> sources.scons be responsible for building it's own object files and that
>>> works great.  It's exactly what I wanted for building the application.  I
>>> suspect this is also the canonically correct way to do it.  The problem is
>>> that, in our real application, we also have a lint target that needs to be
>>> run against all source files so that it can detect issues across
>>> compilation units.  I'd like to avoid having the external projects know
>>> anything about lint, or whatever other targets are available in the
>>> top_project, so I came up with this as a possible solution.
>>>
>>> top_project/SConscript would look something like this:
>>>     env = Environment()
>>>     source_list = []
>>>     def do_lint(target, source, env):
>>>         print 'running lint on %s' % (str(s) for s in source)
>>>
>>>     def aggregate_sources(target, source, env):
>>>         global source_list
>>>         source_list.extend( [str(s) for s in source] )
>>>
>>>     env.Append(BUILDERS={'AggregateSources': Builder(action=aggregate_
>>> sources)})
>>>     env.Append(BUILDERS={'LintBuilder': Builder(action=do_lint)})
>>>
>>>     SrcBuilder = env.Object
>>>     src = SConscript('sources.scons', exports=['SrcBuilder'])
>>>     src.extend( SConscript('extern/foo/sources.scons',
>>> exports=['SrcBuilder']) )
>>>
>>>     prog = env.Program('test', src)
>>>     Default(prog)
>>>
>>>     SrcBuilder = env.AggregateSources
>>>     lint_src = SConscript('sources.scons', exports=['SrcBuilder'])
>>>     lint_src.extend( SConscript('extern/foo/sources.scons',
>>> exports=['SrcBuilder']) )
>>>     lint = env.LintBuilder('lint.out', lint_src)
>>>
>>>     Alias('lint', lint)
>>>
>>> and the sources.scons files would all look something like this:
>>>
>>>     Import('SrcBuilder')
>>>     src = ['src/foo.c']
>>>     built = [SrcBuilder(s) for s in src]
>>>     Return('built')
>>>
>>> This looks a bit silly in this contrived example because the SrcBuilder
>>> would really be part of two separate environments (one for Program and one
>>> for Lint targets), but I think you get the point.  The advantage to this
>>> method is that the builder is provided to sources.scons so it need not know
>>> how we're using the sources but can still handle them appropriately.  The
>>> disadvantage is that SrcBuilder needs to either be some common name for two
>>> wildly different things that are either part of the environment or passed
>>> as an extern.  It would be nicer if I could say something like `export(
>>> env.Object as "SrcBuilder")' and `export( env.AggregateSources as
>>> "SrcBuilder")'.  Is there some way to do this?
>>>
>>> I would appreciate any comments/feedback/suggestions/criticism.  Are
>>> any of these methods even remotely sound?  Is there some canonical way of
>>> doing this that I have just totally missed somehow?  Am I proposing a
>>> flawed architecture that could be easier/better done in some other way?
>>>
>>> Thanks in advance,
>>>   Bobby
>>>
>>>
>>> _______________________________________________
>>> Scons-users mailing list
>>> Scons-users at scons.org
>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>
>>>
>> _______________________________________________
>> Scons-users mailing list
>> Scons-users at scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
>
> _______________________________________________
> Scons-users mailing list
> Scons-users at scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist4.pair.net/pipermail/scons-users/attachments/20160909/14fb307d/attachment-0001.html>


More information about the Scons-users mailing list