-
-
Notifications
You must be signed in to change notification settings - Fork 19.7k
Linking hack for macOS Sierra #27536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
0c37778
9242c8b
1cd74ac
f671b85
539dcb8
a9dd855
eeed181
14e05c3
2e61d8b
cd6c452
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| #! @shell@ | ||
|
|
||
| set -eu -o pipefail | ||
|
|
||
| path_backup="$PATH" | ||
| if [ -n "@coreutils_bin@" ]; then | ||
| PATH="@coreutils_bin@/bin" | ||
| fi | ||
|
|
||
| declare -r recurThreshold=300 | ||
|
|
||
| declare overflowCount=0 | ||
| for ((n=0; n < $#; ++n)); do | ||
| case "${!n}" in | ||
| -l*) let overflowCount+=1 ;; | ||
| -reexport-l*) let overflowCount+=1 ;; | ||
| *) ;; | ||
| esac | ||
| done | ||
|
|
||
| declare -a allArgs=() | ||
|
|
||
| if (( "$overflowCount" <= "$recurThreshold" )); then | ||
| allArgs=("$@") | ||
| else | ||
| declare -a childrenLookup=() childrenLink=() | ||
|
|
||
| while (( $# )); do | ||
| case "$1" in | ||
| -L/*) | ||
| childrenLookup+=("$1") | ||
| allArgs+=("$1") | ||
| ;; | ||
| -L) | ||
| echo "cctools LD does not support '-L foo' or '-l foo'" >&2 | ||
| exit 1 | ||
| ;; | ||
| -l) | ||
| echo "cctools LD does not support '-L foo' or '-l foo'" >&2 | ||
| exit 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How can a general purpose linker just fail to process these args? This is bound to break linking something.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I suppose the man page could be wrong. I thought i tested too but let me double check.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this isn't a failure to parse
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't know that macOS
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @orivej Yes I should special case the rest of those--I only did |
||
| ;; | ||
| -lto_library) allArgs+=("$1") ;; | ||
| # We aren't linking any "to_library" | ||
| -lSystem) allArgs+=("$1") ;; | ||
| # Special case as indirection seems like a bad idea for something | ||
| # so fundamental. Can be removed for simplicity. | ||
| -l?*) childrenLink+=("$1") ;; | ||
| -reexport-l?*) childrenLink+=("$1") ;; | ||
| *) allArgs+=("$1") ;; | ||
| esac | ||
|
|
||
| shift | ||
| done | ||
|
|
||
| declare n=0 | ||
| while (( $n < "${#childrenLink[@]}" )); do | ||
| if [[ "${childrenLink[n]}" = -l* ]]; then | ||
| childrenLink[n]="-reexport${childrenLink[n]}" | ||
| fi | ||
| let ++n | ||
| done | ||
| unset n | ||
|
|
||
| declare -r outputNameLibless=$(basename $( \ | ||
| if [[ -z "${outputName:+isUndefined}" ]]; then | ||
| echo unnamed | ||
| elif [[ "${outputName:0:3}" = lib ]]; then | ||
| echo "${outputName:3}" | ||
| else | ||
| echo "${outputName}" | ||
| fi)) | ||
| declare -ra children=("$outputNameLibless-reexport-delegate-0" \ | ||
| "$outputNameLibless-reexport-delegate-1") | ||
|
|
||
| mkdir -p "$out/lib" | ||
|
|
||
| PATH="$PATH:@out@/bin" | ||
|
|
||
| symbolBloatObject=$outputNameLibless-symbol-hack.o | ||
| if [[ ! -e $symbolBloatObject ]]; then | ||
| printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' \ | ||
| | @binPrefix@as -- -o $symbolBloatObject | ||
| fi | ||
|
|
||
| # first half of libs | ||
| @binPrefix@ld -macosx_version_min 10.10 -arch x86_64 -dylib \ | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copumpkin @LnL7 / other Darwin people. I just cargo-culted
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||
| -o "$out/lib/lib${children[0]}.dylib" \ | ||
| -install_name "$out/lib/lib${children[0]}.dylib" \ | ||
| "${childrenLookup[@]}" "$symbolBloatObject" \ | ||
| "${childrenLink[@]:0:$((${#childrenLink[@]} / 2 ))}" | ||
|
|
||
| # second half of libs | ||
| @binPrefix@ld -macosx_version_min 10.10 -arch x86_64 -dylib \ | ||
| -o "$out/lib/lib${children[1]}.dylib" \ | ||
| -install_name "$out/lib/lib${children[1]}.dylib" \ | ||
| "${childrenLookup[@]}" "$symbolBloatObject" \ | ||
| "${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}" | ||
|
|
||
| allArgs+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}") | ||
| fi | ||
|
|
||
| PATH="$path_backup" | ||
| exec @prog@ "${allArgs[@]}" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -297,7 +297,7 @@ in rec { | |
| initialPath = import ../common-path.nix { inherit pkgs; }; | ||
| shell = "${pkgs.bash}/bin/bash"; | ||
|
|
||
| cc = import ../../build-support/cc-wrapper { | ||
| cc = lib.callPackageWith {} ../../build-support/cc-wrapper { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this do?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It adds the override field so I can replace cc while leaving everything else the same. Probably should add a note for that. |
||
| inherit (pkgs) stdenv; | ||
| inherit shell; | ||
| nativeTools = false; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| { lib, clangStdenv, clang-sierraHack-stdenv, stdenvNoCC }: | ||
|
|
||
| let | ||
| makeBigExe = stdenv: prefix: rec { | ||
|
|
||
| count = 500; | ||
|
|
||
| sillyLibs = lib.genList (i: stdenv.mkDerivation rec { | ||
| name = "${prefix}-fluff-${toString i}"; | ||
| unpackPhase = '' | ||
| src=$PWD | ||
| cat << 'EOF' > ${name}.c | ||
| unsigned int asdf_${toString i}(void) { | ||
| return ${toString i}; | ||
| } | ||
| EOF | ||
| ''; | ||
| buildPhase = '' | ||
| $CC -std=c99 -shared ${name}.c -o lib${name}.dylib -Wl,-install_name,$out/lib/lib${name}.dylib | ||
| ''; | ||
| installPhase = '' | ||
| mkdir -p "$out/lib" | ||
| mv lib${name}.dylib "$out/lib" | ||
| ''; | ||
| meta.platforms = lib.platforms.darwin; | ||
| }) count; | ||
|
|
||
| finalExe = stdenv.mkDerivation rec { | ||
| name = "${prefix}-final-asdf"; | ||
| unpackPhase = '' | ||
| src=$PWD | ||
| cat << 'EOF' > main.cxx | ||
|
|
||
| #include <cstdlib> | ||
| #include <iostream> | ||
|
|
||
| ${toString (lib.genList (i: "extern \"C\" unsigned int asdf_${toString i}(void); ") count)} | ||
|
|
||
| unsigned int (*funs[])(void) = { | ||
| ${toString (lib.genList (i: "asdf_${toString i},") count)} | ||
| }; | ||
|
|
||
| int main(int argc, char **argv) { | ||
| bool ret; | ||
| unsigned int i = 0; | ||
| for (auto f : funs) { | ||
| if (f() != i++) { | ||
| std::cerr << "Failed to get expected response from function #" << i << std::endl; | ||
| return EXIT_FAILURE; | ||
| } | ||
| } | ||
| return EXIT_SUCCESS; | ||
| } | ||
| EOF | ||
| ''; | ||
| buildPhase = '' | ||
| $CXX -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o ${prefix}-asdf | ||
| ''; | ||
| buildInputs = sillyLibs; | ||
| installPhase = '' | ||
| mkdir -p "$out/bin" | ||
| mv ${prefix}-asdf "$out/bin" | ||
| ''; | ||
| meta.platforms = lib.platforms.darwin; | ||
| }; | ||
|
|
||
| }; | ||
|
|
||
| good = makeBigExe clang-sierraHack-stdenv "good"; | ||
|
|
||
| bad = makeBigExe clangStdenv "bad"; | ||
|
|
||
| in stdenvNoCC.mkDerivation { | ||
| name = "macos-sierra-shared-test"; | ||
| buildInputs = [ good.finalExe bad.finalExe ]; | ||
| # TODO(@Ericson2314): Be impure or require exact MacOS version of builder? | ||
| buildCommand = '' | ||
| if bad-asdf | ||
| then echo "bad-asdf can succeed on non-sierra, OK" >&2 | ||
| else echo "bad-asdf should fail on sierra, OK" >&2 | ||
| fi | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love that we won't be able to catch regressions due to the exe just no longer breaking the limit for some reason
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neither do I. But I couldn't think of anything better without much more work. |
||
|
|
||
| # Must succeed on all supported MacOS versions | ||
| good-asdf | ||
|
|
||
| touch $out | ||
| ''; | ||
| meta.platforms = lib.platforms.darwin; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we handle
--here or elsewhere?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I wasn't aware of it; looking up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean just plain paths to dylibs passed in? I didn't see any
--in the man page.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just mean the standard
--to separate command line flags from files that start with--, no idea if ld supports it but most tools do.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shlevy Well I don't yet handle libraries passed in by path yet at all, in fact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shlevy Well I don't yet handle libraries passed in by path yet at all, in fact. I'll look into
--and that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, let's just do this as followup if needed.