Skip to content

Commit

Permalink
handle new ld options in a nicer way, and launch the older ld if targ…
Browse files Browse the repository at this point in the history
…etting macOS <= 10.6
  • Loading branch information
devernay committed Jan 21, 2017
1 parent 2117574 commit 9eee276
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 39 deletions.
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----------------------------------
Expand Down
111 changes: 82 additions & 29 deletions XcodeLegacy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 9eee276

Please sign in to comment.