1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-03-28 14:56:28 +01:00

Bug 567488: re-add what was lost in rebase

Change-Id: Ib9342193a91bda76d6809464fb2350fb56ed8175
Signed-off-by: Martin Weber <fifteenknots505@gmail.com>
This commit is contained in:
Martin Weber 2020-10-28 21:36:37 +01:00
parent 4d40c5b68f
commit 9a70f31c4e
5 changed files with 328 additions and 202 deletions

View file

@ -26,6 +26,7 @@ import java.util.function.Consumer;
import org.eclipse.cdt.cmake.core.ICMakeToolChainFile;
import org.eclipse.cdt.cmake.core.ICMakeToolChainManager;
import org.eclipse.cdt.cmake.core.internal.CommandDescriptorBuilder.CommandDescriptor;
import org.eclipse.cdt.cmake.core.properties.CMakeGenerator;
import org.eclipse.cdt.cmake.core.properties.ICMakeProperties;
import org.eclipse.cdt.cmake.core.properties.ICMakePropertiesController;
@ -59,8 +60,6 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
public class CMakeBuildConfiguration extends CBuildConfiguration {
@ -76,8 +75,9 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
private CMakePropertiesController pc;
private Map<IResource, IScannerInfo> infoPerResource;
/** whether one of the CMakeLists.txt files in the project has been
* modified and saved by the user since the last build.<br>
/**
* whether one of the CMakeLists.txt files in the project has been modified and saved by the
* user since the last build.<br>
* Cmake-generated build scripts re-run cmake if one of the CMakeLists.txt files was modified,
* but that output goes through ErrorParserManager and is impossible to parse because cmake
* outputs to both stderr and stdout and ErrorParserManager intermixes these streams making it
@ -85,7 +85,8 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
* To work around that, we run cmake in advance with its dedicated working error parser.
*/
private boolean cmakeListsModified;
/** whether we have to delete file CMakeCache.txt to avoid complaints by cmake
/**
* whether we have to delete file CMakeCache.txt to avoid complaints by cmake
*/
private boolean deleteCMakeCache;
@ -106,10 +107,11 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
this.toolChainFile = toolChainFile;
}
/** Gets the tool-chain description file to pass to the cmake command-line.
/**
* Gets the tool-chain description file to pass to the cmake command-line.
*
* @return the tool-chain file or <code>null</code> if cmake should take the native (i.e. the tools first found on
* the executable search path aka $path)
* @return the tool-chain file or <code>null</code> if cmake should take the native (i.e. the
* tools first found on the executable search path aka $path)
*/
public ICMakeToolChainFile getToolChainFile() {
return toolChainFile;
@ -147,21 +149,23 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
ICMakeProperties cmakeProperties = getPropertiesController().load();
runCMake |= !Files.exists(buildDir.resolve("CMakeCache.txt")); //$NON-NLS-1$
IOsOverrides overrides = extractCMakeOsOverrides(cmakeProperties);
CMakeGenerator generator = overrides.getGenerator();
final SimpleOsOverridesSelector overridesSelector = new SimpleOsOverridesSelector();
if (!runCMake) {
CMakeGenerator generator = overridesSelector.getOsOverrides(cmakeProperties).getGenerator();
runCMake |= !Files.exists(buildDir.resolve(generator.getMakefileName()));
}
CommandDescriptorBuilder cmdBuilder = new CommandDescriptorBuilder(cmakeProperties, overridesSelector);
if (runCMake) {
CMakeBuildConfiguration.deleteCMakeErrorMarkers(project);
infoStream.write(String.format(Messages.CMakeBuildConfiguration_Configuring, buildDir));
List<String> command = makeCMakeCommandline(cmakeProperties, overrides);
CommandDescriptor command = cmdBuilder
.makeCMakeCommandline(toolChainFile != null ? toolChainFile.getPath() : null);
// tell cmake where its script is located..
IContainer srcFolder = project;
command.add(new File(srcFolder.getLocationURI()).getAbsolutePath());
command.getArguments().add(new File(srcFolder.getLocationURI()).getAbsolutePath());
infoStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$
infoStream.write(String.join(" ", command.getArguments()) + '\n'); //$NON-NLS-1$
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
getBuildDirectory().toString());
@ -173,8 +177,8 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
// TODO startBuildProcess() calls java.lang.ProcessBuilder.
// Use org.eclipse.cdt.core.ICommandLauncher
// in order to run builds in a container.
Process p = startBuildProcess(command, new IEnvironmentVariable[0], workingDir, errConsole,
monitor);
Process p = startBuildProcess(command.getArguments(), new IEnvironmentVariable[0], workingDir,
errConsole, monitor);
if (p == null) {
console.getErrorStream().write(String.format(Messages.CMakeBuildConfiguration_Failure, "")); //$NON-NLS-1$
return null;
@ -194,8 +198,6 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
getToolChain().getErrorParserIds())) {
epm.setOutputStream(console.getOutputStream());
List<String> command = makeCMakeBuildCommandline(cmakeProperties, overrides, "all"); //$NON-NLS-1$
String envStr = getProperty(CMAKE_ENV);
List<IEnvironmentVariable> envVars = new ArrayList<>();
if (envStr != null) {
@ -210,12 +212,15 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
}
}
CommandDescriptor commandDescr = cmdBuilder.makeCMakeBuildCommandline("all"); //$NON-NLS-1$
List<String> command = commandDescr.getArguments();
infoStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
getBuildDirectory().toString());
// TODO startBuildProcess() calls java.lang.ProcessBuilder. Use org.eclipse.cdt.core.ICommandLauncher
// in order to run builds in a container.
// TODO pass envvars from CommandDescriptor once we use ICommandLauncher
Process p = startBuildProcess(command, envVars.toArray(new IEnvironmentVariable[0]), workingDir,
console, monitor);
if (p == null) {
@ -238,24 +243,6 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
}
}
/**
* @param cmakeProperties
* @return
*/
private IOsOverrides extractCMakeOsOverrides(ICMakeProperties cmakeProperties) {
IOsOverrides overrides;
// get overrides. Simplistic approach ATM, probably a strategy might fit better.
// see comment in CMakeIndexerInfoConsumer#getFileForCMakePath()
final String os = Platform.getOS();
if (Platform.OS_WIN32.equals(os)) {
overrides = cmakeProperties.getWindowsOverrides();
} else {
// fall back to linux, if OS is unknown
overrides = cmakeProperties.getLinuxOverrides();
}
return overrides;
}
@Override
public void clean(IConsole console, IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
@ -264,8 +251,9 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
ICMakeProperties cmakeProperties = getPropertiesController().load();
IOsOverrides overrides = extractCMakeOsOverrides(cmakeProperties);
List<String> command = makeCMakeBuildCommandline(cmakeProperties, overrides, "clean"); //$NON-NLS-1$
CommandDescriptorBuilder cmdBuilder = new CommandDescriptorBuilder(cmakeProperties,
new SimpleOsOverridesSelector());
CommandDescriptor command = cmdBuilder.makeCMakeBuildCommandline("clean"); //$NON-NLS-1$
ConsoleOutputStream outStream = console.getOutputStream();
Path buildDir = getBuildDirectory();
@ -275,13 +263,14 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
return;
}
outStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$
outStream.write(String.join(" ", command.getArguments()) + '\n'); //$NON-NLS-1$
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
getBuildDirectory().toString());
// TODO startBuildProcess() calls java.lang.ProcessBuilder. Use org.eclipse.cdt.core.ICommandLauncher
// in order to run builds in a container.
Process p = startBuildProcess(command, new IEnvironmentVariable[0], workingDir, console, monitor);
Process p = startBuildProcess(command.getArguments(), new IEnvironmentVariable[0], workingDir, console,
monitor);
if (p == null) {
console.getErrorStream().write(String.format(Messages.CMakeBuildConfiguration_Failure, "")); //$NON-NLS-1$
return;
@ -299,134 +288,9 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
}
/**
* Build the command-line for cmake. The first argument will be the
* cmake-command.
*
* @throws CoreException
*/
private List<String> makeCMakeCommandline(ICMakeProperties cmakeProps, IOsOverrides osOverrideProps)
throws CoreException {
List<String> args = new ArrayList<>();
// default for all OSes (maybe replaced later)
args.add("cmake"); //$NON-NLS-1$
/* add general settings */
if (cmakeProps.isWarnNoDev())
args.add("-Wno-dev"); //$NON-NLS-1$
if (cmakeProps.isDebugTryCompile())
args.add("--debug-trycompile"); //$NON-NLS-1$
if (cmakeProps.isDebugOutput())
args.add("--debug-output"); //$NON-NLS-1$
if (cmakeProps.isTrace())
args.add("--trace"); //$NON-NLS-1$
if (cmakeProps.isWarnUnitialized())
args.add("--warn-unitialized"); //$NON-NLS-1$
if (cmakeProps.isWarnUnused())
args.add("--warn-unused"); //$NON-NLS-1$
{
String file = cmakeProps.getCacheFile();
if (!(file == null || file.isBlank())) {
args.add("-C"); //$NON-NLS-1$
args.add(file);
}
}
if (toolChainFile != null) {
args.add("-DCMAKE_TOOLCHAIN_FILE=" + toolChainFile.getPath().toString()); //$NON-NLS-1$
}
appendCMakeArguments(args, cmakeProps.getExtraArguments());
/* add settings for the operating system we are running under */
appendCMakeOsOverrideArgs(args, osOverrideProps);
/* add our requirements */
{
// set argument for build type..
String bt = cmakeProps.getBuildType();
if (!(bt == null || bt.isBlank())) {
args.add("-DCMAKE_BUILD_TYPE=" + bt); //$NON-NLS-1$
}
// tell cmake to write compile commands to a JSON file
args.add("-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"); //$NON-NLS-1$
}
return args;
}
/**
* Build the command-line for cmake to build the project. The first argument will be the
* cmake-command.
*
* @throws CoreException
*/
private List<String> makeCMakeBuildCommandline(ICMakeProperties cmakeProps, IOsOverrides osOverrides,
String buildscriptTarget) throws CoreException {
List<String> args = new ArrayList<>();
if (osOverrides.getUseDefaultCommand()) {
args.add("cmake"); //$NON-NLS-1$
} else {
IStringVariableManager varManager = VariablesPlugin.getDefault().getStringVariableManager();
String cmd = varManager.performStringSubstitution(osOverrides.getCommand());
args.add(cmd);
}
args.add("--build"); //$NON-NLS-1$
args.add("."); //$NON-NLS-1$
args.add("--target"); //$NON-NLS-1$
args.add(buildscriptTarget);
// TODO parallel build: use CMAKE_BUILD_PARALLEL_LEVEL envvar (since cmake 3.12)
// TODO verbose build: use VERBOSE envvar (since cmake 3.14)
// TODO stop on first error: query CMakeGenerator object for argument
return args;
}
/**
* Appends the additional arguments to pass on the cmake command-line. Performs variable substitutions.
*
* @param argList
* the list to append cmake-arguments to
* @param moreArgs
* the arguments to substitute and append
* @throws CoreException
* if unable to resolve the value of one or more variables
*/
private void appendCMakeArguments(List<String> argList, final List<String> moreArgs) throws CoreException {
IStringVariableManager mgr = VariablesPlugin.getDefault().getStringVariableManager();
for (String arg : moreArgs) {
String expanded = mgr.performStringSubstitution(arg);
argList.add(expanded);
}
}
/**
* Appends arguments specific to the given OS preferences for build-script generation.
* The first argument in the list will be replaced by the cmake command from the specified preferences,
* if given.
*
* @param args
* the list to append cmake-arguments to.
* @param prefs
* the generic OS specific cmake build properties to convert and append.
* @throws CoreException
* if unable to resolve the value of one or more variables
*/
private void appendCMakeOsOverrideArgs(List<String> args, final IOsOverrides prefs) throws CoreException {
// replace cmake command, if given
if (!prefs.getUseDefaultCommand()) {
IStringVariableManager varManager = VariablesPlugin.getDefault().getStringVariableManager();
String cmd = varManager.performStringSubstitution(prefs.getCommand());
args.set(0, cmd);
}
args.add("-G"); //$NON-NLS-1$
final CMakeGenerator generator = prefs.getGenerator();
args.add(generator.getCMakeName());
appendCMakeArguments(args, prefs.getExtraArguments());
}
/**
* @param console the console to print the compiler output during built-ins
* detection to or <code>null</code> if no separate console is to
* be allocated. Ignored if workspace preferences indicate that
* no console output is wanted.
* @param console the console to print the compiler output during built-ins detection to or
* <code>null</code> if no separate console is to be allocated. Ignored if
* workspace preferences indicate that no console output is wanted.
* @param monitor the job's progress monitor
*/
private void processCompileCommandsFile(IConsole console, IProgressMonitor monitor) throws CoreException {
@ -479,13 +343,10 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
@Override
@SuppressWarnings("unchecked")
public <T> T getAdapter(Class<T> adapter) {
T adapter0 = super.getAdapter(adapter);
if (adapter0 == null) {
if (ICMakePropertiesController.class.equals(adapter)) {
adapter0 = (T) getPropertiesController();
}
if (ICMakePropertiesController.class.equals(adapter)) {
return (T) pc;
}
return adapter0;
return super.getAdapter(adapter);
}
/**
@ -510,7 +371,9 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
this.infoPerResource = infoPerResource;
}
/** Overwritten to detect whether one of the CMakeLists.txt files in the project was modified since the last build.
/**
* Overwritten to detect whether one of the CMakeLists.txt files in the project was modified
* since the last build.
*/
@Override
public void elementChanged(ElementChangedEvent event) {
@ -523,8 +386,10 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
}
}
/** Processes the delta in order to detect whether one of the CMakeLists.txt files in the project has been
* modified and saved by the user since the last build.
/**
* Processes the delta in order to detect whether one of the CMakeLists.txt files in the project
* has been modified and saved by the user since the last build.
*
* @return <code>true</code> to continue with delta processing, otherwise <code>false</code>
*/
private boolean processElementDelta(ICElementDelta delta) {
@ -561,7 +426,8 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
return true;
}
/** Overwritten since we do not parse console output to get scanner information.
/**
* Overwritten since we do not parse console output to get scanner information.
*/
// interface IConsoleParser2
@Override
@ -569,7 +435,8 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
return true;
}
/** Overwritten since we do not parse console output to get scanner information.
/**
* Overwritten since we do not parse console output to get scanner information.
*/
// interface IConsoleParser2
@Override
@ -577,7 +444,8 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
return true;
}
/** Overwritten since we do not parse console output to get scanner information.
/**
* Overwritten since we do not parse console output to get scanner information.
*/
// interface IConsoleParser2
@Override
@ -587,8 +455,7 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
/**
* Deletes all CMake error markers on the specified project.
*
* @param project
* the project where to remove the error markers.
* @param project the project where to remove the error markers.
* @throws CoreException
*/
private static void deleteCMakeErrorMarkers(IProject project) throws CoreException {
@ -597,16 +464,14 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
private static class CMakeIndexerInfoConsumer implements IIndexerInfoConsumer {
/**
* gathered IScannerInfo objects or <code>null</code> if no new IScannerInfo was
* received
* gathered IScannerInfo objects or <code>null</code> if no new IScannerInfo was received
*/
private Map<IResource, IScannerInfo> infoPerResource = new HashMap<>();
private boolean haveUpdates;
private final Consumer<Map<IResource, IScannerInfo>> resultSetter;
/**
* @param resultSetter receives the all scanner information when processing is
* finished
* @param resultSetter receives the all scanner information when processing is finished
*/
public CMakeIndexerInfoConsumer(Consumer<Map<IResource, IScannerInfo>> resultSetter) {
this.resultSetter = Objects.requireNonNull(resultSetter);
@ -627,12 +492,11 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
}
/**
* Gets an IFile object that corresponds to the source file name given in CMake
* notation.
* Gets an IFile object that corresponds to the source file name given in CMake notation.
*
* @param sourceFileName the name of the source file, in CMake notation. Note
* that on windows, CMake writes filenames with forward
* slashes (/) such as {@code H://path//to//source.c}.
* @param sourceFileName the name of the source file, in CMake notation. Note that on
* windows, CMake writes filenames with forward slashes (/) such as
* {@code H://path//to//source.c}.
* @return a IFile object or <code>null</code>
*/
private IFile getFileForCMakePath(String sourceFileName) {
@ -656,5 +520,23 @@ public class CMakeBuildConfiguration extends CBuildConfiguration {
haveUpdates = false;
}
}
}
} // CMakeIndexerInfoConsumer
private static class SimpleOsOverridesSelector implements IOsOverridesSelector {
@Override
public IOsOverrides getOsOverrides(ICMakeProperties cmakeProperties) {
IOsOverrides overrides;
// get overrides. Simplistic approach ATM, probably a strategy might fit better.
// see comment in CMakeIndexerInfoConsumer#getFileForCMakePath()
final String os = Platform.getOS();
if (Platform.OS_WIN32.equals(os)) {
overrides = cmakeProperties.getWindowsOverrides();
} else {
// fall back to linux, if OS is unknown
overrides = cmakeProperties.getLinuxOverrides();
}
return overrides;
}
} // SimpleOsOverridesSelector
}

View file

@ -83,16 +83,8 @@ class CMakePropertiesController implements ICMakePropertiesController {
@Override
public void save(ICMakeProperties properties) throws IOException {
// detect whether changes force us to delete file CMakeCache.txt to avoid complaints by cmake
if (!Objects.equals(buildType, properties.getBuildType())
|| !Objects.equals(cacheFile, properties.getCacheFile())
|| !Objects.equals(generatorLinux, properties.getLinuxOverrides().getGenerator())
|| !Objects.equals(generatorWindows, properties.getWindowsOverrides().getGenerator())) {
cmakeCacheDirtyMarker.run(); // must remove cmake cachefile
} else if (hasExtraArgumentChanged(extraArguments, properties.getExtraArguments())
|| hasExtraArgumentChanged(extraArgumentsLinux, properties.getLinuxOverrides().getExtraArguments())
|| hasExtraArgumentChanged(extraArgumentsWindows,
properties.getWindowsOverrides().getExtraArguments())) {
cmakeCacheDirtyMarker.run(); // must remove cmake cachefile
if (isPropertyModified(properties) || isExtraArgumentsPropertyModified(properties)) {
cmakeCacheDirtyMarker.run(); // mark cmake cache file for removal
}
if (!Files.exists(storageFile)) {
try {
@ -107,6 +99,25 @@ class CMakePropertiesController implements ICMakePropertiesController {
setupModifyDetection(properties);
}
/** Gets whether changes in one of the basic properties force us to delete file CMakeCache.txt
* to avoid complaints by cmake.
*/
private boolean isPropertyModified(ICMakeProperties properties) {
return !Objects.equals(buildType, properties.getBuildType())
|| !Objects.equals(cacheFile, properties.getCacheFile())
|| !Objects.equals(generatorLinux, properties.getLinuxOverrides().getGenerator())
|| !Objects.equals(generatorWindows, properties.getWindowsOverrides().getGenerator());
}
/** Gets whether changes in one of the extra arguments properties force us to delete file CMakeCache.txt
* to avoid complaints by cmake.
*/
private boolean isExtraArgumentsPropertyModified(ICMakeProperties properties) {
return hasExtraArgumentChanged(extraArguments, properties.getExtraArguments())
|| hasExtraArgumentChanged(extraArgumentsLinux, properties.getLinuxOverrides().getExtraArguments())
|| hasExtraArgumentChanged(extraArgumentsWindows, properties.getWindowsOverrides().getExtraArguments());
}
/** Sets up detection of modifications that force us to delete file CMakeCache.txt to avoid complaints by cmake
*/
private void setupModifyDetection(ICMakeProperties properties) {

View file

@ -0,0 +1,200 @@
/*******************************************************************************
* Copyright (c) 2020 Martin Weber.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.cdt.cmake.core.internal;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.eclipse.cdt.cmake.core.properties.CMakeGenerator;
import org.eclipse.cdt.cmake.core.properties.ICMakeProperties;
import org.eclipse.cdt.cmake.core.properties.IOsOverrides;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
/**
* Builds lists of command-line arguments and environment variables for build-script generation
* and/or for performing the actual build of a project.
*
* @author Martin Weber
*/
class CommandDescriptorBuilder {
private final ICMakeProperties cmakeProperties;
private final IOsOverridesSelector overridesSelector;
/**
* @param cmakeProperties the project properties related to the cmake command
*/
CommandDescriptorBuilder(ICMakeProperties cmakeProperties, IOsOverridesSelector overridesSelector) {
this.cmakeProperties = Objects.requireNonNull(cmakeProperties);
this.overridesSelector = Objects.requireNonNull(overridesSelector);
}
/**
* Builds the command-line for cmake to generate the build-scripts.
*
* @param toolChainFile the cmake toolchain file or {@code null} if cmake should use the native
* tools it will find in the PATH environment variable
*
* @return the command-line arguments and environment to invoke cmake.
* @throws CoreException
*/
CommandDescriptor makeCMakeCommandline(Path toolChainFile) throws CoreException {
List<String> args = new ArrayList<>();
List<String> env = new ArrayList<>();
// defaults for all OSes...
args.add("cmake"); //$NON-NLS-1$
/* add general settings */
if (cmakeProperties.isWarnNoDev())
args.add("-Wno-dev"); //$NON-NLS-1$
if (cmakeProperties.isDebugTryCompile())
args.add("--debug-trycompile"); //$NON-NLS-1$
if (cmakeProperties.isDebugOutput())
args.add("--debug-output"); //$NON-NLS-1$
if (cmakeProperties.isTrace())
args.add("--trace"); //$NON-NLS-1$
if (cmakeProperties.isWarnUnitialized())
args.add("--warn-unitialized"); //$NON-NLS-1$
if (cmakeProperties.isWarnUnused())
args.add("--warn-unused"); //$NON-NLS-1$
{
String file = cmakeProperties.getCacheFile();
if (!(file == null || file.isBlank())) {
args.add("-C"); //$NON-NLS-1$
args.add(file);
}
}
CommandDescriptorBuilder.appendCMakeArguments(args, cmakeProperties.getExtraArguments());
/* add settings for the operating system we are running under */
CommandDescriptorBuilder.appendCMakeOsOverrideArgs(args, overridesSelector.getOsOverrides(cmakeProperties));
/* at last, add our requirements that override extra args specified by the user... */
{
// set argument for build type..
String bt = cmakeProperties.getBuildType();
if (!(bt == null || bt.isBlank())) {
args.add("-DCMAKE_BUILD_TYPE=" + bt); //$NON-NLS-1$
}
// tell cmake to write compile commands to a JSON file
args.add("-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"); //$NON-NLS-1$
}
if (toolChainFile != null) {
args.add("-DCMAKE_TOOLCHAIN_FILE=" + toolChainFile.toString()); //$NON-NLS-1$
}
return new CommandDescriptor(args, env);
}
/**
* Builds the command-line for cmake to build the project. The first argument will be the
* cmake-command.
*
* @return the command-line arguments and environment to invoke cmake.
* @throws CoreException
*/
CommandDescriptor makeCMakeBuildCommandline(String buildscriptTarget) throws CoreException {
List<String> args = new ArrayList<>();
List<String> env = new ArrayList<>();
IOsOverrides osOverrides = overridesSelector.getOsOverrides(cmakeProperties);
if (osOverrides.getUseDefaultCommand()) {
args.add("cmake"); //$NON-NLS-1$
} else {
IStringVariableManager varManager = VariablesPlugin.getDefault().getStringVariableManager();
String cmd = varManager.performStringSubstitution(osOverrides.getCommand());
args.add(cmd);
}
args.add("--build"); //$NON-NLS-1$
args.add("."); //$NON-NLS-1$
args.add("--target"); //$NON-NLS-1$
args.add(buildscriptTarget);
// TODO parallel build: use CMAKE_BUILD_PARALLEL_LEVEL envvar (since cmake 3.12)
// TODO verbose build: use VERBOSE envvar (since cmake 3.14)
// TODO stop on first error: query CMakeGenerator object for argument
return new CommandDescriptor(args, env);
}
/**
* Appends the additional arguments to pass on the cmake command-line. Performs variable
* substitutions.
*
* @param argList the list to append cmake-arguments to
* @param moreArgs the arguments to substitute and append
* @throws CoreException if unable to resolve the value of one or more variables
*/
private static void appendCMakeArguments(List<String> argList, final List<String> moreArgs) throws CoreException {
IStringVariableManager mgr = VariablesPlugin.getDefault().getStringVariableManager();
for (String arg : moreArgs) {
String expanded = mgr.performStringSubstitution(arg);
argList.add(expanded);
}
}
/**
* Appends arguments specific to the given OS preferences for build-script generation. The first
* argument in the list will be replaced by the cmake command from the specified preferences, if
* given.
*
* @param args the list to append cmake-arguments to.
* @param prefs the generic OS specific cmake build properties to convert and append.
* @throws CoreException if unable to resolve the value of one or more variables
*/
private static void appendCMakeOsOverrideArgs(List<String> args, final IOsOverrides prefs) throws CoreException {
// replace cmake command, if given
if (!prefs.getUseDefaultCommand()) {
IStringVariableManager varManager = VariablesPlugin.getDefault().getStringVariableManager();
String cmd = varManager.performStringSubstitution(prefs.getCommand());
args.set(0, cmd);
}
args.add("-G"); //$NON-NLS-1$
final CMakeGenerator generator = prefs.getGenerator();
args.add(generator.getCMakeName());
appendCMakeArguments(args, prefs.getExtraArguments());
}
/**
* Command-lin arguments and additional environment variables to be used to run a process.
* @author Martin Weber
*/
static final class CommandDescriptor {
private final List<String> arguments;
private final List<String> environment;
/**
* @param arguments
* @param environment the list of environment variables in variable=value format to pass to
* the process.
*/
CommandDescriptor(List<String> arguments, List<String> environment) {
this.arguments = Objects.requireNonNull(arguments);
this.environment = Objects.requireNonNull(environment);
}
/**
* Gets the command-line arguments for the process.
*/
public List<String> getArguments() {
return arguments;
}
/**
* Gets the list of environment variables in variable=value format to pass to the process.
*/
public List<String> getEnvironment() {
return environment;
}
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2020 Martin Weber.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.cdt.cmake.core.internal;
import org.eclipse.cdt.cmake.core.properties.ICMakeProperties;
import org.eclipse.cdt.cmake.core.properties.IOsOverrides;
/**
* Responsible for retrieving the {@link IOsOverrides} that match the target operating system of a
* project build.
*
* @author Martin Weber
*/
interface IOsOverridesSelector {
/**
* Gets the overrides from the specified {@code ICMakeProperties} object that match the target
* operating system. <br>
* Intended to get the command-line arguments to generate build-scripts or perform the build if
* the platform the eclipse workbench is running on differs from the platform the build
* artifacts are to be build for. (E.g.: The workbench runs on windows but the build is to run
* in a container that runs linux.)
*/
IOsOverrides getOsOverrides(ICMakeProperties cmakeProperties);
}

View file

@ -14,7 +14,7 @@ package org.eclipse.cdt.cmake.core.properties;
import java.util.List;
/**
* Properties that override/augment the generic properties when running under a
* Properties that override/augment the generic properties when running under/building for a
* specific OS.
*
* @author Martin Weber