mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Use CommandLineUtil to split and join command lines in CBS Makefile support
Without this the build and clean command entered in the CBS settings could be parsed and re-assembled incorrectly. A simple example is that an extra space (e.g. "make clean") would lead to an error when running make like: ``` make: *** empty string invalid as file name. Stop. ``` This happened because the code used trivial split on " " and join with " " to handle parsing that command line string into array of arguments. This change fixes that by using the functionality already available in CommandLineUtil Fixes #1072
This commit is contained in:
parent
c8e47b321d
commit
c55db63bad
4 changed files with 70 additions and 40 deletions
|
@ -24,6 +24,11 @@ The following classes have been removed or modified in API breaking ways:
|
||||||
- spelling corrected for methods with Uninitialized in the name
|
- spelling corrected for methods with Uninitialized in the name
|
||||||
- setWarnUnused renamed to setWarnUnusedVars and isWarnUnused renamed to isWarnUnusedVars
|
- setWarnUnused renamed to setWarnUnusedVars and isWarnUnused renamed to isWarnUnusedVars
|
||||||
|
|
||||||
|
### StandardBuildConfiguration.setBuildCommand(String[]) and StandardBuildConfiguration.setCleanCommand(String[]) removed
|
||||||
|
|
||||||
|
These methods (in `org.eclipse.cdt.core.build.StandardBuildConfiguration`) made it difficult to save and load users build and clean command without modifying it.
|
||||||
|
They have been replaced with methods that take only a `String` for consistent parsing of command lines.
|
||||||
|
See [#1072](https://github.com/eclipse-cdt/cdt/issues/1072) for more details on motivation for this change.
|
||||||
|
|
||||||
## API Changes in CDT 11.5.
|
## API Changes in CDT 11.5.
|
||||||
|
|
||||||
|
|
|
@ -198,19 +198,8 @@ public class MakeBuildSettingsTab extends CommonBuildTab {
|
||||||
stdConfig.setBuildContainer(stdConfig.getProject());
|
stdConfig.setBuildContainer(stdConfig.getProject());
|
||||||
}
|
}
|
||||||
|
|
||||||
String buildCommand = buildCmdText.getText().trim();
|
stdConfig.setBuildCommand(buildCmdText.getText());
|
||||||
if (!buildCommand.isEmpty()) {
|
stdConfig.setCleanCommand(cleanCmdText.getText());
|
||||||
stdConfig.setBuildCommand(buildCommand.split(" ")); //$NON-NLS-1$
|
|
||||||
} else {
|
|
||||||
stdConfig.setBuildCommand(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
String cleanCommand = cleanCmdText.getText().trim();
|
|
||||||
if (!cleanCommand.isEmpty()) {
|
|
||||||
stdConfig.setCleanCommand(cleanCommand.split(" ")); //$NON-NLS-1$
|
|
||||||
} else {
|
|
||||||
stdConfig.setCleanCommand(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
MakeUIPlugin.log(e.getStatus());
|
MakeUIPlugin.log(e.getStatus());
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||||
import org.eclipse.cdt.core.model.ICModelMarker;
|
import org.eclipse.cdt.core.model.ICModelMarker;
|
||||||
import org.eclipse.cdt.core.resources.IConsole;
|
import org.eclipse.cdt.core.resources.IConsole;
|
||||||
import org.eclipse.cdt.internal.core.build.Messages;
|
import org.eclipse.cdt.internal.core.build.Messages;
|
||||||
|
import org.eclipse.cdt.utils.CommandLineUtil;
|
||||||
import org.eclipse.core.resources.IBuildConfiguration;
|
import org.eclipse.core.resources.IBuildConfiguration;
|
||||||
import org.eclipse.core.resources.IContainer;
|
import org.eclipse.core.resources.IContainer;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
|
@ -61,11 +62,11 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
*/
|
*/
|
||||||
public static final String CLEAN_COMMAND = "stdbuild.clean.command"; //$NON-NLS-1$
|
public static final String CLEAN_COMMAND = "stdbuild.clean.command"; //$NON-NLS-1$
|
||||||
|
|
||||||
private static final String[] DEFAULT_BUILD_COMMAND = new String[] { "make" }; //$NON-NLS-1$
|
private static final String DEFAULT_BUILD_COMMAND = "make"; //$NON-NLS-1$
|
||||||
private static final String[] DEFAULT_CLEAN_COMMAND = new String[] { "make", "clean" }; //$NON-NLS-1$ //$NON-NLS-2$
|
private static final String DEFAULT_CLEAN_COMMAND = "make clean"; //$NON-NLS-1$
|
||||||
|
|
||||||
private String[] buildCommand = DEFAULT_BUILD_COMMAND;
|
private String buildCommand = DEFAULT_BUILD_COMMAND;
|
||||||
private String[] cleanCommand = DEFAULT_CLEAN_COMMAND;
|
private String cleanCommand = DEFAULT_CLEAN_COMMAND;
|
||||||
private IContainer buildContainer;
|
private IContainer buildContainer;
|
||||||
private IEnvironmentVariable[] envVars;
|
private IEnvironmentVariable[] envVars;
|
||||||
|
|
||||||
|
@ -97,18 +98,18 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
private void applyProperties() {
|
private void applyProperties() {
|
||||||
setBuildContainer(getProperty(BUILD_CONTAINER));
|
setBuildContainer(getProperty(BUILD_CONTAINER));
|
||||||
|
|
||||||
String buildCmd = getProperty(BUILD_COMMAND);
|
String buildCommand = getProperty(BUILD_COMMAND);
|
||||||
if (buildCmd != null && !buildCmd.trim().isEmpty()) {
|
if (buildCommand != null && !buildCommand.isBlank()) {
|
||||||
buildCommand = buildCmd.split(" "); //$NON-NLS-1$
|
this.buildCommand = buildCommand;
|
||||||
} else {
|
} else {
|
||||||
buildCommand = DEFAULT_BUILD_COMMAND;
|
this.buildCommand = DEFAULT_BUILD_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
String cleanCmd = getProperty(CLEAN_COMMAND);
|
String cleanCommand = getProperty(CLEAN_COMMAND);
|
||||||
if (cleanCmd != null && !cleanCmd.trim().isEmpty()) {
|
if (cleanCommand != null && !cleanCommand.isBlank()) {
|
||||||
cleanCommand = cleanCmd.split(" "); //$NON-NLS-1$
|
this.cleanCommand = cleanCommand;
|
||||||
} else {
|
} else {
|
||||||
cleanCommand = DEFAULT_CLEAN_COMMAND;
|
this.cleanCommand = DEFAULT_CLEAN_COMMAND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,20 +162,32 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBuildCommand(String[] buildCommand) {
|
/**
|
||||||
if (buildCommand != null) {
|
* Set the build command to use. The string will be converted to
|
||||||
|
* command line arguments using {@link CommandLineUtil}
|
||||||
|
*
|
||||||
|
* @since 9.0
|
||||||
|
*/
|
||||||
|
public void setBuildCommand(String buildCommand) {
|
||||||
|
if (buildCommand != null && !buildCommand.isBlank()) {
|
||||||
this.buildCommand = buildCommand;
|
this.buildCommand = buildCommand;
|
||||||
setProperty(BUILD_COMMAND, String.join(" ", buildCommand)); //$NON-NLS-1$
|
setProperty(BUILD_COMMAND, buildCommand);
|
||||||
} else {
|
} else {
|
||||||
this.buildCommand = DEFAULT_BUILD_COMMAND;
|
this.buildCommand = DEFAULT_BUILD_COMMAND;
|
||||||
removeProperty(BUILD_COMMAND);
|
removeProperty(BUILD_COMMAND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCleanCommand(String[] cleanCommand) {
|
/**
|
||||||
if (cleanCommand != null) {
|
* Set the build command to use. The string will be converted to
|
||||||
|
* command line arguments using {@link CommandLineUtil}
|
||||||
|
*
|
||||||
|
* @since 9.0
|
||||||
|
*/
|
||||||
|
public void setCleanCommand(String cleanCommand) {
|
||||||
|
if (cleanCommand != null && !cleanCommand.isBlank()) {
|
||||||
this.cleanCommand = cleanCommand;
|
this.cleanCommand = cleanCommand;
|
||||||
setProperty(CLEAN_COMMAND, String.join(" ", cleanCommand)); //$NON-NLS-1$
|
setProperty(CLEAN_COMMAND, cleanCommand);
|
||||||
} else {
|
} else {
|
||||||
this.cleanCommand = DEFAULT_CLEAN_COMMAND;
|
this.cleanCommand = DEFAULT_CLEAN_COMMAND;
|
||||||
removeProperty(CLEAN_COMMAND);
|
removeProperty(CLEAN_COMMAND);
|
||||||
|
@ -212,9 +225,9 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case BUILD_COMMAND:
|
case BUILD_COMMAND:
|
||||||
return String.join(" ", buildCommand); //$NON-NLS-1$
|
return buildCommand;
|
||||||
case CLEAN_COMMAND:
|
case CLEAN_COMMAND:
|
||||||
return String.join(" ", cleanCommand); //$NON-NLS-1$
|
return cleanCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -242,8 +255,9 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
|
|
||||||
infoStream.write(String.format(Messages.StandardBuildConfiguration_0, buildDir.toString()));
|
infoStream.write(String.format(Messages.StandardBuildConfiguration_0, buildDir.toString()));
|
||||||
|
|
||||||
|
String[] parsedBuildCommand = CommandLineUtil.argumentsToArray(buildCommand);
|
||||||
List<String> command = new ArrayList<>();
|
List<String> command = new ArrayList<>();
|
||||||
command.add(buildCommand[0]);
|
command.add(parsedBuildCommand[0]);
|
||||||
|
|
||||||
if (!getBuildContainer().equals(getProject())) {
|
if (!getBuildContainer().equals(getProject())) {
|
||||||
Path makefile = Paths.get(getProject().getFile("Makefile").getLocationURI()); //$NON-NLS-1$
|
Path makefile = Paths.get(getProject().getFile("Makefile").getLocationURI()); //$NON-NLS-1$
|
||||||
|
@ -252,15 +266,16 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
command.add(relative.toString());
|
command.add(relative.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < buildCommand.length; i++) {
|
for (int i = 1; i < parsedBuildCommand.length; i++) {
|
||||||
command.add(buildCommand[i]);
|
command.add(parsedBuildCommand[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try (ErrorParserManager epm = new ErrorParserManager(project, getProject().getLocationURI(), this,
|
try (ErrorParserManager epm = new ErrorParserManager(project, getProject().getLocationURI(), this,
|
||||||
getToolChain().getErrorParserIds())) {
|
getToolChain().getErrorParserIds())) {
|
||||||
epm.setOutputStream(console.getOutputStream());
|
epm.setOutputStream(console.getOutputStream());
|
||||||
// run make
|
// run make
|
||||||
console.getOutputStream().write(String.format("%s\n", String.join(" ", command))); //$NON-NLS-1$ //$NON-NLS-2$
|
console.getOutputStream()
|
||||||
|
.write(String.format("%s\n", CommandLineUtil.argumentsToString(command, false))); //$NON-NLS-1$
|
||||||
|
|
||||||
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
|
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
|
||||||
getBuildDirectory().toString());
|
getBuildDirectory().toString());
|
||||||
|
@ -301,9 +316,9 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
List<String> command = new ArrayList<>();
|
List<String> command = new ArrayList<>();
|
||||||
List<String> buildCommand;
|
List<String> buildCommand;
|
||||||
if (cleanCommand != null) {
|
if (cleanCommand != null) {
|
||||||
buildCommand = Arrays.asList(cleanCommand);
|
buildCommand = Arrays.asList(CommandLineUtil.argumentsToArray(cleanCommand));
|
||||||
} else {
|
} else {
|
||||||
buildCommand = Arrays.asList(DEFAULT_CLEAN_COMMAND);
|
buildCommand = Arrays.asList(CommandLineUtil.argumentsToArray(DEFAULT_CLEAN_COMMAND));
|
||||||
}
|
}
|
||||||
|
|
||||||
command.add(buildCommand.get(0));
|
command.add(buildCommand.get(0));
|
||||||
|
@ -321,7 +336,7 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
// run make
|
// run make
|
||||||
infoStream.write(String.format("%s\n", String.join(" ", command))); //$NON-NLS-1$ //$NON-NLS-2$
|
infoStream.write(String.format("%s\n", CommandLineUtil.argumentsToString(command, false))); //$NON-NLS-1$
|
||||||
|
|
||||||
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
|
org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(
|
||||||
getBuildDirectory().toString());
|
getBuildDirectory().toString());
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package org.eclipse.cdt.utils;
|
package org.eclipse.cdt.utils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
import org.eclipse.osgi.service.environment.Constants;
|
import org.eclipse.osgi.service.environment.Constants;
|
||||||
|
@ -269,6 +270,26 @@ public class CommandLineUtil {
|
||||||
return aList.toArray(new String[aList.size()]);
|
return aList.toArray(new String[aList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts argument array to a string suitable for passing to Bash like:
|
||||||
|
*
|
||||||
|
* This process reverses {@link #argumentsToArray(String)}, but does not
|
||||||
|
* restore the exact same results.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* the arguments to convert and escape
|
||||||
|
* @param encodeNewline
|
||||||
|
* <code>true</code> if newline (<code>\r</code> or
|
||||||
|
* <code>\n</code>) should be encoded
|
||||||
|
*
|
||||||
|
* @return args suitable for passing to some process that decodes the string
|
||||||
|
* into an argument array
|
||||||
|
* @since 9.0
|
||||||
|
*/
|
||||||
|
public static String argumentsToString(Collection<String> args, boolean encodeNewline) {
|
||||||
|
return argumentsToString(args.toArray(String[]::new), encodeNewline);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts argument array to a string suitable for passing to Bash like:
|
* Converts argument array to a string suitable for passing to Bash like:
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue