From ee7612bdf84e7f9dd3d300f1922d3a717841fc24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yves=20Desgagn=C3=A9?= Date: Sun, 4 Feb 2024 12:24:51 -0500 Subject: [PATCH] Added flang part --- Dockerfile | 12 ++++ bin/flang.sh | 6 ++ bin/gfortran | 152 +++++++++++++++++++++++++++++++++++++++++++++++++ setup-iOS.sh | 16 ++++++ share/proxy.sh | 5 ++ 5 files changed, 191 insertions(+) create mode 100644 Dockerfile create mode 100755 bin/flang.sh create mode 100755 bin/gfortran create mode 100755 share/proxy.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6d409b1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:jammy + +# persistent dependencies +RUN set -eux ; \ + apt-get -y update ; \ + apt-get -y --no-install-recommends install ca-certificates build-essential wget libncurses5 ; + +# flang +RUN wget https://github.com/flang-compiler/flang/releases/download/flang_20190329/flang-20190329-x86-70.tgz ; \ + tar -xvzf *.tgz ; \ + rm -f *.tgz ; \ + ldconfig ; diff --git a/bin/flang.sh b/bin/flang.sh new file mode 100755 index 0000000..bf3b365 --- /dev/null +++ b/bin/flang.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2068 +docker exec -it flang /root/host/proxy.sh "${PWD}" ${@} +cp -rf inbox/* "${PWD}" &> /dev/null +rm -rf inbox/* &> /dev/null diff --git a/bin/gfortran b/bin/gfortran new file mode 100755 index 0000000..ec2092a --- /dev/null +++ b/bin/gfortran @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 + +import sys +import os +import shlex +import subprocess +import string +import random +import shutil + +def join_args(args): + return ' '.join(shlex.quote(x) for x in args) + +if "-dumpversion" in sys.argv: + print("10.2.0") + sys.exit(0) + +arguments = [] +sys_args = sys.argv +del sys_args[0] + +try: + for arg in os.environ["ARCHFLAGS"].split(" "): + sys_args.append(arg) +except KeyError: + pass + +if "-h" in sys_args or "--help" in sys_args: + print("The running executable emulates a Fortran compiler. If '-arch arm64' is passed, the compiler will produce an arm64 object file for iOS from the passed source. If not, gfortran located in '/opt/homebrew/bin/' will be executed.") + print("Because flang runs in a Docker container, only files under '/Users/', '/var/folders' or '/Library' can be compiled.") + sys.exit(0) + +all_args_are_object_files = True + +for arg in sys_args: + + if os.path.isfile(arg) and not arg.endswith(".o"): + all_args_are_object_files = False + +if (not "-c" and not all_args_are_object_files) in sys_args or not "-arch arm64" in " ".join(sys_args): + print("The executed Fortran compiler only supports producing object files for iOS arm64, falling back to gfortran.", file=sys.stderr) + print("To compile sources for iOS arm64, make sure to add -arch arm64 and -c.", file=sys.stderr) + sys.exit(os.system(shlex.join(["/opt/homebrew/bin/gfortran"]+sys_args))) + +if "-bundle" in sys_args or all_args_are_object_files: + args = ["clang", "-undefined", "dynamic_lookup", "-shared"] + try: + for arg in os.environ["LDFLAGS"].split(" "): + args.append(arg) + except KeyError: + pass + for arg in sys_args: + if arg != "-bundle": + args.append(arg) + + command = shlex.join(args) + sys.exit(os.system(command)) + +def convert_to_docker_path(arg): + if arg.startswith("/"): + arg = "/¡"+arg + else: + arg = os.path.join(os.getcwd(), arg) + + return arg + +the_previous_parameter_was_dash_o = False +the_previous_parameter_was_dash_c = False +the_previous_parameter_was_dash_arch = False +output_path = None +source = None + +for arg in sys_args: + + if arg == "-c": + the_previous_parameter_was_dash_c = True + elif the_previous_parameter_was_dash_c: + the_previous_parameter_was_dash_c = False + source = arg + + if arg == "-o": + the_previous_parameter_was_dash_o = True + continue + elif the_previous_parameter_was_dash_o: + the_previous_parameter_was_dash_o = False + output_path = arg + continue + + if arg == "-arch": + the_previous_parameter_was_dash_arch = True + continue + elif the_previous_parameter_was_dash_arch: + the_previous_parameter_was_dash_arch = False + continue + + if arg == "-fallow-argument-mismatch": + continue + + if os.path.exists(arg): + arg = convert_to_docker_path(arg) + if arg.startswith("-I"): + path = arg.split("-I")[-1] + arg = "-I"+convert_to_docker_path(path) + + if arg.startswith("/¡"): + arg = arg[2:] + + arguments.append(arg) + +if output_path is None and source is not None: + parts = source.split(".") + del parts[-1] + output_path = os.getcwd()+"/"+".".join(parts)+".o" + +if os.path.isfile(output_path): + sys.exit(0) + +print(output_path) + +dir = os.path.dirname(os.path.abspath(__file__)) +cwd = os.getcwd() + +arguments.insert(0, os.path.abspath(os.path.join(dir, "flang.sh"))) +arguments.insert(1, "--save-temps") +flang_command = join_args(arguments) + +inbox = os.path.join(cwd, ".inbox"+''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(5))) + +try: + os.mkdir(inbox) +except FileExistsError: + pass + +os.chdir(inbox) + +os.system(flang_command) +file_path = None + +for file in os.listdir("."): + if not file.endswith(".ll"): + try: + os.remove(file) + except FileNotFoundError: + pass + else: + file_path = os.path.join(os.getcwd(), file) + +os.chdir(cwd) +llc = [os.path.join(dir, "llc"), "-mtriple=arm64-apple-ios", "-filetype=obj", file_path, "-o", output_path] +subprocess.run(llc, stdout=None, stderr=None) + +shutil.rmtree(inbox) diff --git a/setup-iOS.sh b/setup-iOS.sh index dc96acd..ebae9b1 100755 --- a/setup-iOS.sh +++ b/setup-iOS.sh @@ -99,6 +99,22 @@ export MOBILE_FORGE_IPHONEOS_ARM64=$PYTHON_APPLE_SUPPORT/install/iOS/iphoneos.ar export MOBILE_FORGE_IPHONESIMULATOR_ARM64=$PYTHON_APPLE_SUPPORT/install/iOS/iphonesimulator.arm64/python-$PYTHON_VERSION/bin/python$PYTHON_VER export MOBILE_FORGE_IPHONESIMULATOR_X86_64=$PYTHON_APPLE_SUPPORT/install/iOS/iphonesimulator.x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER +# Setup docker for fortran/flang + +if ! docker info &>/dev/null; then + echo "Docker daemon not running!" + exit 1 +fi + +export DOCKER_DEFAULT_PLATFORM=linux/amd64 +# shellcheck disable=SC2048,SC2086 +DOCKER_BUILDKIT=1 docker build -t flang --compress . $* +docker stop flang &>/dev/null || true +docker rm flang &>/dev/null || true +docker run -d --name flang -v "$(pwd)/share:/root/host" -v /Users:/Users -v /var/folders:/var/folders -it flang + +# Print help + echo echo "You can now build packages with forge; e.g.:" echo diff --git a/share/proxy.sh b/share/proxy.sh new file mode 100755 index 0000000..34a57da --- /dev/null +++ b/share/proxy.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +cd /root/host || exit +cd "${1}" || exit +flang "${@:2}"