Skip to content
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

iOS and OS X library dependencies #506

Merged
merged 2 commits into from
Oct 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,22 @@ class J2objcConfig {
*/
String minIosVersion = '8.3'

/**
* The minimum OS X version to build against. You cannot use APIs that are not supported
* in this version.
* <p/>
* See https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html#//apple_ref/doc/uid/10000163i-CH1-SW2
*/
String minOsxVersion = '10.8'

/**
* The minimum Watch OS version to build against. You cannot use APIs that are not supported
* in this version.
* <p/>
* See https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html#//apple_ref/doc/uid/10000163i-CH1-SW2
*/
String minWatchosVersion = '2.0'

// XCODE
/**
* Directory of the target Xcode project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,15 @@ class J2objcPlugin implements Plugin<Project> {
group 'verification'
// This transitively depends on the 'test' task from the java plugin
description 'Runs all tests in the generated Objective-C code'
buildType = 'debug'
buildType = 'Debug'
testBinaryFile = file("${buildDir}/binaries/testJ2objcExecutable/debug/testJ2objc")
}
tasks.create(name: 'j2objcTestRelease', type: TestTask,
dependsOn: ['test', 'releaseTestJ2objcExecutable']) {
group 'verification'
// This transitively depends on the 'test' task from the java plugin
description 'Runs all tests in the generated Objective-C code'
buildType = 'release'
buildType = 'Release'
testBinaryFile = file("${buildDir}/binaries/testJ2objcExecutable/release/testJ2objc")
}
tasks.create(name: 'j2objcTest', type: DefaultTask,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,13 @@ class NativeCompilation {
// https://docs.gradle.org/current/userguide/nativeBinaries.html#N161B3
task('j2objcBuildObjcDebug').configure {
dependsOn binaries.withType(NativeLibraryBinary).matching { NativeLibraryBinary lib ->
// Internal build type is lowercase 'debug'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must revert this change. Internally the build type is lower case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to 'debug'

lib.buildable && lib.buildType.name == 'debug'
}
}
task('j2objcBuildObjcRelease').configure {
dependsOn binaries.withType(NativeLibraryBinary).matching { NativeLibraryBinary lib ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must revert this change. Internally the build type is lower case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to 'release'

// Internal build type is lowercase 'release'
lib.buildable && lib.buildType.name == 'release'
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class PackLibrariesTask extends DefaultTask {
@TaskAction
void packLibraries() {
Utils.requireMacOSX('j2objcPackLibraries task')
assert buildType in ['Debug', 'Release']

Utils.projectDelete(project, getOutputLibDirFile())
getOutputLibDirFile().mkdirs()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import groovy.transform.CompileStatic
import org.gradle.api.DefaultTask
import org.gradle.api.InvalidUserDataException
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

Expand Down Expand Up @@ -89,29 +88,57 @@ class PodspecTask extends DefaultTask {

// podspec creation
// TODO: allow custom list of libraries
String libDirDebug = new File(getDestLibDirFile(), '/iosDebug').absolutePath
String libDirRelease = new File(getDestLibDirFile(), '/iosRelease').absolutePath
// iOS packed libraries are shared with watchOS
String libDirIosDebug = new File(getDestLibDirFile(), '/iosDebug').absolutePath
String libDirIosRelease = new File(getDestLibDirFile(), '/iosRelease').absolutePath
String libDirOsxDebug = new File(getDestLibDirFile(), '/x86_64Debug').absolutePath
String libDirOsxRelease = new File(getDestLibDirFile(), '/x86_64Release').absolutePath
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm having second thoughts about the ordering here.
Does absolutePath function before the directory is created? I thought the FS actually resolves the path?

Until the AssembleLibrariesTask has run, j2objcOutputs/lib/BLAH is never created. Does this work for you after a ./gradlew clean then ./gradlew build?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ordering is fine. The absolutePath is resolved internally without referencing the FS. I can run j2objcPodspec and it happily refers to a non-existent directory. Then after running the full build, it now refers to a directory that exists. Indeed, the clean and then build is enforced by the run-test.sh script.


J2objcConfig j2objcConfig = J2objcConfig.from(project)

String minIos = j2objcConfig.minIosVersion
String minOsx = j2objcConfig.minOsxVersion
String minWatchos = j2objcConfig.minWatchosVersion
validateNumericVersion(minIos, 'minIosVersion')
validateNumericVersion(minOsx, 'minOsxVersion')
validateNumericVersion(minWatchos, 'minWatchosVersion')

String podspecContentsDebug =
genPodspec(getPodNameDebug(), libDirDebug, libName, getJ2objcHome(),
headerIncludePath, resourceIncludePath)
genPodspec(getPodNameDebug(), headerIncludePath, resourceIncludePath,
libName, getJ2objcHome(),
libDirIosDebug, libDirOsxDebug, libDirIosDebug,
minIos, minOsx, minWatchos)
String podspecContentsRelease =
genPodspec(getPodNameRelease(), libDirRelease, libName, getJ2objcHome(),
headerIncludePath, resourceIncludePath)
genPodspec(getPodNameRelease(), headerIncludePath, resourceIncludePath,
libName, getJ2objcHome(),
libDirIosRelease, libDirOsxRelease, libDirIosRelease,
minIos, minOsx, minWatchos)

logger.debug("Writing debug podspec... ${getPodspecDebug()}")
getPodspecDebug().write(podspecContentsDebug)
logger.debug("Writing release podspec... ${getPodspecRelease()}")
getPodspecRelease().write(podspecContentsRelease)
}

@VisibleForTesting
void validateNumericVersion(String version, String type) {
// Requires at least a major and minor version number
Matcher versionMatcher = (version =~ /^[0-9]*(\.[0-9]+)+$/)
if (!versionMatcher.find()) {
logger.warn("Non-numeric version for $type: $version")
}
}

// Podspec references are relative to project.buildDir
@VisibleForTesting
static String genPodspec(String podname, String libDir, String libName, String j2objcHome,
String publicHeadersDir, String resourceDir) {
static String genPodspec(String podname, String publicHeadersDir, String resourceDir,
String libName, String j2objcHome,
String libDirIos, String libDirOsx, String libDirWatchos,
String minIos, String minOsx, String minWatchos) {

// Absolute paths for Xcode command line
validatePodspecPath(libDir, false)
validatePodspecPath(libDirIos, false)
validatePodspecPath(libDirOsx, false)
validatePodspecPath(j2objcHome, false)

// Relative paths for content referenced by CocoaPods
Expand All @@ -121,8 +148,8 @@ class PodspecTask extends DefaultTask {
// TODO: CocoaPods strongly recommends switching from 'resources' to 'resource_bundles'
// http://guides.cocoapods.org/syntax/podspec.html#resource_bundles

// TODO: Distinguish ios to OS X builds:
// https://github.com/j2objc-contrib/j2objc-gradle/issues/488
// TODO: replace xcconfig with {pod|user}_target_xcconfig
// See 'Split of xcconfig' from: http://blog.cocoapods.org/CocoaPods-0.38/

// File and line separators assumed to be '/' and '\n' as podspec can only be used on OS X
return "Pod::Spec.new do |spec|\n" +
Expand All @@ -134,9 +161,22 @@ class PodspecTask extends DefaultTask {
" spec.libraries = " + // continuation of same line
"'ObjC', 'guava', 'javax_inject', 'jre_emul', 'jsr305', 'z', 'icucore', '$libName'\n" +
" spec.xcconfig = {\n" +
" 'HEADER_SEARCH_PATHS' => '$j2objcHome/include $publicHeadersDir',\n" +
" 'LIBRARY_SEARCH_PATHS' => '$j2objcHome/lib $libDir'\n" +
" 'HEADER_SEARCH_PATHS' => '$j2objcHome/include $publicHeadersDir'\n" +
" }\n" +
" spec.ios.xcconfig = {\n" +
" 'LIBRARY_SEARCH_PATHS' => '$j2objcHome/lib $libDirIos'\n" +
" }\n" +
" spec.osx.xcconfig = {\n" +
" 'LIBRARY_SEARCH_PATHS' => '$j2objcHome/lib/macosx $libDirOsx'\n" +
" }\n" +
" spec.watchos.xcconfig = {\n" +
" 'LIBRARY_SEARCH_PATHS' => '$j2objcHome/lib $libDirWatchos'\n" +
" }\n" +
// http://guides.cocoapods.org/syntax/podspec.html#deployment_target
" spec.ios.deployment_target = '$minIos'\n" +
" spec.osx.deployment_target = '$minOsx'\n" +
" spec.watchos.deployment_target = '$minWatchos'\n" +
" spec.osx.frameworks = 'ExceptionHandling'\n" +
"end\n"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class TestTask extends DefaultTask {
@InputFile
File testBinaryFile

// 'debug' or 'release'
// 'Debug' or 'Release'
@Input
String buildType

Expand Down Expand Up @@ -88,7 +88,7 @@ class TestTask extends DefaultTask {
@OutputDirectory
// Combines main/test resources and test executables
File getJ2objcTestDirFile() {
assert buildType in ['debug', 'release']
assert buildType in ['Debug', 'Release']
return new File(project.buildDir, "j2objcTest/$buildType")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,21 @@ class PodspecTaskTest {
" spec.requires_arc = true",
" spec.libraries = 'ObjC', 'guava', 'javax_inject', 'jre_emul', 'jsr305', 'z', 'icucore', '$libName'",
" spec.xcconfig = {",
" 'HEADER_SEARCH_PATHS' => '${j2objcHome}/include ${proj.file('build/j2objcOutputs/src/main/objc')}',",
" 'HEADER_SEARCH_PATHS' => '${j2objcHome}/include ${proj.file('build/j2objcOutputs/src/main/objc')}'",
" }",
" spec.ios.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '${j2objcHome}/lib ${proj.file('build/j2objcOutputs/lib/iosDebug').absolutePath}'",
" }",
" spec.osx.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '${j2objcHome}/lib/macosx ${proj.file('build/j2objcOutputs/lib/x86_64Debug').absolutePath}'",
" }",
" spec.watchos.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '${j2objcHome}/lib ${proj.file('build/j2objcOutputs/lib/iosDebug').absolutePath}'",
" }",
" spec.ios.deployment_target = '8.3'",
" spec.osx.deployment_target = '10.8'",
" spec.watchos.deployment_target = '2.0'",
" spec.osx.frameworks = 'ExceptionHandling'",
"end"]
File podspecDebug = proj.file("build/${podNameDebug}.podspec")
List<String> readPodspecDebug = podspecDebug.readLines()
Expand All @@ -93,9 +105,21 @@ class PodspecTaskTest {
" spec.requires_arc = true",
" spec.libraries = 'ObjC', 'guava', 'javax_inject', 'jre_emul', 'jsr305', 'z', 'icucore', '$libName'",
" spec.xcconfig = {",
" 'HEADER_SEARCH_PATHS' => '${j2objcHome}/include ${proj.file('build/j2objcOutputs/src/main/objc')}',",
" 'HEADER_SEARCH_PATHS' => '${j2objcHome}/include ${proj.file('build/j2objcOutputs/src/main/objc')}'",
" }",
" spec.ios.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '${j2objcHome}/lib ${proj.file('build/j2objcOutputs/lib/iosRelease').absolutePath}'",
" }",
" spec.osx.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '${j2objcHome}/lib/macosx ${proj.file('build/j2objcOutputs/lib/x86_64Release').absolutePath}'",
" }",
" spec.watchos.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '${j2objcHome}/lib ${proj.file('build/j2objcOutputs/lib/iosRelease').absolutePath}'",
" }",
" spec.ios.deployment_target = '8.3'",
" spec.osx.deployment_target = '10.8'",
" spec.watchos.deployment_target = '2.0'",
" spec.osx.frameworks = 'ExceptionHandling'",
"end"]
File podspecRelease = proj.file("build/${podNameRelease}.podspec")
List<String> readPodspecRelease = podspecRelease.readLines()
Expand All @@ -105,8 +129,11 @@ class PodspecTaskTest {
@Test
void testGenPodspec() {
List<String> podspecDebug = PodspecTask.genPodspec(
'POD-NAME', '/DEST-LIB-DIR', 'LIB-NAME',
'/J2OBJC_HOME', '/HEADER_INCLUDE', 'MAIN-RESOURCES').split('\n')
'POD-NAME', '/HEADER_INCLUDE', 'MAIN-RESOURCES',
'LIB-NAME', '/J2OBJC_HOME',
'/LIB-DIR-IOS', '/LIB-DIR-OSX', '/LIB-DIR-WATCHOS',
// Using non-existent OS version numbers to ensure that no defaults are being used
'8.3.1', '10.8.1', '2.0.1').split('\n')

List<String> expectedPodspecDebug = [
"Pod::Spec.new do |spec|",
Expand All @@ -117,9 +144,21 @@ class PodspecTaskTest {
" spec.requires_arc = true",
" spec.libraries = 'ObjC', 'guava', 'javax_inject', 'jre_emul', 'jsr305', 'z', 'icucore', 'LIB-NAME'",
" spec.xcconfig = {",
" 'HEADER_SEARCH_PATHS' => '/J2OBJC_HOME/include /HEADER_INCLUDE',",
" 'LIBRARY_SEARCH_PATHS' => '/J2OBJC_HOME/lib /DEST-LIB-DIR'",
" 'HEADER_SEARCH_PATHS' => '/J2OBJC_HOME/include /HEADER_INCLUDE'",
" }",
" spec.ios.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '/J2OBJC_HOME/lib /LIB-DIR-IOS'",
" }",
" spec.osx.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '/J2OBJC_HOME/lib/macosx /LIB-DIR-OSX'",
" }",
" spec.watchos.xcconfig = {",
" 'LIBRARY_SEARCH_PATHS' => '/J2OBJC_HOME/lib /LIB-DIR-WATCHOS'",
" }",
" spec.ios.deployment_target = '8.3.1'",
" spec.osx.deployment_target = '10.8.1'",
" spec.watchos.deployment_target = '2.0.1'",
" spec.osx.frameworks = 'ExceptionHandling'",
"end"]

assert expectedPodspecDebug == podspecDebug
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class TestTaskTest {

j2objcTest = (TestTask) proj.tasks.create(name: 'j2objcTest', type: TestTask) {
testBinaryFile = proj.file(proj.file('build/binaries/testJ2objcExecutable/debug/testJ2objc'))
buildType = 'debug'
buildType = 'Debug'
}
}

Expand All @@ -167,7 +167,7 @@ class TestTaskTest {
mockProjectExec.demandExecAndReturn(
null,
[
proj.file('build/j2objcTest/debug/testJ2objc').absolutePath,
proj.file('build/j2objcTest/Debug/testJ2objc').absolutePath,
"org.junit.runner.JUnitCore",
],
'OK (0 test)', // NOTE: 'test' is singular for stdout
Expand All @@ -194,7 +194,7 @@ class TestTaskTest {
mockProjectExec.demandExecAndReturn(
null,
[
proj.file('build/j2objcTest/debug/testJ2objc').absolutePath,
proj.file('build/j2objcTest/Debug/testJ2objc').absolutePath,
"org.junit.runner.JUnitCore",
],
'OK (0 test)', // NOTE: 'test' is singular for stdout
Expand All @@ -215,7 +215,7 @@ class TestTaskTest {
mockProjectExec.demandExecAndReturn(
null,
[
proj.file('build/j2objcTest/debug/testJ2objc').absolutePath,
proj.file('build/j2objcTest/Debug/testJ2objc').absolutePath,
"org.junit.runner.JUnitCore",
],
'OK (1 test)', // NOTE: 'test' is singular for stdout
Expand All @@ -236,7 +236,7 @@ class TestTaskTest {
mockProjectExec.demandExecAndReturn(
null,
[
proj.file('build/j2objcTest/debug/testJ2objc').absolutePath,
proj.file('build/j2objcTest/Debug/testJ2objc').absolutePath,
"org.junit.runner.JUnitCore",
],
'IGNORE\nOK (2 tests)\nIGNORE', // stdout
Expand All @@ -257,7 +257,7 @@ class TestTaskTest {
mockProjectExec.demandExecAndReturn(
null,
[
proj.file('build/j2objcTest/debug/testJ2objc').absolutePath,
proj.file('build/j2objcTest/Debug/testJ2objc').absolutePath,
"org.junit.runner.JUnitCore",
],
'OK (2 testXXXX)', // NOTE: invalid stdout fails matchRegexOutputs
Expand All @@ -272,16 +272,16 @@ class TestTaskTest {
private void demandCopyForJ2objcTest(MockProjectExec mockProjectExec) {
// Delete test directory
mockProjectExec.demandDeleteAndReturn(
proj.file('build/j2objcTest/debug').absolutePath)
proj.file('build/j2objcTest/Debug').absolutePath)
// Copy main resources, test resources and test binary to test directory
mockProjectExec.demandMkDirAndReturn(
proj.file('build/j2objcTest/debug').absolutePath)
proj.file('build/j2objcTest/Debug').absolutePath)
mockProjectExec.demandCopyAndReturn(
proj.file('build/j2objcTest/debug').absolutePath,
proj.file('build/j2objcTest/Debug').absolutePath,
proj.file('src/main/resources').absolutePath,
proj.file('src/test/resources').absolutePath)
mockProjectExec.demandCopyAndReturn(
proj.file('build/j2objcTest/debug').absolutePath,
proj.file('build/j2objcTest/Debug').absolutePath,
proj.file('build/binaries/testJ2objcExecutable/debug/testJ2objc').absolutePath)
}

Expand Down
8 changes: 4 additions & 4 deletions systemTests/multiProject1/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ EXTERNAL SOURCES:
:path: ../extended/build

SPEC CHECKSUMS:
j2objc-base-debug: d6324af485dfb6c80ea99bf2efb69ae70966b10e
j2objc-base-release: d769f0c555c8c5d1be0f775920c51f01c74f23dd
j2objc-extended-debug: 6ea07587317140c13f85c24e8aa172349174f640
j2objc-extended-release: 24d25ad17f44675a51cd0609dc5b996dbd2981b8
j2objc-base-debug: 478bb2f19db54654adc8cc3e606914adaacaef5c
j2objc-base-release: 65381df5900d9be5b05afd7d41580d1e98ce1dee
j2objc-extended-debug: ea5b498adb5bfe52c3126b90d16a1dfcbc9f2af4
j2objc-extended-release: 9c2696a59c8e50aeed6d40bb661574cd1b833c52

COCOAPODS: 0.38.2