From 092f9c6e99eb60fb35b42b8ff213df55e96f5e9a Mon Sep 17 00:00:00 2001 From: stevenknight Date: Wed, 12 Feb 2003 03:52:10 +0000 Subject: [PATCH] Make the Install() method copy files (by default). git-svn-id: http://scons.tigris.org/svn/scons/trunk@590 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- doc/man/scons.1 | 21 ++++++ src/CHANGES.txt | 6 ++ src/engine/SCons/Defaults.py | 13 +++- src/engine/SCons/Environment.py | 12 +++- test/Install.py | 118 +++++++++++++++----------------- 5 files changed, 106 insertions(+), 64 deletions(-) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 40191bb5..1bf91579 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -1881,6 +1881,27 @@ in the $CPPPATH and $F77PATH construction variables when the $_CPPINCFLAGS and $_F77INCFLAGS variables are automatically generated. +.IP INSTALL +A function to be called to install a file into a +destination file name. +The default function copies the file into the destination +(and sets the destination file's mode and permission bits +to match the source file's). +The function takes the following arguments: + +.ES +def install(dest, source, env): +.EE +.IP +.I dest +is the path name of the destination file. +.I source +is the path name of the source file. +.I env +is the construction environment +(a dictionary of construction values) +in force for this file installation. + .IP LATEX The LaTeX structured formatter and typesetter. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index a696a2db..7533c9d1 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -10,6 +10,12 @@ RELEASE 0.12 - XXX + From Steven Knight: + + - Added an INSTALL construction variable that can be set to a function + to control how the Install() and InstallAs() Builders install files. + The default INSTALL function now copies, not links, files. + RELEASE 0.11 - Tue, 11 Feb 2003 05:24:33 -0600 diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 6a3659dc..f0c2163f 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -37,8 +37,10 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os -import string import os.path +import shutil +import stat +import string import SCons.Action import SCons.Builder @@ -183,6 +185,14 @@ Program = SCons.Builder.Builder(action=[ StaticCheck, '$LINKCOM' ], src_builder='Object', scanner = ProgScan) +def copyFunc(dest, source, env): + """Install a source file into a destination by copying it (and its + permission/mode bits).""" + shutil.copy2(source, dest) + st = os.stat(source) + os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) + return 0 + def _concat(prefix, list, suffix, locals, globals, f=lambda x: x): """Creates a new list from 'list' by first interpolating each element in the list using 'locals' and 'globals' and then calling f @@ -257,6 +267,7 @@ ConstructionEnvironment = { 'PSPREFIX' : '', 'PSSUFFIX' : '.ps', 'ENV' : {}, + 'INSTALL' : copyFunc, '_concat' : _concat, '_stripixes' : _stripixes, '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, locals(), globals())}', diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index f9c793d7..6356776c 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -34,6 +34,7 @@ import copy import os import os.path import re +import shutil from UserDict import UserDict import SCons.Action @@ -47,10 +48,19 @@ import SCons.Tool import SCons.Util import SCons.Warnings +def installFunc(target, source, env): + """Install a source file into a target using the function specified + as the INSTALL construction variable.""" + try: + install = env['INSTALL'] + except KeyError: + raise SCons.Errors.UserError('Missing INSTALL construction variable.') + return install(target[0].path, source[0].path, env) + def installString(target, source, env): return 'Install file: "%s" as "%s"' % (source[0], target[0]) -installAction = SCons.Action.Action(SCons.Node.FS.LinkFunc, installString) +installAction = SCons.Action.Action(installFunc, installString) InstallBuilder = SCons.Builder.Builder(name='Install', action=installAction) diff --git a/test/Install.py b/test/Install.py index a79dfc82..629c136c 100644 --- a/test/Install.py +++ b/test/Install.py @@ -24,93 +24,87 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Verify that the Install() Builder works +""" + import os.path import sys import time import TestSCons -if sys.platform == 'win32': - _exe = '.exe' - _obj = '.obj' -else: - _exe = '' - _obj = '.o' - test = TestSCons.TestSCons() -foo1 = test.workpath('export/foo1' + _exe) -foo2 = test.workpath('export/foo2' + _exe) - -test.write('SConstruct', """ -env=Environment() -t=env.Program(target='foo1', source='f1.c') -env.Install(dir='export', source=t) -t=env.Program(target='foo2', source='f2.c') -env.Install(dir='export', source=t) +f1_out = test.workpath('export', 'f1.out') +f2_out = test.workpath('export', 'f2.out') +f3_out = test.workpath('export', 'f3.out') + +test.write('SConstruct', """\ +def cat(env, source, target): + target = str(target[0]) + source = map(str, source) + f = open(target, "wb") + for src in source: + f.write(open(src, "rb").read()) + f.close() + +def my_install(dest, source, env): + import shutil + shutil.copy2(source, dest) + open('my_install.out', 'ab').write(dest) + +env1 = Environment() +env1.Append(BUILDERS={'Cat':Builder(action=cat)}) +env3 = env1.Copy(INSTALL = my_install) + +t = env1.Cat(target='f1.out', source='f1.in') +env1.Install(dir='export', source=t) +t = env1.Cat(target='f2.out', source='f2.in') +env1.Install(dir='export', source=t) + +t = env3.Cat(target='f3.out', source='f3.in') +env3.Install(dir='export', source=t) """) -test.write('f1.c', r""" -#include - -int main(void) -{ - printf("f1.c\n"); - return 0; -} -""") - -test.write('f2.c', r""" -#include - -int main(void) -{ - printf("f2.c\n"); - return 0; -} -""") +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") test.run(arguments = '.') -test.run(program = foo1, stdout = "f1.c\n") -test.run(program = foo2, stdout = "f2.c\n") +test.fail_test(test.read(f1_out) != "f1.in\n") +test.fail_test(test.read(f2_out) != "f2.in\n") +test.fail_test(test.read(f3_out) != "f3.in\n") -# make sure the programs didn't get rebuilt, because nothing changed: -oldtime1 = os.path.getmtime(foo1) -oldtime2 = os.path.getmtime(foo2) +test.fail_test(test.read('my_install.out') != os.path.join('export', 'f3.out')) -test.write('f1.c', r""" -#include +# make sure the programs didn't get rebuilt, because nothing changed: +oldtime1 = os.path.getmtime(f1_out) +oldtime2 = os.path.getmtime(f2_out) -int main(void) -{ - printf("f1.c again\n"); - return 0; -} -""") +test.write('f1.in', "f1.in again\n") time.sleep(2) # introduce a small delay, to make the test valid test.run(arguments = '.') -test.fail_test(oldtime1 == os.path.getmtime(foo1)) -test.fail_test(oldtime2 != os.path.getmtime(foo2)) +test.fail_test(oldtime1 == os.path.getmtime(f1_out)) +test.fail_test(oldtime2 != os.path.getmtime(f2_out)) + +# Verify that we didn't link to the Installed file. +open(f2_out, 'wb').write("xyzzy\n") +test.fail_test(test.read('f2.out') != "f2.in\n") # Verify that scons prints an error message # if a target can not be unlinked before building it: -test.write('f1.c', r""" -#include - -int main(void) -{ - printf("f1.c again again\n"); - return 0; -} -""") +test.write('f1.in', "f1.in again again\n") -os.chmod(test.workpath('.'), 0555) -f = open(test.workpath('f1' + _obj), 'rb') +os.chmod(test.workpath('export'), 0555) +f = open(f1_out, 'rb') -test.run(arguments = foo1, stderr="scons: *** [Errno 13] Permission denied: 'f1%s'\n"%_obj, status=2) +test.run(arguments = f1_out, + stderr="scons: *** [Errno 13] Permission denied: '%s'\n" % os.path.join('export', 'f1.out'), + status=2) f.close() -- 2.26.2