]>
Commit | Line | Data |
---|---|---|
ea8adc8c | 1 | #!/usr/bin/env python |
ea8adc8c XL |
2 | |
3 | # ignore-tidy-linelength | |
4 | ||
abe05a73 | 5 | from __future__ import absolute_import, division, print_function |
ea8adc8c XL |
6 | import sys |
7 | import os | |
8 | rust_dir = os.path.dirname(os.path.abspath(__file__)) | |
9 | rust_dir = os.path.dirname(rust_dir) | |
10 | rust_dir = os.path.dirname(rust_dir) | |
11 | sys.path.append(os.path.join(rust_dir, "src", "bootstrap")) | |
12 | import bootstrap | |
13 | ||
abe05a73 XL |
14 | |
15 | class Option(object): | |
ea8adc8c XL |
16 | def __init__(self, name, rustbuild, desc, value): |
17 | self.name = name | |
18 | self.rustbuild = rustbuild | |
19 | self.desc = desc | |
20 | self.value = value | |
21 | ||
abe05a73 | 22 | |
ea8adc8c XL |
23 | options = [] |
24 | ||
abe05a73 | 25 | |
ea8adc8c XL |
26 | def o(*args): |
27 | options.append(Option(*args, value=False)) | |
28 | ||
abe05a73 | 29 | |
ea8adc8c XL |
30 | def v(*args): |
31 | options.append(Option(*args, value=True)) | |
32 | ||
abe05a73 | 33 | |
064997fb | 34 | o("debug", "rust.debug", "enables debugging environment; does not affect optimization of bootstrapped code") |
ea8adc8c XL |
35 | o("docs", "build.docs", "build standard library documentation") |
36 | o("compiler-docs", "build.compiler-docs", "build compiler documentation") | |
37 | o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") | |
94b46f34 | 38 | o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests") |
ea8adc8c XL |
39 | o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds") |
40 | o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds") | |
41 | o("local-rust", None, "use an installed rustc rather than downloading a snapshot") | |
42 | v("local-rust-root", None, "set prefix for local rust binary") | |
43 | o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version") | |
44 | o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM") | |
45 | o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)") | |
46 | o("rpath", "rust.rpath", "build rpaths into rustc itself") | |
47 | o("llvm-version-check", "llvm.version-check", "check if the LLVM version is supported, build anyway") | |
6522a427 | 48 | o("codegen-tests", "rust.codegen-tests", "run the tests/codegen tests") |
ea8adc8c XL |
49 | o("option-checking", None, "complain about unrecognized options in this configure script") |
50 | o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)") | |
51 | o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date") | |
52 | o("vendor", "build.vendor", "enable usage of vendored Rust crates") | |
6a06907d | 53 | o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, lsan, msan, tsan, hwasan)") |
ea8adc8c | 54 | o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball") |
0bf4aa26 | 55 | o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo") |
ea8adc8c | 56 | o("profiler", "build.profiler", "build the profiler runtime") |
0531ce1d | 57 | o("full-tools", None, "enable all tools") |
a1dfa0c6 | 58 | o("lld", "rust.lld", "build lld") |
94222f64 | 59 | o("clang", "llvm.clang", "build clang") |
0bf4aa26 | 60 | o("missing-tools", "dist.missing-tools", "allow failures when building tools") |
dfeec247 | 61 | o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") |
74b04a01 | 62 | o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") |
ea8adc8c | 63 | |
74b04a01 XL |
64 | v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags") |
65 | v("llvm-cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") | |
66 | v("llvm-ldflags", "llvm.ldflags", "build LLVM with these extra linker flags") | |
9fa01778 | 67 | |
29967ef6 | 68 | v("llvm-libunwind", "rust.llvm-libunwind", "use LLVM libunwind") |
532ac7d7 | 69 | |
ea8adc8c XL |
70 | # Optimization and debugging options. These may be overridden by the release |
71 | # channel, etc. | |
ea8adc8c XL |
72 | o("optimize-llvm", "llvm.optimize", "build optimized LLVM") |
73 | o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") | |
94222f64 | 74 | o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface") |
ea8adc8c | 75 | o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") |
c295e0f8 | 76 | o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions") |
94222f64 | 77 | o("overflow-checks", "rust.overflow-checks", "build with overflow checks") |
c295e0f8 | 78 | o("overflow-checks-std", "rust.overflow-checks-std", "build the standard library with overflow checks") |
ea8adc8c | 79 | o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata") |
dc9dc135 XL |
80 | v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code") |
81 | v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler") | |
82 | v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library") | |
83 | v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools") | |
84 | v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest") | |
ff7c6d11 | 85 | v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file") |
ea8adc8c XL |
86 | |
87 | v("prefix", "install.prefix", "set installation prefix") | |
88 | v("localstatedir", "install.localstatedir", "local state directory") | |
89 | v("datadir", "install.datadir", "install data") | |
90 | v("sysconfdir", "install.sysconfdir", "install system configuration files") | |
91 | v("infodir", "install.infodir", "install additional info") | |
92 | v("libdir", "install.libdir", "install libraries") | |
93 | v("mandir", "install.mandir", "install man pages in PATH") | |
94 | v("docdir", "install.docdir", "install documentation in PATH") | |
95 | v("bindir", "install.bindir", "install binaries") | |
96 | ||
97 | v("llvm-root", None, "set LLVM root") | |
0bf4aa26 XL |
98 | v("llvm-config", None, "set path to llvm-config") |
99 | v("llvm-filecheck", None, "set path to LLVM's FileCheck utility") | |
ea8adc8c | 100 | v("python", "build.python", "set path to python") |
ea8adc8c XL |
101 | v("android-cross-path", "target.arm-linux-androideabi.android-ndk", |
102 | "Android NDK standalone path (deprecated)") | |
103 | v("i686-linux-android-ndk", "target.i686-linux-android.android-ndk", | |
104 | "i686-linux-android NDK standalone path") | |
105 | v("arm-linux-androideabi-ndk", "target.arm-linux-androideabi.android-ndk", | |
106 | "arm-linux-androideabi NDK standalone path") | |
107 | v("armv7-linux-androideabi-ndk", "target.armv7-linux-androideabi.android-ndk", | |
108 | "armv7-linux-androideabi NDK standalone path") | |
0731742a XL |
109 | v("thumbv7neon-linux-androideabi-ndk", "target.thumbv7neon-linux-androideabi.android-ndk", |
110 | "thumbv7neon-linux-androideabi NDK standalone path") | |
ea8adc8c XL |
111 | v("aarch64-linux-android-ndk", "target.aarch64-linux-android.android-ndk", |
112 | "aarch64-linux-android NDK standalone path") | |
113 | v("x86_64-linux-android-ndk", "target.x86_64-linux-android.android-ndk", | |
114 | "x86_64-linux-android NDK standalone path") | |
115 | v("musl-root", "target.x86_64-unknown-linux-musl.musl-root", | |
116 | "MUSL root installation directory (deprecated)") | |
117 | v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root", | |
118 | "x86_64-unknown-linux-musl install directory") | |
2c00a5a8 XL |
119 | v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root", |
120 | "i586-unknown-linux-musl install directory") | |
ea8adc8c XL |
121 | v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root", |
122 | "i686-unknown-linux-musl install directory") | |
123 | v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root", | |
124 | "arm-unknown-linux-musleabi install directory") | |
125 | v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", | |
126 | "arm-unknown-linux-musleabihf install directory") | |
83c7162d XL |
127 | v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root", |
128 | "armv5te-unknown-linux-musleabi install directory") | |
416331ca XL |
129 | v("musl-root-armv7", "target.armv7-unknown-linux-musleabi.musl-root", |
130 | "armv7-unknown-linux-musleabi install directory") | |
131 | v("musl-root-armv7hf", "target.armv7-unknown-linux-musleabihf.musl-root", | |
ea8adc8c XL |
132 | "armv7-unknown-linux-musleabihf install directory") |
133 | v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root", | |
134 | "aarch64-unknown-linux-musl install directory") | |
2c00a5a8 XL |
135 | v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root", |
136 | "mips-unknown-linux-musl install directory") | |
137 | v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root", | |
138 | "mipsel-unknown-linux-musl install directory") | |
e74abb32 XL |
139 | v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root", |
140 | "mips64-unknown-linux-muslabi64 install directory") | |
141 | v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root", | |
142 | "mips64el-unknown-linux-muslabi64 install directory") | |
ea8adc8c XL |
143 | v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs", |
144 | "rootfs in qemu testing, you probably don't want to use this") | |
145 | v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", | |
146 | "rootfs in qemu testing, you probably don't want to use this") | |
f035d41b XL |
147 | v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", |
148 | "rootfs in qemu testing, you probably don't want to use this") | |
ea8adc8c XL |
149 | v("experimental-targets", "llvm.experimental-targets", |
150 | "experimental LLVM targets to build") | |
151 | v("release-channel", "rust.channel", "the name of the release channel to build") | |
fc512014 | 152 | v("release-description", "rust.description", "optional descriptive string for version output") |
5869c6ff XL |
153 | v("dist-compression-formats", None, |
154 | "comma-separated list of compression formats to use") | |
ea8adc8c | 155 | |
abe05a73 | 156 | # Used on systems where "cc" is unavailable |
ea8adc8c | 157 | v("default-linker", "rust.default-linker", "the default linker") |
ea8adc8c XL |
158 | |
159 | # Many of these are saved below during the "writing configuration" step | |
160 | # (others are conditionally saved). | |
161 | o("manage-submodules", "build.submodules", "let the build manage the git submodules") | |
064997fb | 162 | o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)") |
ea8adc8c XL |
163 | o("extended", "build.extended", "build an extended rust tool set") |
164 | ||
83c7162d | 165 | v("tools", None, "List of extended tools will be installed") |
136023e0 | 166 | v("codegen-backends", None, "List of codegen backends to build") |
ea8adc8c XL |
167 | v("build", "build.build", "GNUs ./configure syntax LLVM build triple") |
168 | v("host", None, "GNUs ./configure syntax LLVM host triples") | |
169 | v("target", None, "GNUs ./configure syntax LLVM target triples") | |
170 | ||
171 | v("set", None, "set arbitrary key/value pairs in TOML configuration") | |
172 | ||
abe05a73 | 173 | |
ea8adc8c XL |
174 | def p(msg): |
175 | print("configure: " + msg) | |
176 | ||
abe05a73 | 177 | |
ea8adc8c XL |
178 | def err(msg): |
179 | print("configure: error: " + msg) | |
180 | sys.exit(1) | |
181 | ||
abe05a73 | 182 | |
ea8adc8c XL |
183 | if '--help' in sys.argv or '-h' in sys.argv: |
184 | print('Usage: ./configure [options]') | |
185 | print('') | |
186 | print('Options') | |
187 | for option in options: | |
188 | if 'android' in option.name: | |
189 | # no one needs to know about these obscure options | |
190 | continue | |
191 | if option.value: | |
192 | print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc)) | |
193 | else: | |
194 | print('\t{:30} {}'.format('--enable-{}'.format(option.name), option.desc)) | |
195 | print('') | |
196 | print('This configure script is a thin configuration shim over the true') | |
197 | print('configuration system, `config.toml`. You can explore the comments') | |
198 | print('in `config.toml.example` next to this configure script to see') | |
199 | print('more information about what each option is. Additionally you can') | |
200 | print('pass `--set` as an argument to set arbitrary key/value pairs') | |
201 | print('in the TOML configuration if desired') | |
202 | print('') | |
203 | print('Also note that all options which take `--enable` can similarly') | |
204 | print('be passed with `--disable-foo` to forcibly disable the option') | |
205 | sys.exit(0) | |
206 | ||
207 | # Parse all command line arguments into one of these three lists, handling | |
208 | # boolean and value-based options separately | |
209 | unknown_args = [] | |
210 | need_value_args = [] | |
211 | known_args = {} | |
212 | ||
213 | p("processing command line") | |
214 | i = 1 | |
215 | while i < len(sys.argv): | |
216 | arg = sys.argv[i] | |
217 | i += 1 | |
218 | if not arg.startswith('--'): | |
219 | unknown_args.append(arg) | |
220 | continue | |
221 | ||
222 | found = False | |
223 | for option in options: | |
224 | value = None | |
225 | if option.value: | |
226 | keyval = arg[2:].split('=', 1) | |
227 | key = keyval[0] | |
228 | if option.name != key: | |
229 | continue | |
230 | ||
231 | if len(keyval) > 1: | |
232 | value = keyval[1] | |
233 | elif i < len(sys.argv): | |
234 | value = sys.argv[i] | |
235 | i += 1 | |
236 | else: | |
237 | need_value_args.append(arg) | |
238 | continue | |
239 | else: | |
240 | if arg[2:] == 'enable-' + option.name: | |
241 | value = True | |
242 | elif arg[2:] == 'disable-' + option.name: | |
243 | value = False | |
244 | else: | |
245 | continue | |
246 | ||
247 | found = True | |
abe05a73 | 248 | if option.name not in known_args: |
ea8adc8c XL |
249 | known_args[option.name] = [] |
250 | known_args[option.name].append((option, value)) | |
251 | break | |
252 | ||
253 | if not found: | |
254 | unknown_args.append(arg) | |
255 | p("") | |
256 | ||
abe05a73 XL |
257 | # Note: here and a few other places, we use [-1] to apply the *last* value |
258 | # passed. But if option-checking is enabled, then the known_args loop will | |
259 | # also assert that options are only passed once. | |
260 | option_checking = ('option-checking' not in known_args | |
261 | or known_args['option-checking'][-1][1]) | |
262 | if option_checking: | |
ea8adc8c XL |
263 | if len(unknown_args) > 0: |
264 | err("Option '" + unknown_args[0] + "' is not recognized") | |
265 | if len(need_value_args) > 0: | |
266 | err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0])) | |
267 | ||
268 | # Parse all known arguments into a configuration structure that reflects the | |
269 | # TOML we're going to write out | |
270 | config = {} | |
271 | ||
abe05a73 | 272 | |
ea8adc8c XL |
273 | def build(): |
274 | if 'build' in known_args: | |
abe05a73 | 275 | return known_args['build'][-1][1] |
29967ef6 | 276 | return bootstrap.default_build_triple(verbose=False) |
ea8adc8c | 277 | |
abe05a73 | 278 | |
ea8adc8c | 279 | def set(key, value): |
5e7ed085 FG |
280 | if isinstance(value, list): |
281 | # Remove empty values, which value.split(',') tends to generate. | |
282 | value = [v for v in value if v] | |
283 | ||
abe05a73 XL |
284 | s = "{:20} := {}".format(key, value) |
285 | if len(s) < 70: | |
286 | p(s) | |
287 | else: | |
288 | p(s[:70] + " ...") | |
289 | ||
290 | arr = config | |
291 | parts = key.split('.') | |
292 | for i, part in enumerate(parts): | |
293 | if i == len(parts) - 1: | |
294 | arr[part] = value | |
295 | else: | |
296 | if part not in arr: | |
297 | arr[part] = {} | |
298 | arr = arr[part] | |
299 | ||
ea8adc8c XL |
300 | |
301 | for key in known_args: | |
302 | # The `set` option is special and can be passed a bunch of times | |
303 | if key == 'set': | |
304 | for option, value in known_args[key]: | |
305 | keyval = value.split('=', 1) | |
306 | if len(keyval) == 1 or keyval[1] == "true": | |
307 | value = True | |
308 | elif keyval[1] == "false": | |
309 | value = False | |
310 | else: | |
311 | value = keyval[1] | |
312 | set(keyval[0], value) | |
313 | continue | |
314 | ||
315 | # Ensure each option is only passed once | |
316 | arr = known_args[key] | |
abe05a73 | 317 | if option_checking and len(arr) > 1: |
ea8adc8c | 318 | err("Option '{}' provided more than once".format(key)) |
abe05a73 | 319 | option, value = arr[-1] |
ea8adc8c XL |
320 | |
321 | # If we have a clear avenue to set our value in rustbuild, do so | |
322 | if option.rustbuild is not None: | |
323 | set(option.rustbuild, value) | |
324 | continue | |
325 | ||
326 | # Otherwise we're a "special" option and need some extra handling, so do | |
327 | # that here. | |
328 | if option.name == 'sccache': | |
329 | set('llvm.ccache', 'sccache') | |
330 | elif option.name == 'local-rust': | |
331 | for path in os.environ['PATH'].split(os.pathsep): | |
332 | if os.path.exists(path + '/rustc'): | |
333 | set('build.rustc', path + '/rustc') | |
334 | break | |
335 | for path in os.environ['PATH'].split(os.pathsep): | |
336 | if os.path.exists(path + '/cargo'): | |
337 | set('build.cargo', path + '/cargo') | |
338 | break | |
339 | elif option.name == 'local-rust-root': | |
340 | set('build.rustc', value + '/bin/rustc') | |
341 | set('build.cargo', value + '/bin/cargo') | |
342 | elif option.name == 'llvm-root': | |
343 | set('target.{}.llvm-config'.format(build()), value + '/bin/llvm-config') | |
0bf4aa26 XL |
344 | elif option.name == 'llvm-config': |
345 | set('target.{}.llvm-config'.format(build()), value) | |
346 | elif option.name == 'llvm-filecheck': | |
347 | set('target.{}.llvm-filecheck'.format(build()), value) | |
83c7162d XL |
348 | elif option.name == 'tools': |
349 | set('build.tools', value.split(',')) | |
136023e0 XL |
350 | elif option.name == 'codegen-backends': |
351 | set('rust.codegen-backends', value.split(',')) | |
ea8adc8c XL |
352 | elif option.name == 'host': |
353 | set('build.host', value.split(',')) | |
354 | elif option.name == 'target': | |
355 | set('build.target', value.split(',')) | |
0531ce1d | 356 | elif option.name == 'full-tools': |
e74abb32 | 357 | set('rust.codegen-backends', ['llvm']) |
0531ce1d | 358 | set('rust.lld', True) |
8faf50e0 | 359 | set('rust.llvm-tools', True) |
0531ce1d | 360 | set('build.extended', True) |
ea8adc8c XL |
361 | elif option.name == 'option-checking': |
362 | # this was handled above | |
363 | pass | |
5869c6ff XL |
364 | elif option.name == 'dist-compression-formats': |
365 | set('dist.compression-formats', value.split(',')) | |
ea8adc8c XL |
366 | else: |
367 | raise RuntimeError("unhandled option {}".format(option.name)) | |
368 | ||
369 | set('build.configure-args', sys.argv[1:]) | |
370 | ||
371 | # "Parse" the `config.toml.example` file into the various sections, and we'll | |
372 | # use this as a template of a `config.toml` to write out which preserves | |
373 | # all the various comments and whatnot. | |
374 | # | |
375 | # Note that the `target` section is handled separately as we'll duplicate it | |
b7449926 | 376 | # per configured target, so there's a bit of special handling for that here. |
ea8adc8c XL |
377 | sections = {} |
378 | cur_section = None | |
379 | sections[None] = [] | |
380 | section_order = [None] | |
381 | targets = {} | |
382 | ||
383 | for line in open(rust_dir + '/config.toml.example').read().split("\n"): | |
384 | if line.startswith('['): | |
385 | cur_section = line[1:-1] | |
386 | if cur_section.startswith('target'): | |
387 | cur_section = 'target' | |
388 | elif '.' in cur_section: | |
389 | raise RuntimeError("don't know how to deal with section: {}".format(cur_section)) | |
390 | sections[cur_section] = [line] | |
391 | section_order.append(cur_section) | |
392 | else: | |
393 | sections[cur_section].append(line) | |
394 | ||
395 | # Fill out the `targets` array by giving all configured targets a copy of the | |
396 | # `target` section we just loaded from the example config | |
397 | configured_targets = [build()] | |
398 | if 'build' in config: | |
399 | if 'host' in config['build']: | |
400 | configured_targets += config['build']['host'] | |
401 | if 'target' in config['build']: | |
402 | configured_targets += config['build']['target'] | |
403 | if 'target' in config: | |
404 | for target in config['target']: | |
405 | configured_targets.append(target) | |
406 | for target in configured_targets: | |
407 | targets[target] = sections['target'][:] | |
6522a427 EL |
408 | # For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target. |
409 | # Avoid using quotes unless it's necessary. | |
410 | targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target) | |
ea8adc8c | 411 | |
abe05a73 | 412 | |
a1dfa0c6 | 413 | def is_number(value): |
74b04a01 XL |
414 | try: |
415 | float(value) | |
416 | return True | |
417 | except ValueError: | |
418 | return False | |
419 | ||
a1dfa0c6 | 420 | |
ea8adc8c | 421 | # Here we walk through the constructed configuration we have from the parsed |
abe05a73 | 422 | # command line arguments. We then apply each piece of configuration by |
ea8adc8c XL |
423 | # basically just doing a `sed` to change the various configuration line to what |
424 | # we've got configure. | |
425 | def to_toml(value): | |
426 | if isinstance(value, bool): | |
427 | if value: | |
428 | return "true" | |
429 | else: | |
430 | return "false" | |
431 | elif isinstance(value, list): | |
432 | return '[' + ', '.join(map(to_toml, value)) + ']' | |
433 | elif isinstance(value, str): | |
a1dfa0c6 XL |
434 | # Don't put quotes around numeric values |
435 | if is_number(value): | |
436 | return value | |
437 | else: | |
438 | return "'" + value + "'" | |
ea8adc8c | 439 | else: |
abe05a73 XL |
440 | raise RuntimeError('no toml') |
441 | ||
ea8adc8c XL |
442 | |
443 | def configure_section(lines, config): | |
444 | for key in config: | |
445 | value = config[key] | |
446 | found = False | |
447 | for i, line in enumerate(lines): | |
448 | if not line.startswith('#' + key + ' = '): | |
449 | continue | |
450 | found = True | |
451 | lines[i] = "{} = {}".format(key, to_toml(value)) | |
452 | break | |
453 | if not found: | |
cdc7bbd5 XL |
454 | # These are used by rpm, but aren't accepted by x.py. |
455 | # Give a warning that they're ignored, but not a hard error. | |
456 | if key in ["infodir", "localstatedir"]: | |
457 | print("warning: {} will be ignored".format(key)) | |
458 | else: | |
459 | raise RuntimeError("failed to find config line for {}".format(key)) | |
ea8adc8c | 460 | |
abe05a73 | 461 | |
ea8adc8c XL |
462 | for section_key in config: |
463 | section_config = config[section_key] | |
abe05a73 XL |
464 | if section_key not in sections: |
465 | raise RuntimeError("config key {} not in sections".format(section_key)) | |
ea8adc8c XL |
466 | |
467 | if section_key == 'target': | |
468 | for target in section_config: | |
469 | configure_section(targets[target], section_config[target]) | |
470 | else: | |
471 | configure_section(sections[section_key], section_config) | |
472 | ||
473 | # Now that we've built up our `config.toml`, write it all out in the same | |
474 | # order that we read it in. | |
475 | p("") | |
476 | p("writing `config.toml` in current directory") | |
8faf50e0 | 477 | with bootstrap.output('config.toml') as f: |
ea8adc8c XL |
478 | for section in section_order: |
479 | if section == 'target': | |
480 | for target in targets: | |
481 | for line in targets[target]: | |
482 | f.write(line + "\n") | |
483 | else: | |
484 | for line in sections[section]: | |
485 | f.write(line + "\n") | |
486 | ||
8faf50e0 | 487 | with bootstrap.output('Makefile') as f: |
ea8adc8c XL |
488 | contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in') |
489 | contents = open(contents).read() | |
490 | contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/') | |
491 | contents = contents.replace("$(CFG_PYTHON)", sys.executable) | |
492 | f.write(contents) | |
493 | ||
ea8adc8c | 494 | p("") |
abe05a73 | 495 | p("run `python {}/x.py --help`".format(rust_dir)) |