From 72c578fd4b0b4a5a43e18594339ac4ff26c376dc Mon Sep 17 00:00:00 2001 From: Luca Falavigna Date: Sat, 2 Jan 2010 20:56:27 +0100 Subject: Imported Upstream version 1.2.0.d20091224 --- doc/user/environments.xml | 1684 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1684 insertions(+) create mode 100644 doc/user/environments.xml (limited to 'doc/user/environments.xml') diff --git a/doc/user/environments.xml b/doc/user/environments.xml new file mode 100644 index 0000000..b9a60b9 --- /dev/null +++ b/doc/user/environments.xml @@ -0,0 +1,1684 @@ + + + + + + + An environment + is a collection of values that + can affect how a program executes. + &SCons; distinguishes between three + different types of environments + that can affect the behavior of &SCons; itself + (subject to the configuration in the &SConscript; files), + as well as the compilers and other tools it executes: + + + + + + + External Environment + + + + + The external environment + is the set of variables in the user's environment + at the time the user runs &SCons;. + These variables are available within the &SConscript; files + through the Python os.environ dictionary. + See , below. + + + + + + + &ConsEnv; + + + + + A &consenv; + is a distinct object creating within + a &SConscript; file and + and which contains values that + affect how &SCons; decides + what action to use to build a target, + and even to define which targets + should be built from which sources. + One of the most powerful features of &SCons; + is the ability to create multiple &consenvs;, + including the ability to clone a new, customized + &consenv; from an existing &consenv;. + See , below. + + + + + + + Execution Environment + + + + + An execution environment + is the values that &SCons; sets + when executing an external + command (such as a compiler or linker) + to build one or more targets. + Note that this is not the same as + the external environment + (see above). + See , below. + + + + + + + + + + Unlike &Make;, &SCons; does not automatically + copy or import values between different environments + (with the exception of explicit clones of &consenvs;, + which inherit values from their parent). + This is a deliberate design choice + to make sure that builds are, + by default, repeatable regardless of + the values in the user's external environment. + This avoids a whole class of problems with builds + where a developer's local build works + because a custom variable setting + causes a different compiler or build option to be used, + but the checked-in change breaks the official build + because it uses different environment variable settings. + + + + + + Note that the &SConscript; writer can + easily arrange for variables to be + copied or imported between environments, + and this is often very useful + (or even downright necessary) + to make it easy for developers + to customize the build in appropriate ways. + The point is not + that copying variables between different environments + is evil and must always be avoided. + Instead, it should be up to the + implementer of the build system + to make conscious choices + about how and when to import + a variable from one environment to another, + making informed decisions about + striking the right balance + between making the build + repeatable on the one hand + and convenient to use on the other. + + + +
+ Using Values From the External Environment + + + + The external environment + variable settings that + the user has in force + when executing &SCons; + are available through the normal Python + os.environ + dictionary. + This means that you must add an + import os statement + to any &SConscript; file + in which you want to use + values from the user's external environment. + + + + + import os + + + + + More usefully, you can use the + os.environ + dictionary in your &SConscript; + files to initialize &consenvs; + with values from the user's external environment. + See the next section, + , + for information on how to do this. + + + +
+ +
+ Construction Environments + + + + It is rare that all of the software in a large, + complicated system needs to be built the same way. + For example, different source files may need different options + enabled on the command line, + or different executable programs need to be linked + with different libraries. + &SCons; accommodates these different build + requirements by allowing you to create and + configure multiple &consenvs; + that control how the software is built. + A &consenv; is an object + that has a number of associated + &consvars;, each with a name and a value. + (A construction environment also has an attached + set of &Builder; methods, + about which we'll learn more later.) + + + +
+ Creating a &ConsEnv;: the &Environment; Function + + + + A &consenv; is created by the &Environment; method: + + + + + env = Environment() + + + + + By default, &SCons; initializes every + new construction environment + with a set of &consvars; + based on the tools that it finds on your system, + plus the default set of builder methods + necessary for using those tools. + The construction variables + are initialized with values describing + the C compiler, + the Fortran compiler, + the linker, + etc., + as well as the command lines to invoke them. + + + + + + When you initialize a construction environment + you can set the values of the + environment's &consvars; + to control how a program is built. + For example: + + + + + import os + + env = Environment(CC = 'gcc', + CCFLAGS = '-O2') + + env.Program('foo.c') + + + + + The construction environment in this example + is still initialized with the same default + construction variable values, + except that the user has explicitly specified use of the + GNU C compiler &gcc;, + and further specifies that the -O2 + (optimization level two) + flag should be used when compiling the object file. + In other words, the explicit initializations of + &cv-link-CC; and &cv-link-CCFLAGS; + override the default values in the newly-created + construction environment. + So a run from this example would look like: + + + + + % scons -Q + gcc -o foo.o -c -O2 foo.c + gcc -o foo foo.o + + +
+ +
+ Fetching Values From a &ConsEnv; + + + + You can fetch individual construction variables + using the normal syntax + for accessing individual named items in a Python dictionary: + + + + + env = Environment() + print "CC is:", env['CC'] + + + + + This example &SConstruct; file doesn't build anything, + but because it's actually a Python script, + it will print the value of &cv-link-CC; for us: + + + + + % scons -Q + CC is: cc + scons: `.' is up to date. + + + + + A construction environment, however, + is actually an object with associated methods, etc. + If you want to have direct access to only the + dictionary of construction variables, + you can fetch this using the &Dictionary; method: + + + + + env = Environment(FOO = 'foo', BAR = 'bar') + dict = env.Dictionary() + for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']: + print "key = %s, value = %s" % (key, dict[key]) + + + + + This &SConstruct; file + will print the specified dictionary items for us on POSIX + systems as follows: + + + + + % scons -Q + key = OBJSUFFIX, value = .o + key = LIBSUFFIX, value = .a + key = PROGSUFFIX, value = + scons: `.' is up to date. + + + + + And on Windows: + + + + + C:\>scons -Q + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + key = OBJSUFFIX, value = .obj + key = LIBSUFFIX, value = .lib + key = PROGSUFFIX, value = .exe + scons: `.' is up to date. + + + + + If you want to loop and print the values of + all of the construction variables in a construction environment, + the Python code to do that in sorted order might look something like: + + + + + env = Environment() + dict = env.Dictionary() + keys = dict.keys() + keys.sort() + for key in keys: + print "construction variable = '%s', value = '%s'" % (key, dict[key]) + + +
+ +
+ Expanding Values From a &ConsEnv;: the &subst; Method + + + + Another way to get information from + a construction environment. + is to use the &subst; method + on a string containing $ expansions + of construction variable names. + As a simple example, + the example from the previous + section that used + env['CC'] + to fetch the value of &cv-link-CC; + could also be written as: + + + + + env = Environment() + print "CC is:", env.subst('$CC') + + + + + One advantage of using + &subst; to expand strings is + that construction variables + in the result get re-expanded until + there are no expansions left in the string. + So a simple fetch of a value like + &cv-link-CCCOM;: + + + + + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env['CCCOM'] + + + + + Will print the unexpanded value of &cv-CCCOM;, + showing us the construction + variables that still need to be expanded: + + + + + % scons -Q + CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES + scons: `.' is up to date. + + + + + Calling the &subst; method on $CCOM, + however: + + + + + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env.subst('$CCCOM') + + + + + Will recursively expand all of + the construction variables prefixed + with $ (dollar signs), + showing us the final output: + + + + + % scons -Q + CCCOM is: gcc -DFOO -c -o + scons: `.' is up to date. + + + + + Note that because we're not expanding this + in the context of building something + there are no target or source files + for &cv-link-TARGET; and &cv-link-SOURCES; to expand. + + + +
+ +
+ Controlling the Default &ConsEnv;: the &DefaultEnvironment; Function + + + + All of the &Builder; functions that we've introduced so far, + like &Program; and &Library;, + actually use a default &consenv; + that contains settings + for the various compilers + and other tools that + &SCons; configures by default, + or otherwise knows about + and has discovered on your system. + The goal of the default construction environment + is to make many configurations to "just work" + to build software using + readily available tools + with a minimum of configuration changes. + + + + + + You can, however, control the settings + in the default contstruction environment + by using the &DefaultEnvironment; function + to initialize various settings: + + + + + + DefaultEnvironment(CC = '/usr/local/bin/gcc') + + + + + + When configured as above, + all calls to the &Program; + or &Object; Builder + will build object files with the + /usr/local/bin/gcc + compiler. + + + + + + Note that the &DefaultEnvironment; function + returns the initialized + default construction environment object, + which can then be manipulated like any + other construction environment. + So the following + would be equivalent to the + previous example, + setting the &cv-CC; + variable to /usr/local/bin/gcc + but as a separate step after + the default construction environment has been initialized: + + + + + + env = DefaultEnvironment() + env['CC'] = '/usr/local/bin/gcc' + + + + + + One very common use of the &DefaultEnvironment; function + is to speed up &SCons; initialization. + As part of trying to make most default + configurations "just work," + &SCons; will actually + search the local system for installed + compilers and other utilities. + This search can take time, + especially on systems with + slow or networked file systems. + If you know which compiler(s) and/or + other utilities you want to configure, + you can control the search + that &SCons; performs + by specifying some specific + tool modules with which to + initialize the default construction environment: + + + + + + env = DefaultEnvironment(tools = ['gcc', 'gnulink'], + CC = '/usr/local/bin/gcc') + + + + + + So the above example would tell &SCons; + to explicitly configure the default environment + to use its normal GNU Compiler and GNU Linker settings + (without having to search for them, + or any other utilities for that matter), + and specifically to use the compiler found at + /usr/local/bin/gcc. + + + +
+ +
+ Multiple &ConsEnvs; + + + + The real advantage of construction environments + is that you can create as many different construction + environments as you need, + each tailored to a different way to build + some piece of software or other file. + If, for example, we need to build + one program with the -O2 flag + and another with the -g (debug) flag, + we would do this like so: + + + + + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + opt.Program('foo', 'foo.c') + + dbg.Program('bar', 'bar.c') + + + + % scons -Q + cc -o bar.o -c -g bar.c + cc -o bar bar.o + cc -o foo.o -c -O2 foo.c + cc -o foo foo.o + + + + + We can even use multiple construction environments to build + multiple versions of a single program. + If you do this by simply trying to use the + &b-link-Program; builder with both environments, though, + like this: + + + + + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + opt.Program('foo', 'foo.c') + + dbg.Program('foo', 'foo.c') + + + + + Then &SCons; generates the following error: + + + + + % scons -Q + + scons: warning: Two different environments were specified for target foo.o, + but they appear to have the same action: CCCom(target, source, env) + File "/home/my/project/SConstruct", line 6, in ? + + scons: warning: Two different environments were specified for target foo, + but they appear to have the same action: Cat(target, source, env) + File "/home/my/project/SConstruct", line 6, in ? + cc -o foo.o -c -g foo.c + cc -o foo foo.o + + + + + This is because the two &b-Program; calls have + each implicitly told &SCons; to generate an object file named + foo.o, + one with a &cv-link-CCFLAGS; value of + -O2 + and one with a &cv-link-CCFLAGS; value of + -g. + &SCons; can't just decide that one of them + should take precedence over the other, + so it generates the error. + To avoid this problem, + we must explicitly specify + that each environment compile + foo.c + to a separately-named object file + using the &b-link-Object; builder, like so: + + + + + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + + + + + Notice that each call to the &b-Object; builder + returns a value, + an internal &SCons; object that + represents the object file that will be built. + We then use that object + as input to the &b-Program; builder. + This avoids having to specify explicitly + the object file name in multiple places, + and makes for a compact, readable + &SConstruct; file. + Our &SCons; output then looks like: + + + + + % scons -Q + cc -o foo-dbg.o -c -g foo.c + cc -o foo-dbg foo-dbg.o + cc -o foo-opt.o -c -O2 foo.c + cc -o foo-opt foo-opt.o + + +
+ +
+ Making Copies of &ConsEnvs;: the &Clone; Method + + + + Sometimes you want more than one construction environment + to share the same values for one or more variables. + Rather than always having to repeat all of the common + variables when you create each construction environment, + you can use the &Clone; method + to create a copy of a construction environment. + + + + + + Like the &Environment; call that creates a construction environment, + the &Clone; method takes &consvar; assignments, + which will override the values in the copied construction environment. + For example, suppose we want to use &gcc; + to create three versions of a program, + one optimized, one debug, and one with neither. + We could do this by creating a "base" construction environment + that sets &cv-link-CC; to &gcc;, + and then creating two copies, + one which sets &cv-link-CCFLAGS; for optimization + and the other which sets &cv-CCFLAGS; for debugging: + + + + + env = Environment(CC = 'gcc') + opt = env.Clone(CCFLAGS = '-O2') + dbg = env.Clone(CCFLAGS = '-g') + + env.Program('foo', 'foo.c') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + + + + + Then our output would look like: + + + + + % scons -Q + gcc -o foo.o -c foo.c + gcc -o foo foo.o + gcc -o foo-dbg.o -c -g foo.c + gcc -o foo-dbg foo-dbg.o + gcc -o foo-opt.o -c -O2 foo.c + gcc -o foo-opt foo-opt.o + + +
+ +
+ Replacing Values: the &Replace; Method + + + + You can replace existing construction variable values + using the &Replace; method: + + + + + env = Environment(CCFLAGS = '-DDEFINE1') + env.Replace(CCFLAGS = '-DDEFINE2') + env.Program('foo.c') + + + + + The replacing value + (-DDEFINE2 in the above example) + completely replaces the value in the + construction environment: + + + + + % scons -Q + cc -o foo.o -c -DDEFINE2 foo.c + cc -o foo foo.o + + + + + You can safely call &Replace; + for construction variables that + don't exist in the construction environment: + + + + + env = Environment() + env.Replace(NEW_VARIABLE = 'xyzzy') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + + + + + In this case, + the construction variable simply + gets added to the construction environment: + + + + + % scons -Q + NEW_VARIABLE = xyzzy + scons: `.' is up to date. + + + + + Because the variables + aren't expanded until the construction environment + is actually used to build the targets, + and because &SCons; function and method calls + are order-independent, + the last replacement "wins" + and is used to build all targets, + regardless of the order in which + the calls to Replace() are + interspersed with calls to + builder methods: + + + + + env = Environment(CCFLAGS = '-DDEFINE1') + print "CCFLAGS =", env['CCFLAGS'] + env.Program('foo.c') + + env.Replace(CCFLAGS = '-DDEFINE2') + print "CCFLAGS =", env['CCFLAGS'] + env.Program('bar.c') + + + + + The timing of when the replacement + actually occurs relative + to when the targets get built + becomes apparent + if we run &scons; without the -Q + option: + + + + + % scons + scons: Reading SConscript files ... + CCFLAGS = -DDEFINE1 + CCFLAGS = -DDEFINE2 + scons: done reading SConscript files. + scons: Building targets ... + cc -o bar.o -c -DDEFINE2 bar.c + cc -o bar bar.o + cc -o foo.o -c -DDEFINE2 foo.c + cc -o foo foo.o + scons: done building targets. + + + + + Because the replacement occurs while + the &SConscript; files are being read, + the &cv-link-CCFLAGS; + variable has already been set to + -DDEFINE2 + by the time the &foo_o; target is built, + even though the call to the &Replace; + method does not occur until later in + the &SConscript; file. + + + +
+ +
+ Setting Values Only If They're Not Already Defined: the &SetDefault; Method + + + + Sometimes it's useful to be able to specify + that a construction variable should be + set to a value only if the construction environment + does not already have that variable defined + You can do this with the &SetDefault; method, + which behaves similarly to the set_default + method of Python dictionary objects: + + + + + env.SetDefault(SPECIAL_FLAG = '-extra-option') + + + + + This is especially useful + when writing your own Tool modules + to apply variables to construction environments. + + + + +
+ +
+ Appending to the End of Values: the &Append; Method + + + + You can append a value to + an existing construction variable + using the &Append; method: + + + + + env = Environment(CCFLAGS = ['-DMY_VALUE']) + env.Append(CCFLAGS = ['-DLAST']) + env.Program('foo.c') + + + + + &SCons; then supplies both the -DMY_VALUE and + -DLAST flags when compiling the object file: + + + + + % scons -Q + cc -o foo.o -c -DMY_VALUE -DLAST foo.c + cc -o foo foo.o + + + + + If the construction variable doesn't already exist, + the &Append; method will create it: + + + + + env = Environment() + env.Append(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + + + + + Which yields: + + + + + % scons -Q + NEW_VARIABLE = added + scons: `.' is up to date. + + + + + Note that the &Append; function tries to be "smart" + about how the new value is appended to the old value. + If both are strings, the previous and new strings + are simply concatenated. + Similarly, if both are lists, + the lists are concatenated. + If, however, one is a string and the other is a list, + the string is added as a new element to the list. + + + +
+ +
+ Appending Unique Values: the &AppendUnique; Method + + + + Some times it's useful to add a new value + only if the existing construction variable + doesn't already contain the value. + This can be done using the &AppendUnique; method: + + + + + env.AppendUnique(CCFLAGS=['-g']) + + + + + In the above example, + the -g would be added + only if the &cv-CCFLAGS; variable + does not already contain a -g value. + + + +
+ +
+ Appending to the Beginning of Values: the &Prepend; Method + + + + You can append a value to the beginning of + an existing construction variable + using the &Prepend; method: + + + + + env = Environment(CCFLAGS = ['-DMY_VALUE']) + env.Prepend(CCFLAGS = ['-DFIRST']) + env.Program('foo.c') + + + + + &SCons; then supplies both the -DFIRST and + -DMY_VALUE flags when compiling the object file: + + + + + % scons -Q + cc -o foo.o -c -DFIRST -DMY_VALUE foo.c + cc -o foo foo.o + + + + + If the construction variable doesn't already exist, + the &Prepend; method will create it: + + + + + env = Environment() + env.Prepend(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + + + + + Which yields: + + + + + % scons -Q + NEW_VARIABLE = added + scons: `.' is up to date. + + + + + Like the &Append; function, + the &Prepend; function tries to be "smart" + about how the new value is appended to the old value. + If both are strings, the previous and new strings + are simply concatenated. + Similarly, if both are lists, + the lists are concatenated. + If, however, one is a string and the other is a list, + the string is added as a new element to the list. + + + +
+ +
+ Prepending Unique Values: the &PrependUnique; Method + + + + Some times it's useful to add a new value + to the beginning of a construction variable + only if the existing value + doesn't already contain the to-be-added value. + This can be done using the &PrependUnique; method: + + + + + env.PrependUnique(CCFLAGS=['-g']) + + + + + In the above example, + the -g would be added + only if the &cv-CCFLAGS; variable + does not already contain a -g value. + + + +
+ +
+ +
+ Controlling the Execution Environment for Issued Commands + + + + When &SCons; builds a target file, + it does not execute the commands with + the same external environment + that you used to execute &SCons;. + Instead, it uses the dictionary + stored in the &cv-link-ENV; construction variable + as the external environment + for executing commands. + + + + + + The most important ramification of this behavior + is that the &PATH; environment variable, + which controls where the operating system + will look for commands and utilities, + is not the same as in the external environment + from which you called &SCons;. + This means that &SCons; will not, by default, + necessarily find all of the tools + that you can execute from the command line. + + + + + + The default value of the &PATH; environment variable + on a POSIX system + is /usr/local/bin:/bin:/usr/bin. + The default value of the &PATH; environment variable + on a Windows system comes from the Windows registry + value for the command interpreter. + If you want to execute any commands--compilers, linkers, etc.--that + are not in these default locations, + you need to set the &PATH; value + in the &cv-ENV; dictionary + in your construction environment. + + + + + + The simplest way to do this is to initialize explicitly + the value when you create the construction environment; + this is one way to do that: + + + + + path = ['/usr/local/bin', '/bin', '/usr/bin'] + env = Environment(ENV = {'PATH' : path}) + + + + + Assign a dictionary to the &cv-ENV; + construction variable in this way + completely resets the external environment + so that the only variable that will be + set when external commands are executed + will be the &PATH; value. + If you want to use the rest of + the values in &cv-ENV; and only + set the value of &PATH;, + the most straightforward way is probably: + + + + + env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] + + + + + Note that &SCons; does allow you to define + the directories in the &PATH; in a string, + separated by the pathname-separator character + for your system (':' on POSIX systems, ';' on Windows): + + + + + env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' + + + + + But doing so makes your &SConscript; file less portable, + (although in this case that may not be a huge concern + since the directories you list are likley system-specific, anyway). + + + + + +
+ Propagating &PATH; From the External Environment + + + + You may want to propagate the external &PATH; + to the execution environment for commands. + You do this by initializing the &PATH; + variable with the &PATH; value from + the os.environ + dictionary, + which is Python's way of letting you + get at the external environment: + + + + + import os + env = Environment(ENV = {'PATH' : os.environ['PATH']}) + + + + + Alternatively, you may find it easier + to just propagate the entire external + environment to the execution environment + for commands. + This is simpler to code than explicity + selecting the &PATH; value: + + + + + import os + env = Environment(ENV = os.environ) + + + + + Either of these will guarantee that + &SCons; will be able to execute + any command that you can execute from the command line. + The drawback is that the build can behave + differently if it's run by people with + different &PATH; values in their environment--for example, + if both the /bin and + /usr/local/bin directories + have different &cc; commands, + then which one will be used to compile programs + will depend on which directory is listed + first in the user's &PATH; variable. + + + +
+ +
+ Adding to <varname>PATH</varname> Values in the Execution Environment + + + + One of the most common requirements + for manipulating a variable in the execution environment + is to add one or more custom directories to a search + like the $PATH variable on Linux or POSIX systems, + or the %PATH% variable on Windows, + so that a locally-installed compiler or other utility + can be found when &SCons; tries to execute it to update a target. + &SCons; provides &PrependENVPath; and &AppendENVPath; functions + to make adding things to execution variables convenient. + You call these functions by specifying the variable + to which you want the value added, + and then value itself. + So to add some /usr/local directories + to the $PATH and $LIB variables, + you might: + + + + + env = Environment(ENV = os.environ) + env.PrependENVPath('PATH', '/usr/local/bin') + env.AppendENVPath('LIB', '/usr/local/lib') + + + + + Note that the added values are strings, + and if you want to add multiple directories to + a variable like $PATH, + you must include the path separate character + (: on Linux or POSIX, + ; on Windows) + in the string. + + + +
+ +
-- cgit v1.2.3