Changeset 4e9aaf5 in mainline for tools/autotool.py


Ignore:
Timestamp:
2010-03-19T18:30:12Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8023571, b535aeb, e2b73d4f
Parents:
3c80f2b
Message:

more autotooling: run actually the compiler in autotool.py and detect sizes of integers, generate common.h
more build system cleanup: remove redundancy, remove config.defs, merge kernel makefiles to a single file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tools/autotool.py

    r3c80f2b r4e9aaf5  
    3434import sys
    3535import os
     36import shutil
    3637import re
    3738import time
    3839import subprocess
    3940
    40 MAKEFILE = 'Makefile.config'
    41 COMMON = 'Makefile.common'
     41SANDBOX = 'autotool'
     42CONFIG = 'Makefile.config'
     43MAKEFILE = 'Makefile.common'
     44HEADER = 'common.h'
     45GUARD = 'AUTOTOOL_COMMON_H_'
     46
     47PROBE_SOURCE = 'probe.c'
     48PROBE_OUTPUT = 'probe.s'
    4249
    4350PACKAGE_BINUTILS = "usually part of binutils"
    4451PACKAGE_GCC = "preferably version 4.4.3 or newer"
    4552PACKAGE_CROSS = "use tools/toolchain.sh to build the cross-compiler toolchain"
     53
     54COMPILER_FAIL = "The compiler is probably not capable to compile HelenOS."
     55
     56PROBE_HEAD = """#define AUTOTOOL_DECLARE(category, subcategory, name, value) \\
     57        asm volatile ( \\
     58                "AUTOTOOL_DECLARE\\t" category "\\t" subcategory "\\t" name "\\t%[val]\\n" \\
     59                : \\
     60                : [val] "n" (value) \\
     61        )
     62
     63#define DECLARE_INTSIZE(type) \\
     64        AUTOTOOL_DECLARE("intsize", "unsigned", #type, sizeof(unsigned type)); \\
     65        AUTOTOOL_DECLARE("intsize", "signed", #type, sizeof(signed type))
     66
     67int main(int argc, char *argv[])
     68{
     69"""
     70
     71PROBE_TAIL = """}
     72"""
    4673
    4774def read_config(fname, config):
     
    7097        sys.exit(1)
    7198
     99def sandbox_enter():
     100        "Create a temporal sandbox directory for running tests"
     101       
     102        if (os.path.exists(SANDBOX)):
     103                if (os.path.isdir(SANDBOX)):
     104                        try:
     105                                shutil.rmtree(SANDBOX)
     106                        except:
     107                                print_error(["Unable to cleanup the directory \"%s\"." % SANDBOX])
     108                else:
     109                        print_error(["Please inspect and remove unexpected directory,",
     110                                     "entry \"%s\"." % SANDBOX])
     111       
     112        try:
     113                os.mkdir(SANDBOX)
     114        except:
     115                print_error(["Unable to create sandbox directory \"%s\"." % SANDBOX])
     116       
     117        owd = os.getcwd()
     118        os.chdir(SANDBOX)
     119       
     120        return owd
     121
     122def sandbox_leave(owd):
     123        "Leave the temporal sandbox directory"
     124       
     125        os.chdir(owd)
     126
    72127def check_config(config, key):
    73128        "Check whether the configuration key exists"
     
    77132                             "Try running \"make config\" again.",
    78133                             "If the problem persists, please contact the developers of HelenOS."])
     134
     135def check_common(common, key):
     136        "Check whether the common key exists"
     137       
     138        if (not key in common):
     139                print_error(["Failed to determine the value %s." % key,
     140                             "Please contact the developers of HelenOS."])
    79141
    80142def check_app(args, name, details):
     
    122184        check_app([common['OBJDUMP'], "--version"], "GNU Objdump utility", details)
    123185
    124 def create_output(cmname, common):
    125         "Create common parameters output"
    126        
    127         outcm = file(cmname, 'w')
    128        
    129         outcm.write('#########################################\n')
    130         outcm.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
    131         outcm.write('#########################################\n\n')
     186def probe_compiler(common, sizes):
     187        "Generate, compile and parse probing source"
     188       
     189        check_common(common, "CC")
     190       
     191        outf = file(PROBE_SOURCE, 'w')
     192        outf.write(PROBE_HEAD)
     193       
     194        for typedef in sizes:
     195                outf.write("\tDECLARE_INTSIZE(%s);\n" % typedef)
     196       
     197        outf.write(PROBE_TAIL)
     198        outf.close()
     199       
     200        args = [common['CC'], "-S", "-o", PROBE_OUTPUT, PROBE_SOURCE]
     201       
     202        try:
     203                sys.stderr.write("Checking compiler properties ... ")
     204                output = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
     205        except:
     206                sys.stderr.write("failed\n")
     207                print_error(["Error executing \"%s\"." % " ".join(args),
     208                             "Make sure that the compiler works properly."])
     209       
     210        if (not os.path.isfile(PROBE_OUTPUT)):
     211                sys.stderr.write("failed\n")
     212                print output[1]
     213                print_error(["Error executing \"%s\"." % " ".join(args),
     214                             "The compiler did not produce the output file \"%s\"." % PROBE_OUTPUT,
     215                             "",
     216                             output[0],
     217                             output[1]])
     218       
     219        sys.stderr.write("ok\n")
     220       
     221        inf = file(PROBE_OUTPUT, 'r')
     222        lines = inf.readlines()
     223        inf.close()
     224       
     225        unsigned_sizes = {}
     226        signed_sizes = {}
     227       
     228        for j in range(len(lines)):
     229                tokens = lines[j].strip().split("\t")
     230               
     231                if (len(tokens) > 0):
     232                        if (tokens[0] == "AUTOTOOL_DECLARE"):
     233                                if (len(tokens) < 5):
     234                                        print_error(["Malformed declaration in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
     235                               
     236                                category = tokens[1]
     237                                subcategory = tokens[2]
     238                                name = tokens[3]
     239                                value = tokens[4]
     240                               
     241                                if (category == "intsize"):
     242                                        base = 10
     243                                       
     244                                        if ((value.startswith('$')) or (value.startswith('#'))):
     245                                                value = value[1:]
     246                                       
     247                                        if (value.startswith('0x')):
     248                                                value = value[2:]
     249                                                base = 16
     250                                       
     251                                        try:
     252                                                value_int = int(value, base)
     253                                        except:
     254                                                print_error(["Integer value expected in \"%s\" on line %s." % (PROBE_OUTPUT, j), COMPILER_FAIL])
     255                                       
     256                                        if (subcategory == "unsigned"):
     257                                                unsigned_sizes[name] = value_int
     258                                        elif (subcategory == "signed"):
     259                                                signed_sizes[name] = value_int
     260                                        else:
     261                                                print_error(["Unexpected keyword \"%s\" in \"%s\" on line %s." % (subcategory, PROBE_OUTPUT, j), COMPILER_FAIL])
     262       
     263        return {'unsigned_sizes' : unsigned_sizes, 'signed_sizes' : signed_sizes}
     264
     265def detect_uints(unsigned_sizes, signed_sizes, bytes):
     266        "Detect correct types for fixed-size integer types"
     267       
     268        typedefs = []
     269       
     270        for b in bytes:
     271                fnd = False
     272                newtype = "uint%s_t" % (b * 8)
     273               
     274                for name, value in unsigned_sizes.items():
     275                        if (value == b):
     276                                oldtype = "unsigned %s" % name
     277                                typedefs.append({'oldtype' : oldtype, 'newtype' : newtype})
     278                                fnd = True
     279                                break
     280               
     281                if (not fnd):
     282                        print_error(['Unable to find appropriate integer type for %s' % newtype,
     283                                     COMPILER_FAIL])
     284               
     285               
     286                fnd = False
     287                newtype = "int%s_t" % (b * 8)
     288               
     289                for name, value in signed_sizes.items():
     290                        if (value == b):
     291                                oldtype = "signed %s" % name
     292                                typedefs.append({'oldtype' : oldtype, 'newtype' : newtype})
     293                                fnd = True
     294                                break
     295               
     296                if (not fnd):
     297                        print_error(['Unable to find appropriate integer type for %s' % newtype,
     298                                     COMPILER_FAIL])
     299       
     300        return typedefs
     301
     302def create_makefile(mkname, common):
     303        "Create makefile output"
     304       
     305        outmk = file(mkname, 'w')
     306       
     307        outmk.write('#########################################\n')
     308        outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
     309        outmk.write('#########################################\n\n')
    132310       
    133311        for key, value in common.items():
    134                 outcm.write('%s = %s\n' % (key, value))
    135        
    136         outcm.close()
     312                outmk.write('%s = %s\n' % (key, value))
     313       
     314        outmk.close()
     315
     316def create_header(hdname, typedefs):
     317        "Create header output"
     318       
     319        outhd = file(hdname, 'w')
     320       
     321        outhd.write('/***************************************\n')
     322        outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
     323        outhd.write(' ***************************************/\n\n')
     324       
     325        outhd.write('#ifndef %s\n' % GUARD)
     326        outhd.write('#define %s\n\n' % GUARD)
     327       
     328        for typedef in typedefs:
     329                outhd.write('typedef %s %s;\n' % (typedef['oldtype'], typedef['newtype']))
     330       
     331        outhd.write('\n#endif\n')
     332        outhd.close()
    137333
    138334def main():
     
    141337       
    142338        # Read and check configuration
    143         if os.path.exists(MAKEFILE):
    144                 read_config(MAKEFILE, config)
     339        if os.path.exists(CONFIG):
     340                read_config(CONFIG, config)
    145341        else:
    146                 print_error(["Configuration file %s not found! Make sure that the" % MAKEFILE,
     342                print_error(["Configuration file %s not found! Make sure that the" % CONFIG,
    147343                             "configuration phase of HelenOS build went OK. Try running",
    148344                             "\"make config\" again."])
     
    164360                binutils_prefix = ""
    165361       
    166         # Common utilities
    167         check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
    168         check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
    169         check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
    170         check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
    171         check_app(["find", "--version"], "Find utility", "usually part of findutils")
    172         check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
    173         check_app(["make", "--version"], "Make utility", "preferably GNU Make")
    174         check_app(["makedepend", "-f", "-"], "Makedepend utility", "usually part of imake or xutils")
    175        
    176         # Compiler
    177         if (config['COMPILER'] == "gcc_cross"):
    178                 if (config['PLATFORM'] == "abs32le"):
    179                         check_config(config, "CROSS_TARGET")
    180                         target = config['CROSS_TARGET']
    181                        
    182                         if (config['CROSS_TARGET'] == "arm32"):
     362        owd = sandbox_enter()
     363       
     364        try:
     365                # Common utilities
     366                check_app(["ln", "--version"], "Symlink utility", "usually part of coreutils")
     367                check_app(["rm", "--version"], "File remove utility", "usually part of coreutils")
     368                check_app(["mkdir", "--version"], "Directory creation utility", "usually part of coreutils")
     369                check_app(["cp", "--version"], "Copy utility", "usually part of coreutils")
     370                check_app(["find", "--version"], "Find utility", "usually part of findutils")
     371                check_app(["diff", "--version"], "Diff utility", "usually part of diffutils")
     372                check_app(["make", "--version"], "Make utility", "preferably GNU Make")
     373                check_app(["makedepend", "-f", "-"], "Makedepend utility", "usually part of imake or xutils")
     374               
     375                # Compiler
     376                if (config['COMPILER'] == "gcc_cross"):
     377                        if (config['PLATFORM'] == "abs32le"):
     378                                check_config(config, "CROSS_TARGET")
     379                                target = config['CROSS_TARGET']
     380                               
     381                                if (config['CROSS_TARGET'] == "arm32"):
     382                                        gnu_target = "arm-linux-gnu"
     383                               
     384                                if (config['CROSS_TARGET'] == "ia32"):
     385                                        gnu_target = "i686-pc-linux-gnu"
     386                               
     387                                if (config['CROSS_TARGET'] == "mips32"):
     388                                        gnu_target = "mipsel-linux-gnu"
     389                       
     390                        if (config['PLATFORM'] == "amd64"):
     391                                target = config['PLATFORM']
     392                                gnu_target = "amd64-linux-gnu"
     393                       
     394                        if (config['PLATFORM'] == "arm32"):
     395                                target = config['PLATFORM']
    183396                                gnu_target = "arm-linux-gnu"
    184397                       
    185                         if (config['CROSS_TARGET'] == "ia32"):
     398                        if (config['PLATFORM'] == "ia32"):
     399                                target = config['PLATFORM']
    186400                                gnu_target = "i686-pc-linux-gnu"
    187401                       
    188                         if (config['CROSS_TARGET'] == "mips32"):
    189                                 gnu_target = "mipsel-linux-gnu"
    190                
    191                 if (config['PLATFORM'] == "amd64"):
    192                         target = config['PLATFORM']
    193                         gnu_target = "amd64-linux-gnu"
    194                
    195                 if (config['PLATFORM'] == "arm32"):
    196                         target = config['PLATFORM']
    197                         gnu_target = "arm-linux-gnu"
    198                
    199                 if (config['PLATFORM'] == "ia32"):
    200                         target = config['PLATFORM']
    201                         gnu_target = "i686-pc-linux-gnu"
    202                
    203                 if (config['PLATFORM'] == "ia64"):
    204                         target = config['PLATFORM']
    205                         gnu_target = "ia64-pc-linux-gnu"
    206                
    207                 if (config['PLATFORM'] == "mips32"):
    208                         check_config(config, "MACHINE")
    209                        
    210                         if ((config['MACHINE'] == "lgxemul") or (config['MACHINE'] == "msim")):
    211                                 target = config['PLATFORM']
    212                                 gnu_target = "mipsel-linux-gnu"
    213                        
    214                         if (config['MACHINE'] == "bgxemul"):
    215                                 target = "mips32eb"
    216                                 gnu_target = "mips-linux-gnu"
    217                
    218                 if (config['PLATFORM'] == "ppc32"):
    219                         target = config['PLATFORM']
    220                         gnu_target = "ppc-linux-gnu"
    221                
    222                 if (config['PLATFORM'] == "sparc64"):
    223                         target = config['PLATFORM']
    224                         gnu_target = "sparc64-linux-gnu"
    225                
    226                 path = "%s/%s/bin" % (cross_prefix, target)
    227                 prefix = "%s-" % gnu_target
    228                
    229                 check_gcc(path, prefix, common, PACKAGE_CROSS)
    230                 check_binutils(path, prefix, common, PACKAGE_CROSS)
    231                 common['CC'] = common['GCC']
    232        
    233         if (config['COMPILER'] == "gcc_native"):
    234                 check_gcc(None, "", common, PACKAGE_GCC)
    235                 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
    236                 common['CC'] = common['GCC']
    237        
    238         if (config['COMPILER'] == "icc"):
    239                 common['CC'] = "icc"
    240                 check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
    241                 check_gcc(None, "", common, PACKAGE_GCC)
    242                 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
    243        
    244         if (config['COMPILER'] == "suncc"):
    245                 common['CC'] = "suncc"
    246                 check_app([common['CC'], "-V"], "Sun Studio Compiler", "support is experimental")
    247                 check_gcc(None, "", common, PACKAGE_GCC)
    248                 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
    249        
    250         if (config['COMPILER'] == "clang"):
    251                 common['CC'] = "clang"
    252                 check_app([common['CC'], "--version"], "Clang compiler", "preferably version 1.0 or newer")
    253                 check_gcc(None, "", common, PACKAGE_GCC)
    254                 check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
    255        
    256         # Platform-specific utilities
    257         if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
    258                 check_app(["mkisofs", "--version"], "ISO 9660 creation utility", "usually part of genisoimage")
    259        
    260         create_output(COMMON, common)
     402                        if (config['PLATFORM'] == "ia64"):
     403                                target = config['PLATFORM']
     404                                gnu_target = "ia64-pc-linux-gnu"
     405                       
     406                        if (config['PLATFORM'] == "mips32"):
     407                                check_config(config, "MACHINE")
     408                               
     409                                if ((config['MACHINE'] == "lgxemul") or (config['MACHINE'] == "msim")):
     410                                        target = config['PLATFORM']
     411                                        gnu_target = "mipsel-linux-gnu"
     412                               
     413                                if (config['MACHINE'] == "bgxemul"):
     414                                        target = "mips32eb"
     415                                        gnu_target = "mips-linux-gnu"
     416                       
     417                        if (config['PLATFORM'] == "ppc32"):
     418                                target = config['PLATFORM']
     419                                gnu_target = "ppc-linux-gnu"
     420                       
     421                        if (config['PLATFORM'] == "sparc64"):
     422                                target = config['PLATFORM']
     423                                gnu_target = "sparc64-linux-gnu"
     424                       
     425                        path = "%s/%s/bin" % (cross_prefix, target)
     426                        prefix = "%s-" % gnu_target
     427                       
     428                        check_gcc(path, prefix, common, PACKAGE_CROSS)
     429                        check_binutils(path, prefix, common, PACKAGE_CROSS)
     430                       
     431                        check_common(common, "GCC")
     432                        common['CC'] = common['GCC']
     433               
     434                if (config['COMPILER'] == "gcc_native"):
     435                        check_gcc(None, "", common, PACKAGE_GCC)
     436                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
     437                       
     438                        check_common(common, "GCC")
     439                        common['CC'] = common['GCC']
     440               
     441                if (config['COMPILER'] == "icc"):
     442                        common['CC'] = "icc"
     443                        check_app([common['CC'], "-V"], "Intel C++ Compiler", "support is experimental")
     444                        check_gcc(None, "", common, PACKAGE_GCC)
     445                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
     446               
     447                if (config['COMPILER'] == "suncc"):
     448                        common['CC'] = "suncc"
     449                        check_app([common['CC'], "-V"], "Sun Studio Compiler", "support is experimental")
     450                        check_gcc(None, "", common, PACKAGE_GCC)
     451                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
     452               
     453                if (config['COMPILER'] == "clang"):
     454                        common['CC'] = "clang"
     455                        check_app([common['CC'], "--version"], "Clang compiler", "preferably version 1.0 or newer")
     456                        check_gcc(None, "", common, PACKAGE_GCC)
     457                        check_binutils(None, binutils_prefix, common, PACKAGE_BINUTILS)
     458               
     459                # Platform-specific utilities
     460                if ((config['BARCH'] == "amd64") or (config['BARCH'] == "ia32") or (config['BARCH'] == "ppc32") or (config['BARCH'] == "sparc64")):
     461                        check_app(["mkisofs", "--version"], "ISO 9660 creation utility", "usually part of genisoimage")
     462               
     463                probe = probe_compiler(common,
     464                        [
     465                                "char",
     466                                "short int",
     467                                "int",
     468                                "long int",
     469                                "long long int",
     470                        ]
     471                )
     472               
     473                typedefs = detect_uints(probe['unsigned_sizes'], probe['signed_sizes'], [1, 2, 4, 8])
     474               
     475        finally:
     476                sandbox_leave(owd)
     477       
     478        create_makefile(MAKEFILE, common)
     479        create_header(HEADER, typedefs)
    261480       
    262481        return 0
Note: See TracChangeset for help on using the changeset viewer.