Scons: command-line build variables without restrictions on allowed values - scons

Used Scons version: 3.0.1 (for historic reasons)
I want to add a command-line build variable in my Scons script which is not limited by which values it expects. Both EnumVariable and ListVariable require you to provide a list of allowed values or elements.
I want a variable that (just like a C++ define can be passed to g++ via -Dfoo=bar (or at least -Dfoo_bar) ) can be passed to the Scons script.
Anything like
scons my_define=foo_bar
or
scons my_define=foo=bar,gnarl=argl
or
scons my_define=foo my_define=bar
would work.
I did not find anything like that in the user guide or searching via Google.
Is this possible? If yes, how?

Yes. It's in the users guide at
https://scons.org/doc/production/HTML/scons-user.html#idp140637539360912
While there are validated variable types provided by the various vars.Add*() methods. You can have a non-validated variable by just using plain vars.Add()
Here's an example from the manpage.
vars.Add('CC', help='The C compiler')

Related

How can I append to a construction variable in a Program() call?

I have a custom environment set up for my tests:
test_env = env.Clone()
test_env.Append(LIBS=['boost_unit_test_framework'])
But for one of my tests, I want to link against an additional library:
test_env.Program('foo_tests',
source='foo/tests.cpp',
LIBS=['extralib'],
LIBPATH=['.'])
Sadly this overrides the LIBS from the environment, when I'd like it to just add to it. Is there a better (i.e. more canonical) way to do this than LIBS=test_env['LIBS'] + ['extralib']?
Specifying a new value for an environment variable in a Builder call (like Program) is always interpreted as an "override". So there is no way around compiling the full replacement value, as you did in your example above.
The other option would be to Clone the environment "test_env" again, and then use Append to add the "extralib" to LIBS...
It's possible to do it like this:
test_env.Program('foo_tests',
source='foo/tests.cpp',
LIBS=['$LIBS', 'extralib'],
LIBPATH=['$LIBPATH', '.'])
SCons is clever enough to properly expand the variable into a list there.

How to check for the existence of a header of a package?

In Autoconf, when you want to check for the existence of some header, you do:
AC_CHECK_HEADERS([foo.h])
Now, let's suppose that I have some package, sponge, of which pkg-config knows, and I want to find out if it has a header named spongefoo.h.
I can do the following:
PKG_CHECK_MODULES([SPONGE])
CPPFLAGS="$CPPFLAGS $SPONGE_CFLAGS"
AC_CHECK_HEADERS([spongefoo.h])
This would work, but the Autoconf/Automake documentation says (my additions in brackets):
"Sometimes package developers are tempted to set user variables such as 'CFLAGS' [and, I add, 'CPPFLAGS'] because it appears to make their job easier. However, the package itself should never set a user variable, [...] To get around this problem, Automake introduces an automake-specific shadow variable [named AM_CPPFLAGS]"
However, AC_CHECK_HEADERS() and other test macros don't know about Automake's shadow variables.
So how do I properly check that a package has some header?
(BTW, AC_CHECK_HEADER() gets a 4'th argument, "INCLUDES", but this is a verbatim '"#include"' text, not a '"-I..."' switch, so it doesn't help me much.)
The requirement to temporarily set a user variable like CPPFLAGS to some value and run a compilation test while preserving the original value is actually done quite often. This is usually accomplished in Autoconf using a pattern similar to the following:
ac_save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $SPONGE_CFLAGS"
AC_CHECK_HEADERS([spongefoo.h])
CPPFLAGS=$ac_save_CPPFLAGS
Note that the ac_ shell variable prefix is informally reserved for Autoconf itself, you might want to use your own variable name like proj_save_CPPFLAGS.

SCons: how to explicitly express the dependencies between envs?

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?
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:
Why doesn't SCons implicitly figure out the dependencies?
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

Rename the 'makefile' build.exe expects to something that won't clash?

In the DDK/WDK the build.exe expects certain files in a folder. As soon as you give a sources file, you are also expected to have a makefile in the same folder. Obviously this name clashes with all kinds of make variants in a mixed source tree that is built on various platforms and tool chains.
Is there a way to name it something else, such as makefile.ddk and have nmake.exe (the backend to build.exe for this step) pick up on that other name?
I'm not afraid to script things, but I would prefer if I could pass an option to build.exe, e.g. via the /nmake args switch. I am using a range of DDKs/WDKs from the 2003 Server IFS Kit to the latest Windows 7 and 8 WDKs.
The /nmake option will do the job. I just tested this and it works:
build /nmake "/f makefile.ddk"
The quotes are necessary.

autoconf: AC_PROG_CC checks for object and executable suffix, but how to get this?

I'm a newbie to autoconf, and found out that a call of the macro AC_PROG_CC checks for the suffixes of executables and object files. Now I want to use the results of these checks and replace them in my Makefile.in, but there is no adequate documentation or mentioning in the autoconf docs on how to use this.
I'm also having the general problem: Which macro gives me which variables, and where is a reference to get know about?
Thanks for any help.
The variables you are looking for are #EXEEXT# and #OBJEXT#.
This link takes you to the index of all the output variables from the Autoconf manual.
Unfortunately there's no easy table of which ones are defined by which macros, you just have to read the descriptions.

Resources