<!ENTITY Options "<function>Options</function>">
<!ENTITY PackageOption "<function>PackageOption</function>">
<!ENTITY PathOption "<function>PathOption</function>">
+<!ENTITY PathOption_PathAccept "<function>PathOption.PathAccept</function>">
+<!ENTITY PathOption_PathExists "<function>PathOption.PathExists</function>">
+<!ENTITY PathOption_PathIsDir "<function>PathOption.PathIsDir</function>">
+<!ENTITY PathOption_PathIsDirCreate "<function>PathOption.PathIsDirCreate</function>">
+<!ENTITY PathOption_PathIsFile "<function>PathOption.PathIsFile</function>">
<!ENTITY Precious "<function>Precious</function>">
<!ENTITY Prepend "<function>Prepend</function>">
<!ENTITY Replace "<function>Replace</function>">
<command>scons -Q CONFIG=__ROOT__/usr/local/etc/other_config foo.o</command>
</scons_output>
+ <para>
+
+ By default, &PathOption; checks to make sure
+ that the specified path exists and generates an error if it
+ doesn't:
+
+ </para>
+
+ <scons_output example="PathOption">
+ <command>scons -Q CONFIG=__ROOT__/does/not/exist foo.o</command>
+ </scons_output>
+
+ <para>
+
+ &PathOption; provides a number of methods
+ that you can use to change this behavior.
+ If you want to ensure that any specified paths are,
+ in fact, files and not directories,
+ use the &PathOption_PathIsFile; method:
+
+ </para>
+
+ <scons_example name="PathIsFile">
+ <file name="SConstruct" printme="1">
+ opts = Options('custom.py')
+ opts.Add(PathOption('CONFIG',
+ 'Path to configuration file',
+ '__ROOT__/etc/my_config',
+ PathOption.PathIsFile))
+ env = Environment(options = opts,
+ CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/etc/my_config">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ Conversely, to ensure that any specified paths are
+ directories and not files,
+ use the &PathOption_PathIsDir; method:
+
+ </para>
+
+ <scons_example name="PathIsDir">
+ <file name="SConstruct" printme="1">
+ opts = Options('custom.py')
+ opts.Add(PathOption('DBDIR',
+ 'Path to database directory',
+ '__ROOT__/var/my_dbdir',
+ PathOption.PathIsDir))
+ env = Environment(options = opts,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/var/my_dbdir">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ If you want to make sure that any specified paths
+ are directories,
+ and you would like the directory created
+ if it doesn't already exist,
+ use the &PathOption_PathIsDirCreate; method:
+
+ </para>
+
+ <scons_example name="PathIsDirCreate">
+ <file name="SConstruct" printme="1">
+ opts = Options('custom.py')
+ opts.Add(PathOption('DBDIR',
+ 'Path to database directory',
+ '__ROOT__/var/my_dbdir',
+ PathOption.PathIsDirCreate))
+ env = Environment(options = opts,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="__ROOT__/var/my_dbdir">
+ /opt/location
+ </file>
+ </scons_example>
+
+ <para>
+
+ Lastly, if you don't care whether the path exists,
+ is a file, or a directory,
+ use the &PathOption_PathAccept; method
+ to accept any path that the user supplies:
+
+ </para>
+
+ <scons_example name="PathAccept">
+ <file name="SConstruct" printme="1">
+ opts = Options('custom.py')
+ opts.Add(PathOption('OUTPUT',
+ 'Path to output file or directory',
+ None,
+ PathOption.PathAccept))
+ env = Environment(options = opts,
+ CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
+ env.Program('foo.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ </scons_example>
+
</section>
<section>
scons: `foo.o' is up to date.
</screen>
+ <para>
+
+ By default, &PathOption; checks to make sure
+ that the specified path exists and generates an error if it
+ doesn't:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput>
+
+ scons: *** Path for option CONFIG does not exist: /does/not/exist
+ File "SConstruct", line 6, in ?
+ </screen>
+
+ <para>
+
+ &PathOption; provides a number of methods
+ that you can use to change this behavior.
+ If you want to ensure that any specified paths are,
+ in fact, files and not directories,
+ use the &PathOption_PathIsFile; method:
+
+ </para>
+
+ <programlisting>
+ opts = Options('custom.py')
+ opts.Add(PathOption('CONFIG',
+ 'Path to configuration file',
+ '/etc/my_config',
+ PathOption.PathIsFile))
+ env = Environment(options = opts,
+ CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Conversely, to ensure that any specified paths are
+ directories and not files,
+ use the &PathOption_PathIsDir; method:
+
+ </para>
+
+ <programlisting>
+ opts = Options('custom.py')
+ opts.Add(PathOption('DBDIR',
+ 'Path to database directory',
+ '/var/my_dbdir',
+ PathOption.PathIsDir))
+ env = Environment(options = opts,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ If you want to make sure that any specified paths
+ are directories,
+ and you would like the directory created
+ if it doesn't already exist,
+ use the &PathOption_PathIsDirCreate; method:
+
+ </para>
+
+ <programlisting>
+ opts = Options('custom.py')
+ opts.Add(PathOption('DBDIR',
+ 'Path to database directory',
+ '/var/my_dbdir',
+ PathOption.PathIsDirCreate))
+ env = Environment(options = opts,
+ CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+ env.Program('foo.c')
+ </programlisting>
+
+ <para>
+
+ Lastly, if you don't care whether the path exists,
+ is a file, or a directory,
+ use the &PathOption_PathAccept; method
+ to accept any path that the user supplies:
+
+ </para>
+
+ <programlisting>
+ opts = Options('custom.py')
+ opts.Add(PathOption('OUTPUT',
+ 'Path to output file or directory',
+ None,
+ PathOption.PathAccept))
+ env = Environment(options = opts,
+ CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
+ env.Program('foo.c')
+ </programlisting>
+
</section>
<section>
which cleans up a lot of special-case code in various methods and
caches additional values to speed up most configurations.
+ - Add a PathAccept validator to the list of new canned PathOption
+ validators.
+
From Levi Stephen:
- Allow $JARCHDIR to be expanded to other construction variables.
-"""engine.SCons.Options.PathOption
+"""SCons.Options.PathOption
-This file defines an option type for SCons implementing 'package
-activation'.
+This file defines an option type for SCons implementing path settings.
-To be used whenever a 'package' may be enabled/disabled and the
-package path may be specified.
+To be used whenever a a user-specified path override should be allowed.
+
+Arguments to PathOption are:
+ option-name = name of this option on the command line (e.g. "prefix")
+ option-help = help string for option
+ option-dflt = default value for this option
+ validator = [optional] validator for option value. Predefined
+ validators are:
+
+ PathAccept -- accepts any path setting; no validation
+ PathIsDir -- path must be an existing directory
+ PathIsDirCreate -- path must be a dir; will create
+ PathIsFile -- path must be a file
+ PathExists -- path must exist (any type) [default]
+
+ The validator is a function that is called and which
+ should return True or False to indicate if the path
+ is valid. The arguments to the validator function
+ are: (key, val, env). The key is the name of the
+ option, the val is the path specified for the option,
+ and the env is the env to which the Otions have been
+ added.
Usage example:
Examples:
- x11=no (disables X11 support)
- x11=yes (will search for the package installation dir)
- x11=/usr/local/X11 (will check this path for existance)
-
- To replace autoconf's --with-xxx=yyy
+ prefix=/usr/local
opts = Options()
opts = Options()
opts.Add(PathOption('qtdir',
'where the root of Qt is installed',
- qtdir))
+ qtdir, PathIsDir))
opts.Add(PathOption('qt_includes',
'where the Qt includes are installed',
- '$qtdir/includes'))
+ '$qtdir/includes', PathIsDirCreate))
opts.Add(PathOption('qt_libraries',
'where the Qt library is installed',
'$qtdir/lib'))
class _PathOptionClass:
+ def PathAccept(self, key, val, env):
+ """Accepts any path, no checking done."""
+ pass
+
def PathIsDir(self, key, val, env):
"""Validator to check if Path is a directory."""
if not os.path.isdir(val):
are returned with the correct converter and validator appended. The
result is usable for input to opts.Add() .
- A 'package list' option may either be 'all', 'none' or a list of
- package names (seperated by space).
+ The 'default' option specifies the default path to use if the
+ user does not specify an override with this option.
validator is a validator, see this file for examples
"""
except:
raise "did not catch expected UserError"
+ def test_PathAccept(self):
+ """Test the PathAccept validator"""
+ opts = SCons.Options.Options()
+ opts.Add(SCons.Options.PathOption('test',
+ 'test option help',
+ '/default/path',
+ SCons.Options.PathOption.PathAccept))
+
+ test = TestCmd.TestCmd(workdir='')
+ test.subdir('dir')
+ test.write('file', "file\n")
+
+ o = opts.options[0]
+
+ o.validator('X', test.workpath('file'), {})
+
+ d = test.workpath('d')
+ o.validator('X', d, {})
+
+ dne = test.workpath('does_not_exist')
+ o.validator('X', dne, {})
+
def test_validator(self):
"""Test the PathOption validator argument"""
opts = SCons.Options.Options()
+test.write('SConstruct', """\
+opts = Options(args=ARGUMENTS)
+opts.AddOptions(
+ PathOption('X', 'X variable', r'%s', validator=PathOption.PathAccept),
+ )
+
+env = Environment(options=opts)
+
+print env['X']
+
+Default(env.Alias('dummy', None))
+""" % default_subdir)
+
+test.run()
+check([default_subdir])
+
+test.run(arguments='"X=%s"' % existing_file)
+check([existing_file])
+
+test.run(arguments='"X=%s"' % non_existing_file)
+check([non_existing_file])
+
+test.run(arguments='"X=%s"' % existing_subdir)
+check([existing_subdir])
+
+test.run(arguments='"X=%s"' % non_existing_subdir)
+check([non_existing_subdir])
+
+test.must_not_exist(non_existing_file)
+test.must_not_exist(non_existing_subdir)
+
+
+
test.write('SConstruct', """\
opts = Options(args=ARGUMENTS)
opts.AddOptions(