Tweak svn/git ignores
[zxing.git] / cpp / scons / scons-local-2.0.0.final.0 / SCons / Tool / install.py
1 """SCons.Tool.install
2
3 Tool-specific initialization for the install tool.
4
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
7 selection method.
8 """
9
10 #
11 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation
12 #
13 # Permission is hereby granted, free of charge, to any person obtaining
14 # a copy of this software and associated documentation files (the
15 # "Software"), to deal in the Software without restriction, including
16 # without limitation the rights to use, copy, modify, merge, publish,
17 # distribute, sublicense, and/or sell copies of the Software, and to
18 # permit persons to whom the Software is furnished to do so, subject to
19 # the following conditions:
20 #
21 # The above copyright notice and this permission notice shall be included
22 # in all copies or substantial portions of the Software.
23 #
24 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #
32
33 __revision__ = "src/engine/SCons/Tool/install.py 5023 2010/06/14 22:05:46 scons"
34
35 import os
36 import shutil
37 import stat
38
39 import SCons.Action
40 from SCons.Util import make_path_relative
41
42 #
43 # We keep track of *all* installed files.
44 _INSTALLED_FILES = []
45 _UNIQUE_INSTALLED_FILES = None
46
47 #
48 # Functions doing the actual work of the Install Builder.
49 #
50 def copyFunc(dest, source, env):
51     """Install a source file or directory into a destination by copying,
52     (including copying permission/mode bits)."""
53
54     if os.path.isdir(source):
55         if os.path.exists(dest):
56             if not os.path.isdir(dest):
57                 raise SCons.Errors.UserError("cannot overwrite non-directory `%s' with a directory `%s'" % (str(dest), str(source)))
58         else:
59             parent = os.path.split(dest)[0]
60             if not os.path.exists(parent):
61                 os.makedirs(parent)
62         shutil.copytree(source, dest)
63     else:
64         shutil.copy2(source, dest)
65         st = os.stat(source)
66         os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
67
68     return 0
69
70 def installFunc(target, source, env):
71     """Install a source file into a target using the function specified
72     as the INSTALL construction variable."""
73     try:
74         install = env['INSTALL']
75     except KeyError:
76         raise SCons.Errors.UserError('Missing INSTALL construction variable.')
77
78     assert len(target)==len(source), \
79            "Installing source %s into target %s: target and source lists must have same length."%(list(map(str, source)), list(map(str, target)))
80     for t,s in zip(target,source):
81         if install(t.get_path(),s.get_path(),env):
82             return 1
83
84     return 0
85
86 def stringFunc(target, source, env):
87     installstr = env.get('INSTALLSTR')
88     if installstr:
89         return env.subst_target_source(installstr, 0, target, source)
90     target = str(target[0])
91     source = str(source[0])
92     if os.path.isdir(source):
93         type = 'directory'
94     else:
95         type = 'file'
96     return 'Install %s: "%s" as "%s"' % (type, source, target)
97
98 #
99 # Emitter functions
100 #
101 def add_targets_to_INSTALLED_FILES(target, source, env):
102     """ an emitter that adds all target files to the list stored in the
103     _INSTALLED_FILES global variable. This way all installed files of one
104     scons call will be collected.
105     """
106     global _INSTALLED_FILES, _UNIQUE_INSTALLED_FILES
107     _INSTALLED_FILES.extend(target)
108     _UNIQUE_INSTALLED_FILES = None
109     return (target, source)
110
111 class DESTDIR_factory(object):
112     """ a node factory, where all files will be relative to the dir supplied
113     in the constructor.
114     """
115     def __init__(self, env, dir):
116         self.env = env
117         self.dir = env.arg2nodes( dir, env.fs.Dir )[0]
118
119     def Entry(self, name):
120         name = make_path_relative(name)
121         return self.dir.Entry(name)
122
123     def Dir(self, name):
124         name = make_path_relative(name)
125         return self.dir.Dir(name)
126
127 #
128 # The Builder Definition
129 #
130 install_action   = SCons.Action.Action(installFunc, stringFunc)
131 installas_action = SCons.Action.Action(installFunc, stringFunc)
132
133 BaseInstallBuilder               = None
134
135 def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw):
136     if target and dir:
137         import SCons.Errors
138         raise SCons.Errors.UserError("Both target and dir defined for Install(), only one may be defined.")
139     if not dir:
140         dir=target
141
142     import SCons.Script
143     install_sandbox = SCons.Script.GetOption('install_sandbox')
144     if install_sandbox:
145         target_factory = DESTDIR_factory(env, install_sandbox)
146     else:
147         target_factory = env.fs
148
149     try:
150         dnodes = env.arg2nodes(dir, target_factory.Dir)
151     except TypeError:
152         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))
153     sources = env.arg2nodes(source, env.fs.Entry)
154     tgt = []
155     for dnode in dnodes:
156         for src in sources:
157             # Prepend './' so the lookup doesn't interpret an initial
158             # '#' on the file name portion as meaning the Node should
159             # be relative to the top-level SConstruct directory.
160             target = env.fs.Entry('.'+os.sep+src.name, dnode)
161             #tgt.extend(BaseInstallBuilder(env, target, src, **kw))
162             tgt.extend(BaseInstallBuilder(env, target, src, **kw))
163     return tgt
164
165 def InstallAsBuilderWrapper(env, target=None, source=None, **kw):
166     result = []
167     for src, tgt in map(lambda x, y: (x, y), source, target):
168         #result.extend(BaseInstallBuilder(env, tgt, src, **kw))
169         result.extend(BaseInstallBuilder(env, tgt, src, **kw))
170     return result
171
172 added = None
173
174 def generate(env):
175
176     from SCons.Script import AddOption, GetOption
177     global added
178     if not added:
179         added = 1
180         AddOption('--install-sandbox',
181                   dest='install_sandbox',
182                   type="string",
183                   action="store",
184                   help='A directory under which all installed files will be placed.')
185
186     global BaseInstallBuilder
187     if BaseInstallBuilder is None:
188         install_sandbox = GetOption('install_sandbox')
189         if install_sandbox:
190             target_factory = DESTDIR_factory(env, install_sandbox)
191         else:
192             target_factory = env.fs
193
194         BaseInstallBuilder = SCons.Builder.Builder(
195                               action         = install_action,
196                               target_factory = target_factory.Entry,
197                               source_factory = env.fs.Entry,
198                               multi          = 1,
199                               emitter        = [ add_targets_to_INSTALLED_FILES, ],
200                               name           = 'InstallBuilder')
201
202     env['BUILDERS']['_InternalInstall'] = InstallBuilderWrapper
203     env['BUILDERS']['_InternalInstallAs'] = InstallAsBuilderWrapper
204
205     # We'd like to initialize this doing something like the following,
206     # but there isn't yet support for a ${SOURCE.type} expansion that
207     # will print "file" or "directory" depending on what's being
208     # installed.  For now we punt by not initializing it, and letting
209     # the stringFunc() that we put in the action fall back to the
210     # hand-crafted default string if it's not set.
211     #
212     #try:
213     #    env['INSTALLSTR']
214     #except KeyError:
215     #    env['INSTALLSTR'] = 'Install ${SOURCE.type}: "$SOURCES" as "$TARGETS"'
216
217     try:
218         env['INSTALL']
219     except KeyError:
220         env['INSTALL']    = copyFunc
221
222 def exists(env):
223     return 1
224
225 # Local Variables:
226 # tab-width:4
227 # indent-tabs-mode:nil
228 # End:
229 # vim: set expandtab tabstop=4 shiftwidth=4: