#!/usr/bin/env python3 import os import shutil import sys import platform import subprocess import tempfile prefix = '/usr/local' clean = True defaultimpl = 'kernel' host = platform.machine() host = ''.join(c for c in host if c in '_0123456789abcdefghijklmnopqrstuvwxyz') if host == 'x86_64': host = 'amd64' if host == 'i386': host = 'x86' if host == 'i686': host = 'x86' if host.startswith('armv8') or host.startswith('aarch64'): host = 'arm64' if host.startswith('arm'): host = 'arm32' if host.startswith('riscv64'): host = 'riscv64' if host.startswith('riscv'): host = 'riscv32' if host.startswith('mips64'): host = 'mips64' if host.startswith('mips'): host = 'mips32' if host.startswith('powerpc64') or host.startswith('ppc64'): host = 'ppc64' if host.startswith('powerpc') or host.startswith('ppc'): host = 'ppc32' if host.startswith('sparcv9') or host.startswith('sun4u'): host = 'sparc64' if host.startswith('sparc') or host.startswith('sun'): host = 'sparc32' makefile = '' for arg in sys.argv[1:]: if arg.startswith('--prefix='): prefix = arg[9:] continue if arg.startswith('--host='): host = arg[7:] host = host.split('-')[0] continue if arg == '--clean': clean = True continue if arg == '--noclean': clean = False continue raise ValueError('unrecognized argument %s' % arg) echoargs = './configure' echoargs += ' --prefix=%s' % prefix echoargs += ' --host=%s' % host if clean: echoargs += ' --clean' if not clean: echoargs += ' --noclean' print(echoargs) if prefix[0] != '/': raise ValueError('prefix %s is not an absolute path' % prefix) rpath = None # XXX: rpath = '%s/lib' % prefix if clean: shutil.rmtree('build/%s' % host,ignore_errors=True) def dirlinksym(dir,source,target): with tempfile.TemporaryDirectory(dir=dir) as t: os.symlink(target,'%s/symlink' % t) os.rename('%s/symlink' % t,'%s/%s' % (dir,source)) os.makedirs('build/%s' % host,exist_ok=True) os.makedirs('build/%s/package/bin' % host,exist_ok=True) os.makedirs('build/%s/package/lib' % host,exist_ok=True) os.makedirs('build/%s/package/include' % host,exist_ok=True) if clean: os.symlink('../..','build/%s/src' % host) # ----- build scripts os.makedirs('build/%s/scripts'%host,exist_ok=True) for fn in sorted(os.listdir('scripts-build')): dirlinksym('build/%s/scripts'%host,fn,'../src/scripts-build/%s'%fn) # ----- compilers def compilerversion(c): try: p = subprocess.Popen(c.split()+['--version'],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,universal_newlines=True) out,err = p.communicate() assert not err assert not p.returncode return out except: pass firstcompiler = None with open('compilers/default') as f: for c in f.readlines(): c = c.strip() cv = compilerversion(c) if cv == None: print('skipping default compiler %s' % c) continue print('using default compiler %s' % c) firstcompiler = c break if firstcompiler is None: raise ValueError('did not find a working compiler') with open('build/%s/scripts/cdcompile' % host,'w') as f: f.write('#!/bin/sh\n') f.write('\n') f.write('cd "$1"; shift\n') f.write('exec %s "$@"\n' % firstcompiler) os.chmod('build/%s/scripts/cdcompile' % host,0o755) # ----- librandombytes def alternatives(dir,fn): with open('%s/%s' % (dir,fn)) as f: for line in f: line = line.split() if len(line) >= 3 and line[:2] == ['//','automatic-alternatives']: return ' '.join(line[2:]) return '1' for manpage in sorted(os.listdir('doc/man')): section = 'man%s' % manpage[-1] targetdir = 'build/%s/package/man/%s' % (host,section) os.makedirs(targetdir,exist_ok=True) shutil.copy2('doc/man/%s'%manpage,'%s/%s'%(targetdir,manpage)) objects = {} for dir in 'kernel','openssl','include': builddir = 'build/%s/%s' % (host,dir) os.makedirs(builddir,exist_ok=True) for fn in sorted(os.listdir(dir)): dirlinksym(builddir,fn,'../src/%s/%s' % (dir,fn)) if dir == 'include': shutil.copy2('include/%s'%fn,'build/%s/package/include/%s'%(host,fn)) if fn.endswith('.c'): alt = alternatives(dir,fn) base = fn[:-2] M = '%s/%s.o: %s/%s.c' % (dir,base,dir,base) for obj in alt.split()[1:]: if obj.endswith('.o') and not obj.startswith('-l'): M += ' %s/%s' % (dir,obj) M += '\n' M += '\tscripts/compilealternatives %s %s %s\n' % (dir,base,alternatives(dir,fn)) M += '\n' makefile = M + makefile if dir not in objects: objects[dir] = [] objects[dir] += ['%s/%s.o'%(dir,base)] for lib in sorted(objects): M = 'package/lib/librandombytes-%s.a: scripts/staticlib %s\n' % (lib,' '.join(objects[lib])) M += '\tscripts/staticlib librandombytes-%s %s\n' % (lib,' '.join(objects[lib])) M += '\n' makefile = M + makefile M = 'package/lib/librandombytes-%s.so.1: scripts/sharedlib %s\n' % (lib,' '.join(objects[lib])) if lib == 'openssl': M += '\tscripts/sharedlib librandombytes-%s %s -lcrypto\n' % (lib,' '.join(objects[lib])) else: M += '\tscripts/sharedlib librandombytes-%s %s\n' % (lib,' '.join(objects[lib])) M += '\n' makefile = M + makefile M = 'package/lib/librandombytes-%s.so: package/lib/librandombytes-%s.so.1\n' % (lib,lib) M += '\trm -f package/lib/librandombytes-%s.so\n' % lib M += '\tln -s librandombytes-%s.so.1 package/lib/librandombytes-%s.so\n' % (lib,lib) M += '\n' makefile = M + makefile for link in 'a','so.1','so': M = 'package/lib/librandombytes.%s: package/lib/librandombytes-%s.%s\n' % (link,defaultimpl,link) M += '\trm -f package/lib/librandombytes.%s\n' % link M += '\tln -s librandombytes-%s.%s package/lib/librandombytes.%s\n' % (defaultimpl,link,link) M += '\n' makefile = M + makefile # ----- command os.makedirs('build/%s/command'%host) for c in sorted(os.listdir('command')): dirlinksym('build/%s/command'%host,c,'../src/command/%s'%c) dirlinksym('build/%s/command'%host,'bin','../package/bin') dirlinksym('build/%s/command'%host,'lib','../package/lib') dirlinksym('build/%s/command'%host,'include','../package/include') commands = [] for fn in sorted(os.listdir('command')): if not fn.endswith('.c'): continue base = fn[:-2] M = 'command/%s.o: command/%s.c\n' % (base,base) M += '\tscripts/cdcompile command -I include -c %s.c\n' % base M += '\n' makefile = M + makefile M = 'package/bin/%s: command/%s.o package/lib/librandombytes.so\n' % (base,base) link = ['%s.o'%base,'-L','lib','-lrandombytes','-lm'] M += '\tscripts/cdcompile command -o bin/%s %s\n' % (base,' '.join(link)) M += '\n' makefile = M + makefile commands += ['package/bin/%s' % base] M = 'commands: %s\n' % ' '.join(commands) M += '\n' makefile = M + makefile # ----- make install M = 'install: scripts/install default\n' M += '\tscripts/install %s\n' % prefix M += '\n' makefile = M + makefile # ----- make default M = 'default: \\\n' for lib in sorted(objects): M += 'package/lib/librandombytes-%s.a \\\n' % lib M += 'package/lib/librandombytes-%s.so \\\n' % lib M += 'package/lib/librandombytes-%s.so.1 \\\n' % lib M += 'package/lib/librandombytes.a \\\n' M += 'package/lib/librandombytes.so \\\n' M += 'package/lib/librandombytes.so.1 \\\n' M += 'commands\n' M += '\n' makefile = M + makefile with open('build/%s/Makefile' % host,'w') as f: f.write(makefile) # ----- build/0, build/Makefile dirlinksym('build','0',host) with open('build/Makefile','w') as f: f.write('default:\n') f.write('\tcd %s && $(MAKE)\n' % host) f.write('\n') f.write('install:\n') f.write('\tcd %s && $(MAKE) install\n' % host) f.write('\n') f.write('clean:\n') f.write('\trm -r %s\n' % host)