Skip to content
This repository has been archived by the owner on Jul 4, 2018. It is now read-only.

Commit

Permalink
Refactor of native compilation to support separate ios vs. osx librar…
Browse files Browse the repository at this point in the history
…ies.

Issue j2objc-contrib#466
  • Loading branch information
advayDev1 committed Oct 5, 2015
1 parent 40f66ee commit fdd1da3
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 141 deletions.
10 changes: 8 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ matrix:
# Having verified their other OS X images, this is the only version
# that has JDK 1.7:
# https://travis-ci.org/j2objc-contrib/j2objc-gradle/builds/77036011
- os: osx
osx_image: xcode7
language: objective-c
env:
- USING_OS=osx
- USING_XCODE=7
- os: osx
language: objective-c
env:
Expand All @@ -46,8 +52,8 @@ install:
# Don't spew graphic art.
- export TERM=dumb
- env
# We need JDK 7 specifically on OS X. This will fail if there is no 1.7
- if [ "$USING_OS" = "osx" ]; then (/usr/libexec/java_home -v 1.7 -F -V); fi
# We need JDK 7 specifically on OSX with Xcode 6.1. This will fail if there is no 1.7
- if [ "$USING_XCODE" = "6.1" ]; then (/usr/libexec/java_home -v 1.7 -F -V); fi
- java -Xmx32m -version && javac -J-Xmx32m -version
- ./gradlew wrapper
- ./gradlew dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,15 +288,15 @@ class J2objcConfig {
*/
// J2objc default libraries, from $J2OBJC_HOME/lib/..., without '.a' extension.
// TODO: auto add libraries based on java dependencies, warn on version differences
List<String> linkJ2objcLibs = ['guava', 'j2objc_main', 'javax_inject', 'jsr305']
List<String> linkJ2objcLibs = ['guava', 'javax_inject', 'jsr305']

/**
* Additional native libraries that are part of the j2objc distribution to link
* with the test code.
*/
// J2objc default libraries, from $J2OBJC_HOME/lib/..., without '.a' extension.
// TODO: auto add libraries based on java dependencies, warn on version differences
List<String> linkJ2objcTestLibs = ['junit', 'mockito']
List<String> linkJ2objcTestLibs = ['junit', 'mockito', 'j2objc_main']

// TODO: warn if different versions than testCompile from Java plugin
/**
Expand Down Expand Up @@ -416,9 +416,9 @@ class J2objcConfig {
* <p/>
* By default, only common modern iOS architectures will be built:
* ios_arm64, ios_armv7, ios_x86_64. You may choose to add any of the remaining
* entries from NativeCompilation.ALL_SUPPORTED_ARCHS (ios_i386 and ios_armv7s)
* entries from NativeCompilation.ALL_IOS_ARCHS (ios_i386 and ios_armv7s)
* to support all possible iOS architectures. Listing any new architectures outside of
* ALL_SUPPORTED_ARCHS will fail the build.
* ALL_IOS_ARCHS will fail the build.
* <p/>
* Removing an architecture here will cause that architecture not to be built
* and corresponding gradle tasks to not be created.
Expand All @@ -432,7 +432,7 @@ class J2objcConfig {
* <li>'ios_i386' => iOS Simulator on 32-bit OS X
* <li>'ios_x86_64' => iOS Simulator on 64-bit OS X
* </ul>
* @see NativeCompilation#ALL_SUPPORTED_ARCHS
* @see NativeCompilation#ALL_IOS_ARCHS
*/
// Public to allow assignment of array of targets as shown in example
List<String> supportedArchs = ['ios_arm64', 'ios_armv7', 'ios_x86_64']
Expand All @@ -458,7 +458,7 @@ class J2objcConfig {
// instead we want no architectures at all in this case.
enabledArchs.remove('')
List<String> invalidArchs = enabledArchs.minus(
NativeCompilation.ALL_SUPPORTED_ARCHS.clone() as List<String>).toList()
NativeCompilation.ALL_IOS_ARCHS.clone() as List<String>).toList()
if (!invalidArchs.isEmpty()) {
throw new InvalidUserDataException("Invalid 'enabledArchs' entry: " + invalidArchs.join(', '))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,112 @@
*/

package com.github.j2objccontrib.j2objcgradle

import com.github.j2objccontrib.j2objcgradle.tasks.Utils
import groovy.transform.PackageScope
import org.gradle.api.Action
import org.gradle.api.InvalidUserDataException
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.nativeplatform.NativeExecutableSpec
import org.gradle.nativeplatform.NativeLibraryBinary
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.Clang

import org.gradle.nativeplatform.toolchain.GccPlatformToolChain
import org.gradle.platform.base.Platform
/**
* Compilation of libraries for debug/release and architectures listed below.
*/
class NativeCompilation {

static final String[] ALL_SUPPORTED_ARCHS = ['ios_arm64', 'ios_armv7', 'ios_armv7s', 'ios_i386', 'ios_x86_64']
static final String[] ALL_IOS_ARCHS = ['ios_arm64', 'ios_armv7', 'ios_armv7s', 'ios_i386', 'ios_x86_64']
// TODO: Provide a mechanism to vary which OSX architectures are built.
static final String[] ALL_OSX_ARCHS = ['x86_64']

private final Project project

NativeCompilation(Project project) {
this.project = project
}

enum TargetSpec {
TARGET_IOS_DEVICE,
TARGET_IOS_SIMULATOR,
TARGET_OSX,
}

String[] simulatorClangArgs = [
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/' +
'iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
'-mios-simulator-version-min=8.3',
]
String[] iphoneClangArgs = [
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/' +
'iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk',
'-miphoneos-version-min=8.3',
]

void definePlatforms(NamedDomainObjectContainer<Platform> d, List<String> names) {
names.each { String name ->
d.create(name, {
architecture name
})
}
}

void defineTarget(Clang d, String name, TargetSpec targetSpec, final String architecture) {
d.target(name, new Action<GccPlatformToolChain>() {
@Override
void execute(GccPlatformToolChain gccPlatformToolChain) {
// Arguments common to the compiler and linker.
String[] clangArgs = [
'-arch',
architecture]
// Arguments specific to the compiler.
String[] compilerArgs = []
// Arguments specific to the linker.
String[] linkerArgs = []
String j2objcPath = Utils.j2objcHome(project)
switch (targetSpec) {
case TargetSpec.TARGET_IOS_DEVICE:
clangArgs += iphoneClangArgs
linkerArgs += ["-L$j2objcPath/lib"]
break
case TargetSpec.TARGET_IOS_SIMULATOR:
clangArgs += simulatorClangArgs
linkerArgs += ["-L$j2objcPath/lib"]
break
case TargetSpec.TARGET_OSX:
if (Utils.j2objcHasOsxDistribution(project)) {
linkerArgs += ["-L$j2objcPath/lib/macosx"]
} else {
String msg = "J2ObjC distribution at $j2objcPath lacks a lib/macosx directory.\n" +
"Please update to J2ObjC 0.9.8.2.1 or higher; earlier versions will\n" +
"not work correctly with Xcode 7 or higher."
project.logger.warn(msg)
// We'll keep going - it works for people with Xcode 6.
linkerArgs += ["-L$j2objcPath/lib"]
}
linkerArgs += ['-framework', 'ExceptionHandling']
break
}
compilerArgs += clangArgs
linkerArgs += clangArgs
gccPlatformToolChain.objcCompiler.withArguments { List<String> args ->
args.addAll(compilerArgs)
}
gccPlatformToolChain.objcppCompiler.withArguments { List<String> args ->
args.addAll(compilerArgs)
}
gccPlatformToolChain.linker.withArguments { List<String> args ->
args.addAll(linkerArgs)
}
}
})
}

@PackageScope
void apply(File srcGenMainDir, File srcGenTestDir) {
project.with {
Expand Down Expand Up @@ -72,19 +154,6 @@ class NativeCompilation {
file("${buildDir}/j2objcHackToForceTestCompilation").mkdirs()
file("${buildDir}/j2objcHackToForceTestCompilation/EmptyTest.m").createNewFile()

String[] simulatorClangArgs = [
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/' +
'iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
'-mios-simulator-version-min=8.3',
]
String[] iphoneClangArgs = [
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/' +
'iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk',
'-miphoneos-version-min=8.3',
]

model {
buildTypes {
debug
Expand All @@ -94,114 +163,17 @@ class NativeCompilation {
// Modify clang command line arguments since we need them to vary by target.
// https://docs.gradle.org/current/userguide/nativeBinaries.html#withArguments
clang(Clang) {
target('ios_arm64') {
String[] iosClangArgs = [
'-arch',
'arm64']
iosClangArgs += iphoneClangArgs
objcCompiler.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
linker.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
}
target('ios_armv7') {
String[] iosClangArgs = [
'-arch',
'armv7']
iosClangArgs += iphoneClangArgs
objcCompiler.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
linker.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
}
target('ios_armv7s') {
String[] iosClangArgs = [
'-arch',
'armv7s']
iosClangArgs += iphoneClangArgs
objcCompiler.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
linker.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
}
target('ios_i386') {
String[] iosClangArgs = [
'-arch',
'i386']
iosClangArgs += simulatorClangArgs
objcCompiler.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
linker.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
}
target('ios_x86_64') {
String[] iosClangArgs = [
'-arch',
'x86_64']
iosClangArgs += simulatorClangArgs
objcCompiler.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
linker.withArguments { List<String> args ->
iosClangArgs.each { String arg ->
args << arg
}
}
}
target('x86_64') {
linker.withArguments { List<String> args ->
args << '-framework'
args << 'ExceptionHandling'
}
}
defineTarget(delegate, 'ios_arm64', TargetSpec.TARGET_IOS_DEVICE, 'arm64')
defineTarget(delegate, 'ios_armv7', TargetSpec.TARGET_IOS_DEVICE, 'armv7')
defineTarget(delegate, 'ios_armv7s', TargetSpec.TARGET_IOS_DEVICE, 'armv7s')
defineTarget(delegate, 'ios_i386', TargetSpec.TARGET_IOS_SIMULATOR, 'i386')
defineTarget(delegate, 'ios_x86_64', TargetSpec.TARGET_IOS_SIMULATOR, 'x86_64')
defineTarget(delegate, 'x86_64', TargetSpec.TARGET_OSX, 'x86_64')
}
}
platforms {
x86_64 {
architecture 'x86_64'
}
// The rest of this list must match ALL_SUPPORTED_ARCHS.
ios_arm64 {
architecture 'ios_arm64'
}
ios_armv7 {
architecture 'ios_armv7'
}
ios_armv7s {
architecture 'ios_armv7s'
}
ios_i386 {
architecture 'ios_i386'
}
ios_x86_64 {
architecture 'ios_x86_64'
}
definePlatforms(delegate as NamedDomainObjectContainer<Platform>, ALL_OSX_ARCHS as List<String>)
definePlatforms(delegate as NamedDomainObjectContainer<Platform>, ALL_IOS_ARCHS as List<String>)
}

components {
Expand All @@ -224,9 +196,9 @@ class NativeCompilation {
}
}
j2objcConfig.activeArchs.each { String arch ->
if (!(arch in ALL_SUPPORTED_ARCHS)) {
if (!(arch in ALL_IOS_ARCHS)) {
throw new InvalidUserDataException(
"Requested architecture $arch must be one of $ALL_SUPPORTED_ARCHS")
"Requested architecture $arch must be one of $ALL_IOS_ARCHS")
}
targetPlatform arch
}
Expand Down Expand Up @@ -297,19 +269,18 @@ class NativeCompilation {

linker.args '-ObjC'

// J2ObjC provided libraries and search path:
// J2ObjC provided libraries:
// TODO: should we link to all? Or just the 'standard' J2ObjC libraries?
linker.args '-ljre_emul'
j2objcConfig.linkJ2objcLibs.each { String libArg ->
linker.args "-l$libArg"
}
linker.args "-L$j2objcPath/lib"

// J2ObjC iOS library dependencies:
linker.args '-lc++' // C++ runtime for protobuf runtime
linker.args '-licucore' // java.text
linker.args '-lz' // java.util.zip
linker.args '-framework', 'foundation' // core ObjC classes: NSObject, NSString
linker.args '-framework', 'Foundation' // core ObjC classes: NSObject, NSString
linker.args '-framework', 'Security' // secure hash generation
linker.args j2objcConfig.extraLinkerArgs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ class Utils {
return j2objcHomeFile.absolutePath
}

static String j2objcHasOsxDistribution(Project proj) {
return proj.file("${j2objcHome(proj)}/lib/macosx").exists()
}

// Reads properties file and arguments from translateArgs (last argument takes precedence)
// --prefixes dir/prefixes.properties --prefix com.ex.dir=Short --prefix com.ex.dir2=Short2
// TODO: separate this out to a distinct argument that's added to translateArgs
Expand Down
Loading

0 comments on commit fdd1da3

Please sign in to comment.