blob: b5a21c515f13ee4be95c037810ec944a77ae87fa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2016 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
*******************************************************************************/
package org.eclipse.cdt.internal.qt.core.build;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.build.BuildCommandRunner;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.internal.qt.core.Activator;
import org.eclipse.cdt.internal.qt.core.Messages;
import org.eclipse.cdt.qt.core.IQtBuildConfiguration;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
public class QtBuilder extends ACBuilder {
public static final String ID = Activator.ID + ".qtBuilder"; //$NON-NLS-1$
@Override
protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
try {
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
IConsole console = CCorePlugin.getDefault().getConsole();
console.start(project);
ConsoleOutputStream errStream = console.getErrorStream();
ConsoleOutputStream outStream = console.getOutputStream();
ICBuildConfiguration cconfig = getBuildConfig().getAdapter(ICBuildConfiguration.class);
IQtBuildConfiguration qtConfig = cconfig.getAdapter(QtBuildConfiguration.class);
if (qtConfig == null) {
// Qt hasn't been configured yet print a message and bale
errStream.write(Messages.QtBuilder_0);
return null;
}
Path makeCommand = getMakeCommand(getBuildConfig());
if (makeCommand == null) {
errStream.write("'make' not found.\n");
return null;
}
try (ErrorParserManager epm = new ErrorParserManager(project, qtConfig.getBuildDirectory().toUri(), this,
qtConfig.getToolChain().getErrorParserIds())) {
BuildCommandRunner runner = new BuildCommandRunner(project, console, epm);
Path buildDir = qtConfig.getBuildDirectory();
if (!buildDir.resolve("Makefile").toFile().exists()) { //$NON-NLS-1$
// Need to run qmake
List<String> command = new ArrayList<>();
command.add(qtConfig.getQmakeCommand().toString());
String config = qtConfig.getQmakeConfig();
if (config != null) {
command.add(config);
}
IFile projectFile = qtConfig.getBuildConfiguration().getProject()
.getFile(project.getName() + ".pro"); //$NON-NLS-1$
command.add(projectFile.getLocation().toOSString());
ProcessBuilder processBuilder = new ProcessBuilder(command)
.directory(qtConfig.getBuildDirectory().toFile());
CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(processBuilder.environment(),
getBuildConfig(), true);
Process process = processBuilder.start();
StringBuilder msg = new StringBuilder();
for (String arg : command) {
msg.append(arg).append(' ');
}
msg.append('\n');
outStream.write(msg.toString());
runner.monitor(process);
}
// run make
ProcessBuilder procBuilder = new ProcessBuilder(makeCommand.toString()).directory(buildDir.toFile());
CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(procBuilder.environment(),
getBuildConfig(), true);
Process process = procBuilder.start();
outStream.write(makeCommand.toString() + '\n');
runner.monitor(process);
}
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
// clear the scanner info cache
// TODO be more surgical about what to clear based on what was
// built.
// qtConfig.clearScannerInfoCache();
outStream.write("Complete.\n");
return new IProject[] { project };
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Building " + project.getName(), e)); //$NON-NLS-1$
}
}
@Override
protected void clean(IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
try {
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
IConsole console = CCorePlugin.getDefault().getConsole();
console.start(getProject());
ConsoleOutputStream errStream = console.getErrorStream();
ConsoleOutputStream outStream = console.getOutputStream();
ICBuildConfiguration cconfig = getBuildConfig().getAdapter(ICBuildConfiguration.class);
IQtBuildConfiguration qtConfig = cconfig.getAdapter(QtBuildConfiguration.class);
if (qtConfig == null) {
// Qt hasn't been configured yet print a message and bale
errStream.write(Messages.QtBuilder_0);
return;
}
Path makeCommand = getMakeCommand(getBuildConfig());
if (makeCommand == null) {
errStream.write("'make' not found.\n");
return;
}
Path buildDir = qtConfig.getBuildDirectory();
try (ErrorParserManager epm = new ErrorParserManager(project, qtConfig.getBuildDirectory().toUri(), this,
qtConfig.getToolChain().getErrorParserIds())) {
BuildCommandRunner runner = new BuildCommandRunner(project, console, epm);
// run make
ProcessBuilder procBuilder = new ProcessBuilder(makeCommand.toString(), "clean") //$NON-NLS-1$
.directory(buildDir.toFile());
CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(procBuilder.environment(),
getBuildConfig(), true);
Process process = procBuilder.start();
outStream.write(makeCommand.toString() + "clean\n"); //$NON-NLS-1$
runner.monitor(process);
}
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
// clear the scanner info cache
// TODO be more surgical about what to clear based on what was
// built.
// qtConfig.clearScannerInfoCache();
outStream.write("Complete.\n");
// TODO Auto-generated method stub
super.clean(monitor);
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Cleaning " + project.getName(), e)); //$NON-NLS-1$
}
}
public Path getMakeCommand(IBuildConfiguration config) {
Path makeCommand = findCommand(getBuildConfig(), "make"); //$NON-NLS-1$
if (makeCommand == null) {
makeCommand = findCommand(getBuildConfig(), "mingw32-make"); //$NON-NLS-1$
}
return makeCommand;
}
public Path findCommand(IBuildConfiguration config, String command) {
if (Platform.getOS().equals(Platform.OS_WIN32)) {
command += ".exe"; //$NON-NLS-1$
}
Map<String, String> env = new HashMap<>(System.getenv());
CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(env, config, true);
String[] path = env.get("PATH").split(File.pathSeparator); //$NON-NLS-1$
for (String dir : path) {
Path commandPath = Paths.get(dir, command);
if (Files.exists(commandPath)) {
return commandPath;
}
}
return null;
}
}