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
RevLine 
[4248ce5]1#!/usr/bin/env python
[177e4ea]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#
[3c80f2b]29
[177e4ea]30"""
31Detect important prerequisites and parameters for building HelenOS
32"""
33
34import sys
35import os
[4e9aaf5]36import shutil
[177e4ea]37import re
38import time
39import subprocess
40
[4e9aaf5]41SANDBOX = 'autotool'
42CONFIG = 'Makefile.config'
43MAKEFILE = 'Makefile.common'
44
[177e4ea]45PACKAGE_CROSS = "use tools/toolchain.sh to build the cross-compiler toolchain"
[84eb4edd]46PACKAGE_CLANG = "reasonably recent version of clang needs to be installed"
[177e4ea]47
48def read_config(fname, config):
49 "Read HelenOS build configuration"
[a35b458]50
[28f4adb]51 inf = open(fname, 'r')
[a35b458]52
[177e4ea]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)
[a35b458]57
[177e4ea]58 inf.close()
59
60def print_error(msg):
61 "Print a bold error message"
[a35b458]62
[177e4ea]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")
[a35b458]70
[177e4ea]71 sys.exit(1)
72
[4e9aaf5]73def sandbox_enter():
74 "Create a temporal sandbox directory for running tests"
[a35b458]75
[4e9aaf5]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])
[a35b458]85
[4e9aaf5]86 try:
87 os.mkdir(SANDBOX)
88 except:
89 print_error(["Unable to create sandbox directory \"%s\"." % SANDBOX])
[a35b458]90
[4e9aaf5]91 owd = os.getcwd()
92 os.chdir(SANDBOX)
[a35b458]93
[4e9aaf5]94 return owd
95
96def sandbox_leave(owd):
97 "Leave the temporal sandbox directory"
[a35b458]98
[4e9aaf5]99 os.chdir(owd)
100
[177e4ea]101def check_config(config, key):
102 "Check whether the configuration key exists"
[a35b458]103
[177e4ea]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
[4e9aaf5]109def check_common(common, key):
110 "Check whether the common key exists"
[a35b458]111
[4e9aaf5]112 if (not key in common):
113 print_error(["Failed to determine the value %s." % key,
114 "Please contact the developers of HelenOS."])
115
[95e370f8]116def get_target(config):
[b08941d]117 platform = None
118 target = None
[a35b458]119
[39ba6d5]120 if (config['PLATFORM'] == "abs32le"):
121 check_config(config, "CROSS_TARGET")
[b08941d]122 platform = config['CROSS_TARGET']
[a35b458]123
[39ba6d5]124 if (config['CROSS_TARGET'] == "arm32"):
[bbe5e34]125 target = "arm-helenos"
[a35b458]126
[39ba6d5]127 if (config['CROSS_TARGET'] == "ia32"):
[bbe5e34]128 target = "i686-helenos"
[a35b458]129
[39ba6d5]130 if (config['CROSS_TARGET'] == "mips32"):
[bbe5e34]131 target = "mipsel-helenos"
[a35b458]132
[39ba6d5]133 if (config['PLATFORM'] == "amd64"):
[b08941d]134 platform = config['PLATFORM']
[bbe5e34]135 target = "amd64-helenos"
[a35b458]136
[39ba6d5]137 if (config['PLATFORM'] == "arm32"):
[b08941d]138 platform = config['PLATFORM']
[bbe5e34]139 target = "arm-helenos"
[a35b458]140
[84176f3]141 if (config['PLATFORM'] == "arm64"):
142 platform = config['PLATFORM']
143 target = "aarch64-helenos"
144
[39ba6d5]145 if (config['PLATFORM'] == "ia32"):
[b08941d]146 platform = config['PLATFORM']
[bbe5e34]147 target = "i686-helenos"
[a35b458]148
[39ba6d5]149 if (config['PLATFORM'] == "ia64"):
[b08941d]150 platform = config['PLATFORM']
[bbe5e34]151 target = "ia64-helenos"
[a35b458]152
[39ba6d5]153 if (config['PLATFORM'] == "mips32"):
154 check_config(config, "MACHINE")
[a35b458]155
[b183ce0a]156 if ((config['MACHINE'] == "msim") or (config['MACHINE'] == "lmalta")):
[b08941d]157 platform = config['PLATFORM']
[bbe5e34]158 target = "mipsel-helenos"
[a35b458]159
[b183ce0a]160 if ((config['MACHINE'] == "bmalta")):
[b08941d]161 platform = "mips32eb"
[bbe5e34]162 target = "mips-helenos"
[a35b458]163
[39ba6d5]164 if (config['PLATFORM'] == "mips64"):
165 check_config(config, "MACHINE")
[a35b458]166
[39ba6d5]167 if (config['MACHINE'] == "msim"):
[b08941d]168 platform = config['PLATFORM']
[bbe5e34]169 target = "mips64el-helenos"
[a35b458]170
[39ba6d5]171 if (config['PLATFORM'] == "ppc32"):
[b08941d]172 platform = config['PLATFORM']
[bbe5e34]173 target = "ppc-helenos"
[a35b458]174
[114d098]175 if (config['PLATFORM'] == "riscv64"):
[b08941d]176 platform = config['PLATFORM']
[bbe5e34]177 target = "riscv64-helenos"
[a35b458]178
[39ba6d5]179 if (config['PLATFORM'] == "sparc64"):
[b08941d]180 platform = config['PLATFORM']
[bbe5e34]181 target = "sparc64-helenos"
[a35b458]182
[b2aaaa0]183 return (platform, target)
[39ba6d5]184
[177e4ea]185def check_app(args, name, details):
186 "Check whether an application can be executed"
[a35b458]187
[177e4ea]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])
[a35b458]197
[177e4ea]198 sys.stderr.write("ok\n")
199
[bbe5e34]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
[7174403]209def check_app_alternatives(alts, args, name, details):
210 "Check whether an application can be executed (use several alternatives)"
[a35b458]211
[7174403]212 tried = []
213 found = None
[a35b458]214
[7174403]215 for alt in alts:
216 working = True
217 cmdline = [alt] + args
218 tried.append(" ".join(cmdline))
[a35b458]219
[7174403]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
[a35b458]226
[7174403]227 if (working):
228 sys.stderr.write("ok\n")
229 found = alt
230 break
[a35b458]231
[7174403]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)
[a35b458]239
[7174403]240 return found
241
[a0a273e]242def check_clang(path, prefix, common, details):
243 "Check for clang"
[a35b458]244
[a0a273e]245 common['CLANG'] = "%sclang" % prefix
[9fb280c]246 common['CLANGXX'] = "%sclang++" % prefix
[a35b458]247
[a0a273e]248 if (not path is None):
249 common['CLANG'] = "%s/%s" % (path, common['CLANG'])
[9fb280c]250 common['CLANGXX'] = "%s/%s" % (path, common['CLANGXX'])
[a35b458]251
[a0a273e]252 check_app([common['CLANG'], "--version"], "clang", details)
253
[177e4ea]254def check_gcc(path, prefix, common, details):
255 "Check for GCC"
[a35b458]256
[177e4ea]257 common['GCC'] = "%sgcc" % prefix
[8e2154e7]258 common['GXX'] = "%sg++" % prefix
[a35b458]259
[177e4ea]260 if (not path is None):
261 common['GCC'] = "%s/%s" % (path, common['GCC'])
[8e2154e7]262 common['GXX'] = "%s/%s" % (path, common['GXX'])
[a35b458]263
[177e4ea]264 check_app([common['GCC'], "--version"], "GNU GCC", details)
265
[279188c0]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
[177e4ea]290def check_binutils(path, prefix, common, details):
291 "Check for binutils toolchain"
[a35b458]292
[177e4ea]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
[a4125fb1]298 common['STRIP'] = "%sstrip" % prefix
[a35b458]299
[177e4ea]300 if (not path is None):
[a4125fb1]301 for key in ["AS", "LD", "AR", "OBJCOPY", "OBJDUMP", "STRIP"]:
[177e4ea]302 common[key] = "%s/%s" % (path, common[key])
[a35b458]303
[177e4ea]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)
[a4125fb1]309 check_app([common['STRIP'], "--version"], "GNU strip", details)
[177e4ea]310
[4e9aaf5]311def create_makefile(mkname, common):
312 "Create makefile output"
[a35b458]313
[28f4adb]314 outmk = open(mkname, 'w')
[a35b458]315
[4e9aaf5]316 outmk.write('#########################################\n')
317 outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
[571239a]318 outmk.write('## Generated by: tools/autotool.py ##\n')
[4e9aaf5]319 outmk.write('#########################################\n\n')
[a35b458]320
[177e4ea]321 for key, value in common.items():
[7174403]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))
[a35b458]326
[4e9aaf5]327 outmk.close()
328
[ce55b43]329def create_header(hdname, macros):
[4e9aaf5]330 "Create header output"
[a35b458]331
[28f4adb]332 outhd = open(hdname, 'w')
[a35b458]333
[4e9aaf5]334 outhd.write('/***************************************\n')
335 outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
[571239a]336 outhd.write(' * Generated by: tools/autotool.py *\n')
[4e9aaf5]337 outhd.write(' ***************************************/\n\n')
[a35b458]338
[4e9aaf5]339 outhd.write('#ifndef %s\n' % GUARD)
340 outhd.write('#define %s\n\n' % GUARD)
[a35b458]341
[ce55b43]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')
[a35b458]346
[4e9aaf5]347 outhd.write('\n#endif\n')
348 outhd.close()
[177e4ea]349
350def main():
351 config = {}
352 common = {}
[a35b458]353
[177e4ea]354 # Read and check configuration
[4e9aaf5]355 if os.path.exists(CONFIG):
356 read_config(CONFIG, config)
[177e4ea]357 else:
[4e9aaf5]358 print_error(["Configuration file %s not found! Make sure that the" % CONFIG,
[177e4ea]359 "configuration phase of HelenOS build went OK. Try running",
360 "\"make config\" again."])
[a35b458]361
[177e4ea]362 check_config(config, "PLATFORM")
363 check_config(config, "COMPILER")
364 check_config(config, "BARCH")
[a35b458]365
[177e4ea]366 # Cross-compiler prefix
367 if ('CROSS_PREFIX' in os.environ):
368 cross_prefix = os.environ['CROSS_PREFIX']
369 else:
[603c8740]370 cross_prefix = "/usr/local/cross"
[a35b458]371
[4e9aaf5]372 owd = sandbox_enter()
[a35b458]373
[4e9aaf5]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")
[9ce911d]383 check_app(["unzip"], "unzip utility", "usually part of zip/unzip utilities")
[75701004]384 check_app(["tar", "--version"], "tar utility", "usually part of tar")
[a35b458]385
[b2aaaa0]386 platform, target = get_target(config)
[a35b458]387
[b08941d]388 if (platform is None) or (target is None):
389 print_error(["Unsupported compiler target.",
390 "Please contact the developers of HelenOS."])
[a35b458]391
[bbe5e34]392 path = None
393
394 if not check_path_gcc(target):
395 path = "%s/bin" % cross_prefix
[a35b458]396
[2660ee3]397 common['TARGET'] = target
[b08941d]398 prefix = "%s-" % target
[a35b458]399
[b2aaaa0]400 cc_autogen = None
401
[279188c0]402 # We always need to check for GCC as we
403 # need libgcc
404 check_gcc(path, prefix, common, PACKAGE_CROSS)
405
[b08941d]406 # Compiler
[bbe5e34]407 if (config['COMPILER'] == "gcc_cross"):
[8f2eca0]408 check_binutils(path, prefix, common, PACKAGE_CROSS)
[a35b458]409
[8f2eca0]410 check_common(common, "GCC")
[b2aaaa0]411 common['CC'] = common['GCC']
412 cc_autogen = common['CC']
[a35b458]413
[8e2154e7]414 check_common(common, "GXX")
415 common['CXX'] = common['GXX']
[058c240]416
[4e9aaf5]417 if (config['COMPILER'] == "clang"):
[84eb4edd]418 check_binutils(path, prefix, common, PACKAGE_CROSS)
419 check_clang(path, prefix, common, PACKAGE_CLANG)
[a35b458]420
[a0a273e]421 check_common(common, "CLANG")
[b2aaaa0]422 common['CC'] = common['CLANG']
[9fb280c]423 common['CXX'] = common['CLANGXX']
[b2aaaa0]424 cc_autogen = common['CC'] + " -no-integrated-as"
[a35b458]425
[a0a273e]426 if (config['INTEGRATED_AS'] == "yes"):
427 common['CC'] += " -integrated-as"
[9fb280c]428 common['CXX'] += " -integrated-as"
[a35b458]429
[a0a273e]430 if (config['INTEGRATED_AS'] == "no"):
431 common['CC'] += " -no-integrated-as"
[9fb280c]432 common['CXX'] += " -no-integrated-as"
[a35b458]433
[279188c0]434 # Find full path to libgcc
435 check_libgcc(common)
436
[4e9aaf5]437 # Platform-specific utilities
[84176f3]438 if (config['BARCH'] in ('amd64', 'arm64', 'ia32', 'ppc32', 'sparc64')):
[ff87f70]439 common['GENISOIMAGE'] = check_app_alternatives(["genisoimage", "mkisofs", "xorriso"], ["--version"], "ISO 9660 creation utility", "usually part of genisoimage")
[b6bbc74]440 if common['GENISOIMAGE'] == 'xorriso':
[92c07dc]441 common['GENISOIMAGE'] += ' -as genisoimage'
[a35b458]442
[4e9aaf5]443 finally:
444 sandbox_leave(owd)
[a35b458]445
[4e9aaf5]446 create_makefile(MAKEFILE, common)
[a35b458]447
[177e4ea]448 return 0
449
450if __name__ == '__main__':
451 sys.exit(main())
Note: See TracBrowser for help on using the repository browser.