mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +02:00
Add Run ninja command context menu item for Meson projects
- add new RunNinjaCommandHandler, RunNinja, AbstractMesonCommandHandler, and RunNinjaPage classes to support running ninja manually with env variables added and options specified - add a new build method to MesonBuildConfiguration which specifies ninja options and environment variables - add SWTImagesFactory for supplying the meson logo image - add WizardMessages class for specifying messages for meson ui wizards - add new MesonUtils class and move stripEnvVars from MesonBuildConfiguration to here - add new constants to IMesonConstants interface Change-Id: I8d635b2bd96792800bb07f4b3f1730be6e41eb24
This commit is contained in:
parent
db1cd491d6
commit
ba7f4f26eb
14 changed files with 811 additions and 56 deletions
|
@ -17,8 +17,6 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.core.CommandLauncherManager;
|
||||
import org.eclipse.cdt.core.ConsoleOutputStream;
|
||||
|
@ -102,8 +100,13 @@ public class MesonBuildConfiguration extends CBuildConfiguration {
|
|||
@Override
|
||||
public IProject[] build(int kind, Map<String, String> args, IConsole console, IProgressMonitor monitor)
|
||||
throws CoreException {
|
||||
return build(kind, args, null, null, console, monitor);
|
||||
}
|
||||
|
||||
public IProject[] build(int kind, Map<String, String> args, String[] ninjaEnv, String[] ninjaArgs, IConsole console, IProgressMonitor monitor)
|
||||
throws CoreException {
|
||||
IProject project = getProject();
|
||||
|
||||
|
||||
try {
|
||||
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
|
||||
|
||||
|
@ -117,7 +120,7 @@ public class MesonBuildConfiguration extends CBuildConfiguration {
|
|||
if (toolChainFile == null && !isLocal()) {
|
||||
IMesonToolChainManager manager = Activator.getService(IMesonToolChainManager.class);
|
||||
toolChainFile = manager.getToolChainFileFor(getToolChain());
|
||||
|
||||
|
||||
if (toolChainFile == null) {
|
||||
// error
|
||||
console.getErrorStream().write(Messages.MesonBuildConfiguration_NoToolchainFile);
|
||||
|
@ -133,12 +136,12 @@ public class MesonBuildConfiguration extends CBuildConfiguration {
|
|||
}
|
||||
|
||||
List<String> argsList = new ArrayList<>();
|
||||
|
||||
|
||||
String userArgs = getProperty(IMesonConstants.MESON_ARGUMENTS);
|
||||
if (userArgs != null) {
|
||||
argsList.addAll(Arrays.asList(userArgs.trim().split("\\s+"))); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
argsList.add(getBuildDirectory().toString());
|
||||
|
||||
Map<String, String> envMap = System.getenv();
|
||||
|
@ -148,25 +151,25 @@ public class MesonBuildConfiguration extends CBuildConfiguration {
|
|||
}
|
||||
String envStr = getProperty(IMesonConstants.MESON_ENV);
|
||||
if (envStr != null) {
|
||||
envList.addAll(stripEnvVars(envStr));
|
||||
envList.addAll(MesonUtils.stripEnvVars(envStr));
|
||||
}
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
|
||||
ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(this);
|
||||
|
||||
|
||||
launcher.setProject(getProject());
|
||||
if (launcher instanceof ICBuildCommandLauncher) {
|
||||
((ICBuildCommandLauncher)launcher).setBuildConfiguration(this);
|
||||
}
|
||||
|
||||
monitor.subTask(Messages.MesonBuildConfiguration_RunningMeson);
|
||||
|
||||
|
||||
org.eclipse.core.runtime.Path mesonPath = new org.eclipse.core.runtime.Path(path.toString());
|
||||
outStream.write(String.join(" ", envStr != null ? envStr : "", //$NON-NLS-1$ //$NON-NLS-2$
|
||||
mesonPath.toString(), userArgs, "\n")); //$NON-NLS-1$
|
||||
outStream.write(getBuildDirectory() + "\n"); //$NON-NLS-1$
|
||||
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(getBuildDirectory().getParent().getParent().toString());
|
||||
|
||||
|
||||
launcher.execute(mesonPath, argsList.toArray(new String[0]), env, workingDir, monitor);
|
||||
if (launcher.waitAndRead(outStream, outStream, SubMonitor.convert(monitor)) != ICommandLauncher.OK) {
|
||||
String errMsg = launcher.getErrorMessage();
|
||||
|
@ -178,28 +181,39 @@ public class MesonBuildConfiguration extends CBuildConfiguration {
|
|||
try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this,
|
||||
getToolChain().getErrorParserIds())) {
|
||||
epm.setOutputStream(console.getOutputStream());
|
||||
|
||||
|
||||
String buildCommand = getProperty(IMesonConstants.BUILD_COMMAND);
|
||||
if (buildCommand == null || buildCommand.isEmpty()) {
|
||||
buildCommand = "ninja";
|
||||
}
|
||||
|
||||
String[] env = new String[0];
|
||||
Map<String, String> envMap = System.getenv();
|
||||
List<String> envList = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : envMap.entrySet()) {
|
||||
envList.add(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
if (ninjaEnv != null) {
|
||||
envList.addAll(Arrays.asList(ninjaEnv));
|
||||
}
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
|
||||
ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(this);
|
||||
|
||||
|
||||
launcher.setProject(getProject());
|
||||
if (launcher instanceof ICBuildCommandLauncher) {
|
||||
((ICBuildCommandLauncher)launcher).setBuildConfiguration(this);
|
||||
}
|
||||
|
||||
monitor.subTask(Messages.MesonBuildConfiguration_RunningMeson);
|
||||
|
||||
monitor.subTask(Messages.MesonBuildConfiguration_RunningNinja);
|
||||
|
||||
org.eclipse.core.runtime.Path ninjaPath = new org.eclipse.core.runtime.Path(buildCommand);
|
||||
outStream.write(String.join(" ", ninjaPath.toString() + '\n')); //$NON-NLS-1$
|
||||
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(getBuildDirectory().toString());
|
||||
|
||||
launcher.execute(ninjaPath, new String[] {"-v"}, env, workingDir, monitor); //$NON-NLS-1$
|
||||
if (ninjaArgs == null) {
|
||||
ninjaArgs = new String[] {"-v"}; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
launcher.execute(ninjaPath, ninjaArgs, env, workingDir, monitor);
|
||||
if (launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), SubMonitor.convert(monitor)) != ICommandLauncher.OK) {
|
||||
String errMsg = launcher.getErrorMessage();
|
||||
console.getErrorStream().write(String.format(Messages.MesonBuildConfiguration_RunningNinjaFailure, errMsg));
|
||||
|
@ -300,44 +314,6 @@ public class MesonBuildConfiguration extends CBuildConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip a command of VAR=VALUE pairs that appear ahead or behind the command and add
|
||||
* them to a list of environment variables.
|
||||
*
|
||||
* @param command - command to strip
|
||||
* @param envVars - ArrayList to add environment variables to
|
||||
* @return stripped command
|
||||
*/
|
||||
public static List<String> stripEnvVars(String envString) {
|
||||
Pattern p1 = Pattern.compile("(\\w+[=]\\\".*?\\\").*"); //$NON-NLS-1$
|
||||
Pattern p2 = Pattern.compile("(\\w+[=]'.*?').*"); //$NON-NLS-1$
|
||||
Pattern p3 = Pattern.compile("(\\w+[=][^\\s]+).*"); //$NON-NLS-1$
|
||||
boolean finished = false;
|
||||
List<String> envVars = new ArrayList<>();
|
||||
while (!finished) {
|
||||
Matcher m1 = p1.matcher(envString);
|
||||
if (m1.matches()) {
|
||||
envString = envString.replaceFirst("\\w+[=]\\\".*?\\\"","").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
String s = m1.group(1).trim();
|
||||
envVars.add(s.replaceAll("\\\"", "")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
Matcher m2 = p2.matcher(envString);
|
||||
if (m2.matches()) {
|
||||
envString = envString.replaceFirst("\\w+[=]'.*?'", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
String s = m2.group(1).trim();
|
||||
envVars.add(s.replaceAll("'", "")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
Matcher m3 = p3.matcher(envString);
|
||||
if (m3.matches()) {
|
||||
envString = envString.replaceFirst("\\w+[=][^\\s]+", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
envVars.add(m3.group(1).trim());
|
||||
} else {
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return envVars;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc. 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
|
||||
*
|
||||
* Red Hat Inc. - initial version
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MesonUtils {
|
||||
|
||||
/**
|
||||
* Parse a string containing environment variables into individual VAR=VALUE pairs.
|
||||
*
|
||||
* @param envString - String to parse
|
||||
* @return List of var=value Strings
|
||||
*/
|
||||
public static List<String> stripEnvVars(String envString) {
|
||||
Pattern p1 = Pattern.compile("(\\w+[=]\\\".*?\\\").*"); //$NON-NLS-1$
|
||||
Pattern p2 = Pattern.compile("(\\w+[=]'.*?').*"); //$NON-NLS-1$
|
||||
Pattern p3 = Pattern.compile("(\\w+[=][^\\s]+).*"); //$NON-NLS-1$
|
||||
boolean finished = false;
|
||||
List<String> envVars = new ArrayList<>();
|
||||
while (!finished) {
|
||||
Matcher m1 = p1.matcher(envString);
|
||||
if (m1.matches()) {
|
||||
envString = envString.replaceFirst("\\w+[=]\\\".*?\\\"","").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
String s = m1.group(1).trim();
|
||||
envVars.add(s.replaceAll("\\\"", "")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
Matcher m2 = p2.matcher(envString);
|
||||
if (m2.matches()) {
|
||||
envString = envString.replaceFirst("\\w+[=]'.*?'", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
String s = m2.group(1).trim();
|
||||
envVars.add(s.replaceAll("'", "")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
Matcher m3 = p3.matcher(envString);
|
||||
if (m3.matches()) {
|
||||
envString = envString.replaceFirst("\\w+[=][^\\s]+", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
envVars.add(m3.group(1).trim());
|
||||
} else {
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return envVars;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ public class Messages extends NLS {
|
|||
public static String MesonBuildConfiguration_BuildingComplete;
|
||||
public static String MesonBuildConfiguration_Cleaning;
|
||||
public static String MesonBuildConfiguration_RunningMeson;
|
||||
public static String MesonBuildConfiguration_RunningNinja;
|
||||
public static String MesonBuildConfiguration_RunningMesonFailure;
|
||||
public static String MesonBuildConfiguration_RunningNinjaFailure;
|
||||
public static String MesonBuildConfiguration_NoToolchainFile;
|
||||
|
|
|
@ -12,6 +12,7 @@ MesonBuildConfiguration_BuildingIn=Building in: %s\n
|
|||
MesonBuildConfiguration_BuildingComplete=Build complete: %s\n
|
||||
MesonBuildConfiguration_Cleaning=Cleaning %s
|
||||
MesonBuildConfiguration_RunningMeson=Running meson
|
||||
MesonBuildConfiguration_RunningNinja=Running ninja
|
||||
MesonBuildConfiguration_ProcCompCmds=Processing compile commands %s
|
||||
MesonBuildConfiguration_ProcCompJson=Processing compile_commands.json
|
||||
MesonBuildConfiguration_NoToolchainFile=No toolchain file found for this target.
|
||||
|
|
|
@ -14,6 +14,8 @@ public interface IMesonConstants {
|
|||
|
||||
public static final String MESON_ARGUMENTS = "meson.arguments"; //$NON-NLS-1$
|
||||
public static final String MESON_ENV = "meson.environment"; //$NON-NLS-1$
|
||||
public static final String NINJA_ENV = "meson.ninja.environment"; //$NON-NLS-1$
|
||||
public static final String NINJA_ARGUMENTS = "meson.ninja.arguments"; //$NON-NLS-1$
|
||||
public static final String MESON_ENV_SEPARATOR = "|"; //$NON-NLS-1$
|
||||
String MESON_GENERATOR = "meson.generator"; //$NON-NLS-1$
|
||||
String BUILD_COMMAND = "meson.command.build"; //$NON-NLS-1$
|
||||
|
|
|
@ -7,3 +7,5 @@
|
|||
###############################################################################
|
||||
|
||||
meson.preferences.name = Meson
|
||||
meson.run.ninja.label=Run ninja
|
||||
meson.run.ninja.mnemonic=j
|
||||
|
|
|
@ -74,5 +74,63 @@
|
|||
tabClass="org.eclipse.cdt.internal.meson.ui.MesonBuildTab">
|
||||
</provider>
|
||||
</extension>
|
||||
<extension
|
||||
id="org.eclipse.cdt.meson.ui.commands.ninja"
|
||||
name="%meson.run.ninja.label"
|
||||
point="org.eclipse.ui.commands">
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="org.eclipse.cdt.internal.meson.ui.commands.RunNinjaCommandHandler"
|
||||
commandId="org.eclipse.cdt.meson.ui.command.runninja">
|
||||
</handler>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.core.expressions.definitions">
|
||||
<definition
|
||||
id="org.eclipse.cdt.meson.ui.handlerEnablement">
|
||||
<with
|
||||
variable="selection">
|
||||
<count
|
||||
value="1">
|
||||
</count>
|
||||
<iterate
|
||||
ifEmpty="false"
|
||||
operator="and">
|
||||
<adapt
|
||||
type="org.eclipse.core.resources.IResource">
|
||||
<test
|
||||
property="org.eclipse.core.resources.projectNature"
|
||||
value="org.eclipse.cdt.meson.core.mesonNature">
|
||||
</test>
|
||||
</adapt>
|
||||
</iterate>
|
||||
</with>
|
||||
</definition>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
locationURI="popup:org.eclipse.ui.popup.any?before=additions">
|
||||
<separator
|
||||
name="mesonGroup"
|
||||
visible="true">
|
||||
</separator>
|
||||
</menuContribution>
|
||||
<menuContribution
|
||||
locationURI="popup:org.eclipse.ui.popup.any?after=mesonGroup">
|
||||
<command
|
||||
commandId="org.eclipse.cdt.meson.ui.command.runninja"
|
||||
id="ninja"
|
||||
label="%meson.run.ninja.label"
|
||||
mnemonic="%meson.run.ninja.mnemonic"
|
||||
style="push">
|
||||
<visibleWhen checkEnabled="true"/>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
|
||||
|
||||
|
||||
</plugin>
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc. 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:
|
||||
* Red Hat Inc. - initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.ui;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.cdt.meson.ui.Activator;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.jface.resource.ImageRegistry;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
|
||||
public class SWTImagesFactory {
|
||||
// The plug-in registry
|
||||
private static ImageRegistry imageRegistry = Activator.getPlugin()
|
||||
.getImageRegistry();
|
||||
|
||||
// Sub-directory (under the package containing this class) where 16 color
|
||||
// images are
|
||||
private static URL fgIconBaseURL;
|
||||
|
||||
static {
|
||||
try {
|
||||
fgIconBaseURL = new URL(Activator.getPlugin().getBundle()
|
||||
.getEntry("/"), "icons/"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} catch (MalformedURLException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
}
|
||||
private static final String NAME_PREFIX = Activator.PLUGIN_ID + '.';
|
||||
private static final int NAME_PREFIX_LENGTH = NAME_PREFIX.length();
|
||||
public static final String IMG_MESON = NAME_PREFIX + "meson-logo.png"; //$NON-NLS-1$
|
||||
public static final ImageDescriptor DESC_MESON = createManaged("",
|
||||
IMG_MESON);
|
||||
|
||||
private static ImageDescriptor createManaged(String prefix, String name) {
|
||||
return createManaged(imageRegistry, prefix, name);
|
||||
}
|
||||
|
||||
private static ImageDescriptor createManaged(ImageRegistry registry,
|
||||
String prefix, String name) {
|
||||
ImageDescriptor result = ImageDescriptor.createFromURL(makeIconFileURL(
|
||||
prefix, name.substring(NAME_PREFIX_LENGTH)));
|
||||
registry.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Image get(String key) {
|
||||
return imageRegistry.get(key);
|
||||
}
|
||||
|
||||
private static ImageDescriptor create(String prefix, String name) {
|
||||
return ImageDescriptor.createFromURL(makeIconFileURL(prefix, name));
|
||||
}
|
||||
|
||||
private static URL makeIconFileURL(String prefix, String name) {
|
||||
StringBuffer buffer = new StringBuffer(prefix);
|
||||
buffer.append(name);
|
||||
try {
|
||||
return new URL(fgIconBaseURL, buffer.toString());
|
||||
} catch (MalformedURLException e) {
|
||||
Activator.log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all available image descriptors for the given action.
|
||||
*
|
||||
* @param action
|
||||
* - action
|
||||
* @param type
|
||||
* - type of image descriptor
|
||||
* @param relPath
|
||||
* - relative path
|
||||
*/
|
||||
public static void setImageDescriptors(IAction action, String type,
|
||||
String relPath) {
|
||||
if (relPath.startsWith(NAME_PREFIX))
|
||||
relPath = relPath.substring(NAME_PREFIX_LENGTH);
|
||||
action.setDisabledImageDescriptor(create("d" + type, relPath)); //$NON-NLS-1$
|
||||
action.setImageDescriptor(create("e" + type, relPath)); //$NON-NLS-1$
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to access the image registry from the CUIPlugin class.
|
||||
*/
|
||||
static ImageRegistry getImageRegistry() {
|
||||
return imageRegistry;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc. 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:
|
||||
* Red Hat Incorporated - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.ui.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.cdt.core.model.ICContainer;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.core.commands.AbstractHandler;
|
||||
import org.eclipse.core.commands.ExecutionEvent;
|
||||
import org.eclipse.core.resources.IContainer;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.jface.dialogs.MessageDialog;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.handlers.HandlerUtil;
|
||||
|
||||
public abstract class AbstractMesonCommandHandler extends AbstractHandler {
|
||||
|
||||
private IContainer fContainer;
|
||||
|
||||
protected abstract void run(Shell activeShell);
|
||||
|
||||
protected Object execute1(ExecutionEvent event) {
|
||||
ISelection k = HandlerUtil.getCurrentSelection(event);
|
||||
if (!k.isEmpty() && k instanceof IStructuredSelection) {
|
||||
Object obj = ((IStructuredSelection)k).getFirstElement();
|
||||
IContainer container = getContainer(obj);
|
||||
if (container != null) {
|
||||
setSelectedContainer(container);
|
||||
run(HandlerUtil.getActiveShell(event));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected IContainer getContainer(Object obj) {
|
||||
IContainer fContainer = null;
|
||||
|
||||
if (obj instanceof Collection) {
|
||||
Collection<Object> c = (Collection<Object>)obj;
|
||||
Object[] objArray = c.toArray();
|
||||
if (objArray.length > 0)
|
||||
obj = objArray[0];
|
||||
}
|
||||
if (obj instanceof ICElement) {
|
||||
if ( obj instanceof ICContainer || obj instanceof ICProject) {
|
||||
fContainer = (IContainer) ((ICElement) obj).getUnderlyingResource();
|
||||
} else {
|
||||
obj = ((ICElement)obj).getResource();
|
||||
if ( obj != null) {
|
||||
fContainer = ((IResource)obj).getParent();
|
||||
}
|
||||
}
|
||||
} else if (obj instanceof IResource) {
|
||||
if (obj instanceof IContainer) {
|
||||
fContainer = (IContainer) obj;
|
||||
} else {
|
||||
fContainer = ((IResource)obj).getParent();
|
||||
}
|
||||
} else {
|
||||
fContainer = null;
|
||||
}
|
||||
return fContainer;
|
||||
}
|
||||
|
||||
public final String SHELL_COMMAND = "sh"; //$NON-NLS-1$
|
||||
|
||||
protected void showError(String title, String content) {
|
||||
MessageDialog.openError(new Shell(), title, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Separate targets to array from a string.
|
||||
*
|
||||
* @param rawArgList
|
||||
* @return targets in string[] array. if targets are not formatted properly,
|
||||
* returns null
|
||||
*/
|
||||
protected List<String> separateTargets(String rawArgList) {
|
||||
|
||||
StringTokenizer st = new StringTokenizer(rawArgList, " "); //$NON-NLS-1$
|
||||
List<String> targetList = new ArrayList<>();
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
String currentWord = st.nextToken().trim();
|
||||
|
||||
if (currentWord.startsWith("'")) { //$NON-NLS-1$
|
||||
StringBuilder tmpTarget = new StringBuilder();
|
||||
while (!currentWord.endsWith("'")) { //$NON-NLS-1$
|
||||
tmpTarget.append(currentWord).append(' ');
|
||||
if (!st.hasMoreTokens()) {
|
||||
// quote not closed properly, so return null
|
||||
return null;
|
||||
}
|
||||
currentWord = st.nextToken().trim();
|
||||
}
|
||||
|
||||
tmpTarget.append(currentWord);
|
||||
targetList.add(tmpTarget.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentWord.startsWith("\"")) { //$NON-NLS-1$
|
||||
StringBuilder tmpTarget = new StringBuilder();
|
||||
while (!currentWord.endsWith("\"")) { //$NON-NLS-1$
|
||||
tmpTarget.append(currentWord).append(' ');
|
||||
if (!st.hasMoreTokens()) {
|
||||
// double quote not closed properly, so return null
|
||||
return null;
|
||||
}
|
||||
currentWord = st.nextToken().trim();
|
||||
}
|
||||
|
||||
tmpTarget.append(currentWord);
|
||||
targetList.add(tmpTarget.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
// for targets without quote/double quotes.
|
||||
targetList.add(currentWord);
|
||||
|
||||
}
|
||||
|
||||
return targetList;
|
||||
}
|
||||
|
||||
protected List<String> separateOptions(String rawArgList) {
|
||||
List<String> argList = new ArrayList<>();
|
||||
// May be multiple user-specified options in which case we
|
||||
// need to split them up into individual options
|
||||
rawArgList = rawArgList.trim();
|
||||
boolean finished = false;
|
||||
int lastIndex = rawArgList.indexOf("--"); //$NON-NLS-1$
|
||||
if (lastIndex != -1) {
|
||||
while (!finished) {
|
||||
int index = rawArgList.indexOf("--", lastIndex + 2); //$NON-NLS-1$
|
||||
if (index != -1) {
|
||||
String previous = rawArgList.substring(lastIndex, index).trim();
|
||||
argList.add(previous);
|
||||
rawArgList = rawArgList.substring(index);
|
||||
} else {
|
||||
argList.add(rawArgList);
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return argList;
|
||||
|
||||
}
|
||||
|
||||
protected List<String> simpleParseOptions(String rawArgList) {
|
||||
List<String> argList = new ArrayList<>();
|
||||
int lastArgIndex = -1;
|
||||
int i = 0;
|
||||
while (i < rawArgList.length()) {
|
||||
char ch = rawArgList.charAt(i);
|
||||
// Skip white-space
|
||||
while (Character.isWhitespace(ch)) {
|
||||
++i;
|
||||
if (i < rawArgList.length())
|
||||
ch = rawArgList.charAt(i);
|
||||
else // Otherwise we are done
|
||||
return argList;
|
||||
}
|
||||
|
||||
// Simplistic parser. We break up into strings delimited
|
||||
// by blanks. If quotes are used, we ignore blanks within.
|
||||
// If a backslash is used, we ignore the next character and
|
||||
// pass it through.
|
||||
lastArgIndex = i;
|
||||
boolean inString = false;
|
||||
while (i < rawArgList.length()) {
|
||||
ch = rawArgList.charAt(i);
|
||||
if (ch == '\\') // escape character
|
||||
++i; // skip over the next character
|
||||
else if (ch == '\"') { // double quotes
|
||||
inString = !inString;
|
||||
} else if (Character.isWhitespace(ch)) {
|
||||
if (!inString) {
|
||||
argList.add(rawArgList.substring(lastArgIndex, i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// Look for the case where we ran out of chars for the last
|
||||
// token.
|
||||
if (i >= rawArgList.length())
|
||||
argList.add(rawArgList.substring(lastArgIndex));
|
||||
++i;
|
||||
}
|
||||
return argList;
|
||||
}
|
||||
|
||||
protected IPath getExecDir(IContainer container) {
|
||||
int type = container.getType();
|
||||
IPath execDir = null;
|
||||
if (type == IResource.FILE) {
|
||||
execDir = container.getLocation().removeLastSegments(1);
|
||||
} else {
|
||||
execDir = container.getLocation();
|
||||
}
|
||||
return execDir;
|
||||
}
|
||||
|
||||
protected IPath getCWD(IContainer container) {
|
||||
int type = container.getType();
|
||||
IPath cwd = null;
|
||||
if (type == IResource.FILE) {
|
||||
cwd = container.getFullPath().removeLastSegments(1);
|
||||
} else {
|
||||
cwd = container.getFullPath();
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
protected IContainer getSelectedContainer() {
|
||||
return fContainer;
|
||||
}
|
||||
|
||||
public void setSelectedContainer(IContainer container) {
|
||||
fContainer = container;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc. 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:
|
||||
* Red Hat Inc. - initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.ui.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.build.CBuildConfiguration;
|
||||
import org.eclipse.cdt.core.build.ICBuildConfiguration;
|
||||
import org.eclipse.cdt.core.resources.IConsole;
|
||||
import org.eclipse.cdt.internal.meson.core.MesonBuildConfiguration;
|
||||
import org.eclipse.cdt.internal.meson.core.MesonUtils;
|
||||
import org.eclipse.cdt.internal.meson.ui.wizards.RunNinja;
|
||||
import org.eclipse.cdt.meson.core.IMesonConstants;
|
||||
import org.eclipse.cdt.meson.ui.Activator;
|
||||
import org.eclipse.core.commands.ExecutionEvent;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IncrementalProjectBuilder;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.jface.window.Window;
|
||||
import org.eclipse.jface.wizard.WizardDialog;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
public class RunNinjaCommandHandler extends AbstractMesonCommandHandler {
|
||||
|
||||
@Override
|
||||
public Object execute(ExecutionEvent event) {
|
||||
return execute1(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run (Shell shell) {
|
||||
// Set up console
|
||||
IConsole console = CCorePlugin.getDefault().getConsole();
|
||||
IProject project = getSelectedContainer().getAdapter(IProject.class);
|
||||
console.start(project);
|
||||
try {
|
||||
ICBuildConfiguration buildConfig = ((CBuildConfiguration)project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class));
|
||||
|
||||
if (buildConfig instanceof MesonBuildConfiguration) {
|
||||
MesonBuildConfiguration config = (MesonBuildConfiguration)buildConfig;
|
||||
RunNinja wizard = new RunNinja(buildConfig);
|
||||
final WizardDialog dialog = new WizardDialog(shell, wizard);
|
||||
Display.getDefault().syncExec(() -> {
|
||||
dialog.create();
|
||||
dialog.open();
|
||||
});
|
||||
if (dialog.getReturnCode() == Window.OK) {
|
||||
// Run ninja command in a Job so user can cancel if it stalls
|
||||
Job buildJob = new Job("Running Ninja") {
|
||||
@Override
|
||||
public IStatus run(final IProgressMonitor monitor) {
|
||||
|
||||
String envString = config.getProperty(IMesonConstants.NINJA_ENV);
|
||||
String[] ninjaEnv = null;
|
||||
if (envString != null) {
|
||||
ninjaEnv = MesonUtils.stripEnvVars(envString).toArray(new String[0]);
|
||||
}
|
||||
|
||||
String argString = config.getProperty(IMesonConstants.NINJA_ARGUMENTS);
|
||||
String[] ninjaArgs = null;
|
||||
if (argString != null) {
|
||||
List<String> ninjaArgList = new ArrayList<>();
|
||||
Matcher m = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(argString);
|
||||
while (m.find()) {
|
||||
ninjaArgList.add(m.group(1));
|
||||
}
|
||||
ninjaArgs = ninjaArgList.toArray(new String[0]);
|
||||
}
|
||||
try {
|
||||
config.build(IncrementalProjectBuilder.FULL_BUILD, null, ninjaEnv, ninjaArgs, console, monitor);
|
||||
if (monitor.isCanceled()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
buildJob.schedule();
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc.
|
||||
* 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:
|
||||
* Red Hat Inc. - Initial Contribution
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.ui.wizards;
|
||||
|
||||
import org.eclipse.cdt.core.build.ICBuildConfiguration;
|
||||
import org.eclipse.cdt.meson.core.IMesonConstants;
|
||||
import org.eclipse.jface.wizard.Wizard;
|
||||
|
||||
public class RunNinja extends Wizard {
|
||||
|
||||
private RunNinjaPage mainPage;
|
||||
private ICBuildConfiguration config;
|
||||
private String envStr;
|
||||
private String ninjaArgs;
|
||||
|
||||
public RunNinja(ICBuildConfiguration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPages() {
|
||||
mainPage = new RunNinjaPage(config);
|
||||
addPage(mainPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish() {
|
||||
return mainPage.isPageComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performFinish() {
|
||||
envStr = mainPage.getEnvStr();
|
||||
config.setProperty(IMesonConstants.NINJA_ENV, envStr);
|
||||
ninjaArgs = mainPage.getNinjaArgs();
|
||||
config.setProperty(IMesonConstants.NINJA_ARGUMENTS, ninjaArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getEnvStr() {
|
||||
return envStr;
|
||||
}
|
||||
|
||||
public String getNinjaArgs() {
|
||||
return ninjaArgs;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc
|
||||
* 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:
|
||||
* Red Hat Inc. - Initial Contribution
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.ui.wizards;
|
||||
|
||||
import org.eclipse.cdt.core.build.ICBuildConfiguration;
|
||||
import org.eclipse.cdt.internal.meson.ui.SWTImagesFactory;
|
||||
import org.eclipse.cdt.meson.core.IMesonConstants;
|
||||
import org.eclipse.jface.wizard.WizardPage;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
/**
|
||||
* A standard file selection dialog which solicits a list of files from the user.
|
||||
* The <code>getResult</code> method returns the selected files.
|
||||
* <p>
|
||||
* This class may be instantiated; it is not intended to be subclassed.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>
|
||||
* FileSelectionDialog dialog =
|
||||
* new FileSelectionDialog(getShell(), rootElement, msg);
|
||||
* dialog.setInitialSelections(selectedResources);
|
||||
* dialog.open();
|
||||
* return dialog.getResult();
|
||||
* </pre>
|
||||
* </p>
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class RunNinjaPage extends WizardPage {
|
||||
|
||||
private ICBuildConfiguration config;
|
||||
private Text envText;
|
||||
private Text ninjaArgs;
|
||||
|
||||
public RunNinjaPage(ICBuildConfiguration config) {
|
||||
super(WizardMessages.RunNinjaPage_name);
|
||||
setDescription(WizardMessages.RunNinjaPage_description);
|
||||
setTitle(WizardMessages.RunNinjaPage_title);
|
||||
setImageDescriptor(SWTImagesFactory.DESC_MESON);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createControl(Composite parent) {
|
||||
|
||||
Composite composite = new Composite(parent, SWT.NONE);
|
||||
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
composite.setLayout(new GridLayout(1, true));
|
||||
|
||||
Label envLabel = new Label(composite, SWT.NONE);
|
||||
envLabel.setText(WizardMessages.RunNinjaPage_env_label);
|
||||
envLabel.setLayoutData(new GridData());
|
||||
|
||||
envText = new Text(composite, SWT.BORDER);
|
||||
String lastEnv = config.getProperty(IMesonConstants.NINJA_ENV);
|
||||
if (lastEnv == null) {
|
||||
lastEnv = ""; //$NON-NLS-1$
|
||||
}
|
||||
envText.setToolTipText(WizardMessages.RunNinjaPage_env_description);
|
||||
envText.setText(lastEnv);
|
||||
GridData gdata = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
envText.setLayoutData(gdata);
|
||||
|
||||
Label argLabel = new Label(composite, SWT.NONE);
|
||||
argLabel.setText(WizardMessages.RunNinjaPage_options_label);
|
||||
argLabel.setLayoutData(new GridData());
|
||||
|
||||
ninjaArgs = new Text(composite, SWT.BORDER);
|
||||
String lastNinjaArgs = config.getProperty(IMesonConstants.NINJA_ARGUMENTS);
|
||||
if (lastNinjaArgs == null) {
|
||||
lastNinjaArgs = ""; //$NON-NLS-1$
|
||||
}
|
||||
ninjaArgs.setToolTipText(WizardMessages.RunNinjaPage_options_description);
|
||||
ninjaArgs.setText(lastNinjaArgs);
|
||||
GridData gdata2 = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
ninjaArgs.setLayoutData(gdata2);
|
||||
|
||||
setControl(composite);
|
||||
}
|
||||
|
||||
public String getEnvStr() {
|
||||
return envText.getText();
|
||||
}
|
||||
|
||||
public String getNinjaArgs() {
|
||||
return ninjaArgs.getText();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Red Hat Inc. 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:
|
||||
* Red Hat Inc. - initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.meson.ui.wizards;
|
||||
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
public class WizardMessages extends NLS {
|
||||
|
||||
public static String RunNinjaPage_name;
|
||||
public static String RunNinjaPage_description;
|
||||
public static String RunNinjaPage_title;
|
||||
public static String RunNinjaPage_env_label;
|
||||
public static String RunNinjaPage_env_description;
|
||||
public static String RunNinjaPage_options_label;
|
||||
public static String RunNinjaPage_options_description;
|
||||
|
||||
static {
|
||||
// initialize resource bundle
|
||||
NLS.initializeMessages("org.eclipse.cdt.internal.meson.ui.wizards.wizardmessages", WizardMessages.class); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private WizardMessages() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
################################################################################
|
||||
# Copyright (c) 2018 Red Hat Inc.
|
||||
# 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:
|
||||
# Red Hat Inc. - Initial Contribution
|
||||
################################################################################
|
||||
RunNinjaPage_name=Run ninja
|
||||
RunNinjaPage_description=Run ninja manually for the active build configuration
|
||||
RunNinjaPage_title=Run ninja manually
|
||||
RunNinjaPage_env_label=Environment:
|
||||
RunNinjaPage_env_description=Environment variables for ninja command
|
||||
RunNinjaPage_options_label=Options:
|
||||
RunNinjaPage_options_description=Options to pass to ninja command
|
Loading…
Add table
Reference in a new issue