Add arm64 to the MSVS supported architectures list for VS2017 and later to be consist...
[scons.git] / bootstrap.py
blob3bf53ea5077056fe17418cbe3a1a65e865b3f07b
1 #!/usr/bin/env python
3 # __COPYRIGHT__
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.
24 """bootstrap.py
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_":
36 --bootstrap_dir=DIR
38 Sets the name of the directory into which the SCons files will
39 be copied. The default is "bootstrap" in the local subdirectory.
41 --bootstrap_force
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.
47 --bootstrap_src=DIR
49 Searches for the SCons files relative to the specified DIR,
50 then relative to the directory in which this bootstrap.py
51 script is found.
53 --bootstrap_update
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:
60 -C, --directory
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.
66 """
68 import os
69 import os.path
70 import sys
71 import glob
72 import subprocess
73 import filecmp
74 import shutil
76 def parseManifestLines(basedir, manifest):
77 """
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
89 """
90 sources = []
91 basewd = os.path.abspath(basedir)
92 with open(manifest) as m:
93 lines = m.readlines()
94 for l in lines:
95 if l.startswith('#'):
96 # Skip comments
97 continue
98 l = l.rstrip('\n')
99 if l.endswith('**'):
100 # Glob all files recursively
101 globwd = os.path.dirname(os.path.join(basewd, l))
102 for path, dirs, files in os.walk(globwd):
103 for f in files:
104 fpath = os.path.join(globwd, path, f)
105 sources.append(os.path.relpath(fpath, basewd))
106 elif '*' in l:
107 # Glob file pattern
108 files = glob.glob(os.path.join(basewd, l))
109 for f in files:
110 sources.append(os.path.relpath(f, basewd))
111 else:
112 sources.append(l)
114 return sources
116 def main():
117 script_dir = os.path.abspath(os.path.dirname(__file__))
119 bootstrap_dir = os.path.join(script_dir, 'bootstrap')
121 pass_through_args = []
122 update_only = None
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")
135 sys.exit(2)
137 def must_copy(dst, src):
138 if not os.path.exists(dst):
139 return 1
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':
151 try:
152 bootstrap_dir = command_line_args.pop(0)
153 except IndexError:
154 sys.stderr.write(requires_an_argument % arg)
155 sys.exit(1)
156 elif arg[:16] == '--bootstrap_dir=':
157 bootstrap_dir = arg[16:]
158 elif arg == '--bootstrap_force':
159 def must_copy(dst, src):
160 return 1
161 elif arg == '--bootstrap_src':
162 try:
163 search.insert(0, command_line_args.pop(0))
164 except IndexError:
165 sys.stderr.write(requires_an_argument % arg)
166 sys.exit(1)
167 elif arg[:16] == '--bootstrap_src=':
168 search.insert(0, arg[16:])
169 elif arg == '--bootstrap_update':
170 update_only = 1
171 elif arg in ('-C', '--directory'):
172 try:
173 dir = command_line_args.pop(0)
174 except IndexError:
175 sys.stderr.write(requires_an_argument % arg)
176 sys.exit(1)
177 else:
178 os.chdir(dir)
179 elif arg[:2] == '-C':
180 os.chdir(arg[2:])
181 elif arg[:12] == '--directory=':
182 os.chdir(arg[12:])
183 else:
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),
191 MANIFEST_in)]
193 files = [scons_py] + manifest_files
195 for filename in files:
196 src = find(filename)
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):
201 os.makedirs(dir)
202 try:
203 os.unlink(dst)
204 except Exception as e:
205 pass
207 shutil.copyfile(src, dst)
209 if update_only:
210 sys.exit(0)
212 args = [sys.executable, os.path.join(bootstrap_dir, scons_py)] + pass_through_args
214 sys.stdout.write(" ".join(args) + '\n')
215 sys.stdout.flush()
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__":
223 print("Please use")
224 print("python scripts/scons.py")
225 print("Instead of python bootstrap.py. Bootstrap.py is obsolete")
226 sys.exit(-1)
227 main()
229 # Local Variables:
230 # tab-width:4
231 # indent-tabs-mode:nil
232 # End:
233 # vim: set expandtab tabstop=4 shiftwidth=4: