about summary refs log tree commit diff
path: root/pkgs/development/compilers/swift/wrapper
diff options
context:
space:
mode:
authorStéphan Kochen <git@stephank.nl>2022-07-19 15:30:12 +0200
committerStéphan Kochen <git@stephank.nl>2022-10-10 21:26:47 +0200
commit8ed924c07a72849dbca9eb4fb8f13e45dc0e0429 (patch)
tree344a060aaa39b83b049a475064b3c1e37d6775d5 /pkgs/development/compilers/swift/wrapper
parent2c2b799dba29e6fca8fea3c3911a5291fff42b90 (diff)
swift: compiler only build & darwin support
Diffstat (limited to 'pkgs/development/compilers/swift/wrapper')
-rw-r--r--pkgs/development/compilers/swift/wrapper/default.nix50
-rw-r--r--pkgs/development/compilers/swift/wrapper/setup-hook.sh28
-rw-r--r--pkgs/development/compilers/swift/wrapper/wrapper.sh266
3 files changed, 344 insertions, 0 deletions
diff --git a/pkgs/development/compilers/swift/wrapper/default.nix b/pkgs/development/compilers/swift/wrapper/default.nix
new file mode 100644
index 0000000000000..f244af13fcba2
--- /dev/null
+++ b/pkgs/development/compilers/swift/wrapper/default.nix
@@ -0,0 +1,50 @@
+{ stdenv
+, swift
+, wrapperParams ? swift._wrapperParams
+}:
+
+stdenv.mkDerivation (wrapperParams // {
+  pname = "swift-wrapper";
+  inherit (swift) version meta;
+
+  outputs = [ "out" "man" ];
+
+  # Setup hook variables.
+  inherit swift;
+  inherit (swift)
+    swiftOs swiftArch
+    swiftModuleSubdir swiftLibSubdir
+    swiftStaticModuleSubdir swiftStaticLibSubdir;
+
+  passAsFile = [ "buildCommand" ];
+  buildCommand = ''
+    mkdir -p $out/bin $out/nix-support
+
+    # Symlink all Swift binaries first.
+    # NOTE: This specifically omits clang binaries. We want to hide these for
+    # private use by Swift only.
+    ln -s -t $out/bin/ $swift/bin/swift*
+
+    # Replace specific binaries with wrappers.
+    for executable in swift swiftc swift-frontend; do
+      export prog=$swift/bin/$executable
+      rm $out/bin/$executable
+      substituteAll '${./wrapper.sh}' $out/bin/$executable
+      chmod a+x $out/bin/$executable
+    done
+
+    ln -s ${swift.man} $man
+
+    # This link is here because various tools (swiftpm) check for stdlib
+    # relative to the swift compiler. It's fine if this is for build-time
+    # stuff, but we should patch all cases were it would end up in an output.
+    ln -s ${swift.lib}/lib $out/lib
+
+    substituteAll ${./setup-hook.sh} $out/nix-support/setup-hook
+  '';
+
+  passthru = {
+    inherit swift;
+    inherit (swift) swiftOs swiftArch swiftModuleSubdir swiftLibSubdir;
+  };
+})
diff --git a/pkgs/development/compilers/swift/wrapper/setup-hook.sh b/pkgs/development/compilers/swift/wrapper/setup-hook.sh
new file mode 100644
index 0000000000000..398f19977f667
--- /dev/null
+++ b/pkgs/development/compilers/swift/wrapper/setup-hook.sh
@@ -0,0 +1,28 @@
+# Add import paths for build inputs.
+swiftWrapper_addImports () {
+    # Include subdirectories following both the Swift platform convention, and
+    # a simple `lib/swift` for Nix convenience.
+    for subdir in @swiftModuleSubdir@ @swiftStaticModuleSubdir@ lib/swift; do
+        if [[ -d "$1/$subdir" ]]; then
+            export NIX_SWIFTFLAGS_COMPILE+=" -I $1/$subdir"
+        fi
+    done
+    for subdir in @swiftLibSubdir@ @swiftStaticLibSubdir@ lib/swift; do
+        if [[ -d "$1/$subdir" ]]; then
+            export NIX_LDFLAGS+=" -L $1/$subdir"
+        fi
+    done
+}
+
+addEnvHooks "$targetOffset" swiftWrapper_addImports
+
+# Use a postHook here because we rely on NIX_CC, which is set by the cc-wrapper
+# setup hook, so delay until we're sure it was run.
+swiftWrapper_postHook () {
+    # On Darwin, libc also contains Swift modules.
+    if [[ -e "$NIX_CC/nix-support/orig-libc" ]]; then
+        swiftWrapper_addImports "$(<$NIX_CC/nix-support/orig-libc)"
+    fi
+}
+
+postHooks+=(swiftWrapper_postHook)
diff --git a/pkgs/development/compilers/swift/wrapper/wrapper.sh b/pkgs/development/compilers/swift/wrapper/wrapper.sh
new file mode 100644
index 0000000000000..dd08355903963
--- /dev/null
+++ b/pkgs/development/compilers/swift/wrapper/wrapper.sh
@@ -0,0 +1,266 @@
+#! @shell@
+# NOTE: This wrapper is derived from cc-wrapper.sh, and is hopefully somewhat
+# diffable with the original, so changes can be merged if necessary.
+set -eu -o pipefail +o posix
+shopt -s nullglob
+
+if (( "${NIX_DEBUG:-0}" >= 7 )); then
+    set -x
+fi
+
+cc_wrapper="${NIX_CC:-@default_cc_wrapper@}"
+
+source $cc_wrapper/nix-support/utils.bash
+
+expandResponseParams "$@"
+
+# Check if we should wrap this Swift invocation at all, and how. Specifically,
+# there are some internal tools we don't wrap, plus swift-frontend doesn't link
+# and doesn't understand linker flags. This follows logic in
+# `lib/DriverTool/driver.cpp`.
+prog=@prog@
+progName="$(basename "$prog")"
+firstArg="${params[0]:-}"
+isFrontend=0
+isRepl=0
+
+# These checks follow `shouldRunAsSubcommand`.
+if [[ "$progName" == swift ]]; then
+    case "$firstArg" in
+        "" | -* | *.* | */* | repl)
+            ;;
+        *)
+            exec "swift-$firstArg" "${params[@]:1}"
+            ;;
+    esac
+fi
+
+# These checks follow the first part of `run_driver`.
+#
+# NOTE: The original function short-circuits, but we can't here, because both
+# paths must be wrapped. So we use an 'isFrontend' flag instead.
+case "$firstArg" in
+    -frontend)
+        isFrontend=1
+        # Ensure this stays the first argument.
+        params=( "${params[@]:1}" )
+        extraBefore+=( "-frontend" )
+        ;;
+    -modulewrap)
+        # Don't wrap this integrated tool.
+        exec "$prog" "${params[@]}"
+        ;;
+    repl)
+        isRepl=1
+        params=( "${params[@]:1}" )
+        ;;
+    --driver-mode=*)
+        ;;
+    *)
+        if [[ "$progName" == swift-frontend ]]; then
+            isFrontend=1
+        fi
+        ;;
+esac
+
+path_backup="$PATH"
+
+# That @-vars are substituted separately from bash evaluation makes
+# shellcheck think this, and others like it, are useless conditionals.
+# shellcheck disable=SC2157
+if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then
+    PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"
+fi
+
+# Parse command line options and set several variables.
+# For instance, figure out if linker flags should be passed.
+# GCC prints annoying warnings when they are not needed.
+isCxx=0
+dontLink=$isFrontend
+
+for p in "${params[@]}"; do
+    case "$p" in
+        -enable-cxx-interop)
+            isCxx=1 ;;
+    esac
+done
+
+# NOTE: We don't modify these for Swift, but sourced scripts may use them.
+cxxInclude=1
+cxxLibrary=1
+cInclude=1
+
+linkType=$(checkLinkType "${params[@]}")
+
+# Optionally filter out paths not refering to the store.
+if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then
+    kept=()
+    nParams=${#params[@]}
+    declare -i n=0
+    while (( "$n" < "$nParams" )); do
+        p=${params[n]}
+        p2=${params[n+1]:-} # handle `p` being last one
+        n+=1
+
+        skipNext=false
+        path=""
+        case "$p" in
+            -[IL]/*) path=${p:2} ;;
+            -[IL]) path=$p2 skipNext=true ;;
+        esac
+
+        if [[ -n $path ]] && badPath "$path"; then
+            skip "$path"
+            $skipNext && n+=1
+            continue
+        fi
+
+        kept+=("$p")
+    done
+    # Old bash empty array hack
+    params=(${kept+"${kept[@]}"})
+fi
+
+# Flirting with a layer violation here.
+if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
+    source @bintools@/nix-support/add-flags.sh
+fi
+
+# Put this one second so libc ldflags take priority.
+if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
+    source $cc_wrapper/nix-support/add-flags.sh
+fi
+
+if [[ "$isCxx" = 1 ]]; then
+    if [[ "$cxxInclude" = 1 ]]; then
+        NIX_CFLAGS_COMPILE_@suffixSalt@+=" $NIX_CXXSTDLIB_COMPILE_@suffixSalt@"
+    fi
+    if [[ "$cxxLibrary" = 1 ]]; then
+        NIX_CFLAGS_LINK_@suffixSalt@+=" $NIX_CXXSTDLIB_LINK_@suffixSalt@"
+    fi
+fi
+
+source $cc_wrapper/nix-support/add-hardening.sh
+
+# Add the flags for the C compiler proper.
+addCFlagsToList() {
+    declare -n list="$1"
+    shift
+
+    for ((i = 1; i <= $#; i++)); do
+        local val="${!i}"
+        case "$val" in
+            # Pass through using -Xcc, but also convert to Swift -I.
+            # These have slightly different meaning for Clang, but Swift
+            # doesn't have exact equivalents.
+            -isystem | -idirafter)
+                i=$((i + 1))
+                list+=("-Xcc" "$val" "-Xcc" "${!i}" "-I" "${!i}")
+                ;;
+            # Simple rename.
+            -iframework)
+                i=$((i + 1))
+                list+=("-Fsystem" "${!i}")
+                ;;
+            # Pass through verbatim.
+            -I | -Fsystem)
+                i=$((i + 1))
+                list+=("${val}" "${!i}")
+                ;;
+            -I* | -L* | -F*)
+                list+=("${val}")
+                ;;
+            # Pass through using -Xcc.
+            *)
+                list+=("-Xcc" "$val")
+                ;;
+        esac
+    done
+}
+for i in ${NIX_SWIFTFLAGS_COMPILE:-}; do
+    extraAfter+=("$i")
+done
+for i in ${NIX_SWIFTFLAGS_COMPILE_BEFORE:-}; do
+    extraBefore+=("$i")
+done
+addCFlagsToList extraAfter $NIX_CFLAGS_COMPILE_@suffixSalt@
+addCFlagsToList extraBefore ${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@
+
+if [ "$dontLink" != 1 ]; then
+
+    # Add the flags that should only be passed to the compiler when
+    # linking.
+    addCFlagsToList extraAfter $(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@)
+
+    # Add the flags that should be passed to the linker (and prevent
+    # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
+    for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do
+        extraBefore+=("-Xlinker" "$i")
+    done
+    if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
+        extraBefore+=("-Xlinker" "-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
+    fi
+    for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do
+        if [ "${i:0:3}" = -L/ ]; then
+            extraAfter+=("$i")
+        else
+            extraAfter+=("-Xlinker" "$i")
+        fi
+    done
+    export NIX_LINK_TYPE_@suffixSalt@=$linkType
+fi
+
+# TODO: If we ever need to expand functionality of this hook, it may no longer
+# be compatible with Swift. Right now, it is only used on Darwin to force
+# -target, which also happens to work with Swift.
+if [[ -e $cc_wrapper/nix-support/add-local-cc-cflags-before.sh ]]; then
+    source $cc_wrapper/nix-support/add-local-cc-cflags-before.sh
+fi
+
+# May need to transform the triple injected by the above.
+for ((i = 1; i < ${#extraBefore[@]}; i++)); do
+    if [[ "${extraBefore[i]}" = -target ]]; then
+        i=$((i + 1))
+        # On Darwin only, need to change 'aarch64' to 'arm64'.
+        extraBefore[i]="${extraBefore[i]/aarch64-apple-/arm64-apple-}"
+        # On Darwin, Swift requires the triple to be annotated with a version.
+        # TODO: Assumes macOS.
+        extraBefore[i]="${extraBefore[i]/-apple-darwin/-apple-macosx${MACOSX_DEPLOYMENT_TARGET:-11.0}}"
+        break
+    fi
+done
+
+# As a very special hack, if the arguments are just `-v', then don't
+# add anything.  This is to prevent `gcc -v' (which normally prints
+# out the version number and returns exit code 0) from printing out
+# `No input files specified' and returning exit code 1.
+if [ "$*" = -v ]; then
+    extraAfter=()
+    extraBefore=()
+fi
+
+# Optionally print debug info.
+if (( "${NIX_DEBUG:-0}" >= 1 )); then
+    # Old bash workaround, see ld-wrapper for explanation.
+    echo "extra flags before to $prog:" >&2
+    printf "  %q\n" ${extraBefore+"${extraBefore[@]}"}  >&2
+    echo "original flags to $prog:" >&2
+    printf "  %q\n" ${params+"${params[@]}"} >&2
+    echo "extra flags after to $prog:" >&2
+    printf "  %q\n" ${extraAfter+"${extraAfter[@]}"} >&2
+fi
+
+PATH="$path_backup"
+# Old bash workaround, see above.
+
+if (( "${NIX_CC_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then
+    exec "$prog" @<(printf "%q\n" \
+       ${extraBefore+"${extraBefore[@]}"} \
+       ${params+"${params[@]}"} \
+       ${extraAfter+"${extraAfter[@]}"})
+else
+    exec "$prog" \
+       ${extraBefore+"${extraBefore[@]}"} \
+       ${params+"${params[@]}"} \
+       ${extraAfter+"${extraAfter[@]}"}
+fi