Skip to content

Commit

Permalink
Build universal libs and add iOS Sim support
Browse files Browse the repository at this point in the history
Build universal libs by default now for armv7, armv7s, and i386.  Sample
Xcode projects now allow you to run either on a device or to run in the
iOS simulator.  Also, a coordinated update of iphoneos-apple-support and
druntime to avoid dlyd private API calls.
  • Loading branch information
smolt committed Jul 7, 2015
1 parent 10abee1 commit 21fee5b
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 72 deletions.
36 changes: 25 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,39 @@ $ git submodule update --init --recursive
$ tools/build-all -f
```

You can quickly try the resulting compiler yourself by typing:
You can quickly try the resulting compiler to generate armv7 code by typing:

```
$ tools/iphoneos-ldc2 -c hello.d
$ tools/iphoneos-ldc2 -arch armv7 -c hello.d
```

This only gives you a .o file but using Xcode and a provisioning profile you could link, codesign, bundle, and run it on an iOS device. A sample Xcode [project](#sample-hellod-project) does just that if you have a provisioning profile.
Without a provisioning profile, you can still try out D with the iOS Simulator.

At this point, you have an LDC toolchain and druntime/phobos built for 32-bit armv7 iOS in `build/ldc`. This ldc2 is actually configured to target all iOS devices from original iPhone (armv6) to iPhone 6 (arm64). My only iOS devices are armv7 so that is the only target being built. Plus, all iOS device from iPhone 3gs, iPod 3, AppleTV and up can run armv7 instructions [(see Device Compatibility)](https://developer.apple.com/library/ios/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/DeviceCompatibilityMatrix/DeviceCompatibilityMatrix.html). The equivalent gcc or clang target is armv7-apple-darwin, but under the hood in LLVM it is really thumbv7-apple-ios with cortex-a8 selected to enable neon and vfp3.

`iphoneos-ldc2` is nothing more than a script that does this:
To generate code for the iOS Simulator, just change the `-arch`
option:

```
$ build/ldc/bin/ldc2 -mtriple=thumbv7-apple-ios5 -mcpu=cortex-a8 -c hello.d
$ tools/iphoneos-ldc2 -arch i386 -c hello.d
```

This script makes it easy to manage compiler defaults. Clang presets many options when compiling for iOS based on the -arch switch but these presets are not in ldc2 main yet. For now I think it is easier to tweak options with the iphoneos-ldc2 script. Eventually ldc2 will be taught the iOS clang preset options for each iOS arch: armv6, armv7, armv7s, and arm64.
Note that if you don't specify `-arch`, the default target is now the i386
iOS Simulator (used to be armv7).

At this point, you have an LDC toolchain and universal druntime/phobos libs
in `build/ldc` for 32-bit armv7, armv7s (iPhone 3gs to iPhone 5c),
and i386 iOS Simulator. The compiler can also target armv6 target
(original iPhone and other older devices), but it is left out of the
universal libs to speed build time. Missing is arm64 for iPhone 6 and iPhone 5s, although
these 64-bit devices can run 32-bit instructions too. For more
information
[see Device Compatibility](https://developer.apple.com/library/ios/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/DeviceCompatibilityMatrix/DeviceCompatibilityMatrix.html).

The ldc2 in build/ldc/bin can also target x86 and x86_64. This is for eventual use of the iPhone Simulator. Unfortunately you cannot run LDC compiled source on iPhone Sim yet because ld refuses to link files with OS X thread local variables when targeting iPhone Sim. I assume this is just to prevent running code on the sim that cannot run in iOS. I think we can get around this by using our own ld or using a different TLS approach that ld won't detect.
My only hardware is armv7 so that is all I can really test for the moment.

More will eventually be added to tools. It is could be useful to add tools to your PATH.
`tools/iphoneos-ldc2` is nothing more than a script that redirects to what
is built in `build/ldc/bin/iphoneos-ldc2`. The binaries have a
`iphoneos-` prefix to remind you that the defaut target is iPhoneOS.

## Sample helloD Project
[helloD](https://github.com/smolt/ldc-iphone-dev/tree/master/helloD) is a barebones Xcode project with four simple targets. It only uses the console to demonstrate LDC compiled code running on an iOS device.
Expand All @@ -82,6 +94,9 @@ More will eventually be added to tools. It is could be useful to add tools to y
## Unittests
An Xcode project called [unittester](https://github.com/smolt/ldc-iphone-dev/tree/master/unittester) is included that has targets for running the druntime and phobos unittests. Two are D only with output to the console (nothing to see on the iOS device besides a black screen). The other two are simple scrolling text apps that show the D unittest output as it runs. These apps manage the UI with Objective-C and run the D unittests in another thread.

*Note: the following instructions for running unittests are out-of-date
with latest change to build universal libs. Update in process*

You can build and run the console druntime/phobos unittests from the shell. Here I am running on my iPad mini (cortex-a9):

```
Expand Down Expand Up @@ -131,8 +146,7 @@ Or what is left to do.

In work now:
- Make prebuilt binaries
- Ability to run on iPhone Simulator
- Build universal libs (support sim and device in one lib)
- Get arm64 target working
- Make symbolic debugging work better - this is much improved since Xcode 6.3.1.
- Update to future release LDC 0.16.0 (DMD FE 2.067)

Expand Down
14 changes: 6 additions & 8 deletions helloD/helloD.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v";
};
37FF99AC1A91956E00098723 /* PBXBuildRule */ = {
isa = PBXBuildRule;
Expand All @@ -49,7 +49,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -g -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v";
};
37FF99C41A91988600098723 /* PBXBuildRule */ = {
isa = PBXBuildRule;
Expand All @@ -61,7 +61,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v";
};
37FF99D71A91CE8100098723 /* PBXBuildRule */ = {
isa = PBXBuildRule;
Expand All @@ -73,7 +73,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v";
};
/* End PBXBuildRule section */

Expand Down Expand Up @@ -404,9 +404,8 @@
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = armv7;
VALID_ARCHS = "armv7 armv7s";
};
name = Debug;
};
Expand Down Expand Up @@ -441,10 +440,9 @@
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VALID_ARCHS = armv7;
VALID_ARCHS = "armv7 armv7s";
};
name = Release;
};
Expand Down
2 changes: 1 addition & 1 deletion iphoneos-apple-support
Submodule iphoneos-apple-support updated 2 files
+3 −1 Makefile
+38 −45 threadLocalVariables.c
2 changes: 1 addition & 1 deletion ldc
Submodule ldc updated 2 files
+1 −1 runtime/CMakeLists.txt
+1 −1 runtime/druntime
31 changes: 10 additions & 21 deletions tools/iphoneos-ldc2
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
#!/bin/bash
# Little frontend until ldc2 is updated with proper defaults for
# iPhoneOS. Really all this is doing is defaulting -mtriple
# to values in tools/flag.
# Redirect to ldc2 in build/ldc/bin. Tries with and without iphoneos-
# prefix.

tooldir=`dirname $BASH_SOURCE[0]`
topdir=`cd $tooldir/..; pwd`

source $tooldir/flags # default dflags

case $0 in
*-ldc2) prog=ldc2;;
*-ldmd2) prog=ldmd2;;
esac

[ "$DEBUGGING_SYMBOLS" = YES ] && args="-g"

for arg in "$@"; do
case $arg in
*-mtriple*) triple=;;
-v|-vv) verbose=1;;
esac
done

progpath="$topdir/build/ldc/bin/$prog"

if [ ! -x "$progpath" ]; then
echo >&2 "$progpath does not seem to be built yet"
path="$topdir/build/ldc/bin"
if [ -x "$path/$prog" ]; then
progpath="$path/$prog"
elif [ -x "$path/iphoneos-$prog" ]; then
progpath="$path/iphoneos-$prog"
else
echo >&2 "$prog or iphoneos-$prog do not seem to be built yet"
exit 1
fi

cmd="$progpath $triple"
[ "$verbose" ] && echo $cmd $args "$@"
$cmd $args "$@"
exec $progpath "$@"
35 changes: 11 additions & 24 deletions tools/prepmake-ldc
Original file line number Diff line number Diff line change
@@ -1,44 +1,31 @@
#!/bin/bash
# configure to build LDC for iPhoneOS armv7 (iPhone 4 and later 32-bit stuff)
# assumes LLVM is already built
# Configure to build LDC with universal libs (druntime/phobos) for
# iPhoneOS 32-bit archtectures. Assumes LLVM is already built

# top dir is one up from this script's dir
topdir=`dirname $BASH_SOURCE[0]`/..

# LLVM_ROOT_DIR must be an absolute path for some reason
absolute=`cd $topdir; pwd`
llvmdir="$absolute/build/llvm/Release/"
installdir="$absolute/build/install"

if [ ! -d "$llvmdir" ]; then
echo "Missing $llvmdir"
echo 'LLVM does not seem to be built yet'
exit 1
fi

# Need Xcode with the iPhoneOS SDK
iphonesdk=`xcrun --sdk iphoneos --show-sdk-path`

if [ -z "$iphonesdk" ]; then
echo "Missing iPhoneOS SDK, can't build C code in druntime/phobos"
exit 1
fi

# get cflags, dflags.
# cmake needs dflags to be separated by ';' instead of spaces, so xlate
source $topdir/tools/flags
dflags_cmake=`echo $dflags|tr -s ' ' ';'`

# What's with all these flags?
# -DUSE_OSX_TARGET_REAL compiles in code to use target's native real type
#
# The D versions are to support troubleshooting issues detected by unittest.
#
# WIP_FloatPrecIssue - work in progress for some floating point
# precision problems

cd $topdir/build/ldc && cmake \
-DLLVM_ROOT_DIR=$llvmdir \
-DCMAKE_CXX_FLAGS='-DUSE_OSX_TARGET_REAL' \
-DD_FLAGS="-w;-d;$dflags_cmake;-d-version=WIP_FloatPrecIssue" \
-DTARGET_C_FLAGS="$cflags -isysroot $iphonesdk" \
../../ldc
cd $topdir/build/ldc &&
cmake -DLLVM_ROOT_DIR=$llvmdir \
-DIPHONEOS_ARCHS='all' \
-DPROGRAM_PREFIX=iphoneos- \
-DCMAKE_INSTALL_PREFIX=$installdir \
-DINCLUDE_INSTALL_DIR=$installdir/import ../../ldc


48 changes: 48 additions & 0 deletions tools/xc-iphoneos-dc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
# Wrapper for iphoneos-ldc2 that converts Xcode Custom Build Rule
# script environment into command line switches.
#
# Output Files should be:
# ${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o

# this script is expected to be alongside iphoneos-ldc2
dir=`dirname $BASH_SOURCE[0]`
bindir=`cd $dir; pwd`
ldc=iphoneos-ldc2

# Find the compiler, hopefully right next door
if [ ! -x "$bindir/$ldc" ]; then
echo >&2 "can't find $ldc in $bindir"
exit 1
fi

for arg in "$@"; do
case $arg in
-arch) have_arch=1;;
-c) have_c=1;;
-O*) have_O=1;;
-g*) have_g=1;;
-od*) have_od=1;;
-of*) have_of=1;;
-v|-vv) verbose=1;;
*.d) have_dsrc=1;;
esac
done

args="$bindir/$ldc"
[ -z "$have_arch" -a "$arch" ] &&
args="$args -arch $arch"
[ -z "$have_c" ] &&
args="$args -c"
[ -z "$have_O" -a "$OPTIMIZATION_LEVEL" ] &&
args="$args -O$OPTIMIZATION_LEVEL"
[ -z "$have_g" -a "$DEBUGGING_SYMBOLS" = YES ] &&
args="$args -g"
[ -z "$have_od" -a -d "$DERIVED_FILES_DIR" ] &&
args="$args -od='$DERIVED_FILES_DIR'"
[ -z "$have_dsrc" -a -f "$INPUT_FILE_PATH" ] &&
args="$args '$INPUT_FILE_PATH'"

eval set $args "$@"
[ "$verbose" ] && echo "$@"
exec "$@"
12 changes: 6 additions & 6 deletions unittester/unittester.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v";
};
3781D8A91A9AE0CE00B2C8E6 /* PBXBuildRule */ = {
isa = PBXBuildRule;
Expand All @@ -60,7 +60,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -d-version=UnittestMain -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v -d-version=UnittestMain";
};
3781D8D81A9B09D500B2C8E6 /* PBXBuildRule */ = {
isa = PBXBuildRule;
Expand All @@ -72,7 +72,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v";
};
3781D8EB1A9B0BD600B2C8E6 /* PBXBuildRule */ = {
isa = PBXBuildRule;
Expand All @@ -84,7 +84,7 @@
outputFiles = (
"${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.o",
);
script = "../tools/iphoneos-ldc2 -v -d-version=UnittestMain -O${OPTIMIZATION_LEVEL} -c -od=\"${DERIVED_FILES_DIR}\" \"${INPUT_FILE_PATH}\"";
script = "../tools/xc-iphoneos-dc -v -d-version=UnittestMain";
};
/* End PBXBuildRule section */

Expand Down Expand Up @@ -556,7 +556,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = armv7;
VALID_ARCHS = "armv7 armv7s";
};
name = Debug;
};
Expand Down Expand Up @@ -600,7 +600,7 @@
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VALID_ARCHS = armv7;
VALID_ARCHS = "armv7 armv7s";
};
name = Release;
};
Expand Down

0 comments on commit 21fee5b

Please sign in to comment.