summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-02-12 03:52:10 (GMT)
committerSteven Knight <knight@baldmt.com>2003-02-12 03:52:10 (GMT)
commit5bbe45c7286f8e9e6d0139e611e0763681c2dd45 (patch)
tree0b4258916ddc551ee6ee345ba2943e52f9bab38f
parenta2960be7a116f6e085a1072123976b1b31b09f1b (diff)
downloadSCons-5bbe45c7286f8e9e6d0139e611e0763681c2dd45.zip
SCons-5bbe45c7286f8e9e6d0139e611e0763681c2dd45.tar.gz
SCons-5bbe45c7286f8e9e6d0139e611e0763681c2dd45.tar.bz2
Make the Install() method copy files (by default).
-rw-r--r--doc/man/scons.121
-rw-r--r--src/CHANGES.txt6
-rw-r--r--src/engine/SCons/Defaults.py13
-rw-r--r--src/engine/SCons/Environment.py12
-rw-r--r--test/Install.py118
5 files changed, 106 insertions, 64 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 40191bb..1bf9157 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 a696a2d..7533c9d 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 6a3659d..f0c2163 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 f9c793d..6356776 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 a79dfc8..629c136 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 <stdio.h>
-
-int main(void)
-{
- printf("f1.c\n");
- return 0;
-}
-""")
-
-test.write('f2.c', r"""
-#include <stdio.h>
-
-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 <stdio.h>
+# 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 <stdio.h>
-
-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()