5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 Execute SCons from this source tree. It copies Python scripts and modules
27 from src/ subdirectory into a subdirectory named "bootstrap/" (by default),
28 and executes SCons from there with the supplied command-line arguments.
30 This is a minimal build of SCons to bootstrap the full build of all the
31 packages, as specified in our local SConstruct file.
33 Some options are specific to this bootstrap.py script and are *not* passed
34 on to the SCons script. All of these begin with the string "bootstrap_":
38 Sets the name of the directory into which the SCons files will
39 be copied. The default is "bootstrap" in the local subdirectory.
43 Forces a copy of all necessary files. By default, the
44 bootstrap.py script only updates the bootstrap copy if the
45 content of the source copy is different.
49 Searches for the SCons files relative to the specified DIR,
50 then relative to the directory in which this bootstrap.py
55 Only updates the bootstrap subdirectory, and then exits.
57 In addition to the above, the bootstrap.py script understands
58 the following SCons options:
62 Changes to the specified directory before invoking SCons.
63 Because we change directory right away to the specified directory,
64 the SCons script itself doesn't need to, so this option gets
65 "eaten" by the bootstrap.py script.
76 def parseManifestLines(basedir
, manifest
):
78 Scans a MANIFEST file, and returns the list of source files.
80 Has basic support for recursive globs '**',
81 filename wildcards of the form '*.xml' and
82 comment lines, starting with a '#'.
84 :param basedir: base path to find files in. Note this does not
85 run in an SCons context so path must not need
86 further processing (e.g. no '#' signs)
87 :param manifest: path to manifest file
88 :returns: list of files
91 basewd
= os
.path
.abspath(basedir
)
92 with
open(manifest
) as m
:
100 # Glob all files recursively
101 globwd
= os
.path
.dirname(os
.path
.join(basewd
, l
))
102 for path
, dirs
, files
in os
.walk(globwd
):
104 fpath
= os
.path
.join(globwd
, path
, f
)
105 sources
.append(os
.path
.relpath(fpath
, basewd
))
108 files
= glob
.glob(os
.path
.join(basewd
, l
))
110 sources
.append(os
.path
.relpath(f
, basewd
))
117 script_dir
= os
.path
.abspath(os
.path
.dirname(__file__
))
119 bootstrap_dir
= os
.path
.join(script_dir
, 'bootstrap')
121 pass_through_args
= []
124 requires_an_argument
= 'bootstrap.py: %s requires an argument\n'
126 search
= [script_dir
]
128 def find(filename
, search
=search
):
129 for dir_name
in search
:
130 filepath
= os
.path
.join(dir_name
, filename
)
131 if os
.path
.exists(filepath
):
132 return os
.path
.normpath(filepath
)
133 sys
.stderr
.write("could not find `%s' in search path:\n" % filename
)
134 sys
.stderr
.write("\t" + "\n\t".join(search
) + "\n")
137 def must_copy(dst
, src
):
138 if not os
.path
.exists(dst
):
140 return not filecmp
.cmp(dst
,src
)
142 # Note: We don't use the getopt module to process the command-line
143 # arguments because we'd have to teach it about all of the SCons options.
145 command_line_args
= sys
.argv
[1:]
147 while command_line_args
:
148 arg
= command_line_args
.pop(0)
150 if arg
== '--bootstrap_dir':
152 bootstrap_dir
= command_line_args
.pop(0)
154 sys
.stderr
.write(requires_an_argument
% arg
)
156 elif arg
[:16] == '--bootstrap_dir=':
157 bootstrap_dir
= arg
[16:]
158 elif arg
== '--bootstrap_force':
159 def must_copy(dst
, src
):
161 elif arg
== '--bootstrap_src':
163 search
.insert(0, command_line_args
.pop(0))
165 sys
.stderr
.write(requires_an_argument
% arg
)
167 elif arg
[:16] == '--bootstrap_src=':
168 search
.insert(0, arg
[16:])
169 elif arg
== '--bootstrap_update':
171 elif arg
in ('-C', '--directory'):
173 dir = command_line_args
.pop(0)
175 sys
.stderr
.write(requires_an_argument
% arg
)
179 elif arg
[:2] == '-C':
181 elif arg
[:12] == '--directory=':
184 pass_through_args
.append(arg
)
186 scons_py
= os
.path
.join('scripts', 'scons.py')
187 src_engine
= os
.path
.join('src', 'engine')
188 MANIFEST_in
= find(os
.path
.join(src_engine
, 'MANIFEST.in'))
189 manifest_files
= [os
.path
.join(src_engine
, x
)
190 for x
in parseManifestLines(os
.path
.join(script_dir
, src_engine
),
193 files
= [scons_py
] + manifest_files
195 for filename
in files
:
197 dst
= os
.path
.join(bootstrap_dir
, filename
)
198 if must_copy(dst
, src
):
199 dir = os
.path
.split(dst
)[0]
200 if not os
.path
.isdir(dir):
204 except Exception as e
:
207 shutil
.copyfile(src
, dst
)
212 args
= [sys
.executable
, os
.path
.join(bootstrap_dir
, scons_py
)] + pass_through_args
214 sys
.stdout
.write(" ".join(args
) + '\n')
217 os
.environ
['SCONS_LIB_DIR'] = os
.path
.join(bootstrap_dir
, src_engine
)
219 sys
.exit(subprocess
.Popen(args
, env
=os
.environ
).wait())
222 if __name__
== "__main__":
224 print("python scripts/scons.py")
225 print("Instead of python bootstrap.py. Bootstrap.py is obsolete")
231 # indent-tabs-mode:nil
233 # vim: set expandtab tabstop=4 shiftwidth=4: