From 6624c057abbd9f29cf296e4a53ef4021c9b64df4 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 19 Apr 2021 10:12:19 -0600 Subject: Tweaking of Action Objects docu, update Mkdir() Mostly it's just fiddling; did add a pointer to information on Chmod() on Windows, and that Mkdir() makes intermediate dirs and takes a list as well as a string. While resolving some doc questions, found the function used by Makedir() could be simplified by passing exist_ok=True to os.makedirs(). Signed-off-by: Mats Wichmann --- CHANGES.txt | 2 + SCons/Defaults.py | 11 +-- SCons/Environment.xml | 2 +- doc/man/scons.xml | 242 +++++++++++++++++++++++++++----------------------- 4 files changed, 133 insertions(+), 124 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d907867..9ce5a8a 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -78,6 +78,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Deprecate Python 3.5 as a supported version. - CPPDEFINES now expands construction variable references (issue 2363) - Restore behavior that Install()'d files are writable (issue 3927) + - Simplified Mkdir(), the internal mkdir_func no longer needs to handle + existing directories, it can now pass exist_ok=True to os.makedirs(). From Dillan Mills: - Add support for the (TARGET,SOURCE,TARGETS,SOURCES,CHANGED_TARGETS,CHANGED_SOURCES}.relpath property. diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 6dabfb5..50c30c6 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -309,16 +309,7 @@ def mkdir_func(dest): if not SCons.Util.is_List(dest): dest = [dest] for entry in dest: - try: - os.makedirs(str(entry)) - except os.error as e: - p = str(entry) - if (e.args[0] == errno.EEXIST or - (sys.platform == 'win32' and e.args[0] == 183)) \ - and os.path.isdir(str(entry)): - pass # not an error if already exists - else: - raise + os.makedirs(str(entry), exist_ok=True) Mkdir = ActionFactory(mkdir_func, diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 945ed9c..27e7302 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -258,7 +258,7 @@ a subclass of the SCons.CacheDir.CacheDir class. -(action, [cmd/str/fun, [var, ...]] [option=value, ...]) +(action, [output, [var, ...]] [key=value, ...]) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 3f7eef9..1ffc1a4 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2753,14 +2753,15 @@ Builder methods take two required arguments: and source. Either can be passed as a scalar or as a list. -The target and source arguments +The target and +source arguments can be specified either as positional arguments, in which case target comes first, or as keyword arguments, using target= and source=. -Although both arguments are required, -in one particular case the target argument can actually be omitted -because it can be inferred and &SCons; supplies it (see below). +Although both arguments are nominally required, +if there is a single source and the target can be inferred +the target argument can be omitted (see below). Builder methods also take a variety of keyword arguments, described below. @@ -2830,7 +2831,8 @@ to a relative or absolute path first. -Target and source pathnames can be absolute, relative, or +target and source +can be absolute, relative, or top-relative. Relative pathnames are searched considering the directory of the SConscript file currently being processed as the "current directory". @@ -3098,9 +3100,10 @@ bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR') print("The path to bar_obj is:", str(bar_obj_list[0])) -Note again that because the Builder call returns a list, -you have to access the first element in the list -((bar_obj_list[0])) +Note that because the Builder call returns a +NodeList, +you have to access the first element in the list, +(bar_obj_list[0] in the example) to get at the Node that actually represents the object file. @@ -3162,6 +3165,19 @@ and to use just the filename portion of the targets and source. + +When trying to handle errors that may occur in a builder method, +consider that the corresponding Action is executed at a different +time than the SConscript file statement calling the builder. +It is not useful to wrap a builder call in a +try block, +since success in the builder call is not the same as +the builder itself succeeding. +If necessary, a Builder's Action should be coded to exit with +a useful exception message indicating the problem in the SConscript files - +programmatically recovering from build errors is rarely useful. + + &scons; predefines the following builder methods. Depending on the setup of a particular @@ -5785,25 +5801,25 @@ you need to create the action object using &f-Action;. The &Action; factory function returns an appropriate object for the action -represented by the type of the action argument +represented by the type of the +action argument (the first positional parmeter): -If the action argument is already an Action object, +If action is already an Action object, the object is simply returned. -If the action argument is a string, +If action is a string, a command-line Action is returned. -If such a string begins with -@, -it indicates printing of the command line is to be suppressed. -If the string begins with -- (hyphen), -it indicates the exit status from the specified command -is to be ignored, allowing execution to continue +If such a string begins with @, +the command line is not printed. +If the string begins with hyphen +(-), +the exit status from the specified command +is ignored, allowing execution to continue even if the command reports failure: @@ -5818,14 +5834,13 @@ Action('-build $TARGET $SOURCES') -If the action argument is a list, +If action is a list, then a list of Action objects is returned. An Action object is created as necessary for each element in the list. -If an element -within +If an element within the list is itself a list, -the internal list is taken as the +the embedded list is taken as the command and arguments to be executed via the command line. This allows white space to be enclosed @@ -5838,18 +5853,22 @@ Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']]) -If the action argument is a Python function, -a function Action is returned. -The Python function must accept three keyword arguments: +If action is a Python callable +a Function Action is returned. +The callable must accept three keyword arguments: +target, +source and +env. + - - target - - a Node object representing the target file. - source - - a Node object representing the source file. - env - - the &consenv; used for building the target file. - + +target +is a Node object representing the target file, +source +is a Node object representing the source file and +env +is the &consenv; used for building the target file. + The @@ -5886,17 +5905,22 @@ a = Action(build_it) -If the action argument is not one of the above types, -None is returned. +If +action +is not one of the above types, +no action object is generated and &f-Action; +returns None. -As usual the environment method form &f-link-env-Action; +The environment method form &f-link-env-Action; will expand &consvars; in any argument strings, -including the action argument, at the time it is called, +including +action, +at the time it is called, using the construction variables in the &consenv; through which it was called. The global function form &f-link-Action; -delays variable expansion until +delays variable expansion until the Action object is actually used. @@ -5912,30 +5936,7 @@ The following argument types are accepted: -If the output argument is a function, -the function will be called to obtain a string -describing the action being executed. -The function -must accept these three keyword arguments: - - - source - - a Node object representing the source file. - target - - a Node object representing the target file. - env - the &consenv;. - - -The -target -and -source -arguments may be lists of Node objects if there is -more than one target file or source file. - - - -If the output argument is a string, +If output is a string, substitution is performed on the string before it is printed. The string typically contains variables, notably $TARGET(S) and $SOURCE(S), @@ -5945,7 +5946,21 @@ variable, which is optionally defined somewhere else. -If the argument is None, +If output is a function, +the function will be called to obtain a string +describing the action being executed. +The function +must accept three keyword arguments: +target, +source and +env, +with the same interpretation as for a callable +action argument above. + + + + +If outputis None, output is suppressed entirely. @@ -6022,30 +6037,25 @@ to modify the Action object's behavior: chdir -Specifies that -scons will execute the action -after changing to the specified directory. -If the -chdir -argument is -a string or a directory Node, -scons will change to the specified directory. -If the -chdir -argument -is not a string or Node -and is non-zero, -then scons will change to the +If chdir is true +(the default is False), +&SCons; will change directories before +executing the action. +If the value of chdir +is a string or a directory Node, +&SCons; will change to the specified directory. +Otherwise, if chdir evaluates true, +&SCons; will change to the target file's directory. -Note that scons will +Note that &SCons; will not automatically modify its expansion of &consvars; like &cv-TARGET; and &cv-SOURCE; when using the chdir -keyword argument--that is, +parameter - that is, the expanded file names will still be relative to the top-level directory containing the &SConstruct; file, @@ -6061,8 +6071,7 @@ to use just the filename portion of the targets and source. Example: -a = Action("build < ${SOURCE.file} > ${TARGET.file}", - chdir=1) +a = Action("build < ${SOURCE.file} > ${TARGET.file}", chdir=True) @@ -6070,11 +6079,10 @@ a = Action("build < ${SOURCE.file} > ${TARGET.file}", exitstatfunc -A function -that is passed the exit status -(or return value) -from the specified action -and can return an arbitrary +If provided, must be a callable which accepts a single parameter, +the exit status (or return value) +from the specified action, +and which returns an arbitrary or modified value. This can be used, for example, to specify that an Action object's @@ -6097,7 +6105,7 @@ a = Action("build < ${SOURCE.file} > ${TARGET.file}", batch_key -Specifies that the Action can create multiple target files +If provided, indicates that the Action can create multiple target files by processing multiple independent source files simultaneously. (The canonical example is "batch compilation" of multiple object files @@ -6134,33 +6142,33 @@ will be used to identify different for batch building. A batch_key -function must accept the following arguments: - - - action - The action object. - env - - The &consenv; configured for the target. - target - - The list of targets for a particular configured action. - source - - The list of source for a particular configured action. - +function must accept four parameters: +action, +env, +target and +source. +The first parameter, action, +is the active action object. +The second parameter, env, +is the &consenv; configured for the target. +The target and source +parameters are the lists of targets and sources +for the configured action. + The returned key should typically be a tuple of values derived from the arguments, using any appropriate logic to decide how multiple invocations should be batched. For example, a -batch_key +batch_key function may decide to return -the value of a specific construction -variable from the -env -argument +the value of a specific &consvar; +from env which will cause &scons; to batch-build targets -with matching values of that variable, +with matching values of that &consvar;, or perhaps return the Python id() of the entire &consenv;, @@ -6197,8 +6205,8 @@ a = Action('build $CHANGED_SOURCES', batch_key=batch_key) Miscellaneous Action Functions -&scons; -supplies a number of functions +&SCons; +supplies Action functions that arrange for various common file and directory manipulations to be performed. @@ -6213,8 +6221,8 @@ return an Action object that can be executed at the appropriate time. -In practice, -there are two natural ways + +There are two natural ways that these Action Functions are intended to be used. @@ -6226,7 +6234,7 @@ at the time the SConscript file is being read, you can use the &f-link-Execute; -global function to do so: +global function: Execute(Touch('file')) @@ -6284,6 +6292,12 @@ env.Command('foo.out', 'foo.in', Chmod('$TARGET', "ugo+w")]) + +The behavior of Chmod is limited on Windows, +see the notes in the Python documentation for +os.chmod, which is the underlying function. + + @@ -6346,12 +6360,14 @@ Execute(Delete('file_that_must_exist', must_exist=True)) - Mkdir(dir) + Mkdir(name) Returns an Action -that creates the specified -directory -dir. +that creates the directory +name +and all needed intermediate directories. +name may also be a list +of directories to create. Examples: -- cgit v0.12