Question

I have a project build by scons. In the project there are multiple components, including client, shell, engine and etc...

Each component uses different compile options so they are split into different env. And both shell and engine are going to require client libraries built first.

In the environment settings, both shell and engine has something like "-lclient -L[installpath]/lib", and SConscriptClient is going to build the libclient.a in [installpath]/lib.

So I expect SConscriptClient is run before everything else.

so in the code I have something like:

  clientbuild = clientEnv.SConscript ( 'SConscriptClient', variant_dir=clientDir )
  if hasShell:
     shellbuild = shellEnv.SConscript ( 'SConscriptShell', variant_dir=shellDir )
     Depends ( shellbuild, clientbuild )
  if hasEngine:
     enginebuild = engineEnv.SConscript ( 'SConscriptEngine', variant_dir=engineDir )
     Depends ( enginebuild, clientbuild )

However it seems scons is not smart enough to understand the dependencies between client/shell and engine ( that means the Depends call doesn't take effect ). It still try to run SConscriptShell before SConscriptClient

Is there anything i can do to set the dependeices between sconscript?

Was it helpful?

Solution

You shouldn't have to explicitly set these dependencies with Depends(). If the client library is a target built by SCons and both the shell and engine link that library, then SCons should be able to implicitly determine the dependencies and build the client first.

Basically, I see 2 issues here:

  1. Why doesn't SCons implicitly figure out the dependencies?
  2. Why isn't it working as is with the explicit calls to Depends()?

If we figure out number 1, then we wont have to figure out number 2. But just to be complete, I think number 2 isnt working because of what the call to SConscript() is returning. In the subsidiary SConscript scripts (SConscriptClient, SConscriptShell, and SConscriptEngine) are you returning the target? If not, I would imagine the clientbuild variable would be None. To return the target use the Return() SCons function and pass it the return value of the Library() builder.

As for why SCons cant figure out the dependencies implicitly, we would need to see the subsidiary SConscript build scripts. But I can imagine its because you are probably specifying the client library "by hand", so SCons doesnt see the dependency.

The way to build a program with a library so that SCons can see the dependency, you need to use the LIBS construction variable, as follows:

env.Append(LIBS='client')
env.Append(LIBPATH='path/to/client/lib')
env.Program(target='shell', source='shell.cc')

Notice I don't use the -l nor the -L flags above, SCons will add those in a platform independent manner. If you're specifying the library "by hand" by specifying it like this: '-lclient' then SCons wont see the dependency. This is by design, and is more interesting with include paths: if you have a lot of include paths with header files that will almost never change, then (for performance reasons) you don't want SCons to scan them for changes, and thus specify them "by hand".

One additional comment, normally the different environments are passed to the subsidiary SConscript build scripts differently, as follows:

clientEnv = Environment()
# set the clientEnv accordingly
SConscript ('SConscriptClient', variant_dir=clientDir, exports=['clientEnv'] )

SConscriptClient:

Import('clientEnv')
# You may want to clone the clientEnv here, if you want to make 
# changes that you don't want seen in the rest of the build
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top