[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