From 13c61768b4ff739e2599b0de3f90a8efe15dd9fc Mon Sep 17 00:00:00 2001 From: Gary Oberbrunner Date: Sun, 4 Jul 2010 00:14:53 +0000 Subject: Add all the per-system and per-user site_scons dirs, per discussion in SEP 002. --- doc/man/scons.1 | 58 ++++++++++++++++++++++++++++----- doc/user/builders-writing.in | 26 +++++++++++---- src/CHANGES.txt | 4 +++ src/RELEASE.txt | 5 +++ src/engine/SCons/Script/Main.py | 62 +++++++++++++++++++++++++++++++---- test/site_scons/sysdirs.py | 71 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+), 21 deletions(-) create mode 100644 test/site_scons/sysdirs.py diff --git a/doc/man/scons.1 b/doc/man/scons.1 index da6c918..4f3b1a3 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -100,17 +100,17 @@ file, .B scons looks for a directory named .I site_scons -in the directory containing the +in various system directories (see below) and the directory containing the .I SConstruct -file; if it exists, +file; for each of those dirs which exists, .I site_scons -is added to sys.path, +is prepended to sys.path, the file .IR site_scons/site_init.py , is evaluated if it exists, and the directory .I site_scons/site_tools -is added to the default toolpath if it exist. +is prepended to the default toolpath if it exists. See the .I --no-site-dir and @@ -1095,13 +1095,13 @@ any out-of-date target files, but do not execute the commands. .RI --no-site-dir Prevents the automatic addition of the standard .I site_scons -dir to +dirs to .IR sys.path . Also prevents loading the .I site_scons/site_init.py -module if it exists, and prevents adding +modules if they exist, and prevents adding their .I site_scons/site_tools -to the toolpath. +dirs to the toolpath. .\" .TP .\" .RI -o " file" ", --old-file=" file ", --assume-old=" file @@ -1182,7 +1182,7 @@ Ignored for compatibility with GNU .RI --site-dir= dir Uses the named dir as the site dir rather than the default .I site_scons -dir. This dir will get prepended to +dirs. This dir will get prepended to .IR sys.path , the module .IR dir /site_init.py @@ -1190,6 +1190,48 @@ will get loaded if it exists, and .IR dir /site_tools will get added to the default toolpath. +The default set of +.I site_scons +dirs used when +.I --site-dir +is not specified depends on the system platform, as follows. Note +that the directories are examined in the order given, from most +generic to most specific, so the last-executed site_init.py file is +the most specific one (which gives it the chance to override +everything else), and the dirs are prepended to the paths, again so +the last dir examined comes first in the resulting path. + +.IP "Windows:" +.nf + %ALLUSERSPROFILE/Application Data/scons/site_scons + %USERPROFILE%/Local Settings/Application Data/scons/site_scons + %APPDATA%/scons/site_scons + %HOME%/.scons/site_scons + ./site_scons +.fi +.IP "Mac OS X:" +.nf + /Library/Application Support/SCons/site_scons + /opt/local/share/scons/site_scons (for MacPorts) + /sw/share/scons/site_scons (for Fink) + $HOME/Library/Application Support/SCons/site_scons + $HOME/.scons/site_scons + ./site_scons +.fi +.IP "Solaris:" +.nf + /opt/sfw/scons/site_scons + /usr/share/scons/site_scons + $HOME/.scons/site_scons + ./site_scons +.fi +.IP "Linux, HPUX, and other Posix-like systems:" +.nf + /usr/share/scons/site_scons + $HOME/.scons/site_scons + ./site_scons +.fi + .TP .RI --stack-size= KILOBYTES Set the size stack used to run threads to diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in index 1da45a5..59c1117 100644 --- a/doc/user/builders-writing.in +++ b/doc/user/builders-writing.in @@ -897,7 +897,7 @@ This functionality could be invoked as in the following example: - The site_scons directory gives you a place to + The site_scons directories give you a place to put Python modules you can import into your &SConscript; files (site_scons), add-on tools that can integrate into &SCons; @@ -910,8 +910,18 @@ This functionality could be invoked as in the following example: + Each system type (Windows, Mac, Linux, etc.) searches a canonical + set of directories for site_scons; see the man page for details. + The top-level SConstruct's site_scons dir is always searched last, + and its dir is placed first in the tool path so it overrides all + others. + + + + + If you get a tool from somewhere (the &SCons; wiki or a third party, - for instance) and you'd like to use it in your project, the + for instance) and you'd like to use it in your project, a site_scons dir is the simplest place to put it. Tools come in two flavors; either a Python function that operates on an &Environment; or a Python file containing two functions, @@ -1045,13 +1055,15 @@ This functionality could be invoked as in the following example: - If you have a machine-wide site dir you'd like to use instead of - ./site_scons, use the - --site-dir option to point to your dir. + You can use any of the user- or machine-wide site dirs such as + ~/.scons/site_scons instead of + ./site_scons, or use the + --site-dir option to point to your own dir. site_init.py and site_tools will be located under that dir. - To avoid using a site_scons dir at all, even - if it exists, use the --no-site-dir option. + To avoid using a site_scons dir at all, + even if it exists, use the --no-site-dir + option. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 831546f..9435482 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -7,6 +7,10 @@ RELEASE 2.1.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE + From Gary Oberbrunner: + + - New systemwide and per-user site_scons dirs. + From Dirk Baechle: - XML fixes in User's Guide. diff --git a/src/RELEASE.txt b/src/RELEASE.txt index a60fbd9..c2d2f60 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -31,6 +31,11 @@ NEW FUNCTIONALITY + - SCons now searches for site_scons dirs in several system-wide + and per-user locations, in addition to the SConstruct top dir. + This should enable much easier use of third-party (non-core) + Tools. + - List new features (presumably why a checkpoint is being released) DEPRECATED FUNCTIONALITY diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 875da71..eed782e 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -60,6 +60,7 @@ import SCons.Errors import SCons.Job import SCons.Node import SCons.Node.FS +import SCons.Platform import SCons.SConf import SCons.Script import SCons.Taskmaster @@ -665,15 +666,15 @@ def _create_path(plist): def _load_site_scons_dir(topdir, site_dir_name=None): """Load the site_scons dir under topdir. - Adds site_scons to sys.path, imports site_scons/site_init.py, - and adds site_scons/site_tools to default toolpath.""" + Prepends site_scons to sys.path, imports site_scons/site_init.py, + and prepends site_scons/site_tools to default toolpath.""" if site_dir_name: err_if_not_found = True # user specified: err if missing else: site_dir_name = "site_scons" err_if_not_found = False - site_dir = os.path.join(topdir.path, site_dir_name) + site_dir = os.path.join(topdir, site_dir_name) if not os.path.exists(site_dir): if err_if_not_found: raise SCons.Errors.UserError("site dir %s not found."%site_dir) @@ -682,6 +683,7 @@ def _load_site_scons_dir(topdir, site_dir_name=None): site_init_filename = "site_init.py" site_init_modname = "site_init" site_tools_dirname = "site_tools" + # prepend to sys.path sys.path = [os.path.abspath(site_dir)] + sys.path site_init_file = os.path.join(site_dir, site_init_filename) site_tools_dir = os.path.join(site_dir, site_tools_dirname) @@ -723,7 +725,55 @@ def _load_site_scons_dir(topdir, site_dir_name=None): if fp: fp.close() if os.path.exists(site_tools_dir): - SCons.Tool.DefaultToolpath.append(os.path.abspath(site_tools_dir)) + # prepend to DefaultToolpath + SCons.Tool.DefaultToolpath.insert(0, os.path.abspath(site_tools_dir)) + +def _load_all_site_scons_dirs(topdir, verbose=None): + """Load all of the predefined site_scons dir. + Order is significant; we load them in order from most generic + (machine-wide) to most specific (topdir). + The verbose argument is only for testing. + """ + platform = SCons.Platform.platform_default() + + def homedir(d): + return os.path.expanduser('~/'+d) + + if platform == 'win32' or platform == 'cygwin': + # Note we use $ here instead of %...% because older + # pythons (prior to 2.6?) didn't expand %...% on Windows. + # This set of dirs should work on XP, Vista, 7 and later. + sysdirs=[ + os.path.expandvars('$ALLUSERSPROFILE\\Application Data\\scons'), + os.path.expandvars('$USERPROFILE\\Local Settings\\Application Data\\scons')] + appdatadir = os.path.expandvars('$APPDATA\\scons') + if appdatadir not in sysdirs: + sysdirs.append(appdatadir) + sysdirs.append(homedir('.scons')) + + elif platform == 'darwin': # MacOS X + sysdirs=['/Library/Application Support/SCons', + '/opt/local/share/scons', # (for MacPorts) + '/sw/share/scons', # (for Fink) + homedir('Library/Application Support/SCons'), + homedir('.scons')] + elif platform == 'sunos': # Solaris + sysdirs=['/opt/sfw/scons', + '/usr/share/scons', + homedir('.scons')] + else: # Linux, HPUX, etc. + # assume posix-like, i.e. platform == 'posix' + sysdirs=['/usr/share/scons', + homedir('.scons')] + + dirs=sysdirs + [topdir] + for d in dirs: + if verbose: # this is used by unit tests. + print "Loading site dir ", d + _load_site_scons_dir(d) + +def test_load_all_site_scons_dirs(d): + _load_all_site_scons_dirs(d, True) def version_string(label, module): version = module.__version__ @@ -860,9 +910,9 @@ def _main(parser): progress_display.set_mode(0) if options.site_dir: - _load_site_scons_dir(d, options.site_dir) + _load_site_scons_dir(d.path, options.site_dir) elif not options.no_site_dir: - _load_site_scons_dir(d) + _load_all_site_scons_dirs(d.path) if options.include_dir: sys.path = options.include_dir + sys.path diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py new file mode 100644 index 0000000..c05ef67 --- /dev/null +++ b/test/site_scons/sysdirs.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +""" +Verify site_scons system dirs are getting loaded. +Uses an internal test fixture to get at the site_scons dirs. + +TODO: it would be great to test if it can actually load site_scons +files from the system dirs, but the test harness can't put files in +those dirs (which may not even exist on a build system). +""" + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import SCons.Script +SCons.Script.Main.test_load_all_site_scons_dirs(Dir('.').path) +""") + +test.run(arguments = '-Q .') + +import SCons.Platform +platform = SCons.Platform.platform_default() +if platform in ('win32', 'cygwin'): + dir_to_check_for='Application Data' +elif platform in ('darwin'): + dir_to_check_for='Library' +else: + dir_to_check_for='.scons' + +if 'Loading site dir' not in test.stdout(): + print test.stdout() + test.fail_test() +if dir_to_check_for not in test.stdout(): + print test.stdout() + test.fail_test() + +test.pass_test() + +# end of file + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12