Skip to content

Commit

Permalink
j2objcXcode now dependency of j2objcBuild
Browse files Browse the repository at this point in the history
- j2objcbuild depends on j2objcXcode, which depends on j2objcAssemble
- j2objcXcode @input for project dependencies
- j2objcXcode skips task if xcodeProjectDir is not set
  • Loading branch information
brunobowden committed Oct 21, 2015
1 parent 8f95dd5 commit 3b087fb
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 97 deletions.
15 changes: 4 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ plugins {
// Plugin settings:
j2objcConfig {
// Xcode project directory (suggested directory name)
xcodeProjectDir '../ios'
xcodeProjectDir '../ios' // suggested directory name
xcodeTargetsIos 'IOS-APP', 'IOS-APPTests' // replace with your iOS targets
finalConfigure() // Must be last call to configuration
}
```

Info on additional `j2objcConfig` settings are in
[J2objcConfig.groovy](https://github.com/j2objc-contrib/j2objc-gradle/blob/master/src/main/groovy/com/github/j2objccontrib/j2objcgradle/J2objcConfig.groovy#L30).
The default will link the transpiled code in to all of your Xcode build targets. To specify
a subset, add a line for `xcodeTargets 'IOS-APP', 'IOS-APP-TESTS', 'WATCHKIT-APP', ...`.
The Xcode targets may also be set for xcodeTargetsOsx and xcodeTargetsWatchos
([issue #525 to get watchOS working](https://github.com/j2objc-contrib/j2objc-gradle/issues/525)).
If your `shared` project depends on any other projects or third-party libraries, you may
need to [add them manually](FAQ.md#how-do-i-setup-dependencies-with-j2objc) if they aren't
[linked by default](FAQ.md#what-libraries-are-linked-by-default).
Expand Down Expand Up @@ -98,13 +98,6 @@ be run as follows:

./gradlew shared:build

During development, to build the libraries and update Xcode (skipping the tests):

./gradlew shared:j2objcXcode

For a complete build, run both:

./gradlew shared:build shared:j2objcXcode

### Problems

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,21 +268,20 @@ class J2objcPlugin implements Plugin<Project> {
group 'build'
description "Marker task for all release tasks that take part in regular j2objc builds"
}
// Xcode
tasks.create(name: 'j2objcXcode', type: XcodeTask,
dependsOn: 'j2objcAssemble') {
group 'build'
description 'Depends on j2objc translation, create a Pod file link it to Xcode project'
}
// If users need to depend on this project to build other j2objc projects, they can use this
// marker task.
tasks.create(name: 'j2objcBuild', type: DefaultTask,
dependsOn: ['j2objcBuildDebug', 'j2objcBuildRelease']) {
dependsOn: ['j2objcBuildDebug', 'j2objcBuildRelease', 'j2objcXcode']) {
group 'build'
description "Marker task for all tasks that take part in regular j2objc builds"
}
lateDependsOn(project, 'build', 'j2objcBuild')

// TODO: Where shall we fit this task in the plugin lifecycle?
tasks.create(name: 'j2objcXcode', type: XcodeTask,
dependsOn: 'j2objcAssemble') {
// This is not in the build group because you do not need to do it on every build.
description 'Depends on j2objc translation, create a Pod file link it to Xcode project'
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ class XcodeTask extends DefaultTask {
@Input @Optional
String getXcodeProjectDir() { return J2objcConfig.from(project).xcodeProjectDir }

boolean isTaskActive() { return getXcodeProjectDir() != null }

@Input
// List of all dependencies
List<PodspecDetails> getPodspecDependencies() {
if (!isTaskActive()) {
// Optimization for only calculating dependencies where needed
return []
}
getPodspecDependencies(getProject(), new HashSet<Project>())
}

@Input
List<String> getXcodeTargetsIos() { return J2objcConfig.from(project).xcodeTargetsIos }
@Input
Expand All @@ -69,7 +81,6 @@ class XcodeTask extends DefaultTask {

@OutputFile
File getPodfileFile() {
verifyXcodeArgs()
return project.file(new File(getXcodeProjectDir(), '/Podfile'))
}

Expand Down Expand Up @@ -114,7 +125,25 @@ class XcodeTask extends DefaultTask {
void xcodeConfig() {
Utils.requireMacOSX('j2objcXcode task')

verifyXcodeArgs()
if (!isTaskActive()) {
logger.debug("j2objcXcode task disabled for ${project.name}")
return
}

// // TODO: figure out how to display error when not configured on root project
// String message =
// "xcodeProjectDir need to be configured in ${project.name}'s build.gradle.\n" +
// "The directory should point to the location containing your Xcode project,\n" +
// "including the IOS-APP.xccodeproj file.\n" +
// "\n" +
// "j2objcConfig {\n" +
// " xcodeProjectDir '../ios'\n" +
// "}\n" +
// "\n" +
// "Alternatively disable the j2objcXcode task if you wish to do your own Xcode build.\n"
// "Also see the guidelines for the folder structure:\n" +
// "https://github.com/j2objc-contrib/j2objc-gradle/blob/master/FAQ.md#what-is-the-recommended-folder-structure-for-my-app\n"
// throw new InvalidUserDataException(message)

// link the podspec in pod file
File podfile = getPodfileFile()
Expand All @@ -129,8 +158,8 @@ class XcodeTask extends DefaultTask {
"To fix this:\n" +
"\n" +
"1) Set xcodeProjectDir to the directory containing 'IOS-APP.xcodeproj':\n" +
" current value from j2objcConfig: ${getXcodeProjectDir()}\n" +
" current value for absolute path: $xcodeAbsPath\n" +
" curent value: ${getXcodeProjectDir()}\n" +
" resolves to: $xcodeAbsPath\n" +
"\n" +
"2) Within that directory, create the Podfile with:\n" +
" (cd $xcodeAbsPath && pod init)\n" +
Expand All @@ -142,8 +171,7 @@ class XcodeTask extends DefaultTask {
logger.debug("Pod exists at path: ${getXcodeProjectDir()}")

// Write Podfile based on all the podspecs from dependent projects
List<PodspecDetails> podspecDetailsList =
getPodspecsFromProject(getProject(), new HashSet<Project>())
List<PodspecDetails> podspecDetailsList = getPodspecDependencies()

XcodeTargetDetails xcodeTargetDetails = new XcodeTargetDetails(
getXcodeTargetsIos(), getXcodeTargetsOsx(), getXcodeTargetsWatchos(),
Expand Down Expand Up @@ -196,7 +224,8 @@ class XcodeTask extends DefaultTask {
* @return List of Files corresponding to debug / release pair of podspecs
* Even entries in the list are debug podspecs, odd for release podspecs
*/
private List<PodspecDetails> getPodspecsFromProject(Project proj, Set<Project> visitedProjects) {
@VisibleForTesting
List<PodspecDetails> getPodspecDependencies(Project proj, Set<Project> visitedProjects) {

// Find podspecs generated by this project
List<PodspecDetails> podspecs = new ArrayList<>()
Expand All @@ -211,30 +240,12 @@ class XcodeTask extends DefaultTask {

J2objcConfig j2objcConfig = proj.getExtensions().getByType(J2objcConfig)
j2objcConfig.getBeforeProjects().each { Project beforeProject ->
podspecs.addAll(getPodspecsFromProject(beforeProject, visitedProjects))
podspecs.addAll(getPodspecDependencies(beforeProject, visitedProjects))
}

return podspecs
}

@VisibleForTesting
void verifyXcodeArgs() {
if (getXcodeProjectDir() == null) {
String message =
"xcodeProjectDir need to be configured in ${project.name}'s build.gradle.\n" +
"The directory should point to the location containing your Xcode project,\n" +
"including the IOS-APP.xccodeproj file.\n" +
"\n" +
"j2objcConfig {\n" +
" xcodeProjectDir '../ios'\n" +
"}\n" +
"\n" +
"Also see the guidelines for the folder structure:\n" +
"https://github.com/j2objc-contrib/j2objc-gradle/blob/master/FAQ.md#what-is-the-recommended-folder-structure-for-my-app"
throw new InvalidUserDataException(message)
}
}

/**
* Extracts xcode targets in Podfile.
*/
Expand Down Expand Up @@ -355,7 +366,7 @@ class XcodeTask extends DefaultTask {
List<String> newPodfileLines = new ArrayList<String>(oldPodfileLines)

newPodfileLines = updatePodfile(
newPodfileLines, podspecDetailsList, xcodeTargetDetails, podfile, logger)
newPodfileLines, podspecDetailsList, xcodeTargetDetails, podfile)

// Write file only if it's changed
if (!oldPodfileLines.equals(newPodfileLines)) {
Expand All @@ -368,7 +379,7 @@ class XcodeTask extends DefaultTask {
List<String> podfileLines,
List<PodspecDetails> podspecDetailsList,
XcodeTargetDetails xcodeTargetDetails,
File podfile, Logger logger) {
File podfile) {

List<String> podfileTargets = extractXcodeTargets(podfileLines)
verifyTargets(xcodeTargetDetails.xcodeTargetsIos, podfileTargets, 'xcodeTargetsIos')
Expand All @@ -378,7 +389,7 @@ class XcodeTask extends DefaultTask {
if (xcodeTargetDetails.xcodeTargetsIos.isEmpty() &&
xcodeTargetDetails.xcodeTargetsOsx.isEmpty() &&
xcodeTargetDetails.xcodeTargetsWatchos.isEmpty()) {
// Need to warn about configuring
// Give example for configuring iOS as that's the common case
throw new InvalidUserDataException(
"You must configure the xcode targets for the J2ObjC Gradle Plugin.\n" +
"It must be a subset of the valid targets: '${podfileTargets.join("', '")}'\n" +
Expand All @@ -393,9 +404,8 @@ class XcodeTask extends DefaultTask {
// update pod methods
List<String> newPodfileLines = updatePodMethods(podfileLines, podspecDetailsList, podfile)

// Iterate over all podfileTargets as some may need to be cleared
newPodfileLines = updatePodfileTargets(
newPodfileLines, podspecDetailsList, xcodeTargetDetails)
// update pod targets
newPodfileLines = updatePodfileTargets(newPodfileLines, podspecDetailsList, xcodeTargetDetails)

return newPodfileLines
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,12 @@ class XcodeTaskTest {
j2objcConfig.xcodeTargetsIos = ['IOS-APP']

XcodeTask j2objcXcode = (XcodeTask) proj.tasks.create(name: 'j2objcXcode', type: XcodeTask)
j2objcXcode.verifyXcodeArgs()
File podfile = j2objcXcode.getPodfileFile()

String expectedPath = proj.file('../ios/Podfile').absolutePath
assert expectedPath == podfile.absolutePath
}

// Test that null xcode arguments cause the expected exception
@Test(expected = InvalidUserDataException.class)
void getPodfileFile_Invalid() {
J2objcConfig j2objcConfig =
proj.extensions.create('j2objcConfig', J2objcConfig, proj)
assert null == j2objcConfig.xcodeProjectDir
assert 0 == j2objcConfig.xcodeTargetsIos.size()

XcodeTask j2objcXcode = (XcodeTask) proj.tasks.create(name: 'j2objcXcode', type: XcodeTask)

// Test for fixing issue #226
j2objcXcode.getPodfileFile()
}

@Test
void testXcodeConfig_Windows() {
Utils.setFakeOSWindows()
Expand Down Expand Up @@ -223,26 +208,6 @@ class XcodeTaskTest {
mockProjectExec.verify()
}

@Test
void testVerifyXcodeArgs() {
Object unused
J2objcConfig j2objcConfig
(proj, unused, j2objcConfig) =
TestingUtils.setupProject(new TestingUtils.ProjectConfig(
applyJavaPlugin: true,
createJ2objcConfig: true))
assert null == j2objcConfig.xcodeProjectDir
assert 0 == j2objcConfig.xcodeTargetsIos.size()

XcodeTask j2objcXcode = (XcodeTask) proj.tasks.create(name: 'j2objcXcode', type: XcodeTask)

// Expect exception suggesting to configure j2objcConfig:
expectedException.expect(InvalidUserDataException.class)
expectedException.expectMessage("xcodeProjectDir '../ios'")

j2objcXcode.verifyXcodeArgs()
}

@Test
void testExtractXcodeTargets_Simple() {
List<String> podfileLines = [
Expand Down Expand Up @@ -469,8 +434,7 @@ class XcodeTaskTest {
podfileLines,
podspecDetailsProj,
xcodeTargetDetailsIosAppOnly,
new File('/SRC/ios/Podfile'),
null)
new File('/SRC/ios/Podfile'))

List<String> expectedPodfileLines = [
"# J2ObjC Gradle Plugin - DO NOT MODIFY from here to the first target",
Expand All @@ -490,8 +454,7 @@ class XcodeTaskTest {
newPodfileLines,
podspecDetailsProj,
xcodeTargetDetailsIosAppOnly,
new File('/SRC/ios/Podfile'),
null)
new File('/SRC/ios/Podfile'))
assert expectedPodfileLines == newPodfileLines
}

Expand All @@ -515,8 +478,7 @@ class XcodeTaskTest {
podfileLines,
podspecDetailsProj,
xcodeTargetDetails,
new File('/SRC/ios/Podfile'),
null)
new File('/SRC/ios/Podfile'))

List<String> expectedPodfileLines = [
"# user comment",
Expand Down Expand Up @@ -546,8 +508,7 @@ class XcodeTaskTest {
newPodfileLines,
podspecDetailsProj,
xcodeTargetDetails,
new File('/SRC/ios/Podfile'),
null)
new File('/SRC/ios/Podfile'))
assert expectedPodfileLines == newPodfileLines
}

Expand All @@ -570,7 +531,6 @@ class XcodeTaskTest {
new XcodeTask.XcodeTargetDetails(
[], [], [],
'6.0.0', '10.4.0', '1.0.0'),
null,
null)
}

Expand All @@ -592,7 +552,6 @@ class XcodeTaskTest {
new XcodeTask.XcodeTargetDetails(
['TARGET-DOES-NOT-EXIST'], [], [],
'6.0.0', '10.4.0', '1.0.0'),
null,
null)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ public class ExampleUnitTest {
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
}

0 comments on commit 3b087fb

Please sign in to comment.