Discussion:
[Scons-users] Parallel builds sometimes fails
mingqian Han
2018-05-25 14:48:55 UTC
Permalink
Hi all,

I am trying to implement a building infrastructure based on Scons. Currently it works nicely when doing a non-parallel build (-j1)
However when I run a parallel build, sometimes it fails.
The build is mostly C source files, and some of them include a specific header file, for example, #include "myheader.h"
But myheader.h is a generated file from some configuration files. I have created a custom SCons builder, put under scons_tools, and it generates this file when Scons runs.
However in parallel build, sometimes some source files get to compile before myheader.h is generated, which results in error: myheader.h not found.
And sometimes, when my custom SCons builder gets running, it reports error, saying that it is unable to access this file because other process is using it. In such case, myheader.h is only partially generated.
I know SCons reads all the SConscripts first then decides the order of building itself. So is there any way to make the parallel build success?
Thanks all.

Regards,

Rafael
Russel Winder
2018-05-25 15:03:18 UTC
Permalink
On Fri, 2018-05-25 at 14:48 +0000, mingqian Han wrote:
> Hi all,
>
> I am trying to implement a building infrastructure based on
> Scons. Currently it works nicely when doing a non-parallel build (-
> j1)
> However when I run a parallel build, sometimes it fails.
> The build is mostly C source files, and some of them include a
> specific header file, for example, #include "myheader.h"
> But myheader.h is a generated file from some configuration
> files. I have created a custom SCons builder, put under scons_tools,
> and it generates this file when Scons runs.
> However in parallel build, sometimes some source files get to
> compile before myheader.h is generated, which results in error:
> myheader.h not found.

Sounds to me like some of the source files that depend on this
generated file are not marked in the SCons scripts as being dependent
on it. It sounds like the sequential build is working due to a bit of
luck.

> And sometimes, when my custom SCons builder gets running, it
> reports error, saying that it is unable to access this file because
> other process is using it. In such case, myheader.h is only partially
> generated.
> I know SCons reads all the SConscripts first then decides the
> order of building itself. So is there any way to make the parallel
> build success?
> Thanks all.
>
> Regards,
>
> Rafael
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
--
Russel.
===========================================
Dr Russel Winder t: +44 20 7585 2200
41 Buckmaster Road m: +44 7770 465 077
London SW11 1EN, UK w: www.russel.org.uk
Bill Deegan
2018-05-25 15:02:40 UTC
Permalink
Can you post the code for your builder which generates the header file?
Off the top of my head I'd guess that SCons is unaware that your builder in
responsable for generating that file?

On Fri, May 25, 2018 at 9:48 AM, mingqian Han <***@hotmail.com> wrote:

> Hi all,
>
> I am trying to implement a building infrastructure based on Scons.
> Currently it works nicely when doing a non-parallel build (-j1)
> However when I run a parallel build, sometimes it fails.
> The build is mostly C source files, and some of them include a
> specific header file, for example, #include "myheader.h"
> But myheader.h is a generated file from some configuration files. I
> have created a custom SCons builder, put under scons_tools, and it
> generates this file when Scons runs.
> However in parallel build, sometimes some source files get to
> compile before myheader.h is generated, which results in error: myheader.h
> not found.
> And sometimes, when my custom SCons builder gets running, it reports
> error, saying that it is unable to access this file because other process
> is using it. In such case, myheader.h is only partially generated.
> I know SCons reads all the SConscripts first then decides the order
> of building itself. So is there any way to make the parallel build success?
> Thanks all.
>
> Regards,
>
> Rafael
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
Hua Yanghao
2018-05-25 16:47:24 UTC
Permalink
I am also using generated header files, which in turn is
unconditionally included by all C files.
The way I use is to first collect the entire C objects and mark an
explicit dependency: env.Depends(obj_list, depend_list).

However you need to make the scons build aware of the generated header
files, which in my case is generated by a customer scons builder.

And my builds worked fine with parallel builds.

On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
> Hi all,
>
> I am trying to implement a building infrastructure based on Scons.
> Currently it works nicely when doing a non-parallel build (-j1)
> However when I run a parallel build, sometimes it fails.
> The build is mostly C source files, and some of them include a specific
> header file, for example, #include "myheader.h"
> But myheader.h is a generated file from some configuration files. I
> have created a custom SCons builder, put under scons_tools, and it generates
> this file when Scons runs.
> However in parallel build, sometimes some source files get to compile
> before myheader.h is generated, which results in error: myheader.h not
> found.
> And sometimes, when my custom SCons builder gets running, it reports
> error, saying that it is unable to access this file because other process is
> using it. In such case, myheader.h is only partially generated.
> I know SCons reads all the SConscripts first then decides the order of
> building itself. So is there any way to make the parallel build success?
> Thanks all.
>
> Regards,
>
> Rafael
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
Bill Deegan
2018-05-25 18:30:09 UTC
Permalink
You should not have to explicitly tell SCons that a source file depends on
a header...

On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com> wrote:

> I am also using generated header files, which in turn is
> unconditionally included by all C files.
> The way I use is to first collect the entire C objects and mark an
> explicit dependency: env.Depends(obj_list, depend_list).
>
> However you need to make the scons build aware of the generated header
> files, which in my case is generated by a customer scons builder.
>
> And my builds worked fine with parallel builds.
>
> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
> > Hi all,
> >
> > I am trying to implement a building infrastructure based on Scons.
> > Currently it works nicely when doing a non-parallel build (-j1)
> > However when I run a parallel build, sometimes it fails.
> > The build is mostly C source files, and some of them include a
> specific
> > header file, for example, #include "myheader.h"
> > But myheader.h is a generated file from some configuration files. I
> > have created a custom SCons builder, put under scons_tools, and it
> generates
> > this file when Scons runs.
> > However in parallel build, sometimes some source files get to
> compile
> > before myheader.h is generated, which results in error: myheader.h not
> > found.
> > And sometimes, when my custom SCons builder gets running, it
> reports
> > error, saying that it is unable to access this file because other
> process is
> > using it. In such case, myheader.h is only partially generated.
> > I know SCons reads all the SConscripts first then decides the
> order of
> > building itself. So is there any way to make the parallel build success?
> > Thanks all.
> >
> > Regards,
> >
> > Rafael
> >
> > _______________________________________________
> > Scons-users mailing list
> > Scons-***@scons.org
> > https://pairlist4.pair.net/mailman/listinfo/scons-users
> >
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
Matthew Marinets
2018-05-25 18:42:45 UTC
Permalink
I’m working on a project with a lot of code generation, and I have run into a simple and unavoidable problem that can only be solved by setting an explicit dependency on a header file.

If a generated header file includes another header file, SCons has no way of knowing. It doesn’t scan built files, because there is no guarantee that the file exists or is up to date at scan-time. Hence, imagine the simple example:

Foo.c:
#include “Foo.h”

Foo.h is generated, and when it is up to date, it includes:
#include “Bar.h”

SCons has no way of knowing that Foo.c depends on Bar.h. The simplest solution is to set “Bar.h” as an explicit dependency.

-Matthew

From: Scons-users <scons-users-***@scons.org> On Behalf Of Bill Deegan
Sent: May 25, 2018 11:30
To: SCons users mailing list <scons-***@scons.org>
Subject: Re: [Scons-users] Parallel builds sometimes fails

You should not have to explicitly tell SCons that a source file depends on a header...

On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com<mailto:***@gmail.com>> wrote:
I am also using generated header files, which in turn is
unconditionally included by all C files.
The way I use is to first collect the entire C objects and mark an
explicit dependency: env.Depends(obj_list, depend_list).

However you need to make the scons build aware of the generated header
files, which in my case is generated by a customer scons builder.

And my builds worked fine with parallel builds.

On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com<mailto:***@hotmail.com>> wrote:
> Hi all,
>
> I am trying to implement a building infrastructure based on Scons.
> Currently it works nicely when doing a non-parallel build (-j1)
> However when I run a parallel build, sometimes it fails.
> The build is mostly C source files, and some of them include a specific
> header file, for example, #include "myheader.h"
> But myheader.h is a generated file from some configuration files. I
> have created a custom SCons builder, put under scons_tools, and it generates
> this file when Scons runs.
> However in parallel build, sometimes some source files get to compile
> before myheader.h is generated, which results in error: myheader.h not
> found.
> And sometimes, when my custom SCons builder gets running, it reports
> error, saying that it is unable to access this file because other process is
> using it. In such case, myheader.h is only partially generated.
> I know SCons reads all the SConscripts first then decides the order of
> building itself. So is there any way to make the parallel build success?
> Thanks all.
>
> Regards,
>
> Rafael
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org<mailto:Scons-***@scons.org>
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
_______________________________________________
Scons-users mailing list
Scons-***@scons.org<mailto:Scons-***@scons.org>
https://pairlist4.pair.net/mailman/listinfo/scons-users
Bill Deegan
2018-05-25 19:34:34 UTC
Permalink
Matthew,

It should know that foo.c -> foo.h, and that foo.h isn't ready yet (hasn't
been rebuilt) and thus know foo.c's not ready.

-Bill

On Fri, May 25, 2018 at 11:42 AM, Matthew Marinets <
***@kardium.com> wrote:

> I’m working on a project with a lot of code generation, and I have run
> into a simple and unavoidable problem that can only be solved by setting an
> explicit dependency on a header file.
>
>
>
> If a generated header file includes another header file, SCons has no way
> of knowing. It doesn’t scan built files, because there is no guarantee that
> the file exists or is up to date at scan-time. Hence, imagine the simple
> example:
>
>
>
> Foo.c:
>
> #include “Foo.h”
>
>
>
> Foo.h is generated, and when it is up to date, it includes:
>
> #include “Bar.h”
>
>
>
> SCons has no way of knowing that Foo.c depends on Bar.h. The simplest
> solution is to set “Bar.h” as an explicit dependency.
>
>
>
> -Matthew
>
>
>
> *From:* Scons-users <scons-users-***@scons.org> *On Behalf Of *Bill
> Deegan
> *Sent:* May 25, 2018 11:30
> *To:* SCons users mailing list <scons-***@scons.org>
> *Subject:* Re: [Scons-users] Parallel builds sometimes fails
>
>
>
> You should not have to explicitly tell SCons that a source file depends on
> a header...
>
>
>
> On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com>
> wrote:
>
> I am also using generated header files, which in turn is
> unconditionally included by all C files.
> The way I use is to first collect the entire C objects and mark an
> explicit dependency: env.Depends(obj_list, depend_list).
>
> However you need to make the scons build aware of the generated header
> files, which in my case is generated by a customer scons builder.
>
> And my builds worked fine with parallel builds.
>
>
> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
> > Hi all,
> >
> > I am trying to implement a building infrastructure based on Scons.
> > Currently it works nicely when doing a non-parallel build (-j1)
> > However when I run a parallel build, sometimes it fails.
> > The build is mostly C source files, and some of them include a
> specific
> > header file, for example, #include "myheader.h"
> > But myheader.h is a generated file from some configuration files. I
> > have created a custom SCons builder, put under scons_tools, and it
> generates
> > this file when Scons runs.
> > However in parallel build, sometimes some source files get to
> compile
> > before myheader.h is generated, which results in error: myheader.h not
> > found.
> > And sometimes, when my custom SCons builder gets running, it
> reports
> > error, saying that it is unable to access this file because other
> process is
> > using it. In such case, myheader.h is only partially generated.
> > I know SCons reads all the SConscripts first then decides the
> order of
> > building itself. So is there any way to make the parallel build success?
> > Thanks all.
> >
> > Regards,
> >
> > Rafael
> >
>
> > _______________________________________________
> > Scons-users mailing list
> > Scons-***@scons.org
> > https://pairlist4.pair.net/mailman/listinfo/scons-users
> >
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
Hua Yanghao
2018-05-25 19:42:58 UTC
Permalink
I think Matthew's point is "Bar.h" is not there yet.

foo.h will be built, and then it might just go on and built foo.c,
where it includes foo.h, which in turn includes bar.h.

On Fri, May 25, 2018 at 9:34 PM, Bill Deegan <***@baddogconsulting.com> wrote:
> Matthew,
>
> It should know that foo.c -> foo.h, and that foo.h isn't ready yet (hasn't
> been rebuilt) and thus know foo.c's not ready.
>
> -Bill
>
> On Fri, May 25, 2018 at 11:42 AM, Matthew Marinets
> <***@kardium.com> wrote:
>>
>> I’m working on a project with a lot of code generation, and I have run
>> into a simple and unavoidable problem that can only be solved by setting an
>> explicit dependency on a header file.
>>
>>
>>
>> If a generated header file includes another header file, SCons has no way
>> of knowing. It doesn’t scan built files, because there is no guarantee that
>> the file exists or is up to date at scan-time. Hence, imagine the simple
>> example:
>>
>>
>>
>> Foo.c:
>>
>> #include “Foo.h”
>>
>>
>>
>> Foo.h is generated, and when it is up to date, it includes:
>>
>> #include “Bar.h”
>>
>>
>>
>> SCons has no way of knowing that Foo.c depends on Bar.h. The simplest
>> solution is to set “Bar.h” as an explicit dependency.
>>
>>
>>
>> -Matthew
>>
>>
>>
>> From: Scons-users <scons-users-***@scons.org> On Behalf Of Bill Deegan
>> Sent: May 25, 2018 11:30
>> To: SCons users mailing list <scons-***@scons.org>
>> Subject: Re: [Scons-users] Parallel builds sometimes fails
>>
>>
>>
>> You should not have to explicitly tell SCons that a source file depends on
>> a header...
>>
>>
>>
>> On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com>
>> wrote:
>>
>> I am also using generated header files, which in turn is
>> unconditionally included by all C files.
>> The way I use is to first collect the entire C objects and mark an
>> explicit dependency: env.Depends(obj_list, depend_list).
>>
>> However you need to make the scons build aware of the generated header
>> files, which in my case is generated by a customer scons builder.
>>
>> And my builds worked fine with parallel builds.
>>
>>
>> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
>> > Hi all,
>> >
>> > I am trying to implement a building infrastructure based on Scons.
>> > Currently it works nicely when doing a non-parallel build (-j1)
>> > However when I run a parallel build, sometimes it fails.
>> > The build is mostly C source files, and some of them include a
>> > specific
>> > header file, for example, #include "myheader.h"
>> > But myheader.h is a generated file from some configuration files.
>> > I
>> > have created a custom SCons builder, put under scons_tools, and it
>> > generates
>> > this file when Scons runs.
>> > However in parallel build, sometimes some source files get to
>> > compile
>> > before myheader.h is generated, which results in error: myheader.h not
>> > found.
>> > And sometimes, when my custom SCons builder gets running, it
>> > reports
>> > error, saying that it is unable to access this file because other
>> > process is
>> > using it. In such case, myheader.h is only partially generated.
>> > I know SCons reads all the SConscripts first then decides the
>> > order of
>> > building itself. So is there any way to make the parallel build success?
>> > Thanks all.
>> >
>> > Regards,
>> >
>> > Rafael
>> >
>>
>> > _______________________________________________
>> > Scons-users mailing list
>> > Scons-***@scons.org
>> > https://pairlist4.pair.net/mailman/listinfo/scons-users
>> >
>> _______________________________________________
>> Scons-users mailing list
>> Scons-***@scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
>>
>>
>>
>> _______________________________________________
>> Scons-users mailing list
>> Scons-***@scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
Matthew Marinets
2018-05-25 22:05:33 UTC
Permalink
I wrote out a whole email in response before finding an old minimal case I had lying around. The bug in my main project seems to be a different one; changing the scanners worked in this example, but not in my project for some reason, but it’s still an example of how the scanner can act a little oddly at times.

Apparently scanners will still run even if you’re not using the corresponding builder.

My setup:
Root
+ SConstruct
+ src
| + HelloWorld.c
| | + GenerationRoot.h
| | +SomeHeader.h

HelloWorld.c includes HelloWorld.h
HelloWorld.h includes SomeOtherHeader.h

HelloWorld.h comes from GenerationRoot.h (I run a copy to simulate generation)
SomeOtherHeader.h comes from SomeHeader.h

SConstruct:

# environments
env = Environment(tools = ['mingw'])

# directories
src = Dir('src')
include = src.Dir('include')
build = Dir('build')
export = Dir('export')

env.Append(CPPPATH = build)
genv.Append(CPPPATH = build)

# targets
generateA = env.Command(target = build.File('SomeOtherHeader.h'), source = include.File('SomeHeader.h'),
action = Copy('$TARGET', '$SOURCE'))
genv.Alias('generateA', generateA)

generateB = env.Command(target = build.File('HelloWorld.h'), source = include.File('GenerationRoot.h'),
action = Copy('$TARGET', '$SOURCE'))
env.Alias('generateB', generateB)

Running generateB still tries to run generateA, even though it is not necessary. generateB is purely a copy command, and doesn’t depend on anything but the source, but running generateB with –tree=all is still revealing:

C:\ExampleRoot>scons generateB --tree=all
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Copy("build\SomeOtherHeader.h", "src\include\SomeHeader.h")
Copy("build\HelloWorld.h", "src\include\GenerationRoot.h")
+-generateB
+-build\HelloWorld.h
| +-src\include\GenerationRoot.h
| +-build\SomeOtherHeader.h
| +-src\include\SomeHeader.h
+-build\SomeOtherHeader.h
+-src\include\SomeHeader.h
scons: done building targets.

It scanned HelloWorld.h, even though it’s not building anything with it.

The solution I found was to replace the SCANNERS environment variable with an empty scanner:
emptyScanner = SCons.Scanner.Base(function = lambda *args, **kwargs: [],
skeys = '.h')

And use this in a special generation environment, but I’m not sure if this risks scanning .h files and returning an empty list when they should have been scanned properly.

Moreover this solution didn’t even fix the problem in my actual project. All the bug does in my project is cause an unnecessary copy in specific conditions, so I haven’t bothered trying to do much more investigating, though.

Essentially what this shows is that the scanners in the global env[‘SCANNERS’] variable are a little too enthusiastic about scanning, and will scan things even when you don’t want them to. Moreover, code generation can cause scanners to act oddly if .h files are used both for generation and for building, because implicit dependencies are stored by the node rather than by the executor (I think that’s what it’s called?). This means that either the compile-type scanner adds dependencies that the generator doesn’t need, or the generator-type scanner can omit dependencies that the compiler needs.

Since I couldn’t figure out exactly what was going on in my main project, I thought maybe the problem Hua was having was related, but now I don’t think so.

-Matthew


From: Scons-users <scons-users-***@scons.org> On Behalf Of Bill Deegan
Sent: May 25, 2018 12:35
To: SCons users mailing list <scons-***@scons.org>
Subject: Re: [Scons-users] Parallel builds sometimes fails

Matthew,

It should know that foo.c -> foo.h, and that foo.h isn't ready yet (hasn't been rebuilt) and thus know foo.c's not ready.

-Bill

On Fri, May 25, 2018 at 11:42 AM, Matthew Marinets <***@kardium.com<mailto:***@kardium.com>> wrote:
I’m working on a project with a lot of code generation, and I have run into a simple and unavoidable problem that can only be solved by setting an explicit dependency on a header file.

If a generated header file includes another header file, SCons has no way of knowing. It doesn’t scan built files, because there is no guarantee that the file exists or is up to date at scan-time. Hence, imagine the simple example:

Foo.c:
#include “Foo.h”

Foo.h is generated, and when it is up to date, it includes:
#include “Bar.h”

SCons has no way of knowing that Foo.c depends on Bar.h. The simplest solution is to set “Bar.h” as an explicit dependency.

-Matthew

From: Scons-users <scons-users-***@scons.org<mailto:scons-users-***@scons.org>> On Behalf Of Bill Deegan
Sent: May 25, 2018 11:30
To: SCons users mailing list <scons-***@scons.org<mailto:scons-***@scons.org>>
Subject: Re: [Scons-users] Parallel builds sometimes fails

You should not have to explicitly tell SCons that a source file depends on a header...

On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com<mailto:***@gmail.com>> wrote:
I am also using generated header files, which in turn is
unconditionally included by all C files.
The way I use is to first collect the entire C objects and mark an
explicit dependency: env.Depends(obj_list, depend_list).

However you need to make the scons build aware of the generated header
files, which in my case is generated by a customer scons builder.

And my builds worked fine with parallel builds.

On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com<mailto:***@hotmail.com>> wrote:
> Hi all,
>
> I am trying to implement a building infrastructure based on Scons.
> Currently it works nicely when doing a non-parallel build (-j1)
> However when I run a parallel build, sometimes it fails.
> The build is mostly C source files, and some of them include a specific
> header file, for example, #include "myheader.h"
> But myheader.h is a generated file from some configuration files. I
> have created a custom SCons builder, put under scons_tools, and it generates
> this file when Scons runs.
> However in parallel build, sometimes some source files get to compile
> before myheader.h is generated, which results in error: myheader.h not
> found.
> And sometimes, when my custom SCons builder gets running, it reports
> error, saying that it is unable to access this file because other process is
> using it. In such case, myheader.h is only partially generated.
> I know SCons reads all the SConscripts first then decides the order of
> building itself. So is there any way to make the parallel build success?
> Thanks all.
>
> Regards,
>
> Rafael
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org<mailto:Scons-***@scons.org>
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
_______________________________________________
Scons-users mailing list
Scons-***@scons.org<mailto:Scons-***@scons.org>
https://pairlist4.pair.net/mailman/listinfo/scons-users


_______________________________________________
Scons-users mailing list
Scons-***@scons.org<mailto:Scons-***@scons.org>
https://pairlist4.pair.net/mailman/listinfo/scons-users
mingqian Han
2018-05-28 07:02:16 UTC
Permalink
Hi everyone,

Thanks for your help, I finally figure out that I need a correct Depends.
Previously I was setting Depends on a Library builder, for example:
a = env.Library(...)
env.Depends(a, ...)

However that still does not ensure the custom header generator to run first.
Now I set the Depends on object file list, and it works.
Thanks!

Best,
Rafael
________________________________
From: Scons-users <scons-users-***@scons.org> on behalf of Matthew Marinets <***@Kardium.com>
Sent: Saturday, May 26, 2018 6:05 AM
To: SCons users mailing list
Subject: Re: [Scons-users] Parallel builds sometimes fails


I wrote out a whole email in response before finding an old minimal case I had lying around. The bug in my main project seems to be a different one; changing the scanners worked in this example, but not in my project for some reason, but it’s still an example of how the scanner can act a little oddly at times.



Apparently scanners will still run even if you’re not using the corresponding builder.



My setup:

Root

+ SConstruct

+ src

| + HelloWorld.c

| | + GenerationRoot.h

| | +SomeHeader.h



HelloWorld.c includes HelloWorld.h

HelloWorld.h includes SomeOtherHeader.h



HelloWorld.h comes from GenerationRoot.h (I run a copy to simulate generation)

SomeOtherHeader.h comes from SomeHeader.h



SConstruct:



# environments

env = Environment(tools = ['mingw'])



# directories

src = Dir('src')

include = src.Dir('include')

build = Dir('build')

export = Dir('export')



env.Append(CPPPATH = build)

genv.Append(CPPPATH = build)



# targets

generateA = env.Command(target = build.File('SomeOtherHeader.h'), source = include.File('SomeHeader.h'),

action = Copy('$TARGET', '$SOURCE'))

genv.Alias('generateA', generateA)



generateB = env.Command(target = build.File('HelloWorld.h'), source = include.File('GenerationRoot.h'),

action = Copy('$TARGET', '$SOURCE'))

env.Alias('generateB', generateB)



Running generateB still tries to run generateA, even though it is not necessary. generateB is purely a copy command, and doesn’t depend on anything but the source, but running generateB with –tree=all is still revealing:



C:\ExampleRoot>scons generateB --tree=all

scons: Reading SConscript files ...

scons: done reading SConscript files.

scons: Building targets ...

Copy("build\SomeOtherHeader.h", "src\include\SomeHeader.h")

Copy("build\HelloWorld.h", "src\include\GenerationRoot.h")

+-generateB

+-build\HelloWorld.h

| +-src\include\GenerationRoot.h

| +-build\SomeOtherHeader.h

| +-src\include\SomeHeader.h

+-build\SomeOtherHeader.h

+-src\include\SomeHeader.h

scons: done building targets.



It scanned HelloWorld.h, even though it’s not building anything with it.



The solution I found was to replace the SCANNERS environment variable with an empty scanner:

emptyScanner = SCons.Scanner.Base(function = lambda *args, **kwargs: [],

skeys = '.h')



And use this in a special generation environment, but I’m not sure if this risks scanning .h files and returning an empty list when they should have been scanned properly.



Moreover this solution didn’t even fix the problem in my actual project. All the bug does in my project is cause an unnecessary copy in specific conditions, so I haven’t bothered trying to do much more investigating, though.



Essentially what this shows is that the scanners in the global env[‘SCANNERS’] variable are a little too enthusiastic about scanning, and will scan things even when you don’t want them to. Moreover, code generation can cause scanners to act oddly if .h files are used both for generation and for building, because implicit dependencies are stored by the node rather than by the executor (I think that’s what it’s called?). This means that either the compile-type scanner adds dependencies that the generator doesn’t need, or the generator-type scanner can omit dependencies that the compiler needs.



Since I couldn’t figure out exactly what was going on in my main project, I thought maybe the problem Hua was having was related, but now I don’t think so.



-Matthew





From: Scons-users <scons-users-***@scons.org> On Behalf Of Bill Deegan
Sent: May 25, 2018 12:35
To: SCons users mailing list <scons-***@scons.org>
Subject: Re: [Scons-users] Parallel builds sometimes fails



Matthew,



It should know that foo.c -> foo.h, and that foo.h isn't ready yet (hasn't been rebuilt) and thus know foo.c's not ready.



-Bill



On Fri, May 25, 2018 at 11:42 AM, Matthew Marinets <***@kardium.com<mailto:***@kardium.com>> wrote:

I’m working on a project with a lot of code generation, and I have run into a simple and unavoidable problem that can only be solved by setting an explicit dependency on a header file.



If a generated header file includes another header file, SCons has no way of knowing. It doesn’t scan built files, because there is no guarantee that the file exists or is up to date at scan-time. Hence, imagine the simple example:



Foo.c:

#include “Foo.h”



Foo.h is generated, and when it is up to date, it includes:

#include “Bar.h”



SCons has no way of knowing that Foo.c depends on Bar.h. The simplest solution is to set “Bar.h” as an explicit dependency.



-Matthew



From: Scons-users <scons-users-***@scons.org<mailto:scons-users-***@scons.org>> On Behalf Of Bill Deegan
Sent: May 25, 2018 11:30
To: SCons users mailing list <scons-***@scons.org<mailto:scons-***@scons.org>>
Subject: Re: [Scons-users] Parallel builds sometimes fails



You should not have to explicitly tell SCons that a source file depends on a header...



On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com<mailto:***@gmail.com>> wrote:

I am also using generated header files, which in turn is
unconditionally included by all C files.
The way I use is to first collect the entire C objects and mark an
explicit dependency: env.Depends(obj_list, depend_list).

However you need to make the scons build aware of the generated header
files, which in my case is generated by a customer scons builder.

And my builds worked fine with parallel builds.

On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com<mailto:***@hotmail.com>> wrote:
> Hi all,
>
> I am trying to implement a building infrastructure based on Scons.
> Currently it works nicely when doing a non-parallel build (-j1)
> However when I run a parallel build, sometimes it fails.
> The build is mostly C source files, and some of them include a specific
> header file, for example, #include "myheader.h"
> But myheader.h is a generated file from some configuration files. I
> have created a custom SCons builder, put under scons_tools, and it generates
> this file when Scons runs.
> However in parallel build, sometimes some source files get to compile
> before myheader.h is generated, which results in error: myheader.h not
> found.
> And sometimes, when my custom SCons builder gets running, it reports
> error, saying that it is unable to access this file because other process is
> using it. In such case, myheader.h is only partially generated.
> I know SCons reads all the SConscripts first then decides the order of
> building itself. So is there any way to make the parallel build success?
> Thanks all.
>
> Regards,
>
> Rafael
>

> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org<mailto:Scons-***@scons.org>
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
Bill Deegan
2018-05-28 22:37:44 UTC
Permalink
Rafael,

How is the header created? Do you have a env.Command()?

As I've stated previously, if you need to use env.Depends() most likely
you're missing something in your build logic.
(SCons is unaware that some builder/command is actually generating that
file and thus starting build steps which require it before it's available)

On Mon, May 28, 2018 at 12:02 AM, mingqian Han <***@hotmail.com> wrote:

> Hi everyone,
>
> Thanks for your help, I finally figure out that I need a correct
> Depends.
> Previously I was setting Depends on a Library builder, for example:
> a = env.Library(...)
> env.Depends(a, ...)
>
> However that still does not ensure the custom header generator to run
> first.
> Now I set the Depends on object file list, and it works.
> Thanks!
>
> Best,
> Rafael
> ------------------------------
> *From:* Scons-users <scons-users-***@scons.org> on behalf of Matthew
> Marinets <***@Kardium.com>
> *Sent:* Saturday, May 26, 2018 6:05 AM
> *To:* SCons users mailing list
> *Subject:* Re: [Scons-users] Parallel builds sometimes fails
>
>
> I wrote out a whole email in response before finding an old minimal case I
> had lying around. The bug in my main project seems to be a different one;
> changing the scanners worked in this example, but not in my project for
> some reason, but it’s still an example of how the scanner can act a little
> oddly at times.
>
>
>
> Apparently scanners will still run even if you’re not using the
> corresponding builder.
>
>
>
> My setup:
>
> Root
>
> + SConstruct
>
> + src
>
> | + HelloWorld.c
>
> | | + GenerationRoot.h
>
> | | +SomeHeader.h
>
>
>
> HelloWorld.c includes HelloWorld.h
>
> HelloWorld.h includes SomeOtherHeader.h
>
>
>
> HelloWorld.h comes from GenerationRoot.h (I run a copy to simulate
> generation)
>
> SomeOtherHeader.h comes from SomeHeader.h
>
>
>
> SConstruct:
>
>
>
> # environments
>
> env = Environment(tools = ['mingw'])
>
>
>
> # directories
>
> src = Dir('src')
>
> include = src.Dir('include')
>
> build = Dir('build')
>
> export = Dir('export')
>
>
>
> env.Append(CPPPATH = build)
>
> genv.Append(CPPPATH = build)
>
>
>
> # targets
>
> generateA = env.Command(target = build.File('SomeOtherHeader.h'), source
> = include.File('SomeHeader.h'),
>
> action = Copy('$TARGET', '$SOURCE'))
>
> genv.Alias('generateA', generateA)
>
>
>
> generateB = env.Command(target = build.File('HelloWorld.h'), source =
> include.File('GenerationRoot.h'),
>
> action = Copy('$TARGET', '$SOURCE'))
>
> env.Alias('generateB', generateB)
>
>
>
> Running generateB still tries to run generateA, even though it is not
> necessary. generateB is purely a copy command, and doesn’t depend on
> anything but the source, but running generateB with –tree=all is still
> revealing:
>
>
>
> C:\ExampleRoot>scons generateB --tree=all
>
> scons: Reading SConscript files ...
>
> scons: done reading SConscript files.
>
> scons: Building targets ...
>
> Copy("build\SomeOtherHeader.h", "src\include\SomeHeader.h")
>
> Copy("build\HelloWorld.h", "src\include\GenerationRoot.h")
>
> +-generateB
>
> +-build\HelloWorld.h
>
> | +-src\include\GenerationRoot.h
>
> | +-build\SomeOtherHeader.h
>
> | +-src\include\SomeHeader.h
>
> +-build\SomeOtherHeader.h
>
> +-src\include\SomeHeader.h
>
> scons: done building targets.
>
>
>
> It scanned HelloWorld.h, even though it’s not building anything with it.
>
>
>
> The solution I found was to replace the SCANNERS environment variable with
> an empty scanner:
>
> emptyScanner = SCons.Scanner.Base(function = lambda *args, **kwargs: [],
>
> skeys = '.h')
>
>
>
> And use this in a special generation environment, but I’m not sure if this
> risks scanning .h files and returning an empty list when they should have
> been scanned properly.
>
>
>
> Moreover this solution didn’t even fix the problem in my actual project.
> All the bug does in my project is cause an unnecessary copy in specific
> conditions, so I haven’t bothered trying to do much more investigating,
> though.
>
>
>
> Essentially what this shows is that the scanners in the global
> env[‘SCANNERS’] variable are a little too enthusiastic about scanning, and
> will scan things even when you don’t want them to. Moreover, code
> generation can cause scanners to act oddly if .h files are used both for
> generation and for building, because implicit dependencies are stored by
> the node rather than by the executor (I think that’s what it’s called?).
> This means that either the compile-type scanner adds dependencies that the
> generator doesn’t need, or the generator-type scanner can omit dependencies
> that the compiler needs.
>
>
>
> Since I couldn’t figure out exactly what was going on in my main project,
> I thought maybe the problem Hua was having was related, but now I don’t
> think so.
>
>
>
> -Matthew
>
>
>
>
>
> *From:* Scons-users <scons-users-***@scons.org> *On Behalf Of *Bill
> Deegan
> *Sent:* May 25, 2018 12:35
> *To:* SCons users mailing list <scons-***@scons.org>
> *Subject:* Re: [Scons-users] Parallel builds sometimes fails
>
>
>
> Matthew,
>
>
>
> It should know that foo.c -> foo.h, and that foo.h isn't ready yet (hasn't
> been rebuilt) and thus know foo.c's not ready.
>
>
>
> -Bill
>
>
>
> On Fri, May 25, 2018 at 11:42 AM, Matthew Marinets <
> ***@kardium.com> wrote:
>
> I’m working on a project with a lot of code generation, and I have run
> into a simple and unavoidable problem that can only be solved by setting an
> explicit dependency on a header file.
>
>
>
> If a generated header file includes another header file, SCons has no way
> of knowing. It doesn’t scan built files, because there is no guarantee that
> the file exists or is up to date at scan-time. Hence, imagine the simple
> example:
>
>
>
> Foo.c:
>
> #include “Foo.h”
>
>
>
> Foo.h is generated, and when it is up to date, it includes:
>
> #include “Bar.h”
>
>
>
> SCons has no way of knowing that Foo.c depends on Bar.h. The simplest
> solution is to set “Bar.h” as an explicit dependency.
>
>
>
> -Matthew
>
>
>
> *From:* Scons-users <scons-users-***@scons.org> *On Behalf Of *Bill
> Deegan
> *Sent:* May 25, 2018 11:30
> *To:* SCons users mailing list <scons-***@scons.org>
> *Subject:* Re: [Scons-users] Parallel builds sometimes fails
>
>
>
> You should not have to explicitly tell SCons that a source file depends on
> a header...
>
>
>
> On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com>
> wrote:
>
> I am also using generated header files, which in turn is
> unconditionally included by all C files.
> The way I use is to first collect the entire C objects and mark an
> explicit dependency: env.Depends(obj_list, depend_list).
>
> However you need to make the scons build aware of the generated header
> files, which in my case is generated by a customer scons builder.
>
> And my builds worked fine with parallel builds.
>
>
> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
> > Hi all,
> >
> > I am trying to implement a building infrastructure based on Scons.
> > Currently it works nicely when doing a non-parallel build (-j1)
> > However when I run a parallel build, sometimes it fails.
> > The build is mostly C source files, and some of them include a
> specific
> > header file, for example, #include "myheader.h"
> > But myheader.h is a generated file from some configuration files. I
> > have created a custom SCons builder, put under scons_tools, and it
> generates
> > this file when Scons runs.
> > However in parallel build, sometimes some source files get to
> compile
> > before myheader.h is generated, which results in error: myheader.h not
> > found.
> > And sometimes, when my custom SCons builder gets running, it
> reports
> > error, saying that it is unable to access this file because other
> process is
> > using it. In such case, myheader.h is only partially generated.
> > I know SCons reads all the SConscripts first then decides the
> order of
> > building itself. So is there any way to make the parallel build success?
> > Thanks all.
> >
> > Regards,
> >
> > Rafael
> >
>
> > _______________________________________________
> > Scons-users mailing list
> > Scons-***@scons.org
> > https://pairlist4.pair.net/mailman/listinfo/scons-users
> >
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
Hua Yanghao
2018-05-25 19:39:24 UTC
Permalink
This is also a very good point. Though slightly different in my case.

Also think about auto generated C code, which is also not available before
build actually starts.

On Fri 25. May 2018 at 20:42, Matthew Marinets <***@kardium.com>
wrote:

> I’m working on a project with a lot of code generation, and I have run
> into a simple and unavoidable problem that can only be solved by setting an
> explicit dependency on a header file.
>
>
>
> If a generated header file includes another header file, SCons has no way
> of knowing. It doesn’t scan built files, because there is no guarantee that
> the file exists or is up to date at scan-time. Hence, imagine the simple
> example:
>
>
>
> Foo.c:
>
> #include “Foo.h”
>
>
>
> Foo.h is generated, and when it is up to date, it includes:
>
> #include “Bar.h”
>
>
>
> SCons has no way of knowing that Foo.c depends on Bar.h. The simplest
> solution is to set “Bar.h” as an explicit dependency.
>
>
>
> -Matthew
>
>
>
> *From:* Scons-users <scons-users-***@scons.org> *On Behalf Of *Bill
> Deegan
> *Sent:* May 25, 2018 11:30
> *To:* SCons users mailing list <scons-***@scons.org>
> *Subject:* Re: [Scons-users] Parallel builds sometimes fails
>
>
>
> You should not have to explicitly tell SCons that a source file depends on
> a header...
>
>
>
> On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com>
> wrote:
>
> I am also using generated header files, which in turn is
> unconditionally included by all C files.
> The way I use is to first collect the entire C objects and mark an
> explicit dependency: env.Depends(obj_list, depend_list).
>
> However you need to make the scons build aware of the generated header
> files, which in my case is generated by a customer scons builder.
>
> And my builds worked fine with parallel builds.
>
>
> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
> > Hi all,
> >
> > I am trying to implement a building infrastructure based on Scons.
> > Currently it works nicely when doing a non-parallel build (-j1)
> > However when I run a parallel build, sometimes it fails.
> > The build is mostly C source files, and some of them include a
> specific
> > header file, for example, #include "myheader.h"
> > But myheader.h is a generated file from some configuration files. I
> > have created a custom SCons builder, put under scons_tools, and it
> generates
> > this file when Scons runs.
> > However in parallel build, sometimes some source files get to
> compile
> > before myheader.h is generated, which results in error: myheader.h not
> > found.
> > And sometimes, when my custom SCons builder gets running, it
> reports
> > error, saying that it is unable to access this file because other
> process is
> > using it. In such case, myheader.h is only partially generated.
> > I know SCons reads all the SConscripts first then decides the
> order of
> > building itself. So is there any way to make the parallel build success?
> > Thanks all.
> >
> > Regards,
> >
> > Rafael
> >
>
> > _______________________________________________
> > Scons-users mailing list
> > Scons-***@scons.org
> > https://pairlist4.pair.net/mailman/listinfo/scons-users
> >
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
Hua Yanghao
2018-05-25 19:28:03 UTC
Permalink
My header is not included in the C file, it is unconditional included by
“-include config.h”, how do you expect scons to know that? Parsing GCC
command line? :)

On Fri 25. May 2018 at 20:30, Bill Deegan <***@baddogconsulting.com> wrote:

> You should not have to explicitly tell SCons that a source file depends on
> a header...
>
> On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com>
> wrote:
>
>> I am also using generated header files, which in turn is
>> unconditionally included by all C files.
>> The way I use is to first collect the entire C objects and mark an
>> explicit dependency: env.Depends(obj_list, depend_list).
>>
>> However you need to make the scons build aware of the generated header
>> files, which in my case is generated by a customer scons builder.
>>
>> And my builds worked fine with parallel builds.
>>
>> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com> wrote:
>> > Hi all,
>> >
>> > I am trying to implement a building infrastructure based on Scons.
>> > Currently it works nicely when doing a non-parallel build (-j1)
>> > However when I run a parallel build, sometimes it fails.
>> > The build is mostly C source files, and some of them include a
>> specific
>> > header file, for example, #include "myheader.h"
>> > But myheader.h is a generated file from some configuration files.
>> I
>> > have created a custom SCons builder, put under scons_tools, and it
>> generates
>> > this file when Scons runs.
>> > However in parallel build, sometimes some source files get to
>> compile
>> > before myheader.h is generated, which results in error: myheader.h not
>> > found.
>> > And sometimes, when my custom SCons builder gets running, it
>> reports
>> > error, saying that it is unable to access this file because other
>> process is
>> > using it. In such case, myheader.h is only partially generated.
>> > I know SCons reads all the SConscripts first then decides the
>> order of
>> > building itself. So is there any way to make the parallel build success?
>> > Thanks all.
>> >
>> > Regards,
>> >
>> > Rafael
>> >
>> > _______________________________________________
>> > Scons-users mailing list
>> > Scons-***@scons.org
>> > https://pairlist4.pair.net/mailman/listinfo/scons-users
>> >
>> _______________________________________________
>> Scons-users mailing list
>> Scons-***@scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
Bill Deegan
2018-05-25 19:32:56 UTC
Permalink
Hua,

Ahh gotcha.

On Fri, May 25, 2018 at 12:28 PM, Hua Yanghao <***@gmail.com> wrote:

> My header is not included in the C file, it is unconditional included by
> “-include config.h”, how do you expect scons to know that? Parsing GCC
> command line? :)
>
> On Fri 25. May 2018 at 20:30, Bill Deegan <***@baddogconsulting.com>
> wrote:
>
>> You should not have to explicitly tell SCons that a source file depends
>> on a header...
>>
>> On Fri, May 25, 2018 at 11:47 AM, Hua Yanghao <***@gmail.com>
>> wrote:
>>
>>> I am also using generated header files, which in turn is
>>> unconditionally included by all C files.
>>> The way I use is to first collect the entire C objects and mark an
>>> explicit dependency: env.Depends(obj_list, depend_list).
>>>
>>> However you need to make the scons build aware of the generated header
>>> files, which in my case is generated by a customer scons builder.
>>>
>>> And my builds worked fine with parallel builds.
>>>
>>> On Fri, May 25, 2018 at 4:48 PM, mingqian Han <***@hotmail.com>
>>> wrote:
>>> > Hi all,
>>> >
>>> > I am trying to implement a building infrastructure based on Scons.
>>> > Currently it works nicely when doing a non-parallel build (-j1)
>>> > However when I run a parallel build, sometimes it fails.
>>> > The build is mostly C source files, and some of them include a
>>> specific
>>> > header file, for example, #include "myheader.h"
>>> > But myheader.h is a generated file from some configuration
>>> files. I
>>> > have created a custom SCons builder, put under scons_tools, and it
>>> generates
>>> > this file when Scons runs.
>>> > However in parallel build, sometimes some source files get to
>>> compile
>>> > before myheader.h is generated, which results in error: myheader.h not
>>> > found.
>>> > And sometimes, when my custom SCons builder gets running, it
>>> reports
>>> > error, saying that it is unable to access this file because other
>>> process is
>>> > using it. In such case, myheader.h is only partially generated.
>>> > I know SCons reads all the SConscripts first then decides the
>>> order of
>>> > building itself. So is there any way to make the parallel build
>>> success?
>>> > Thanks all.
>>> >
>>> > Regards,
>>> >
>>> > Rafael
>>> >
>>> > _______________________________________________
>>> > Scons-users mailing list
>>> > Scons-***@scons.org
>>> > https://pairlist4.pair.net/mailman/listinfo/scons-users
>>> >
>>> _______________________________________________
>>> Scons-users mailing list
>>> Scons-***@scons.org
>>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>>
>>
>> _______________________________________________
>> Scons-users mailing list
>> Scons-***@scons.org
>> https://pairlist4.pair.net/mailman/listinfo/scons-users
>>
>
> _______________________________________________
> Scons-users mailing list
> Scons-***@scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>
>
Loading...