haiku/3rdparty/kallisti5/configure.py

251 lines
8.5 KiB
Python
Executable File

#!/bin/env python3
#
# Haiku build configuration tool
# Copyright 2002-2018, Haiku, Inc. All rights reserved.
#
import argparse
import os
import subprocess
import sys
import errno
from pprint import pprint
parser = argparse.ArgumentParser(description='Configure a build of Haiku')
parser.add_argument('--target-arch', nargs=1,
help='Target architectures. First provided is primary.', type=str, action='append',
choices=('x86_gcc2', 'x86', 'x86_64', 'ppc', 'm68k', 'arm', 'arm64', 'riscv64'))
parser.add_argument('--bootstrap', nargs=3,
help='Prepare for a bootstrap build. No pre-built packages will be used, instead they will be built from the sources (in several phases).',
metavar=('<haikuporter>','<haikuports.cross>', '<haikuports>'))
parser.add_argument('--build-gcc-toolchain', nargs=1,
help='Assume cross compilation. Build a gcc-based toolchain.',
metavar=('<buildtools dir>'))
parser.add_argument('--use-gcc-toolchain', nargs=1,
help='Assume cross compilation. Build using an existing gcc-based toolchain.',
metavar=('<prefix>'))
parser.add_argument('--use-clang', default=False, action='store_true', help='Assume native clang build')
parser.add_argument('--distro-compatibility', nargs=1,
help='The distribution\'s level of compatibility with the official Haiku distribution. The generated files will contain the respective trademarks accordingly.',
choices=('official', 'compatible', 'default'), default='default')
args = vars(parser.parse_args())
### Global functions
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise
def bok(message):
start_color = ""
end_color = ""
if sys.stdout.isatty():
start_color = "\033[92m"
end_color = "\033[0m"
print(start_color + message + end_color)
def berror(message):
start_color = ""
end_color = ""
if sys.stdout.isatty():
start_color = "\033[91m"
end_color = "\033[0m"
print(start_color + message + end_color)
def binfo(message):
start_color = ""
end_color = ""
if sys.stdout.isatty():
start_color = "\033[94m"
end_color = "\033[0m"
print(start_color + message + end_color)
### Global Varables
(host_sysname, host_nodename, host_release, host_version, host_machine) = os.uname()
buildConfig = []
# TODO: Remove "../.." if this ever moves to the source root
sourceDir = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + "/../..")
outputDir = os.getcwd()
# If run in our source dir, assume generated
if outputDir == sourceDir:
outputDir = sourceDir + "/generated"
mkdir_p(outputDir)
### Helper Functions
# Run a command, collect stdout into a string
def cmdrun(cmd):
return subprocess.check_output(cmd).decode(sys.stdout.encoding)
# Get a config key
def get_build_config(key):
global buildConfig
for i in buildConfig:
if i["key"] == key:
return i["value"]
return None
# Delete a config key
def drop_build_config(key):
global buildConfig
value = get_build_config(key)
if value != None:
buildConfig.remove({"key": key, "value": value})
# Set a config key
def set_build_config(key, value):
global buildConfig
if get_build_config(key) != None:
drop_build_config(key)
buildConfig.append({"key": key, "value": value})
def write_build_config(filename):
global buildConfig
with open(filename, "w") as fh:
fh.write("# -- WARNING --\n")
fh.write("# This file was AUTOMATICALLY GENERATED by configure, and will be completely\n")
fh.write("# overwritten the next time configure is run.\n\n")
for i in buildConfig:
fh.write(i["key"] + " ?= " + str(i["value"]) + " ;\n")
def triplet_lookup(arch):
if arch == "x86_gcc2":
return "i586-pc-haiku"
elif arch == "x86":
return "i586-pc-haiku"
elif arch == "x86_64":
return "x86_64-unknown-haiku"
elif arch == "ppc":
return "powerpc-apple-haiku"
elif arch == "m68k":
return "m68k-unknown-haiku"
elif arch == "arm":
return "arm-unknown-haiku"
elif arch == "riscv64":
return "riscv64-unknown-haiku"
else:
berror("Unsupported target architecture: " + arch)
exit(1)
def platform_lookup(sysname):
if sysname == "Darwin":
return "darwin"
elif sysname == "FreeBSD":
return "freebsd"
elif sysname == "Haiku":
return "haiku_host"
elif sysname == "Linux":
return "linux"
elif sysname == "OpenBSD":
return "openbsd"
elif sysname == "SunOS":
return "sunos"
else:
berror("Unknown platform: " + sysname)
exit(1)
def setup_bootstrap():
if args["bootstrap"] == None:
return
set_build_config("HOST_HAIKU_PORTER", os.path.abspath(args["bootstrap"][0]))
set_build_config("HAIKU_PORTS", os.path.abspath(args["bootstrap"][1]))
set_build_config("HAIKU_PORTS_CROSS", os.path.abspath(args["bootstrap"][2]))
def setup_host_tools():
set_build_config("HOST_SHA256", "sha256sum")
set_build_config("HOST_EXTENDED_REGEX_SED", "sed -r")
def setup_host_compiler():
cc = os.environ.get("CC")
if cc == None:
# We might want to step through each potential compiler here
cc = "gcc"
set_build_config("HOST_PLATFORM", platform_lookup(host_sysname))
set_build_config("HOST_CC", cc)
set_build_config("HOST_CC_LD", cmdrun([cc, "-print-prog-name=ld"]).strip())
set_build_config("HOST_CC_OBJCOPY", cmdrun([cc, "-print-prog-name=objcopy"]).strip())
set_build_config("HOST_GCC_MACHINE", cmdrun([cc, "-dumpmachine"]).strip())
set_build_config("HOST_GCC_RAW_VERSION", cmdrun([cc, "-dumpversion"]).strip())
def setup_target_compiler(arch):
cc = get_build_config("HOST_CC")
triplet = triplet_lookup(arch)
set_build_config("HAIKU_GCC_RAW_VERSION_" + arch, cmdrun([cc, "-dumpversion"]).strip())
set_build_config("HAIKU_GCC_MACHINE_" + arch, triplet)
set_build_config("HAIKU_CPU_" + arch, arch)
if args["use_clang"]:
set_build_config("HAIKU_CC_" + arch, "clang -target " + triplet + " -B llvm-")
def build_gcc_toolchain(buildtools_dir, arch):
bok(arch + " toolchain build complete!")
### Workflow
umask = os.umask(0)
os.umask(umask)
if umask > 22:
berror("Your umask is too restrictive (should be <= 0022; is actually " + str(umask) + ")")
print()
berror("Additionally, if the source tree was cloned with a too-restrictive umask,")
berror("you will need to run \"git checkout\" again to fix this.")
exit(1)
if args["target_arch"] == None:
berror("You need to specify at least one target architecture via --target-arch")
exit(1)
if args["use_clang"] == False and args["build_gcc_toolchain"] == None and args["use_gcc_toolchain"] == None:
berror("You need to pick a toolchain via --build-gcc-toolchain, --use-gcc-toolchain, or --use-clang")
exit(1)
elif args["use_clang"] == True:
bok("Using the host's clang toolchain with a haiku target.")
elif args["build_gcc_toolchain"] != None:
bok("Building a gcc cross-compiler.")
elif args["use_gcc_toolchain"] != None:
bok("Using the existing gcc toolchain at " + args["use_gcc_toolchain"][0])
mkdir_p(outputDir + "/build")
# Some Defaults
set_build_config("TARGET_PLATFORM", "haiku")
set_build_config("HAIKU_INCLUDE_SOURCES", 0)
set_build_config("HAIKU_USE_GCC_PIPE", 0)
set_build_config("HAIKU_HOST_USE_32BIT", 0)
set_build_config("HAIKU_HOST_USE_XATTR", "")
set_build_config("HAIKU_HOST_USE_XATTR_REF", "")
set_build_config("HAIKU_DISTRO_COMPATIBILITY", args["distro_compatibility"])
setup_bootstrap()
setup_host_tools()
setup_host_compiler()
binfo("Configuring a Haiku build at " + outputDir)
for arch in args["target_arch"]:
binfo("Configuring " + arch[0] + " architecture...")
setup_target_compiler(arch[0])
if args["build_gcc_toolchain"] != None:
build_gcc_toolchain(args["build_gcc_toolchain"][0], arch[0])
write_build_config(outputDir + "/build/BuildConfig")
# Write out an entry Jamfile in our build directory
with open(outputDir + "/Jamfile", "w") as fh:
fh.write("# -- WARNING --\n")
fh.write("# This file was AUTOMATICALLY GENERATED by configure, and will be completely\n")
fh.write("# overwritten the next time configure is run.\n\n")
fh.write("HAIKU_TOP = " + os.path.relpath(sourceDir, outputDir) + " ;\n")
fh.write("HAIKU_OUTPUT_DIR = " + os.path.relpath(outputDir, os.getcwd()) + " ;\n\n")
fh.write("include [ FDirName $(HAIKU_TOP) Jamfile ] ;\n")
bok("Configuration complete!")