source: mainline/tools/autotool.py@ 512579c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 512579c was 32355bc, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Remove the generated common.h header

We haven't used it in some time, instead relying on the compiler
providing types with properties we want. Since we only support
building with GCC and Clang, extra detection code is just dead weight.

  • Property mode set to 100755
File size: 13.1 KB
Line 
1#!/usr/bin/env python
2#
3# Copyright (c) 2010 Martin Decky
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# - Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# - Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution.
15# - The name of the author may not be used to endorse or promote products
16# derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29
30"""
31Detect important prerequisites and parameters for building HelenOS
32"""
33
34import sys
35import os
36import shutil
37import re
38import time
39import subprocess
40
41SANDBOX = 'autotool'
42CONFIG = 'Makefile.config'
43MAKEFILE = 'Makefile.common'
44
45PACKAGE_CROSS = "use tools/toolchain.sh to build the cross-compiler toolchain"
46PACKAGE_CLANG = "reasonably recent version of clang needs to be installed"
47
48def read_config(fname, config):
49 "Read HelenOS build configuration"
50
51 inf = open(fname, 'r')
52
53 for line in inf:
54 res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
55 if (res):
56 config[res.group(1)] = res.group(2)
57
58 inf.close()
59
60def print_error(msg):
61 "Print a bold error message"
62
63 sys.stderr.write("\n")
64 sys.stderr.write("######################################################################\n")
65 sys.stderr.write("HelenOS build sanity check error:\n")
66 sys.stderr.write("\n")
67 sys.stderr.write("%s\n" % "\n".join(msg))
68 sys.stderr.write("######################################################################\n")
69 sys.stderr.write("\n")
70
71 sys.exit(1)
72
73def sandbox_enter():
74 "Create a temporal sandbox directory for running tests"
75
76 if (os.path.exists(SANDBOX)):
77 if (os.path.isdir(SANDBOX)):
78 try:
79 shutil.rmtree(SANDBOX)
80 except:
81 print_error(["Unable to cleanup the directory \"%s\"." % SANDBOX])
82 else:
83 print_error(["Please inspect and remove unexpected directory,",
84 "entry \"%s\"." % SANDBOX])
85
86 try:
87 os.mkdir(SANDBOX)
88 except:
89 print_error(["Unable to create sandbox directory \"%s\"." % SANDBOX])
90
91 owd = os.getcwd()
92 os.chdir(SANDBOX)
93
94 return owd
95
96def sandbox_leave(owd):
97 "Leave the temporal sandbox directory"
98
99 os.chdir(owd)
100
101def check_config(config, key):
102 "Check whether the configuration key exists"
103
104 if (not key in config):
105 print_error(["Build configuration of HelenOS does not contain %s." % key,
106 "Try running \"make config\" again.",
107 "If the problem persists, please contact the developers of HelenOS."])
108
109def check_common(common, key):
110 "Check whether the common key exists"
111
112 if (not key in common):
113 print_error(["Failed to determine the value %s." % key,
114 "Please contact the developers of HelenOS."])
115
116def get_target(config):
117 platform = None
118 target = None
119
120 if (config['PLATFORM'] == "abs32le"):
121 check_config(config, "CROSS_TARGET")
122 platform = config['CROSS_TARGET']
123
124 if (config['CROSS_TARGET'] == "arm32"):
125 target = "arm-helenos"
126
127 if (config['CROSS_TARGET'] == "ia32"):
128 target = "i686-helenos"
129
130 if (config['CROSS_TARGET'] == "mips32"):
131 target = "mipsel-helenos"
132
133 if (config['PLATFORM'] == "amd64"):
134 platform = config['PLATFORM']
135 target = "amd64-helenos"
136
137 if (config['PLATFORM'] == "arm32"):
138 platform = config['PLATFORM']
139 target = "arm-helenos"
140
141 if (config['PLATFORM'] == "arm64"):
142 platform = config['PLATFORM']
143 target = "aarch64-helenos"
144
145 if (config['PLATFORM'] == "ia32"):
146 platform = config['PLATFORM']
147 target = "i686-helenos"
148
149 if (config['PLATFORM'] == "ia64"):
150 platform = config['PLATFORM']
151 target = "ia64-helenos"
152
153 if (config['PLATFORM'] == "mips32"):
154 check_config(config, "MACHINE")
155
156 if ((config['MACHINE'] == "msim") or (config['MACHINE'] == "lmalta")):
157 platform = config['PLATFORM']
158 target = "mipsel-helenos"
159
160 if ((config['MACHINE'] == "bmalta")):
161 platform = "mips32eb"
162 target = "mips-helenos"
163
164 if (config['PLATFORM'] == "mips64"):
165 check_config(config, "MACHINE")
166
167 if (config['MACHINE'] == "msim"):
168 platform = config['PLATFORM']
169 target = "mips64el-helenos"
170
171 if (config['PLATFORM'] == "ppc32"):
172 platform = config['PLATFORM']
173 target = "ppc-helenos"
174
175 if (config['PLATFORM'] == "riscv64"):
176 platform = config['PLATFORM']
177 target = "riscv64-helenos"
178
179 if (config['PLATFORM'] == "sparc64"):
180 platform = config['PLATFORM']
181 target = "sparc64-helenos"
182
183 return (platform, target)
184
185def check_app(args, name, details):
186 "Check whether an application can be executed"
187
188 try:
189 sys.stderr.write("Checking for %s ... " % args[0])
190 subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
191 except:
192 sys.stderr.write("failed\n")
193 print_error(["%s is missing." % name,
194 "",
195 "Execution of \"%s\" has failed. Please make sure that it" % " ".join(args),
196 "is installed in your system (%s)." % details])
197
198 sys.stderr.write("ok\n")
199
200def check_path_gcc(target):
201 "Check whether GCC for a given target is present in $PATH."
202
203 try:
204 subprocess.Popen([ "%s-gcc" % target, "--version" ], stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
205 return True
206 except:
207 return False
208
209def check_app_alternatives(alts, args, name, details):
210 "Check whether an application can be executed (use several alternatives)"
211
212 tried = []
213 found = None
214
215 for alt in alts:
216 working = True
217 cmdline = [alt] + args
218 tried.append(" ".join(cmdline))
219
220 try:
221 sys.stderr.write("Checking for %s ... " % alt)
222 subprocess.Popen(cmdline, stdout = subprocess.PIPE, stderr = subprocess.PIPE).wait()
223 except:
224 sys.stderr.write("failed\n")
225 working = False
226
227 if (working):
228 sys.stderr.write("ok\n")
229 found = alt
230 break
231
232 if (found is None):
233 print_error(["%s is missing." % name,
234 "",
235 "Please make sure that it is installed in your",
236 "system (%s)." % details,
237 "",
238 "The following alternatives were tried:"] + tried)
239
240 return found
241
242def check_clang(path, prefix, common, details):
243 "Check for clang"
244
245 common['CLANG'] = "%sclang" % prefix
246 common['CLANGXX'] = "%sclang++" % prefix
247
248 if (not path is None):
249 common['CLANG'] = "%s/%s" % (path, common['CLANG'])
250 common['CLANGXX'] = "%s/%s" % (path, common['CLANGXX'])
251
252 check_app([common['CLANG'], "--version"], "clang", details)
253
254def check_gcc(path, prefix, common, details):
255 "Check for GCC"
256
257 common['GCC'] = "%sgcc" % prefix
258 common['GXX'] = "%sg++" % prefix
259
260 if (not path is None):
261 common['GCC'] = "%s/%s" % (path, common['GCC'])
262 common['GXX'] = "%s/%s" % (path, common['GXX'])
263
264 check_app([common['GCC'], "--version"], "GNU GCC", details)
265
266def check_libgcc(common):
267 sys.stderr.write("Checking for libgcc.a ... ")
268 libgcc_path = None
269 proc = subprocess.Popen([ common['GCC'], "-print-search-dirs" ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
270 for line in proc.stdout:
271 line = line.decode('utf-8').strip('\n')
272 parts = line.split()
273 if parts[0] == "install:":
274 p = parts[1] + "libgcc.a"
275 if os.path.isfile(p):
276 libgcc_path = p
277 proc.wait()
278
279 if libgcc_path is None:
280 sys.stderr.write("failed\n")
281 print_error(["Unable to find gcc library (libgcc.a).",
282 "",
283 "Please ensure that you have installed the",
284 "toolchain properly."])
285
286 sys.stderr.write("ok\n")
287 common['LIBGCC_PATH'] = libgcc_path
288
289
290def check_binutils(path, prefix, common, details):
291 "Check for binutils toolchain"
292
293 common['AS'] = "%sas" % prefix
294 common['LD'] = "%sld" % prefix
295 common['AR'] = "%sar" % prefix
296 common['OBJCOPY'] = "%sobjcopy" % prefix
297 common['OBJDUMP'] = "%sobjdump" % prefix
298 common['STRIP'] = "%sstrip" % prefix
299
300 if (not path is None):
301 for key in ["AS", "LD", "AR", "OBJCOPY", "OBJDUMP", "STRIP"]:
302 common[key] = "%s/%s" % (path, common[key])
303
304 check_app([common['AS'], "--version"], "GNU Assembler", details)
305 check_app([common['LD'], "--version"], "GNU Linker", details)
306 check_app([common['AR'], "--version"], "GNU Archiver", details)
307 check_app([common['OBJCOPY'], "--version"], "GNU Objcopy utility", details)
308 check_app([common['OBJDUMP'], "--version"], "GNU Objdump utility", details)
309 check_app([common['STRIP'], "--version"], "GNU strip", details)
310
311def create_makefile(mkname, common):
312 "Create makefile output"
313
314 outmk = open(mkname, 'w')
315
316 outmk.write('#########################################\n')
317 outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
318 outmk.write('## Generated by: tools/autotool.py ##\n')
319 outmk.write('#########################################\n\n')
320
321 for key, value in common.items():
322 if (type(value) is list):
323 outmk.write('%s = %s\n' % (key, " ".join(value)))
324 else:
325 outmk.write('%s = %s\n' % (key, value))
326
327 outmk.close()
328
329def create_header(hdname, macros):
330 "Create header output"
331
332 outhd = open(hdname, 'w')
333
334 outhd.write('/***************************************\n')
335 outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
336 outhd.write(' * Generated by: tools/autotool.py *\n')
337 outhd.write(' ***************************************/\n\n')
338
339 outhd.write('#ifndef %s\n' % GUARD)
340 outhd.write('#define %s\n\n' % GUARD)
341
342 for macro in sorted(macros):
343 outhd.write('#ifndef %s\n' % macro)
344 outhd.write('#define %s %s\n' % (macro, macros[macro]))
345 outhd.write('#endif\n\n')
346
347 outhd.write('\n#endif\n')
348 outhd.close()
349
350def main():
351 config = {}
352 common = {}
353
354 # Read and check configuration
355 if os.path.exists(CONFIG):
356 read_config(CONFIG, config)
357 else:
358 print_error(["Configuration file %s not found! Make sure that the" % CONFIG,
359 "configuration phase of HelenOS build went OK. Try running",
360 "\"make config\" again."])
361
362 check_config(config, "PLATFORM")
363 check_config(config, "COMPILER")
364 check_config(config, "BARCH")
365
366 # Cross-compiler prefix
367 if ('CROSS_PREFIX' in os.environ):
368 cross_prefix = os.environ['CROSS_PREFIX']
369 else:
370 cross_prefix = "/usr/local/cross"
371
372 owd = sandbox_enter()
373
374 try:
375 # Common utilities
376 check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
377 check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
378 check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
379 check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
380 check_app(["find", "--version"], "Find utility", "usually part of findutils")
381 check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
382 check_app(["make", "--version"], "Make utility", "preferably GNU Make")
383 check_app(["unzip"], "unzip utility", "usually part of zip/unzip utilities")
384 check_app(["tar", "--version"], "tar utility", "usually part of tar")
385
386 platform, target = get_target(config)
387
388 if (platform is None) or (target is None):
389 print_error(["Unsupported compiler target.",
390 "Please contact the developers of HelenOS."])
391
392 path = None
393
394 if not check_path_gcc(target):
395 path = "%s/bin" % cross_prefix
396
397 common['TARGET'] = target
398 prefix = "%s-" % target
399
400 cc_autogen = None
401
402 # We always need to check for GCC as we
403 # need libgcc
404 check_gcc(path, prefix, common, PACKAGE_CROSS)
405
406 # Compiler
407 if (config['COMPILER'] == "gcc_cross"):
408 check_binutils(path, prefix, common, PACKAGE_CROSS)
409
410 check_common(common, "GCC")
411 common['CC'] = common['GCC']
412 cc_autogen = common['CC']
413
414 check_common(common, "GXX")
415 common['CXX'] = common['GXX']
416
417 if (config['COMPILER'] == "clang"):
418 check_binutils(path, prefix, common, PACKAGE_CROSS)
419 check_clang(path, prefix, common, PACKAGE_CLANG)
420
421 check_common(common, "CLANG")
422 common['CC'] = common['CLANG']
423 common['CXX'] = common['CLANGXX']
424 cc_autogen = common['CC'] + " -no-integrated-as"
425
426 if (config['INTEGRATED_AS'] == "yes"):
427 common['CC'] += " -integrated-as"
428 common['CXX'] += " -integrated-as"
429
430 if (config['INTEGRATED_AS'] == "no"):
431 common['CC'] += " -no-integrated-as"
432 common['CXX'] += " -no-integrated-as"
433
434 # Find full path to libgcc
435 check_libgcc(common)
436
437 # Platform-specific utilities
438 if (config['BARCH'] in ('amd64', 'arm64', 'ia32', 'ppc32', 'sparc64')):
439 common['GENISOIMAGE'] = check_app_alternatives(["genisoimage", "mkisofs", "xorriso"], ["--version"], "ISO 9660 creation utility", "usually part of genisoimage")
440 if common['GENISOIMAGE'] == 'xorriso':
441 common['GENISOIMAGE'] += ' -as genisoimage'
442
443 finally:
444 sandbox_leave(owd)
445
446 create_makefile(MAKEFILE, common)
447
448 return 0
449
450if __name__ == '__main__':
451 sys.exit(main())
Note: See TracBrowser for help on using the repository browser.