diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 6f16256324..e0fdbc0122 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -508,6 +508,16 @@ def __get_rsrcdir(self): def __get_dir(self): return EntryProxy(self.get().dir) + def __get_node_type(self): + actual = self.get() + if isinstance(actual, Dir): + return "directory" + elif isinstance(actual, File): + return "file" + else: + return "other" + + dictSpecialAttrs = { "base" : __get_base_path, "posix" : __get_posix_path, "windows" : __get_windows_path, @@ -521,6 +531,7 @@ def __get_dir(self): "file" : __get_file, "rsrcpath" : __get_rsrcnode, "rsrcdir" : __get_rsrcdir, + "type" : __get_node_type, } def __getattr__(self, name): diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index ad4e85911a..2181a33e0c 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -110,8 +110,9 @@ def generate(env): env['ESCAPE'] = escape env['TEMPFILE'] = TempFileMunge env['TEMPFILEPREFIX'] = '@' - #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion - #Note: specific platforms might rise or lower this value + + # Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion + # Note: specific platforms might increase or decrease this value env['MAXLINELENGTH'] = 128072 # This platform supports RPATH specifications. diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index bb1b46df64..922bcf96b6 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -484,7 +484,6 @@ def generate(env): if enable_virtualenv and not ignore_virtualenv: ImportVirtualenv(env) - # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index dcb3581a47..16d80fa1e5 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -47,9 +47,11 @@ _INSTALLED_FILES = [] _UNIQUE_INSTALLED_FILES = None + class CopytreeError(EnvironmentError): pass + # This is a patched version of shutil.copytree from python 2.5. It # doesn't fail if the dir exists, which regular copytree does # (annoyingly). Note the XXX comment in the docstring. @@ -111,7 +113,10 @@ def copyFunc(dest, source, env): if os.path.isdir(source): if os.path.exists(dest): if not os.path.isdir(dest): - raise SCons.Errors.UserError("cannot overwrite non-directory `%s' with a directory `%s'" % (str(dest), str(source))) + raise SCons.Errors.UserError( + "cannot overwrite non-directory `%s' with a directory `%s'" + % (str(dest), str(source)) + ) else: parent = os.path.split(dest)[0] if not os.path.exists(parent): @@ -124,6 +129,7 @@ def copyFunc(dest, source, env): return 0 + # # Functions doing the actual work of the InstallVersionedLib Builder. # @@ -133,7 +139,9 @@ def copyFuncVersionedLib(dest, source, env): required symlinks.""" if os.path.isdir(source): - raise SCons.Errors.UserError("cannot install directory `%s' as a version library" % str(source) ) + raise SCons.Errors.UserError( + "cannot install directory `%s' as a version library" % str(source) + ) else: # remove the link if it is already there try: @@ -147,79 +155,95 @@ def copyFuncVersionedLib(dest, source, env): return 0 + def listShlibLinksToInstall(dest, source, env): install_links = [] source = env.arg2nodes(source) dest = env.fs.File(dest) install_dir = dest.get_dir() for src in source: - symlinks = getattr(getattr(src,'attributes',None), 'shliblinks', None) + symlinks = getattr(getattr(src, "attributes", None), "shliblinks", None) if symlinks: for link, linktgt in symlinks: link_base = os.path.basename(link.get_path()) - linktgt_base = os.path.basename(linktgt.get_path()) + linktgt_base = os.path.basename(linktgt.get_path()) install_link = env.fs.File(link_base, install_dir) install_linktgt = env.fs.File(linktgt_base, install_dir) install_links.append((install_link, install_linktgt)) return install_links + def installShlibLinks(dest, source, env): """If we are installing a versioned shared library create the required links.""" Verbose = False symlinks = listShlibLinksToInstall(dest, source, env) if Verbose: - print('installShlibLinks: symlinks={!r}'.format(SCons.Tool.StringizeLibSymlinks(symlinks))) + print( + "installShlibLinks: symlinks={!r}".format( + SCons.Tool.StringizeLibSymlinks(symlinks) + ) + ) if symlinks: SCons.Tool.CreateLibSymlinks(env, symlinks) return -def installFunc(target, source, env): + +def legacy_install_function(target, source, env): """Install a source file into a target using the function specified as the INSTALL construction variable.""" try: - install = env['INSTALL'] + install = env["INSTALL"] except KeyError: - raise SCons.Errors.UserError('Missing INSTALL construction variable.') - - assert len(target)==len(source), \ - "Installing source %s into target %s: target and source lists must have same length."%(list(map(str, source)), list(map(str, target))) - for t,s in zip(target,source): - if install(t.get_path(),s.get_path(),env): + raise SCons.Errors.UserError("Missing COPYFUNC construction variable.") + + assert len(target) == len(source), ( + "Installing source %s into target %s: target and source lists must have same length." + % (list(map(str, source)), list(map(str, target))) + ) + for t, s in zip(target, source): + if install(t.get_path(), s.get_path(), env): return 1 return 0 + def installFuncVersionedLib(target, source, env): """Install a versioned library into a target using the function specified as the INSTALLVERSIONEDLIB construction variable.""" try: - install = env['INSTALLVERSIONEDLIB'] + install = env["INSTALLVERSIONEDLIB"] except KeyError: - raise SCons.Errors.UserError('Missing INSTALLVERSIONEDLIB construction variable.') - - assert len(target)==len(source), \ - "Installing source %s into target %s: target and source lists must have same length."%(list(map(str, source)), list(map(str, target))) - for t,s in zip(target,source): - if hasattr(t.attributes, 'shlibname'): + raise SCons.Errors.UserError( + "Missing INSTALLVERSIONEDLIB construction variable." + ) + + assert len(target) == len(source), ( + "Installing source %s into target %s: target and source lists must have same length." + % (list(map(str, source)), list(map(str, target))) + ) + for t, s in zip(target, source): + if hasattr(t.attributes, "shlibname"): tpath = os.path.join(t.get_dir(), t.attributes.shlibname) else: tpath = t.get_path() - if install(tpath,s.get_path(),env): + if install(tpath, s.get_path(), env): return 1 return 0 -def stringFunc(target, source, env): - installstr = env.get('INSTALLSTR') - if installstr: - return env.subst_target_source(installstr, 0, target, source) - target = str(target[0]) - source = str(source[0]) - if os.path.isdir(source): - type = 'directory' - else: - type = 'file' - return 'Install %s: "%s" as "%s"' % (type, source, target) + +# def stringFunc(target, source, env): +# installstr = env.get('INSTALLSTR') +# if installstr: +# return env.subst_target_source(installstr, 0, target, source) +# target = str(target[0]) +# source = str(source[0]) +# if os.path.isdir(source): +# type = 'directory' +# else: +# type = 'file' +# return 'Install %s: "%s" as "%s"' % (type, source, target) + # # Emitter functions @@ -235,6 +259,7 @@ def add_targets_to_INSTALLED_FILES(target, source, env): _UNIQUE_INSTALLED_FILES = None return (target, source) + def add_versioned_targets_to_INSTALLED_FILES(target, source, env): """ An emitter that adds all target files to the list stored in the _INSTALLED_FILES global variable. This way all installed files of one @@ -244,20 +269,26 @@ def add_versioned_targets_to_INSTALLED_FILES(target, source, env): Verbose = False _INSTALLED_FILES.extend(target) if Verbose: - print("add_versioned_targets_to_INSTALLED_FILES: target={!r}".format(list(map(str, target)))) + print( + "add_versioned_targets_to_INSTALLED_FILES: target={!r}".format( + list(map(str, target)) + ) + ) symlinks = listShlibLinksToInstall(target[0], source, env) if symlinks: SCons.Tool.EmitLibSymlinks(env, symlinks, target[0]) _UNIQUE_INSTALLED_FILES = None return (target, source) + class DESTDIR_factory(object): """ A node factory, where all files will be relative to the dir supplied in the constructor. """ + def __init__(self, env, dir): self.env = env - self.dir = env.arg2nodes( dir, env.fs.Dir )[0] + self.dir = env.arg2nodes(dir, env.fs.Dir)[0] def Entry(self, name): name = SCons.Util.make_path_relative(name) @@ -267,24 +298,63 @@ def Dir(self, name): name = SCons.Util.make_path_relative(name) return self.dir.Dir(name) + +def install_command_generator(env, target, source, for_signature=False): + if env.get("INSTALL", False): + return "$INSTALLFUNC" + + if not SCons.Util.is_List(target): + target = [target] + + if not SCons.Util.is_List(source): + source = [source] + + # This get's run even when scons -n is run.. and deletes targets when it shouldn't.. + # if not for_signature: + # for t in target: + # if t.isfile(): + # t.remove() + + if len(target) == 1: + copyingdirs = [s for s in source if s.isdir()] + if copyingdirs: + return "$INSTALLDIRCOPY $INSTALLDIRCOPYFLAGS $SOURCES/. $TARGET" + else: + return "$INSTALLFILECOPY $INSTALLFILECOPYFLAGS $SOURCES $TARGET" + # return 'rm -f $TARGET; $INSTALLFILECOPY $INSTALLFILECOPYFLAGS $SOURCES $TARGET' + + else: + return "$INSTALLFUNC" + + # # The Builder Definition # -install_action = SCons.Action.Action(installFunc, stringFunc) -installas_action = SCons.Action.Action(installFunc, stringFunc) -installVerLib_action = SCons.Action.Action(installFuncVersionedLib, stringFunc) +# stringFunc +install_action = SCons.Action.Action( + install_command_generator, "$INSTALLSTR", generator=True, +) +installas_action = SCons.Action.Action( + install_command_generator, "$INSTALLSTR", generator=True +) +installVerLib_action = SCons.Action.Action(installFuncVersionedLib, "$INSTALLSTR") + +BaseInstallBuilder = None -BaseInstallBuilder = None def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw): if target and dir: import SCons.Errors - raise SCons.Errors.UserError("Both target and dir defined for Install(), only one may be defined.") + + raise SCons.Errors.UserError( + "Both target and dir defined for Install(), only one may be defined." + ) if not dir: - dir=target + dir = target import SCons.Script - install_sandbox = SCons.Script.GetOption('install_sandbox') + + install_sandbox = SCons.Script.GetOption("install_sandbox") if install_sandbox: target_factory = DESTDIR_factory(env, install_sandbox) else: @@ -293,7 +363,10 @@ def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw): try: dnodes = env.arg2nodes(dir, target_factory.Dir) except TypeError: - raise SCons.Errors.UserError("Target `%s' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?" % str(dir)) + raise SCons.Errors.UserError( + "Target `%s' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?" + % str(dir) + ) sources = env.arg2nodes(source, env.fs.Entry) tgt = [] for dnode in dnodes: @@ -301,7 +374,7 @@ def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw): # Prepend './' so the lookup doesn't interpret an initial # '#' on the file name portion as meaning the Node should # be relative to the top-level SConstruct directory. - target = env.fs.Entry('.'+os.sep+src.name, dnode) + target = env.fs.Entry("." + os.sep + src.name, dnode) tgt.extend(BaseInstallBuilder(env, target, src, **kw)) return tgt @@ -312,18 +385,23 @@ def InstallAsBuilderWrapper(env, target=None, source=None, **kw): result.extend(BaseInstallBuilder(env, tgt, src, **kw)) return result + BaseVersionedInstallBuilder = None def InstallVersionedBuilderWrapper(env, target=None, source=None, dir=None, **kw): if target and dir: import SCons.Errors - raise SCons.Errors.UserError("Both target and dir defined for Install(), only one may be defined.") + + raise SCons.Errors.UserError( + "Both target and dir defined for Install(), only one may be defined." + ) if not dir: - dir=target + dir = target import SCons.Script - install_sandbox = SCons.Script.GetOption('install_sandbox') + + install_sandbox = SCons.Script.GetOption("install_sandbox") if install_sandbox: target_factory = DESTDIR_factory(env, install_sandbox) else: @@ -332,7 +410,10 @@ def InstallVersionedBuilderWrapper(env, target=None, source=None, dir=None, **kw try: dnodes = env.arg2nodes(dir, target_factory.Dir) except TypeError: - raise SCons.Errors.UserError("Target `%s' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?" % str(dir)) + raise SCons.Errors.UserError( + "Target `%s' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?" + % str(dir) + ) sources = env.arg2nodes(source, env.fs.Entry) tgt = [] for dnode in dnodes: @@ -340,61 +421,152 @@ def InstallVersionedBuilderWrapper(env, target=None, source=None, dir=None, **kw # Prepend './' so the lookup doesn't interpret an initial # '#' on the file name portion as meaning the Node should # be relative to the top-level SConstruct directory. - target = env.fs.Entry('.'+os.sep+src.name, dnode) + target = env.fs.Entry("." + os.sep + src.name, dnode) tgt.extend(BaseVersionedInstallBuilder(env, target, src, **kw)) return tgt + added = None -def generate(env): +def set_posix_env_vars(env): + """ + Posix OS version + Setup env variables needed for file and dir copying used by Install and InstallAs + :param env: + :return: + """ + env["INSTALLFILECOPY"] = env.get("INSTALLFILECOPY", "cp") + env["INSTALLFILECOPYFLAGS"] = env.get( + "INSTALLFILECOPYFLAGS", + [ + "-p", + # '-v', # for verbose debugging + ], + ) + env["INSTALLDIRCOPY"] = env.get("INSTALLDIRCOPY", "cp") + + if not env.get("INSTALLDIRCOPYFLAGS", False): + env["INSTALLDIRCOPYFLAGS"] = env["INSTALLFILECOPYFLAGS"][:] + env["INSTALLDIRCOPYFLAGS"].append("-r") + + +def set_linux_env_vars(env): + """ + Linux version + Setup env variables needed for file and dir copying used by Install and InstallAs + :param env: + :return: + """ + env["INSTALLFILECOPY"] = env.get("INSTALLFILECOPY", "cp") + env["INSTALLFILECOPYFLAGS"] = env.get( + "INSTALLFILECOPYFLAGS", + [ + "--preserve=all", + # '--verbose', # for verbose debugging + ], + ) + env["INSTALLDIRCOPY"] = env.get("INSTALLDIRCOPY", "cp") + + if not env.get("INSTALLDIRCOPYFLAGS", False): + env["INSTALLDIRCOPYFLAGS"] = env["INSTALLFILECOPYFLAGS"][:] + env["INSTALLDIRCOPYFLAGS"].append("--recursive") + + +def set_win32_env_vars(env): + """ + Win32 version + Setup env variables needed for file and dir copying used by Install and InstallAs + :param env: + :return: + """ + # Flags for INSTALL + env["INSTALLFILECOPY"] = env.get("INSTALLFILECOPY", "copy") + env["INSTALLFILECOPYFLAGS"] = env.get( + "INSTALLFILECOPYFLAGS", + [ + "/Y", # Suppresses prompting to confirm you want to overwrite an existing destination file. + ], + ) + + # env["INSTALLFILECOPY"] = env.get("INSTALLFILECOPY", "mklink") + # env["INSTALLFILECOPYFLAGS"] = env.get( + # "INSTALLFILECOPYFLAGS", + # [ + # "/H", # Suppresses prompting to confirm you want to overwrite an existing destination file. + # ], + # ) + + + if not env.get("INSTALLDIRCOPYFLAGS", False): + env["INSTALLDIRCOPYFLAGS"] = env["INSTALLFILECOPYFLAGS"][:] + + env["INSTALLDIRCOPYFLAGS"] = [ + "/o", # Copies file ownership and discretionary access control list information. + "/x", # Copies file audit settings and system access control list information. + "/i", # If destination does not exist and copying more than one file, + # assumes that destination must be a directory. + "/s", # Copies directories and subdirectories, unless they are empty. + # If you omit /s, xcopy works within a single directory. + "/e", # Copies all subdirectories, even if they are empty. + # Use /e with the /s and /t command-line options. + ] + + env["INSTALLDIRCOPY"] = env.get("INSTALLDIRCOPY", "Xcopy") + +def generate(env): from SCons.Script import AddOption, GetOption + global added if not added: added = 1 - AddOption('--install-sandbox', - dest='install_sandbox', - type="string", - action="store", - help='A directory under which all installed files will be placed.') + AddOption( + "--install-sandbox", + dest="install_sandbox", + type="string", + action="store", + help="A directory under which all installed files will be placed.", + ) global BaseInstallBuilder if BaseInstallBuilder is None: - install_sandbox = GetOption('install_sandbox') + install_sandbox = GetOption("install_sandbox") if install_sandbox: target_factory = DESTDIR_factory(env, install_sandbox) else: target_factory = env.fs BaseInstallBuilder = SCons.Builder.Builder( - action = install_action, - target_factory = target_factory.Entry, - source_factory = env.fs.Entry, - multi = 1, - emitter = [ add_targets_to_INSTALLED_FILES, ], - source_scanner = SCons.Scanner.Base( {}, name = 'Install', recursive = False ), - name = 'InstallBuilder') + action=install_action, + target_factory=target_factory.Entry, + source_factory=env.fs.Entry, + multi=1, + emitter=[add_targets_to_INSTALLED_FILES,], + source_scanner=SCons.Scanner.Base({}, name="Install", recursive=False), + name="InstallBuilder", + ) global BaseVersionedInstallBuilder if BaseVersionedInstallBuilder is None: - install_sandbox = GetOption('install_sandbox') + install_sandbox = GetOption("install_sandbox") if install_sandbox: target_factory = DESTDIR_factory(env, install_sandbox) else: target_factory = env.fs BaseVersionedInstallBuilder = SCons.Builder.Builder( - action = installVerLib_action, - target_factory = target_factory.Entry, - source_factory = env.fs.Entry, - multi = 1, - emitter = [ add_versioned_targets_to_INSTALLED_FILES, ], - name = 'InstallVersionedBuilder') - - env['BUILDERS']['_InternalInstall'] = InstallBuilderWrapper - env['BUILDERS']['_InternalInstallAs'] = InstallAsBuilderWrapper - env['BUILDERS']['_InternalInstallVersionedLib'] = InstallVersionedBuilderWrapper + action=installVerLib_action, + target_factory=target_factory.Entry, + source_factory=env.fs.Entry, + multi=1, + emitter=[add_versioned_targets_to_INSTALLED_FILES,], + name="InstallVersionedBuilder", + ) + + env["BUILDERS"]["_InternalInstall"] = InstallBuilderWrapper + env["BUILDERS"]["_InternalInstallAs"] = InstallAsBuilderWrapper + env["BUILDERS"]["_InternalInstallVersionedLib"] = InstallVersionedBuilderWrapper # We'd like to initialize this doing something like the following, # but there isn't yet support for a ${SOURCE.type} expansion that @@ -403,24 +575,33 @@ def generate(env): # the stringFunc() that we put in the action fall back to the # hand-crafted default string if it's not set. # - #try: - # env['INSTALLSTR'] - #except KeyError: - # env['INSTALLSTR'] = 'Install ${SOURCE.type}: "$SOURCES" as "$TARGETS"' - try: - env['INSTALL'] + env["INSTALLSTR"] except KeyError: - env['INSTALL'] = copyFunc + env["INSTALLSTR"] = 'Install ${SOURCE.type}: "$SOURCES" as "$TARGETS"' + env["INSTALLSTR"] = None + + env["INSTALLFUNC"] = legacy_install_function + + env["INSTALL"] = env.get("INSTALL", None) + + if env["PLATFORM"] == "win32": + set_win32_env_vars(env) + if env["PLATFORM"] == "linux": + set_linux_env_vars(env) + else: + set_posix_env_vars(env) try: - env['INSTALLVERSIONEDLIB'] + env["INSTALLVERSIONEDLIB"] except KeyError: - env['INSTALLVERSIONEDLIB'] = copyFuncVersionedLib + env["INSTALLVERSIONEDLIB"] = copyFuncVersionedLib + def exists(env): return 1 + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Tool/install.xml b/src/engine/SCons/Tool/install.xml index ce70d91139..96041aea6c 100644 --- a/src/engine/SCons/Tool/install.xml +++ b/src/engine/SCons/Tool/install.xml @@ -7,129 +7,200 @@ See its __doc__ string for a discussion of the format. --> -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> + + %scons; + + %builders-mod; + + %functions-mod; + + %tools-mod; + + %variables-mod; + ]> - - - -Sets construction variables for file -and directory installation. - - - -INSTALL -INSTALLSTR - - - - - - -Installs one or more source files or directories -in the specified target, -which must be a directory. -The names of the specified source files or directories -remain the same within the destination directory. The -sources may be given as a string or as a node returned by -a builder. - - - -env.Install(target='/usr/local/bin', source=['foo', 'bar']) - - - -Note that if target paths chosen for the -&Install; builder (and the related &InstallAs; and -&InstallVersionedLib; builders) are outside the -project tree, such as in the example above, -they may not be selected for "building" by default, -since in the absence of other instructions -&scons; builds targets that are underneath the top directory -(the directory that contains the &SConstruct; file, -usually the current directory). -Use command line targets or the &Default; function -in this case. - - - -If the command line -option is given, the target directory will be prefixed -by the directory path specified. -This is useful to test installs without installing to -a "live" location in the system. - - - -See also &FindInstalledFiles;. -For more thoughts on installation, see the User Guide -(particularly the section on Command-Line Targets -and the chapters on Installing Files and on Alias Targets). - - - - - - - - -Installs one or more source files or directories -to specific names, -allowing changing a file or directory name -as part of the installation. -It is an error if the -target -and -source -arguments list different numbers of files or directories. - - - -env.InstallAs(target='/usr/local/bin/foo', - source='foo_debug') -env.InstallAs(target=['../lib/libfoo.a', '../lib/libbar.a'], - source=['libFOO.a', 'libBAR.a']) - - - -See the note under &Install;. - - - - - - - - -Installs a versioned shared library. The symlinks appropriate to the -architecture will be generated based on symlinks of the source library. - - - -env.InstallVersionedLib(target='/usr/local/bin/foo', - source='libxyz.1.5.2.so') - - - -See the note under &Install;. - - - - + + + + Sets construction variables for file + and directory installation. + + + + INSTALL + INSTALLSTR + INSTALLFILECOPY + INSTALLFILECOPYFLAGS + INSTALLDIRCOPY + INSTALLDIRCOPYFLAGS + + + + + + + The command to call to copy a file as part of the Install() and InstallAs() builders. + + + For Posix systems defaults to + cp + + + For Win32 systems defaults to + Xcopy + + + + + + + + Flags to add to the command line for copying a file as part of the Install() and InstallAs() builders. + The defaults below preserve ownership and file permissions. + + + For Posix systems defaults to + -p + + + For Win32 systems defaults to + /o /x + + + + + + + + The command to call to copy a directory tree as part of the Install() and InstallAs() builders. + + + For Posix systems defaults to + cp + + + For Win32 systems defaults to + Xcopy + + + + + + + + Flags to add to the command line for copying a directory tree as part of the Install() and InstallAs() + builders. + The defaults below preserve ownership and file permissions. + + + For Posix systems defaults to + -p -r + + + For Win32 systems defaults to + /o /x /s /e + + + + + + + + Installs one or more source files or directories + in the specified target, + which must be a directory. + The names of the specified source files or directories + remain the same within the destination directory. The + sources may be given as a string or as a node returned by + a builder. + + + + env.Install(target='/usr/local/bin', source=['foo', 'bar']) + + + + Note that if target paths chosen for the + &Install; builder (and the related &InstallAs; and + &InstallVersionedLib; builders) are outside the + project tree, such as in the example above, + they may not be selected for "building" by default, + since in the absence of other instructions + &scons; builds targets that are underneath the top directory + (the directory that contains the &SConstruct; file, + usually the current directory). + Use command line targets or the &Default; function + in this case. + + + + If the command line + option is given, the target directory will be prefixed + by the directory path specified. + This is useful to test installs without installing to + a "live" location in the system. + + + + See also &FindInstalledFiles;. + For more thoughts on installation, see the User Guide + (particularly the section on Command-Line Targets + and the chapters on Installing Files and on Alias Targets). + + + + + + + + + Installs one or more source files or directories + to specific names, + allowing changing a file or directory name + as part of the installation. + It is an error if the + target + and + source + arguments list different numbers of files or directories. + + + + env.InstallAs(target='/usr/local/bin/foo', + source='foo_debug') + env.InstallAs(target=['../lib/libfoo.a', '../lib/libbar.a'], + source=['libFOO.a', 'libBAR.a']) + + + + See the note under &Install;. + + + + + + + + + Installs a versioned shared library. The symlinks appropriate to the + architecture will be generated based on symlinks of the source library. + + + + env.InstallVersionedLib(target='/usr/local/bin/foo', + source='libxyz.1.5.2.so') + + + + See the note under &Install;. + + + + diff --git a/test/Errors/permission-denied.py b/test/Errors/permission-denied.py index 0134803286..13b1a35593 100644 --- a/test/Errors/permission-denied.py +++ b/test/Errors/permission-denied.py @@ -55,11 +55,15 @@ test.writable('test2.out', 1) test.description_set("Incorrect STDERR:\n%s" % test.stderr()) +stderr_lines = test.stderr().splitlines() +test.description_set("Incorrect STDERR:\n%s" % stderr_lines) + +#TODO need windows specific first line.. errs = [ - "scons: *** [test2.out] test2.out: Permission denied\n", - "scons: *** [test2.out] test2.out: permission denied\n", + "cp: cannot create regular file 'test2.out': Permission denied", + "scons: *** [test2.out] Error 1", ] -test.fail_test(test.stderr() not in errs) +test.fail_test(stderr_lines != errs) test.pass_test() diff --git a/test/Install/directories.py b/test/Install/directories.py index 3ebc7139eb..d628166f49 100644 --- a/test/Install/directories.py +++ b/test/Install/directories.py @@ -56,41 +56,42 @@ env.InstallAs('../outside/d4', 'dir4') """) -test.write(['work', 'f1'], "work/f1\n") -test.write(['work', 'dir1', 'f2'], "work/dir1/f2\n") -test.write(['work', 'dir1', 'sub', 'f3'], "work/dir1/sub/f3\n") -test.write(['work', 'dir2', 'f4'], "work/dir2/f4\n") -test.write(['work', 'dir2', 'sub', 'f5'], "work/dir2/sub/f5\n") -test.write(['work', 'dir3', 'f6'], "work/dir3/f6\n") -test.write(['work', 'dir3', 'sub', 'f7'], "work/dir3/sub/f7\n") -test.write(['work', 'dir4', 'f8'], "work/dir4/f8\n") -test.write(['work', 'dir4', 'sub', 'f9'], "work/dir4/sub/f9\n") - +test.write(['work', 'f1'], "work/f1\n") +test.write(['work', 'dir1', 'f2'], "work/dir1/f2\n") +test.write(['work', 'dir1', 'sub', 'f3'], "work/dir1/sub/f3\n") +test.write(['work', 'dir2', 'f4'], "work/dir2/f4\n") +test.write(['work', 'dir2', 'sub', 'f5'], "work/dir2/sub/f5\n") +test.write(['work', 'dir3', 'f6'], "work/dir3/f6\n") +test.write(['work', 'dir3', 'sub', 'f7'], "work/dir3/sub/f7\n") +test.write(['work', 'dir4', 'f8'], "work/dir4/f8\n") +test.write(['work', 'dir4', 'sub', 'f9'], "work/dir4/sub/f9\n") arguments = [ - test.workpath('outside', 'dir1'), test.workpath('outside', 'd2'), - test.workpath('outside', 'dir3'), test.workpath('outside', 'd4'), + test.workpath('outside', 'dir1'), + test.workpath('outside', 'dir3'), ] expect = test.wrap_stdout("""\ -Install directory: "dir1" as "%s" Install directory: "dir2" as "%s" -Install directory: "dir3" as "%s" Install directory: "dir4" as "%s" +Install directory: "dir1" as "%s" +Install directory: "dir3" as "%s" """ % tuple(arguments)) -test.run(chdir = 'work', arguments = arguments, stdout = expect) -test.must_match(test.workpath('outside', 'dir1', 'f2'), "work/dir1/f2\n") -test.must_match(test.workpath('outside', 'dir1', 'sub', 'f3'), "work/dir1/sub/f3\n") -test.must_match(test.workpath('outside', 'd2', 'f4'), "work/dir2/f4\n") -test.must_match(test.workpath('outside', 'd2', 'sub', 'f5'), "work/dir2/sub/f5\n") -test.must_match(test.workpath('outside', 'dir3', 'f6'), "work/dir3/f6\n") -test.must_match(test.workpath('outside', 'dir3', 'sub', 'f7'), "work/dir3/sub/f7\n") -test.must_match(test.workpath('outside', 'd4', 'f8'), "work/dir4/f8\n") -test.must_match(test.workpath('outside', 'd4', 'sub', 'f9'), "work/dir4/sub/f9\n") + +test.run(chdir='work', arguments=arguments, stdout=expect) + +test.must_match(test.workpath('outside', 'dir1', 'f2'), "work/dir1/f2\n") +test.must_match(test.workpath('outside', 'dir1', 'sub', 'f3'), "work/dir1/sub/f3\n") +test.must_match(test.workpath('outside', 'd2', 'f4'), "work/dir2/f4\n") +test.must_match(test.workpath('outside', 'd2', 'sub', 'f5'), "work/dir2/sub/f5\n") +test.must_match(test.workpath('outside', 'dir3', 'f6'), "work/dir3/f6\n") +test.must_match(test.workpath('outside', 'dir3', 'sub', 'f7'), "work/dir3/sub/f7\n") +test.must_match(test.workpath('outside', 'd4', 'f8'), "work/dir4/f8\n") +test.must_match(test.workpath('outside', 'd4', 'sub', 'f9'), "work/dir4/sub/f9\n") test.pass_test() diff --git a/test/Install/multi-dir/src/SConstruct b/test/Install/multi-dir/src/SConstruct index 05b46a96af..2b70d22cf4 100644 --- a/test/Install/multi-dir/src/SConstruct +++ b/test/Install/multi-dir/src/SConstruct @@ -1,9 +1,9 @@ # This tests for a bug where installing a sequence dirs and subdirs # outside the source tree can cause SCons to fail to create the dest # dir. -import os, os.path, shutil +import os.path DefaultEnvironment(tools=[]) env=Environment(tools=[]) dst='../build' -env.Install(os.path.join(dst,'__foo/bar/baz'), 'a') -env.Install(os.path.join(dst,'__foo/bar/baz/a/b'), 'x/y') +env.Install(os.path.join(dst, '__foo/bar/baz'), 'a') +env.Install(os.path.join(dst, '__foo/bar/baz/a/b'), 'x/y')