Skip to content

Commit

Permalink
JENKINS-34998: Make CMake plugin compatible with pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
15knots committed May 21, 2016
1 parent ebd210e commit e95ede2
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 54 deletions.
3 changes: 0 additions & 3 deletions src/main/java/hudson/plugins/cmake/AbstractCmakeBuilder.java
Expand Up @@ -27,9 +27,6 @@ public abstract class AbstractCmakeBuilder extends Builder {
* @param installationName
* the name of the cmake tool installation from the global config
* page.
* @param generator
* the name of cmake´s buildscript generator. May be empty but
* not {@code null}
*/
public AbstractCmakeBuilder(String installationName) {
this.installationName = Util.fixEmptyAndTrim(installationName);
Expand Down
63 changes: 47 additions & 16 deletions src/main/java/hudson/plugins/cmake/CToolBuilder.java
Expand Up @@ -2,6 +2,8 @@

import java.io.IOException;

import javax.annotation.Nonnull;

import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

Expand All @@ -11,18 +13,24 @@
import hudson.Launcher;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.ModelObject;
import hudson.model.Node;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.ArgumentListBuilder;
import hudson.util.ListBoxModel;
import jenkins.tasks.SimpleBuildStep;

/**
* Provides a build step that allows to invoke selected tools of the cmake-suite
* ({@code cmake}, {@code cpack} and {@code ctest}) with arbitrary arguments.
*
* @author Martin Weber
*/
public class CToolBuilder extends AbstractCmakeBuilder {
public class CToolBuilder extends AbstractCmakeBuilder
implements SimpleBuildStep {
/** the ID of the tool in the CMake-suite to invoke {@link Tool}. */
private String toolId;

Expand Down Expand Up @@ -74,23 +82,46 @@ public String getArguments() {
return super.getArguments();
}

public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workSpace,
@Nonnull Launcher launcher, @Nonnull TaskListener listener)
throws InterruptedException, IOException {

CmakeTool installToUse = getSelectedInstallation();
// Raise an error if the cmake installation isn't found
if (installToUse == null) {
listener.fatalError("There is no CMake installation selected."
+ " Please review the build step configuration.");
return false;
run.setResult(Result.FAILURE);
return;
}
{
final Computer compi = workSpace.toComputer();
if (compi == null) {
listener.fatalError("Workspace %1s does not exist.",
workSpace.getRemote());
run.setResult(Result.FAILURE);
return;
}
final Node node = compi.getNode();
if (node == null) {
listener.fatalError("Node for workspace %1s does not exist.",
workSpace.getRemote());
run.setResult(Result.FAILURE);
return;
}
// Get the CMake version for this node, installing it if necessary
installToUse = (CmakeTool) installToUse.translate(node,
EnvVars.getRemote(compi.getChannel()), listener);
}
final EnvVars envs = build.getEnvironment(listener);
envs.overrideAll(build.getBuildVariables());
final String cmakeBin = installToUse.getCmakeExe();

// Get the CMake version for this node, installing it if necessary
installToUse = (CmakeTool) installToUse.translate(build, listener);
final EnvVars envs = run.getEnvironment(listener);
if (run instanceof AbstractBuild) {
// NOT running as a pipeline step, expand variables.
// (Take any value literally, if in pipeline step.)
envs.overrideAll(((AbstractBuild<?, ?>) run).getBuildVariables());
}

final String cmakeBin = installToUse.getCmakeExe();
// strip off the last path segment (usually 'cmake')
String bindir;
{
Expand All @@ -111,27 +142,27 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,

try {
/* Determine remote working directory path. Create it. */
final FilePath workSpace = build.getWorkspace();
final String workDir = getWorkingDir();
final FilePath theWorkDir = makeRemotePath(workSpace,
Util.replaceMacro(workDir, envs));
envs.expand(workDir));
if (workDir != null) {
theWorkDir.mkdirs();
}

/* Invoke tool in working dir */
ArgumentListBuilder cmakeCall = buildToolCall(bindir + getToolId(),
Util.replaceMacro(getArguments(), envs));
envs.expand(getArguments()));
if (0 != launcher.launch().pwd(theWorkDir).envs(envs)
.stdout(listener).cmds(cmakeCall).join()) {
return false; // invocation failed
run.setResult(Result.FAILURE);
return; // invocation failed
}
} catch (IOException e) {
Util.displayIOException(e, listener);
listener.error(e.getLocalizedMessage());
return false;
run.setResult(Result.FAILURE);
return;
}
return true;
}

/**
Expand Down
105 changes: 70 additions & 35 deletions src/main/java/hudson/plugins/cmake/CmakeBuilder.java
Expand Up @@ -4,6 +4,7 @@
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nonnull;
import javax.servlet.ServletException;

import org.kohsuke.stapler.AncestorInPath;
Expand All @@ -18,18 +19,25 @@
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Environment;
import hudson.model.Job;
import hudson.model.Node;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.ArgumentListBuilder;
import hudson.util.FormValidation;
import jenkins.tasks.SimpleBuildStep;

/**
* Executes <tt>cmake</tt> as a build step.
*
* @author Volker Kaiser (initial implementation)
* @author Martin Weber
*/
public class CmakeBuilder extends AbstractCmakeBuilder {
public class CmakeBuilder extends AbstractCmakeBuilder
implements SimpleBuildStep {

/**
* the key for the build variable that holds the build tool that the
Expand All @@ -48,7 +56,7 @@ public class CmakeBuilder extends AbstractCmakeBuilder {
private String preloadScript;
private boolean cleanBuild;

// for backward compatibility with < 2.4.9
// for backward compatibility with < 2.4.0
// see
// https://wiki.jenkins-ci.org/display/JENKINS/Hint+on+retaining+backward+compatibility
private transient String buildDir;
Expand Down Expand Up @@ -195,31 +203,53 @@ public List<BuildToolStep> getSteps() {
return toolSteps;
}

public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workSpace,
@Nonnull Launcher launcher, @Nonnull TaskListener listener)
throws InterruptedException, IOException {

CmakeTool installToUse = getSelectedInstallation();
// Raise an error if the cmake installation isn't found
if (installToUse == null) {
listener.fatalError("There is no CMake installation selected."
+ " Please review the build step configuration.");
return false;
run.setResult(Result.FAILURE);
return;
}
{
final Computer compi = workSpace.toComputer();
if (compi == null) {
listener.fatalError("Workspace %1s does not exist.",
workSpace.getRemote());
run.setResult(Result.FAILURE);
return;
}
final Node node = compi.getNode();
if (node == null) {
listener.fatalError("Node for workspace %1s does not exist.",
workSpace.getRemote());
run.setResult(Result.FAILURE);
return;
}
// Get the CMake version for this node, installing it if necessary
installToUse = (CmakeTool) installToUse.translate(node,
EnvVars.getRemote(compi.getChannel()), listener);
}
final EnvVars envs = build.getEnvironment(listener);
envs.overrideAll(build.getBuildVariables());

// Get the CMake version for this node, installing it if necessary
installToUse = (CmakeTool) installToUse.translate(build, listener);

final String cmakeBin = installToUse.getCmakeExe();
final FilePath workSpace = build.getWorkspace();

final EnvVars envs = run.getEnvironment(listener);
if (run instanceof AbstractBuild) {
// NOT running as a pipeline step, expand variables.
// (Take any value literally, if in pipeline step.)
envs.overrideAll(((AbstractBuild<?, ?>) run).getBuildVariables());
}
try {
/*
* Determine remote build directory path. Clean it, if requested.
* Create it.
*/
final String buildDir = getWorkingDir();
FilePath theBuildDir = makeRemotePath(workSpace,
Util.replaceMacro(buildDir, envs));
envs.expand(buildDir));
if (buildDir != null) {
if (this.cleanBuild && !buildDir.equals(sourceDir)) {
// avoid deleting source dir
Expand All @@ -232,16 +262,16 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,

/* Invoke cmake in build dir */
FilePath theSourceDir = makeRemotePath(workSpace,
Util.replaceMacro(sourceDir, envs));
envs.expand(sourceDir));
ArgumentListBuilder cmakeCall = buildCMakeCall(cmakeBin,
Util.replaceMacro(getGenerator(), envs),
Util.replaceMacro(this.preloadScript, envs), theSourceDir,
Util.replaceMacro(this.buildType, envs),
Util.replaceMacro(getCmakeArgs(), envs));
envs.expand(getGenerator()),
envs.expand(this.preloadScript), theSourceDir,
envs.expand(this.buildType), envs.expand(getCmakeArgs()));
// invoke cmake
if (0 != launcher.launch().pwd(theBuildDir).envs(envs)
.stdout(listener).cmds(cmakeCall).join()) {
return false; // invocation failed
run.setResult(Result.FAILURE);
return;
}

/* parse CMakeCache.txt to get the actual build tool */
Expand All @@ -255,13 +285,16 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
} else {
// add CMAKE_BUILD_TOOL variable for toolSteps
envs.put(CmakeBuilder.ENV_VAR_NAME_CMAKE_BUILD_TOOL, buildTool);
// add CMAKE_BUILD_TOOL to env for other build-steps
EnvVars exportedEnvVars = new EnvVars();
exportedEnvVars.put(CmakeBuilder.ENV_VAR_NAME_CMAKE_BUILD_TOOL,
buildTool);
// export environment
build.getEnvironments()
.add(Environment.create(exportedEnvVars));
if (run instanceof AbstractBuild) {
// add CMAKE_BUILD_TOOL to env for other build-steps
EnvVars exportedEnvVars = new EnvVars();
exportedEnvVars.put(
CmakeBuilder.ENV_VAR_NAME_CMAKE_BUILD_TOOL,
buildTool);
// export environment
((AbstractBuild<?, ?>) run).getEnvironments()
.add(Environment.create(exportedEnvVars));
}
}

/* invoke each build tool step in build dir */
Expand All @@ -271,9 +304,8 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
// invoke directly
// if buildTool == null, let the unexpanded macro show up in
// the log
final String buildToolMacro = Util.replaceMacro("${"
+ CmakeBuilder.ENV_VAR_NAME_CMAKE_BUILD_TOOL + "}",
envs);
final String buildToolMacro = envs.expand("${"
+ CmakeBuilder.ENV_VAR_NAME_CMAKE_BUILD_TOOL + "}");
toolCall = buildBuildToolCall(buildToolMacro,
step.getCommandArguments(envs));
} else {
Expand All @@ -285,15 +317,16 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
.overrideAll(step.getEnvironmentVars(envs, listener));
if (0 != launcher.launch().pwd(theBuildDir).envs(stepEnv)
.stdout(listener).cmds(toolCall).join()) {
return false; // invocation failed
run.setResult(Result.FAILURE);
return;
}
}
} catch (IOException e) {
Util.displayIOException(e, listener);
listener.error(e.getLocalizedMessage());
return false;
run.setResult(Result.FAILURE);
return;
}
return true;
}

/**
Expand Down Expand Up @@ -431,10 +464,12 @@ public String getDisplayName() {
* @param value
*/
public FormValidation doCheckSourceDir(
@AncestorInPath AbstractProject<?, ?> project,
@AncestorInPath Job<?, ?> project,
@QueryParameter final String value)
throws IOException, ServletException {
FilePath ws = project.getSomeWorkspace();
FilePath ws = project instanceof AbstractProject<?, ?>
? ((AbstractProject<?, ?>) project).getSomeWorkspace()
: null;
if (ws == null)
return FormValidation.ok();
return ws.validateRelativePath(value, false, false);
Expand Down

0 comments on commit e95ede2

Please sign in to comment.