SConstruct 3.77 KB
import os

build_path = 'build'

supported_architectures = ['x64', 'x86', 'arm', 'mips', 'ppc']

c_compilers = {'x64': ['gcc', 'clang'],
               'x86': ['./dockcross-linux-x86 gcc'],
               'arm': ['arm-linux-gnueabi-gcc'],
               'mips': ['mips-linux-gnu-gcc'],
               'ppc': ['powerpc-linux-gnu-gcc']}

c_linkers =   {'x86': './dockcross-linux-x86 gcc -m32'}

cpp_compilers = {'x64': ['g++', 'clang'],
                 'x86': ['./dockcross-linux-x86 g++'],
                 'arm': ['arm-linux-gnueabi-g++'],
                 'mips': ['mips-linux-gnu-g++'],
                 'ppc': ['powerpc-linux-gnu-g++']}

c_flags = {'x64': '-g -fno-stack-protector -std=c11',
           'x86': '-g -m32 -fno-stack-protector -std=c11',
           'arm': '-g -fno-stack-protector -std=c11',
           'mips': '-g -fno-stack-protector -std=c11',
           'ppc': '-g -fno-stack-protector -std=c11'}

cpp_flags = {'x64': '-g -fno-stack-protector',
             'x86': '-g -m32 -fno-stack-protector',
             'arm': '-g -fno-stack-protector',
             'mips': '-g -fno-stack-protector',
             'ppc': '-g -fno-stack-protector'}

cpp_linkers =   {'x86': './dockcross-linux-x86 g++ -m32'}

def which(pgm):
    # TODO: check if dockcross containers are installed
    if pgm.startswith('.'):
        return pgm
    path = os.getenv('PATH')
    for p in path.split(os.path.pathsep):
        p = os.path.join(p,pgm)
        if os.path.exists(p) and os.access(p,os.X_OK):
            return p

def optimize(filename):
    optimize_me = ['cwe_476.c']
    if filename in optimize_me:
        return ' -O3'
    else:
        return ' -O0'

def get_compiler_abrev(compiler_name):
    if 'clang' in compiler_name:
        return 'clang'
    else:
        return 'gcc'

def compile_only_on_x64(filename, arch):
    only_x64 = ['cwe_782.c']
    return filename in only_x64 and arch != 'x64'

def build_c(arch, compiler):
    if which(compiler) is not None:
        c_programs = Glob('*.c')
        for p in c_programs:
            if compile_only_on_x64(str(p), arch):
                print('Skipping architecture %s for %s' % (arch, str(p)))
                continue
            
            env = Environment()
            env['CC'] = compiler
            env['CCFLAGS'] = c_flags[arch] + optimize(str(p))
            if arch in c_linkers:
                env['LINK'] = c_linkers[arch]

            compiler_abrev = get_compiler_abrev(compiler)
            env.Program('%s/%s_%s_%s.out' % (build_path, str(p).split('.')[0], arch, compiler_abrev),
                        env.Object(target='%s/%s_%s_%s.o' % (build_path, str(p), arch, compiler_abrev),
                                   source='%s/%s' % (build_path, str(p))))
    else:
        print('Compiler %s for architecture %s is not installed!' % (compiler, arch))


def build_cpp(arch, compiler):
    if which(compiler) is not None:
        cpp_programs = Glob('*.cpp')
        for p in cpp_programs:
            env = Environment()
            env['CCP'] = compiler
            env['CCPFLAGS'] = cpp_flags[arch] + optimize(str(p))
            if arch in c_linkers:
                env['CPPLINK'] = cpp_linkers[arch]

            compiler_abrev = get_compiler_abrev(compiler)
            env.Program('%s/%s_%s_%s.out' % (build_path, str(p).split('.')[0], arch, compiler_abrev),
                        env.Object(target='%s/%s_%s_%s.o' % (build_path, str(p), arch, compiler_abrev),
                                   source='%s/%s' % (build_path, str(p))))
    else:
        print('Compiler %s for architecture %s is not installed!' % (compiler, arch))


VariantDir(build_path, '.', duplicate=0)
for arch in supported_architectures:
    print('Building for architecture %s' % arch)
    for compiler in c_compilers[arch]:
        build_c(arch, compiler)
        build_cpp(arch, compiler)