/*******************************************************************************
* Copyright (c) 2000, 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136)
*******************************************************************************/
package org.eclipse.cdt.make.internal.core;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.make.core.IMakeBuilderInfo;
import org.eclipse.cdt.make.core.IMakeCommonBuildInfo;
import org.eclipse.cdt.make.core.IMakeTarget;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.osgi.service.environment.Constants;
public class MakeTarget extends PlatformObject implements IMakeTarget {
private final static int USE_PROJECT_ENV_SETTING = 3;
private final MakeTargetManager manager;
private final IProject project;
private String name;
private boolean isDefaultBuildCmd;
private boolean isStopOnError;
boolean runAllBuidlers = true;
private final String targetBuilderID;
private IContainer container;
private int appendEnvironment = USE_PROJECT_ENV_SETTING;
private boolean appendProjectEnvironment = true;
private Map<String, String> buildEnvironment = new HashMap<>();
private final Map<String, String> targetAttributes = new HashMap<>();
public MakeTarget(MakeTargetManager manager, IProject project, String targetBuilderID, String name) throws CoreException {
this.manager = manager;
this.project = project;
this.targetBuilderID = targetBuilderID;
this.name = name;
IMakeBuilderInfo info = MakeCorePlugin.createBuildInfo(project, manager.getBuilderID(targetBuilderID));
setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, info.getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, "make")); //$NON-NLS-1$
setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, info.getBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, "")); //$NON-NLS-1$
isDefaultBuildCmd = info.isDefaultBuildCmd();
isStopOnError = info.isStopOnError();
}
@Override
public IProject getProject() {
return project;
}
@Override
public void setContainer(IContainer container) {
this.container = container;
}
@Override
public void setName(String name) {
this.name = name;
}
Map<String, String> getAttributeMap() {
return targetAttributes;
}
@Override
public String getName() {
return name;
}
@Override
public String getTargetBuilderID() {
return targetBuilderID;
}
@Override
public boolean isStopOnError() {
return isStopOnError;
}
@Override
public void setStopOnError(boolean stopOnError) throws CoreException {
isStopOnError = stopOnError;
manager.updateTarget(this);
}
@Override
public boolean isDefaultBuildCmd() {
return isDefaultBuildCmd;
}
@Override
public void setUseDefaultBuildCmd(boolean useDefault) throws CoreException {
isDefaultBuildCmd = useDefault;
manager.updateTarget(this);
}
@Override
public IPath getBuildCommand() {
if (isDefaultBuildCmd()) {
IMakeBuilderInfo info;
try {
info = MakeCorePlugin.createBuildInfo(getProject(), manager.getBuilderID(targetBuilderID));
return info.getBuildCommand();
} catch (CoreException e) {
}
}
String result = getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, "make"); //$NON-NLS-1$
try {
result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result, false);
} catch (CoreException e) {
}
return new Path(result);
}
@Override
public void setBuildCommand(IPath command) throws CoreException {
setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, command.toString());
}
@Override
public String getBuildArguments() {
if (isDefaultBuildCmd()) {
IMakeBuilderInfo info;
try {
info = MakeCorePlugin.createBuildInfo(getProject(), manager.getBuilderID(targetBuilderID));
return info.getBuildArguments();
} catch (CoreException e) {
}
}
String result = getBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, ""); //$NON-NLS-1$
try {
result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result, false);
} catch (CoreException e) {
}
return result;
}
@Override
public void setBuildArguments(String arguments) throws CoreException {
setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, arguments);
}
@Override
public void setBuildTarget(String target) throws CoreException {
setBuildAttribute(IMakeTarget.BUILD_TARGET, target);
}
@Override
public String getBuildTarget() {
String result = getBuildAttribute(IMakeTarget.BUILD_TARGET, ""); //$NON-NLS-1$
try {
result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result, false);
} catch (CoreException e) {
}
return result;
}
@Override
public void setRunAllBuilders(boolean runAllBuilders) throws CoreException {
this.runAllBuidlers = runAllBuilders;
manager.updateTarget(this);
}
@Override
public boolean runAllBuilders() {
return runAllBuidlers;
}
@Override
public void setBuildAttribute(String name, String value) throws CoreException {
targetAttributes.put(name, value);
manager.updateTarget(this);
}
@Override
public String getBuildAttribute(String name, String defaultValue) {
String value = targetAttributes.get(name);
return value != null ? value : defaultValue;
}
@Override
public IPath getBuildLocation() {
return container.getLocation();
}
@Override
public void setBuildLocation(IPath location) throws CoreException {
throw new UnsupportedOperationException();
}
@Override
public String[] getErrorParsers() {
IMakeBuilderInfo projectInfo;
try {
projectInfo = MakeCorePlugin.createBuildInfo(getProject(), manager.getBuilderID(targetBuilderID));
return projectInfo.getErrorParsers();
} catch (CoreException e) {
}
return new String[0];
}
@Override
public void setErrorParsers(String[] parsers) throws CoreException {
throw new UnsupportedOperationException();
}
@Override
public Map<String, String> getExpandedEnvironment() throws CoreException {
Map<String, String> env = null;
if (appendProjectEnvironment()) {
IMakeBuilderInfo projectInfo;
projectInfo = MakeCorePlugin.createBuildInfo(getProject(), manager.getBuilderID(targetBuilderID));
env = projectInfo.getEnvironment();
}
if (env == null) {
env = getEnvironment();
} else {
env.putAll(getEnvironment());
}
HashMap<String, String> envMap = new HashMap<>(env.entrySet().size());
boolean win32 = Platform.getOS().equals(Constants.OS_WIN32);
for (Entry<String, String> entry : env.entrySet()) {
String key = entry.getKey();
if (win32) {
// Win32 vars are case insensitive. Uppercase everything so
// that (for example) "pAtH" will correctly replace "PATH"
key = key.toUpperCase();
}
String value = entry.getValue();
// translate any string substitution variables
String translated = value;
translated = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(value, false);
envMap.put(key, translated);
}
return envMap;
}
@Override
public boolean appendProjectEnvironment() {
return appendProjectEnvironment;
}
@Override
public void setAppendProjectEnvironment(boolean append) {
appendProjectEnvironment = append;
}
@Override
public Map<String, String> getEnvironment() {
return buildEnvironment;
}
@Override
public void setEnvironment(Map<String, String> env) throws CoreException {
buildEnvironment = new HashMap<>(env);
manager.updateTarget(this);
}
@Override
public void setAppendEnvironment(boolean append) throws CoreException {
appendEnvironment = append ? 1 : 0;
manager.updateTarget(this);
}
@Override
public boolean appendEnvironment() {
return appendEnvironment == USE_PROJECT_ENV_SETTING ? getProjectEnvSetting(): appendEnvironment == 1;
}
private boolean getProjectEnvSetting() {
IMakeBuilderInfo projectInfo;
try {
projectInfo = MakeCorePlugin.createBuildInfo(getProject(), manager.getBuilderID(targetBuilderID));
return projectInfo.appendEnvironment();
} catch (CoreException e) {
}
return false;
}
@Override
public IContainer getContainer() {
return container;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof MakeTarget) {
MakeTarget other = (MakeTarget)obj;
return (container != null ? container.equals(other.getContainer()) : other.getContainer() == null) && name.equals(other.getName());
}
return false;
}
@Override
public int hashCode() {
return container.hashCode() * 17 + name != null ? name.hashCode(): 0;
}
@Override
public void build(IProgressMonitor monitor) throws CoreException {
final String builderID = manager.getBuilderID(targetBuilderID);
final HashMap<String, String> infoMap = new HashMap<>();
IMakeBuilderInfo info = MakeCorePlugin.createBuildInfo(infoMap, builderID);
info.setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, "make")); //$NON-NLS-1$
info.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, getBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, "")); //$NON-NLS-1$
info.setUseDefaultBuildCmd(isDefaultBuildCmd());
info.setStopOnError(isStopOnError());
info.setIncrementalBuildEnable(true);
info.setBuildAttribute(IMakeBuilderInfo.BUILD_TARGET_INCREMENTAL, getBuildAttribute(IMakeTarget.BUILD_TARGET, "")); //$NON-NLS-1$
info.setCleanBuildEnable(false);
info.setEnvironment(getExpandedEnvironment());
info.setAppendEnvironment(appendEnvironment());
if (container != null && container != project) {
info.setBuildAttribute(IMakeCommonBuildInfo.BUILD_LOCATION, container.getFullPath().toString());
}
IMakeBuilderInfo projectInfo = MakeCorePlugin.createBuildInfo(getProject(), builderID);
info.setErrorParsers(projectInfo.getErrorParsers());
IWorkspaceRunnable op = new IWorkspaceRunnable() {
/*
* (non-Javadoc)
*
* @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void run(IProgressMonitor monitor) throws CoreException {
if (runAllBuidlers) {
ICommand[] commands = project.getDescription().getBuildSpec();
SubMonitor subMonitor = SubMonitor.convert(monitor, commands.length);
for (ICommand command : commands) {
if (command.getBuilderName().equals(builderID)) {
project.build(IncrementalProjectBuilder.FULL_BUILD, builderID, infoMap, subMonitor.newChild(1));
} else {
project.build(IncrementalProjectBuilder.FULL_BUILD, command.getBuilderName(),
command.getArguments(), subMonitor.newChild(1));
}
}
monitor.done();
} else {
project.build(IncrementalProjectBuilder.FULL_BUILD, builderID, infoMap, monitor);
}
}
};
try {
ResourcesPlugin.getWorkspace().run(op, null, IResource.NONE, monitor);
} finally {
monitor.done();
}
}
}