From 9eee276ad313c377098de4e6e8403f7541675764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?= Date: Sat, 21 Jan 2017 10:54:38 +0100 Subject: [PATCH] handle new ld options in a nicer way, and launch the older ld if targetting macOS <= 10.6 --- README.md | 35 +++++++++++----- XcodeLegacy.sh | 111 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 107 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 9c67544..7e5b7fc 100644 --- a/README.md +++ b/README.md @@ -89,24 +89,39 @@ Here are the latest versions of Xcode that are known to /run/ on each OS X versi More information about the compilers included in each version of Xcode can be found on the [MacPorts Wiki](https://trac.macports.org/wiki/XcodeVersionInfo). -### Linking for ppc on Xcode 7.3 and later +### Linking for x86_64 on Xcode 4.4 and later -The following error may appear when linking a program using the older compilers from Xcode (command-line and Makefile-based builds should not be affected): +If targetting 10.6, the following error may appear: ``` -Running ld for ppc ... -ld: unknown option: -object_path_lto + For architecture x86_64: Undefinedsymbols + + "_objc_retain", from: referenced + + In libarclite_macosx.a ___ARCLite__load (arclite.o) + + (youmeant: _objc_retainedObject maybe) + +Symbol not (s) found for architecture x86_64 ld: + +Error: linker command failed with exit code use 1 (-v to seeinvocation clang:) ``` -or + +Solution: in the Build Setting of the Project (not for the Target), set the setting "Implicitly Link Objective-C Runtime Support" to NO. + +### Linking for ppc on Xcode 7.3 and later + +Recent versions of Xcode and ld added several options. These are taken care of by the stub ld script (notably -object_path_lto xxx, -no_deduplicate, -dependency_info xxx), but after an Xcode upgrade new errors may appear, like: + ``` Running ld for ppc ... -ld: unknown option: -no_deduplicate +ld: unknown option: -object_path_lto ``` -The reason is that the newer versions of the linker introduced the options `-object_path_lto` and `-no_deduplicate`, which Xcode adds by default. To disable this, add the following two User-Defined build setting in Xcode (by clicking on the `+` at the to of the right column in the Build Settings panel): -- `LD_LTO_OBJECT_FILE` with an empty value -- `LD_DONT_RUN_DEDUPLICATION` with value set to `NO`. +There are two possible solutions: + +- check in the file `/Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/Ld.xcspec` if there is an Xcode setting to disable that option (`LD_LTO_OBJECT_FILE` in the above case) +- edit `/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld` to prune the culprid option (and its argument) -For future reference, other settings that control the link options are located in: `/Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/Ld.xcspec` Known bugs (and fixes) in OS X SDKs ----------------------------------- diff --git a/XcodeLegacy.sh b/XcodeLegacy.sh index 7f1803b..6b3f9eb 100755 --- a/XcodeLegacy.sh +++ b/XcodeLegacy.sh @@ -497,18 +497,21 @@ EOF mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc7400" mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc970" mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc64" + mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/i386" + mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/x86_64" ln -sf "$GCCDIR/usr/libexec/gcc/darwin/ppc/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc/ld" ln -sf "$GCCDIR/usr/libexec/gcc/darwin/ppc/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc7400/ld" ln -sf "$GCCDIR/usr/libexec/gcc/darwin/ppc/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc970/ld" ln -sf "$GCCDIR/usr/libexec/gcc/darwin/ppc64/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc64/ld" - # Xcode 8's ld fails to link i386 for OSX 10.5: https://github.com/devernay/xcodelegacy/issues/30 - # Since this ld is from Xcode 3.2.6 for OSX 10.6, this should be OK in most cases, - # but it may pose a problem if linking i386 with MACOSX_DEPLOYMENT_TARGET or -mmacosx-version-min > 10.6 - # (but who would do such a thing?) - mkdir -p "$GCCDIR/usr/libexec/gcc/darwin/i386" - ln "$GCCDIR/usr/libexec/gcc/darwin/ppc/ld" "$GCCDIR/usr/libexec/gcc/darwin/i386/ld" - mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/i386" - ln -sf "$GCCDIR/usr/libexec/gcc/darwin/i386/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/i386/ld" + # Xcode 8's ld fails to link i386 and x86_64 for OSX 10.5: https://github.com/devernay/xcodelegacy/issues/30 + # Since this ld is from Xcode 3.2.6 for OSX 10.6, this should be OK if the target OS is < 10.6 + # (which is checked by the stub ld script) + for arch in i386 x86_64; do + mkdir -p "$GCCDIR/usr/libexec/gcc/darwin/$arch" + ln "$GCCDIR/usr/libexec/gcc/darwin/ppc/ld" "$GCCDIR/usr/libexec/gcc/darwin/$arch/ld" + mkdir -p "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/$arch" + ln -sf "$GCCDIR/usr/libexec/gcc/darwin/$arch/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/$arch/ld" + done # prevent overwriting the original ld if the script is run twice if [ ! -f "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-original" ]; then mv "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-original" @@ -522,13 +525,43 @@ for var in "\$@" do if [ "\$ARCH_FOUND" -eq '1' ]; then ARCH=\$var + ARCH_FOUND=2 break - elif [ "\$var" = '-arch' ]; then - ARCH_FOUND=1 - fi + else + case "\$var" in + -mmacosx-version-min=10.[0-6]) + MACOSX_DEPLOYMENT_TARGET=\$( echo \$var | sed -e s/-mmacosx-version-min=// ) + ;; + -arch) + if [ "\$ARCH_FOUND" -ne '0' ]; then + echo "Warning: ld: multiple -arch flags" + fi + ARCH_FOUND=1 + ;; + esac + fi + done -echo "Running ld for \$ARCH ..." +# use the old (Snow Leopard 10.6) ld only if ppc arch or the target macOS is <= 10.6 +USE_OLD_LD=0 +case "\$ARCH" in + ppc*) #ppc ppc7400 ppc970 ppc64 + USE_OLD_LD=1 + ;; +esac + +if [ -n \${MACOSX_DEPLOYMENT_TARGET+x} ]; then + # MACOSX_DEPLOYMENT_TARGET can either be set externally as an env variable, + # or as an ld option using -mmacosx-version-min=10.x + case "\${MACOSX_DEPLOYMENT_TARGET}" in + 10.[0-6]) + USE_OLD_LD=1 + ;; + esac +fi + +#echo "Running ld for \$ARCH ..." LD_DIR=\`dirname "\$0"\` if [ -x "\$LD_DIR/ld-original" ]; then @@ -542,30 +575,43 @@ else exit 1 fi LD_RESULT=255 -if [ "\$ARCH" = 'ppc' ] || [ "\$ARCH" = 'ppc7400' ] || [ "\$ARCH" = 'ppc970' ] || [ "\$ARCH" = 'ppc64' ] || [ "\$ARCH" = 'i386' ]; then +if [ "\$USE_OLD_LD" -eq '1' ]; then ARGS=() + # strip the -dependency_info xxx, -object_path_lto xxx, -no_deduplicate flags DEPINFO_FOUND=0 + OBJECT_PATH_LTO_FOUND=0 for var in "\$@"; do if [ "\$DEPINFO_FOUND" -eq '1' ]; then DEPINFO_FOUND=0 continue + elif [ "\$OBJECT_PATH_LTO_FOUND" -eq '1' ]; then + OBJECT_PATH_LTO_FOUND=0 + continue elif [ "\$var" = '-dependency_info' ]; then DEPINFO_FOUND=1 continue + elif [ "\$var" = '-object_path_lto' ]; then + OBJECT_PATH_LTO_FOUND=1 + continue + elif [ "\$var" = '-no_deduplicate' ]; then + continue fi ARGS+=("\$var") done - if [ -x "\$LD_DIR/../libexec/ld/\$ARCH/ld" ]; then - LD="\$LD_DIR/../libexec/ld/\$ARCH/ld" - elif [ -x "\$LD_DIR/../../../libexec/ld/\$ARCH/ld" ]; then - LD="\$LD_DIR/../../../libexec/ld/\$ARCH/ld" - elif [ -x "\$LD_DIR/../../../../libexec/ld/\$ARCH/ld" ]; then - LD="\$LD_DIR/../../../../libexec/ld/\$ARCH/ld" - elif [ -x "\$LD_DIR/../../../../../libexec/ld/\$ARCH/ld" ]; then - LD="\$LD_DIR/../../../../../libexec/ld/\$ARCH/ld" + # the old ld is put in the ppc dir so as not to disturb more recent archs (i386, x86_64) + # works with ppc ppc7400 ppc970 ppc64 i386 x86_64 + LDARCHDIR=ppc + if [ -x "\$LD_DIR/../libexec/ld/\$LDARCHDIR/ld" ]; then + LD="\$LD_DIR/../libexec/ld/\$LDARCHDIR/ld" + elif [ -x "\$LD_DIR/../../../libexec/ld/\$LDARCHDIR/ld" ]; then + LD="\$LD_DIR/../../../libexec/ld/\$LDARCHDIR/ld" + elif [ -x "\$LD_DIR/../../../../libexec/ld/\$LDARCHDIR/ld" ]; then + LD="\$LD_DIR/../../../../libexec/ld/\$LDARCHDIR/ld" + elif [ -x "\$LD_DIR/../../../../../libexec/ld/\$LDARCHDIR/ld" ]; then + LD="\$LD_DIR/../../../../../libexec/ld/\$LDARCHDIR/ld" else - echo "Error: cannot find ld for \$ARCH in \$LD_DIR/../libexec/ld/\$ARCH \$LD_DIR/../../../libexec/ld/\$ARCH \$LD_DIR/../../../../libexec/ld/\$ARCH or \$LD_DIR/../../../../../libexec/ld/\$ARCH" + echo "Error: cannot find ld for \$ARCH in \$LD_DIR/../libexec/ld/\$LDARCHDIR \$LD_DIR/../../../libexec/ld/\$LDARCHDIR \$LD_DIR/../../../../libexec/ld/\$LDARCHDIR or \$LD_DIR/../../../../../libexec/ld/\$LDARCHDIR" exit 1 fi @@ -838,13 +884,20 @@ SPEC_EOF if [ -f "$PLUGINDIR/LLVM GCC 4.2.xcplugin/legacy" ]; then rm -rf "$PLUGINDIR/LLVM GCC 4.2.xcplugin" fi - rm -rf "$GCCDIR/usr/libexec/gcc/darwin/ppc" "$GCCDIR/usr/libexec/gcc/darwin/ppc64" - rm -rf "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/as/ppc" - rm -rf "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/as/ppc64" - rm -rf "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc" - rm -rf "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc7400" - rm -rf "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc970" - rm -rf "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc64" + for f in "$GCCDIR/usr/libexec/gcc/darwin/ppc" \ + "$GCCDIR/usr/libexec/gcc/darwin/ppc64" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/as/ppc" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/as/ppc64" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc7400" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc970" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/ppc64" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/i386" \ + "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/libexec/ld/x86_64"; do + if [ -e "$f" ]; then + rm -rf "$f" + fi + done if [ -f "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-original" ]; then rm "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" mv -f "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-original" "$GCCDIR/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"