
de.felixschulze.maven.plugins.xcode.XcodeBuildMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xcode-maven-plugin Show documentation
Show all versions of xcode-maven-plugin Show documentation
A maven build plugin for iOS continuous integration builds
/*
* Copyright (C) 2012 Felix Schulze
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.felixschulze.maven.plugins.xcode;
import java.io.*;
import java.util.*;
import de.felixschulze.maven.plugins.xcode.helper.GitHelper;
import de.felixschulze.maven.plugins.xcode.helper.TeamCityHelper;
import de.felixschulze.maven.plugins.xcode.xcodeprojparser.PBXNativeTarget;
import de.felixschulze.maven.plugins.xcode.xcodeprojparser.PBXProject;
import de.felixschulze.maven.plugins.xcode.xcodeprojparser.XCBuildConfiguration;
import de.felixschulze.maven.plugins.xcode.xcodeprojparser.XcodeprojParser;
import org.apache.maven.plugin.MojoExecutionException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.json.JSONException;
import xmlwise.Plist;
import xmlwise.XmlParseException;
/**
* Run the xcodebuild command line program
*
* @goal xcodebuild
* @phase compile
* @author Felix Schulze
*/
public class XcodeBuildMojo extends AbstractXcodeMojo {
private final String BUNDLE_IDENTIFIER_KEY = "CFBundleIdentifier";
private final String BUNDLE_DISPLAY_NAME_KEY = "CFBundleDisplayName";
private final String BUNDLE_VERSION_KEY = "CFBundleVersion";
private final String INTERFACE_BUILDER_ERROR = "Interface Builder encountered an error communicating with the iOS Simulator.";
private final String COMPILE_XIB_ERROR = "CompileXIB";
private final String IBTOOL_ERROR = "Exception while running ibtool: connection went invalid while waiting for a reply because a mach port died";
/**
* Execute the xcode command line utility.
*/
public void execute() throws MojoExecutionException {
if (!xcodeCommandLine.exists()) {
throw new MojoExecutionException("Invalid path for xcodebuild: " + xcodeCommandLine.getAbsolutePath());
}
if (!buildDirectory.exists()) {
buildDirectory.mkdir();
}
CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
executor.setLogger(this.getLog());
List commands = new ArrayList();
//Parse XCode project (only for testing)
if (xcodeProject != null) {
if (!plutilCommandLine.exists()) {
throw new MojoExecutionException("Invalid path for plutil: " + plutilCommandLine.getAbsolutePath());
}
File xcodeprojJson = new File(buildDirectory, xcodeProject.getName() + ".json");
commands.add("-convert");
commands.add("json");
commands.add("-o");
commands.add(xcodeprojJson.getAbsolutePath());
commands.add(xcodeProject.getAbsolutePath() + "/project.pbxproj");
getLog().info(plutilCommandLine.getAbsolutePath() + " " + commands.toString());
try {
executor.executeCommand(plutilCommandLine.getAbsolutePath(), commands, false);
} catch (ExecutionException e) {
throw new MojoExecutionException("Error while executing: ", e);
}
if (xcodeprojJson.exists()) {
XcodeprojParser parser = new XcodeprojParser(xcodeprojJson);
try {
PBXProject project = parser.parseXcodeFile();
if (project != null) {
for (PBXNativeTarget target : project.getTargets()) {
if (target.getName().equalsIgnoreCase(xcodeTarget)) {
getLog().info("=== PBXNativeTarget ===");
getLog().info(" Target-Name: " + target.getName());
getLog().info(" App-Name: " + target.getAppName());
getLog().info(" Product-Name: " + target.getProductName());
getLog().info(" Type: " + target.getType());
for (XCBuildConfiguration buildConfiguration : target.getBuildConfigurations()) {
if (buildConfiguration.getName().equalsIgnoreCase(xcodeConfiguration)) {
getLog().info("==== XCBuildConfiguration ====");
getLog().info(" Name: " + buildConfiguration.getName());
getLog().info(" InfoPlist: " + buildConfiguration.getInfoPlist().getPath());
}
}
}
}
}
} catch (IOException e) {
throw new MojoExecutionException("Error while executing: ", e);
} catch (JSONException e) {
throw new MojoExecutionException("Error while executing: ", e);
}
}
}
commands = new ArrayList();
if (xcodeProject != null) {
commands.add("-project");
commands.add(xcodeProject.getAbsolutePath());
}
if (xcodeTarget != null) {
commands.add("-target");
commands.add(xcodeTarget);
}
if (xcodeConfiguration != null) {
commands.add("-configuration");
commands.add(xcodeConfiguration);
}
if (xcodeSdk != null) {
commands.add("-sdk");
commands.add(xcodeSdk);
}
commands.add("OBJROOT=" + buildDirectory);
commands.add("SYMROOT=" + buildDirectory);
commands.add("DSTROOT=" + buildDirectory);
if (provisioningProfile != null) {
commands.add("PROVISIONING_PROFILE=\"" + provisioningProfile + "\"");
}
if (codeSignIdentity != null) {
commands.add("CODE_SIGN_IDENTITY=" + codeSignIdentity);
}
if (infoPlist != null) {
changesValuesInPlist();
}
getLog().info(xcodeCommandLine.getAbsolutePath() + " " + commands.toString());
try {
executor.executeCommand(xcodeCommandLine.getAbsolutePath(), commands, false);
} catch (ExecutionException e) {
String errorString = executor.getStandardError();
String outPutString = executor.getStandardOut();
String cleanedErrorString = errorString.substring(errorString.indexOf("** BUILD FAILED **"));
if (errorString.contains(INTERFACE_BUILDER_ERROR) || errorString.contains(IBTOOL_ERROR)
|| outPutString.contains(INTERFACE_BUILDER_ERROR) || outPutString.contains(IBTOOL_ERROR)) {
if (teamCityLog) {
getLog().error("##teamcity[buildStatus status='FAILURE' text='Interface builder crashed']");
}
getLog().error("Interface builder crashed.");
} else {
if (teamCityLog) {
if (cleanedErrorString != null) {
getLog().error("##teamcity[message text='BUILD FAILED' errorDetails='" + TeamCityHelper.escapeString(cleanedErrorString) + "' status='ERROR']");
if (cleanedErrorString.contains(COMPILE_XIB_ERROR)) {
getLog().error("##teamcity[buildStatus status='FAILURE' text='Interface builder crashed']");
} else {
getLog().error("##teamcity[buildStatus status='FAILURE' text='Build failed']");
}
}
}
}
throw new MojoExecutionException("Error while executing: ", e);
}
}
private void changesValuesInPlist() {
try {
Map properties = Plist.load(infoPlist);
Boolean changeInPlist = false;
if (bundleIdentifierSuffix != null) {
if (properties.containsKey(BUNDLE_IDENTIFIER_KEY)) {
String identifier = String.valueOf(properties.get(BUNDLE_IDENTIFIER_KEY));
if (!identifier.endsWith(bundleIdentifierSuffix)) {
getLog().info("Add suffix: \"" + bundleIdentifierSuffix + "\" for: \"" + BUNDLE_IDENTIFIER_KEY + "\"");
identifier = identifier.concat(bundleIdentifierSuffix);
changeInPlist = true;
properties.put(BUNDLE_IDENTIFIER_KEY, identifier);
}
}
}
if (bundleDisplayNameSuffix != null) {
if (properties.containsKey(BUNDLE_DISPLAY_NAME_KEY)) {
String displayName = String.valueOf(properties.get(BUNDLE_DISPLAY_NAME_KEY));
if (!displayName.endsWith(bundleDisplayNameSuffix)) {
getLog().info("Add suffix: \"" + bundleDisplayNameSuffix + "\" for: \"" + BUNDLE_DISPLAY_NAME_KEY + "\"");
displayName = displayName.concat(bundleDisplayNameSuffix);
changeInPlist = true;
properties.put(BUNDLE_DISPLAY_NAME_KEY, displayName);
}
}
}
if (bundleVersionFromGit) {
if (properties.containsKey(BUNDLE_VERSION_KEY)) {
try {
File gitDir = new File(basedir, ".git");
if (gitDir.exists()) {
GitHelper gitHelper = new GitHelper(gitDir);
int numberOfCommits = gitHelper.numberOfCommits();
String uniqueShortId = gitHelper.currentHeadRef();
if (numberOfCommits > 0 && uniqueShortId != null) {
String version = String.valueOf(properties.get(BUNDLE_VERSION_KEY));
String versionSuffix = "-" + numberOfCommits + "-" + uniqueShortId;
if (!version.contains(versionSuffix)) {
version = version.concat(versionSuffix);
getLog().info("Change version to: " + version);
changeInPlist = true;
properties.put(BUNDLE_VERSION_KEY, version);
}
if (teamCityLog) {
getLog().info(TeamCityHelper.createVersionLog(version));
}
}
}
} catch (GitAPIException e) {
getLog().warn("Error while getting version number from git: " + e);
}
}
}
if (changeInPlist) {
Plist.store(properties, infoPlist);
}
} catch (XmlParseException e) {
getLog().warn("Error while parsing plist: " + e);
} catch (IOException e) {
getLog().warn("Can't find plist: " + e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy