diff options
author | Stéphan Kochen <git@stephank.nl> | 2022-07-19 15:30:12 +0200 |
---|---|---|
committer | Stéphan Kochen <git@stephank.nl> | 2022-10-10 21:26:47 +0200 |
commit | 8ed924c07a72849dbca9eb4fb8f13e45dc0e0429 (patch) | |
tree | 344a060aaa39b83b049a475064b3c1e37d6775d5 /pkgs/development/compilers/swift/wrapper | |
parent | 2c2b799dba29e6fca8fea3c3911a5291fff42b90 (diff) |
swift: compiler only build & darwin support
Diffstat (limited to 'pkgs/development/compilers/swift/wrapper')
-rw-r--r-- | pkgs/development/compilers/swift/wrapper/default.nix | 50 | ||||
-rw-r--r-- | pkgs/development/compilers/swift/wrapper/setup-hook.sh | 28 | ||||
-rw-r--r-- | pkgs/development/compilers/swift/wrapper/wrapper.sh | 266 |
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 |