Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Johnston2018-04-10 18:37:17 +0000
committerJeff Johnston2018-04-17 16:20:21 +0000
commit8982ef90e778a059e27d75861a16a91e6287ce03 (patch)
treee320245214a5d9cbf5c255aa3ea7e2f1cbe47688
parentc2b5e840872a122209f418e066c4184fca2c0575 (diff)
downloadorg.eclipse.cdt-8982ef90e778a059e27d75861a16a91e6287ce03.tar.gz
org.eclipse.cdt-8982ef90e778a059e27d75861a16a91e6287ce03.tar.xz
org.eclipse.cdt-8982ef90e778a059e27d75861a16a91e6287ce03.zip
Bug 533444 - Add Container Build support to CMake Projects
- fix CMakePropertyPage to check if the active config is a Container build in which case dynamically build the page using the results of a cmake -LAH call which will give the various configuration values that can be changed - add new CMakePropertyCombo, CMakePropertyText, CMakeUtils and ICMakePropertyPageControl classes - change CMakeBuildConfiguration build methods to use startBuildProcess to run commands similar to what StandardBuildConfiguration does now - change CMakeBuildConfigurationProvider to use a container image name to form a build directory so that differnt image targets are differentiated and easy for the user to figure out what they are for - fix main.cpp sample CMake program to actually be a hello world program Change-Id: Iea9e2b5cc6895bc95194e28b131a3fb7e3b670ca
-rw-r--r--build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java123
-rw-r--r--build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfigurationProvider.java18
-rw-r--r--build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeUtils.java57
-rw-r--r--build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/Messages.java2
-rw-r--r--build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/messages.properties2
-rw-r--r--build/org.eclipse.cdt.cmake.core/templates/simple/main.cpp3
-rw-r--r--build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyCombo.java66
-rw-r--r--build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyText.java66
-rw-r--r--build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/ICMakePropertyPageControl.java53
-rw-r--r--build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java6
-rw-r--r--build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties6
-rw-r--r--build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/properties/CMakePropertyPage.java264
12 files changed, 605 insertions, 61 deletions
diff --git a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java
index fab83820cc..a3f1e77a0d 100644
--- a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java
+++ b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java
@@ -26,6 +26,8 @@ import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.build.CBuildConfiguration;
import org.eclipse.cdt.core.build.IToolChain;
+import org.eclipse.cdt.core.envvar.EnvironmentVariable;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.utils.Platform;
@@ -34,6 +36,7 @@ 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.jobs.Job;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
@@ -43,6 +46,7 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
public static final String CMAKE_GENERATOR = "cmake.generator"; //$NON-NLS-1$
public static final String CMAKE_ARGUMENTS = "cmake.arguments"; //$NON-NLS-1$
+ public static final String CMAKE_ENV = "cmake.environment"; //$NON-NLS-1$
public static final String BUILD_COMMAND = "cmake.command.build"; //$NON-NLS-1$
public static final String CLEAN_COMMAND = "cmake.command.clean"; //$NON-NLS-1$
@@ -97,8 +101,9 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
private boolean isLocal() throws CoreException {
IToolChain toolchain = getToolChain();
- return Platform.getOS().equals(toolchain.getProperty(IToolChain.ATTR_OS))
- && Platform.getOSArch().equals(toolchain.getProperty(IToolChain.ATTR_ARCH));
+ return (Platform.getOS().equals(toolchain.getProperty(IToolChain.ATTR_OS))
+ || "linux-container".equals(toolchain.getProperty(IToolChain.ATTR_OS))) //$NON-NLS-1$
+ && (Platform.getOSArch().equals(toolchain.getProperty(IToolChain.ATTR_ARCH)));
}
@Override
@@ -142,16 +147,10 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
}
if (runCMake) { // $NON-NLS-1$
+
List<String> command = new ArrayList<>();
- // TODO location of CMake out of preferences if not found here
- Path cmakePath = findCommand("cmake"); //$NON-NLS-1$
- if (cmakePath != null) {
- command.add(cmakePath.toString());
- } else {
- command.add("cmake"); //$NON-NLS-1$
- }
-
+ command.add("cmake"); //$NON-NLS-1$
command.add("-G"); //$NON-NLS-1$
command.add(generator);
@@ -164,8 +163,10 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
case "debug": //$NON-NLS-1$
command.add("-DCMAKE_BUILD_TYPE=Debug"); //$NON-NLS-1$
break;
+ case "run": //$NON-NLS-1$
+ command.add("-DCMAKE_BUILD_TYPE=Release"); //$NON-NLS-1$
+ break;
}
-
command.add("-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"); //$NON-NLS-1$
String userArgs = getProperty(CMAKE_ARGUMENTS);
@@ -175,31 +176,59 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
command.add(new File(project.getLocationURI()).getAbsolutePath());
- ProcessBuilder processBuilder = new ProcessBuilder(command).directory(buildDir.toFile());
- setBuildEnvironment(processBuilder.environment());
- Process process = processBuilder.start();
outStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$
- watchProcess(process, console);
+
+ Process p = startBuildProcess(command, new IEnvironmentVariable[0], console, monitor);
+ if (p == null) {
+ console.getErrorStream().write(String.format(Messages.CMakeBuildConfiguration_Failure, "")); //$NON-NLS-1$
+ return null;
+ }
+
+ watchProcess(p, console);
}
try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this,
getToolChain().getErrorParserIds())) {
epm.setOutputStream(console.getOutputStream());
+ List<String> command = new ArrayList<>();
+
+ String envStr = getProperty(CMAKE_ENV);
+ List<IEnvironmentVariable> envVars = new ArrayList<>();
+ if (envStr != null) {
+ List<String> envList = CMakeUtils.stripEnvVars(envStr);
+ for (String s : envList) {
+ int index = s.indexOf("="); //$NON-NLS-1$
+ if (index == -1) {
+ envVars.add(new EnvironmentVariable(s));
+ } else {
+ envVars.add(new EnvironmentVariable(s.substring(0, index), s.substring(index + 1)));
+ }
+ }
+ }
+
String buildCommand = getProperty(BUILD_COMMAND);
- String[] command = buildCommand != null && !buildCommand.trim().isEmpty() ? buildCommand.split(" ") //$NON-NLS-1$
- : new String[] { "cmake", "--build", "." }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- Path cmdPath = findCommand(command[0]);
- if (cmdPath != null) {
- command[0] = cmdPath.toString();
+ if (buildCommand == null) {
+ command.add("cmake"); //$NON-NLS-1$
+ command.add("--build"); //$NON-NLS-1$
+ command.add("."); //$NON-NLS-1$
+ if ("Ninja".equals(generator)) {
+ command.add("--"); //$NON-NLS-1$
+ command.add("-v"); //$NON-NLS-1$
+ }
+ } else {
+ command.addAll(Arrays.asList(buildCommand.split(" "))); //$NON-NLS-1$
}
- ProcessBuilder processBuilder = new ProcessBuilder(command).directory(buildDir.toFile());
- setBuildEnvironment(processBuilder.environment());
- Process process = processBuilder.start();
outStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$
- watchProcess(process, new IConsoleParser[] { epm });
+
+ Process p = startBuildProcess(command, envVars.toArray(new IEnvironmentVariable[0]), console, monitor);
+ if (p == null) {
+ console.getErrorStream().write(String.format(Messages.CMakeBuildConfiguration_Failure, "")); //$NON-NLS-1$
+ return null;
+ }
+
+ watchProcess(p, new IConsoleParser[] { epm });
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
@@ -233,26 +262,34 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
return;
}
+ List<String> command = new ArrayList<>();
String cleanCommand = getProperty(CLEAN_COMMAND);
if (cleanCommand == null) {
if (generator == null || generator.equals("Ninja")) { //$NON-NLS-1$
- cleanCommand = "ninja clean"; //$NON-NLS-1$
+ command.add("ninja"); //$NON-NLS-1$
+ command.add("clean"); //$NON-NLS-1$
} else {
- cleanCommand = "make clean"; //$NON-NLS-1$
+ command.add("make"); //$NON-NLS-1$
+ command.add("clean"); //$NON-NLS-1$
}
- }
- String[] command = cleanCommand.split(" "); //$NON-NLS-1$
-
- Path cmdPath = findCommand(command[0]);
- if (cmdPath != null) {
- command[0] = cmdPath.toString();
- }
+ } else {
+ command.addAll(Arrays.asList(cleanCommand.split(" "))); //$NON-NLS-1$
+ }
+
+ IEnvironmentVariable[] env = new IEnvironmentVariable[0];
- ProcessBuilder processBuilder = new ProcessBuilder(command).directory(buildDir.toFile());
- Process process = processBuilder.start();
outStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$
- watchProcess(process, console);
-
+
+ Process p = startBuildProcess(command, env, console, monitor);
+ if (p == null) {
+ console.getErrorStream().write(String.format(Messages.CMakeBuildConfiguration_Failure, "")); //$NON-NLS-1$
+ return;
+ }
+
+ watchProcess(p, console);
+
+ outStream.write(Messages.CMakeBuildConfiguration_BuildComplete);
+
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
} catch (IOException e) {
throw new CoreException(Activator.errorStatus(String.format(Messages.CMakeBuildConfiguration_Cleaning, project.getName()), e));
@@ -263,6 +300,7 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
IProject project = getProject();
Path commandsFile = getBuildDirectory().resolve("compile_commands.json"); //$NON-NLS-1$
if (Files.exists(commandsFile)) {
+ List<Job> jobsList = new ArrayList<>();
monitor.setTaskName(Messages.CMakeBuildConfiguration_ProcCompJson);
try (FileReader reader = new FileReader(commandsFile.toFile())) {
Gson gson = new Gson();
@@ -272,7 +310,14 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
dedupedCmds.put(command.getFile(), command);
}
for (CompileCommand command : dedupedCmds.values()) {
- processLine(command.getCommand());
+ processLine(command.getCommand(), jobsList);
+ }
+ for (Job j : jobsList) {
+ try {
+ j.join();
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
shutdown();
} catch (IOException e) {
diff --git a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfigurationProvider.java b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfigurationProvider.java
index b3e6b35015..e91fae99e8 100644
--- a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfigurationProvider.java
+++ b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfigurationProvider.java
@@ -108,13 +108,19 @@ public class CMakeBuildConfigurationProvider implements ICBuildConfigurationProv
// create config
StringBuilder configName = new StringBuilder("cmake."); //$NON-NLS-1$
configName.append(launchMode);
- if (os != null) {
+ if ("linux-container".equals(os)) { //$NON-NLS-1$
+ String osConfigName = toolChain.getProperty("linux-container-id"); //$NON-NLS-1$
configName.append('.');
- configName.append(os);
- }
- if (arch != null && !arch.isEmpty()) {
- configName.append('.');
- configName.append(arch);
+ configName.append(osConfigName);
+ } else {
+ if (os != null) {
+ configName.append('.');
+ configName.append(os);
+ }
+ if (arch != null && !arch.isEmpty()) {
+ configName.append('.');
+ configName.append(arch);
+ }
}
String name = configName.toString();
int i = 0;
diff --git a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeUtils.java b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeUtils.java
new file mode 100644
index 0000000000..f264f69be4
--- /dev/null
+++ b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeUtils.java
@@ -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.cmake.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CMakeUtils {
+
+ /**
+ * 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;
+ }
+
+}
diff --git a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/Messages.java b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/Messages.java
index e07d1e9ef6..58ec1b728b 100644
--- a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/Messages.java
+++ b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/Messages.java
@@ -14,11 +14,13 @@ public class Messages extends NLS {
public static String CMakeBuildConfiguration_Building;
public static String CMakeBuildConfiguration_BuildingIn;
public static String CMakeBuildConfiguration_BuildingComplete;
+ public static String CMakeBuildConfiguration_BuildComplete;
public static String CMakeBuildConfiguration_Cleaning;
public static String CMakeBuildConfiguration_NotFound;
public static String CMakeBuildConfiguration_NoToolchainFile;
public static String CMakeBuildConfiguration_ProcCompCmds;
public static String CMakeBuildConfiguration_ProcCompJson;
+ public static String CMakeBuildConfiguration_Failure;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/messages.properties b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/messages.properties
index 2dd536559d..2fd81516d5 100644
--- a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/messages.properties
+++ b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/messages.properties
@@ -8,8 +8,10 @@
CMakeBuildConfiguration_Building=Building %s
CMakeBuildConfiguration_BuildingIn=Building in: %s\n
CMakeBuildConfiguration_BuildingComplete=Build complete (%d errors, %d warnings): %s\n
+CMakeBuildConfiguration_BuildComplete=Build complete\n
CMakeBuildConfiguration_Cleaning=Cleaning %s
CMakeBuildConfiguration_NotFound=CMakeFiles not found. Assuming clean.
CMakeBuildConfiguration_NoToolchainFile=No CMake toolchain file found for this target.
CMakeBuildConfiguration_ProcCompCmds=Processing compile commands %s
CMakeBuildConfiguration_ProcCompJson=Processing compile_commands.json
+CMakeBuildConfiguration_Failure=Failure running cmake: %s\n
diff --git a/build/org.eclipse.cdt.cmake.core/templates/simple/main.cpp b/build/org.eclipse.cdt.cmake.core/templates/simple/main.cpp
index c493b4a556..f1d3a296cb 100644
--- a/build/org.eclipse.cdt.cmake.core/templates/simple/main.cpp
+++ b/build/org.eclipse.cdt.cmake.core/templates/simple/main.cpp
@@ -1,4 +1,7 @@
+#include <iostream>
+using namespace std;
int main(int argc, char **argv) {
+ cout << "Hello world";
return 0;
}
diff --git a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyCombo.java b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyCombo.java
new file mode 100644
index 0000000000..590a817787
--- /dev/null
+++ b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyCombo.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.cmake.ui.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+public class CMakePropertyCombo implements ICMakePropertyPageControl {
+
+ private String name;
+ private String initialValue;
+ private Combo combo;
+
+ public CMakePropertyCombo(Composite composite, String name, String[] values, String initialValue, String tooltip) {
+ this.name = name;
+ this.initialValue = initialValue;
+ Label label = new Label(composite, SWT.NONE);
+ label.setText(name);
+ label.setLayoutData(new GridData());
+ combo = new Combo(composite, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.grabExcessHorizontalSpace = true;
+ combo.setLayoutData(data);
+ combo.setItems(values);
+ combo.setText(initialValue);
+ combo.setToolTipText(tooltip);
+ }
+
+
+ @Override
+ public String getFieldValue() {
+ return combo.getText();
+ }
+
+ @Override
+ public String getFieldName() {
+ return name;
+ }
+
+ @Override
+ public boolean isValueChanged() {
+ return !combo.getText().equals(initialValue);
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return null;
+ }
+
+}
diff --git a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyText.java b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyText.java
new file mode 100644
index 0000000000..1c62a059bd
--- /dev/null
+++ b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/CMakePropertyText.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.cmake.ui.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public class CMakePropertyText implements ICMakePropertyPageControl {
+
+ private String name;
+ private String initialValue;
+ protected Text text;
+
+ public CMakePropertyText(Composite composite, String name, String initialValue, String tooltip) {
+ this.name = name;
+ if (initialValue == null) {
+ initialValue = ""; //$NON-NLS-1$
+ }
+ this.initialValue = initialValue;
+ Label label = new Label(composite, SWT.NONE);
+ label.setText(name);
+ label.setLayoutData(new GridData());
+ text = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.grabExcessHorizontalSpace = true;
+ text.setLayoutData(data);
+ text.setText(initialValue);
+ text.setToolTipText(tooltip);
+ }
+
+ @Override
+ public String getFieldValue() {
+ return text.getText();
+ }
+
+ @Override
+ public String getFieldName() {
+ return name;
+ }
+
+ @Override
+ public boolean isValueChanged() {
+ return !text.getText().equals(initialValue);
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return null;
+ }
+}
diff --git a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/ICMakePropertyPageControl.java b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/ICMakePropertyPageControl.java
new file mode 100644
index 0000000000..b1c1a076ab
--- /dev/null
+++ b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/ICMakePropertyPageControl.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.cmake.ui.internal;
+
+public interface ICMakePropertyPageControl {
+
+ /**
+ * Get the value of the field
+ * @return field value
+ */
+ String getFieldValue();
+
+ /**
+ * Get the name of the field to set for cmake command
+ * @return field name
+ */
+ String getFieldName();
+
+ /**
+ * Has the initial value changed
+ * @return
+ */
+ boolean isValueChanged();
+
+ /**
+ * Is this field valid?
+ * @return
+ */
+ boolean isValid();
+
+ /**
+ * Get the command line parameter if already configured
+ * @return String containing command-line for configured build dir
+ */
+ default String getConfiguredString() {
+ return "-D" + getFieldName() + "=" + getFieldValue(); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Get any error message for the control
+ * @return error message
+ */
+ String getErrorMessage();
+
+}
diff --git a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java
index 91e4a32329..f0606790b6 100644
--- a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java
+++ b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/Messages.java
@@ -30,6 +30,12 @@ public class Messages extends NLS {
public static String CMakePreferencePage_Toolchain;
public static String CMakePropertyPage_FailedToStartCMakeGui_Body;
public static String CMakePropertyPage_FailedToStartCMakeGui_Title;
+ public static String CMakePropertyPage_FailedToGetOS_Body;
+ public static String CMakePropertyPage_FailedToGetOS_Title;
+ public static String CMakePropertyPage_FailedToGetCMakeConfiguration_Body;
+ public static String CMakePropertyPage_FailedToGetCMakeConfiguration_Title;
+ public static String CMakePropertyPage_FailedToConfigure;
+ public static String CMakePropertyPage_Terminated;
public static String CMakePropertyPage_LaunchCMakeGui;
public static String NewCMakeProjectWizard_Description;
diff --git a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties
index 09d2055d8c..3b556d1e5e 100644
--- a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties
+++ b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/internal/messages.properties
@@ -17,6 +17,12 @@ CMakePreferencePage_Remove=Remove
CMakePreferencePage_Toolchain=Toolchain
CMakePropertyPage_FailedToStartCMakeGui_Body=Failed to run the CMake GUI:
CMakePropertyPage_FailedToStartCMakeGui_Title=Failed to run CMake GUI
+CMakePropertyPage_FailedToGetOS_Body=Failed to get target OS for CMake project:
+CMakePropertyPage_FailedToGetOS_Title=Failed to get target OS
+CMakePropertyPage_FailedToFetchCMakeConfiguration_Body=Failed to fetch CMake configuration values
+CMakePropertyPage_FailedToFetchCMakeConfiguration_Title=Failed to fetch CMake configuration
+CMakePropertyPage_FailedToConfigure=Failed to reconfigure CMake
+CMakePropertyPage_Terminated=Command terminated with rc={0}\n
CMakePropertyPage_LaunchCMakeGui=Launch CMake GUI...
NewCMakeProjectWizard_Description=Specify properties of new CMake project.
NewCMakeProjectWizard_PageTitle=New CMake Project
diff --git a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/properties/CMakePropertyPage.java b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/properties/CMakePropertyPage.java
index 7699a3c82d..0a8b174de7 100644
--- a/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/properties/CMakePropertyPage.java
+++ b/build/org.eclipse.cdt.cmake.ui/src/org/eclipse/cdt/cmake/ui/properties/CMakePropertyPage.java
@@ -10,12 +10,37 @@
*******************************************************************************/
package org.eclipse.cdt.cmake.ui.properties;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.cdt.cmake.ui.internal.Activator;
+import org.eclipse.cdt.cmake.ui.internal.CMakePropertyCombo;
+import org.eclipse.cdt.cmake.ui.internal.CMakePropertyText;
+import org.eclipse.cdt.cmake.ui.internal.ICMakePropertyPageControl;
import org.eclipse.cdt.cmake.ui.internal.Messages;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CommandLauncherManager;
+import org.eclipse.cdt.core.ICommandLauncher;
+import org.eclipse.cdt.core.build.CBuildConfiguration;
+import org.eclipse.cdt.core.build.ICBuildCommandLauncher;
+import org.eclipse.cdt.core.build.ICBuildConfiguration;
+import org.eclipse.cdt.core.build.IToolChain;
+import org.eclipse.cdt.core.resources.IConsole;
+import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
@@ -24,6 +49,7 @@ import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.dialogs.PropertyPage;
/**
@@ -35,32 +61,238 @@ import org.eclipse.ui.dialogs.PropertyPage;
* PATH.
*/
public class CMakePropertyPage extends PropertyPage {
+
+ private List<ICMakePropertyPageControl> componentList = new ArrayList<>();
@Override
protected Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(new GridLayout());
-
- Button b = new Button(composite, SWT.NONE);
- b.setText(Messages.CMakePropertyPage_LaunchCMakeGui);
- b.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- IProject project = (IProject) getElement();
+
+ boolean isContainerBuild = false;
+ ICBuildConfiguration cconfig = null;
+ IProject project = (IProject) getElement();
+ try {
+ IBuildConfiguration config = project.getActiveBuildConfig();
+ cconfig = config.getAdapter(ICBuildConfiguration.class);
+ IToolChain toolChain = cconfig.getToolChain();
+ String os = toolChain.getProperty(IToolChain.ATTR_OS);
+ isContainerBuild = os.equals("linux-container"); //$NON-NLS-1$
+ } catch (CoreException e2) {
+ MessageDialog.openError(parent.getShell(), Messages.CMakePropertyPage_FailedToGetOS_Title,
+ Messages.CMakePropertyPage_FailedToGetOS_Body + e2.getMessage());
+ }
+
+ if (isContainerBuild) {
+ try {
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class));
+ launcher.setProject(project);
+ if (launcher instanceof ICBuildCommandLauncher) {
+ ((ICBuildCommandLauncher)launcher).setBuildConfiguration(cconfig);
+ }
+ IPath buildPath = project.getLocation().append("build").append(((CBuildConfiguration)cconfig).getName());
+ Process p = launcher.execute(new Path("/bin/sh"), new String[] { "-c", "cmake -LAH ."}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new String[0], buildPath, new NullProgressMonitor());
+ if (p != null) {
+ ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+ ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+ int rc = -1;
try {
- String configName = project.getActiveBuildConfig().getName();
- String sourceDir = project.getLocation().toOSString();
- String buildDir = project.getLocation().append("build").append(configName).toOSString(); //$NON-NLS-1$
-
- Runtime.getRuntime().exec(new String[] { "cmake-gui", "-H" + sourceDir, "-B" + buildDir }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- } catch (CoreException | IOException e1) {
- MessageDialog.openError(parent.getShell(), Messages.CMakePropertyPage_FailedToStartCMakeGui_Title,
- Messages.CMakePropertyPage_FailedToStartCMakeGui_Body + e1.getMessage());
+ if (launcher.waitAndRead(stdout, stderr, new NullProgressMonitor()) == ICommandLauncher.OK) {
+ p.waitFor();
+ }
+ rc = p.exitValue();
+ } catch (InterruptedException e) {
+ // ignore for now
}
+ if (rc == 0) {
+ componentList = parseConfigureOutput(stdout, composite);
+ }
+ }
+ } catch (CoreException e) {
+ MessageDialog.openError(parent.getShell(), Messages.CMakePropertyPage_FailedToGetCMakeConfiguration_Title,
+ Messages.CMakePropertyPage_FailedToGetCMakeConfiguration_Body + e.getMessage());
}
- });
+
+
+ } else {
+
+ Button b = new Button(composite, SWT.NONE);
+ b.setText(Messages.CMakePropertyPage_LaunchCMakeGui);
+ b.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ IProject project = (IProject) getElement();
+ try {
+ String configName = project.getActiveBuildConfig().getName();
+ String sourceDir = project.getLocation().toOSString();
+ String buildDir = project.getLocation().append("build").append(configName).toOSString(); //$NON-NLS-1$
+
+ Runtime.getRuntime().exec(new String[] { "cmake-gui", "-H" + sourceDir, "-B" + buildDir }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ } catch (CoreException | IOException e1) {
+ MessageDialog.openError(parent.getShell(), Messages.CMakePropertyPage_FailedToStartCMakeGui_Title,
+ Messages.CMakePropertyPage_FailedToStartCMakeGui_Body + e1.getMessage());
+ }
+ }
+ });
+ }
return composite;
}
+
+ @Override
+ public boolean performOk() {
+ List<String> args = new ArrayList<>();
+ args.add("cmake"); //$NON-NLS-1$
+ args.add("-LAH"); //$NON-NLS-1$
+ for (ICMakePropertyPageControl control : componentList) {
+ if (control.isValueChanged()) {
+ args.add(control.getConfiguredString()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ if (args.size() == 2) {
+ return true;
+ }
+ try {
+ IProject project = (IProject) getElement();
+ ICBuildConfiguration buildConfig = project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class);
+ String configName = ((CBuildConfiguration)buildConfig).getName();
+ IPath buildDir = project.getLocation().append("build").append(configName); //$NON-NLS-1$
+ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class));
+ launcher.setProject(project);
+ if (launcher instanceof ICBuildCommandLauncher) {
+ ((ICBuildCommandLauncher)launcher).setBuildConfiguration(buildConfig);
+ }
+ StringBuilder b = new StringBuilder();
+ for (String arg : args) {
+ b.append(arg);
+ b.append(" "); //$NON-NLS-1$
+ }
+ b.append(".");
+ Process p = launcher.execute(new Path("/bin/sh"), new String[] { "-c", b.toString() }, new String[0], buildDir, new NullProgressMonitor()); //$NON-NLS-1$ //$NON-NLS-2$
+ int rc = -1;
+ IConsole console = CCorePlugin.getDefault().getConsole();
+ console.start(project);
+ try (OutputStream stdout = console.getOutputStream()) {
+ OutputStream stderr = stdout;
+ StringBuilder buf = new StringBuilder();
+ for (String arg : args) {
+ buf.append(arg);
+ buf.append(" "); //$NON-NLS-1$
+ }
+ buf.append(System.lineSeparator());
+ stdout.write(buf.toString().getBytes());
+ stdout.flush();
+ try {
+
+ if (launcher.waitAndRead(stdout, stderr, new NullProgressMonitor()) == ICommandLauncher.OK) {
+ p.waitFor();
+ }
+ rc = p.exitValue();
+ stdout.write(NLS.bind(Messages.CMakePropertyPage_Terminated, rc).getBytes());
+ stdout.flush();
+ if (rc != 0) {
+ Display.getDefault().syncExec(() -> {
+ MessageDialog.openError(getShell(), null, Messages.CMakePropertyPage_FailedToConfigure);
+ });
+ }
+ } catch (InterruptedException e) {
+ // ignore for now
+ }
+ } catch (IOException e2) {
+ Activator.log(e2);
+ return false;
+ }
+ } catch (CoreException e3) {
+ // TODO Auto-generated catch block
+ Activator.log(e3);
+ return false;
+ }
+ return true;
+ }
+
+
+ public enum ParseState {
+ INIT, SEENCOMMENT
+ };
+
+ /**
+ * Parse output of cmake -LAH call to determine options to show to user
+ * @param stdout - ByteArrayOutputStream containing output of command
+ * @param composite - Composite to add Controls to
+ * @return - list of Controls
+ */
+ List<ICMakePropertyPageControl> parseConfigureOutput(ByteArrayOutputStream stdout, Composite composite) {
+ List<ICMakePropertyPageControl> controls = new ArrayList<>();
+
+ try {
+ ParseState state = ParseState.INIT;
+
+ String output = stdout.toString(StandardCharsets.UTF_8.name());
+ String[] lines = output.split("\\r?\\n"); //$NON-NLS-1$
+ Pattern commentPattern = Pattern.compile("//(.*)"); //$NON-NLS-1$
+ Pattern argPattern = Pattern.compile("(\\w+):([a-zA-Z]+)=(.*)"); //$NON-NLS-1$
+ Pattern optionPattern = Pattern.compile(".*?options are:((\\s+\\w+(\\(.*\\))?)+).*"); //$NON-NLS-1$
+
+ String lastComment = ""; //$NON-NLS-1$
+ for (String line : lines) {
+ line = line.trim();
+ switch (state) {
+ case INIT:
+ Matcher commentMatcher = commentPattern.matcher(line);
+ if (commentMatcher.matches()) {
+ state = ParseState.SEENCOMMENT;
+
+ lastComment = commentMatcher.group(1);
+ }
+ break;
+ case SEENCOMMENT:
+ Matcher argMatcher = argPattern.matcher(line);
+ if (argMatcher.matches()) {
+ String name = argMatcher.group(1);
+ String type = argMatcher.group(2);
+ String initialValue = argMatcher.group(3);
+ Matcher optionMatcher = optionPattern.matcher(lastComment);
+ if (optionMatcher.matches()) {
+ String optionString = optionMatcher.group(1).trim();
+ String[] options = optionString.split("\\s+"); //$NON-NLS-1$
+ for (int i = 0; i < options.length; ++i) {
+ options[i] = options[i].replaceAll("\\(.*?\\)", "").trim(); //$NON-NLS-1$
+ }
+ ICMakePropertyPageControl control = new CMakePropertyCombo(composite, name, options, initialValue, lastComment);
+ controls.add(control);
+ } else {
+ if ("BOOL".equals(type)) {
+ if ("ON".equals(initialValue) || ("OFF".equals(initialValue))) {
+ ICMakePropertyPageControl control = new CMakePropertyCombo(composite, name, new String[] {"ON","OFF"}, //$NON-NLS-1$ //$NON-NLS-2$
+ initialValue, lastComment);
+ controls.add(control);
+ } else if ("YES".equals(initialValue) || "NO".equals(initialValue)) {
+ ICMakePropertyPageControl control = new CMakePropertyCombo(composite, name, new String[] {"YES","NO"}, //$NON-NLS-1$ //$NON-NLS-2$
+ initialValue, lastComment);
+ controls.add(control);
+ } else {
+ ICMakePropertyPageControl control = new CMakePropertyCombo(composite, name, new String[] {"TRUE", "FALSE"}, //$NON-NLS-1$ //$NON-NLS-2$
+ "TRUE".equals(initialValue) ? "TRUE" : "FALSE", lastComment); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ controls.add(control);
+ }
+ } else {
+ ICMakePropertyPageControl control = new CMakePropertyText(composite, name, initialValue, lastComment);
+ controls.add(control);
+ }
+ }
+ }
+ state = ParseState.INIT;
+ break;
+ }
+ }
+
+ } catch (UnsupportedEncodingException e) {
+ return controls;
+ }
+
+ return controls;
+ }
+
}

Back to the top