diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java index c3700801eae..eb28a1b842d 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java @@ -16,6 +16,7 @@ import org.eclipse.cdt.core.build.StandardBuildConfiguration; import org.eclipse.cdt.launch.ui.corebuild.CommonBuildTab; import org.eclipse.cdt.make.core.MakefileBuildConfigurationProvider; +import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; @@ -200,14 +201,14 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) { String buildCommand = buildCmdText.getText().trim(); if (!buildCommand.isEmpty()) { - stdConfig.setBuildCommand(buildCommand.split(" ")); //$NON-NLS-1$ + stdConfig.setBuildCommand(CommandLineUtil.argumentsToArray(buildCommand)); } else { stdConfig.setBuildCommand(null); } String cleanCommand = cleanCmdText.getText().trim(); if (!cleanCommand.isEmpty()) { - stdConfig.setCleanCommand(cleanCommand.split(" ")); //$NON-NLS-1$ + stdConfig.setCleanCommand(CommandLineUtil.argumentsToArray(cleanCommand)); } else { stdConfig.setCleanCommand(null); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java index 179cbdda0a4..7201b4e6ed2 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java @@ -29,6 +29,7 @@ import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.resources.IConsole; 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.IContainer; import org.eclipse.core.resources.IProject; @@ -99,14 +100,14 @@ private void applyProperties() { String buildCmd = getProperty(BUILD_COMMAND); if (buildCmd != null && !buildCmd.trim().isEmpty()) { - buildCommand = buildCmd.split(" "); //$NON-NLS-1$ + buildCommand = CommandLineUtil.argumentsToArray(buildCmd); } else { buildCommand = DEFAULT_BUILD_COMMAND; } String cleanCmd = getProperty(CLEAN_COMMAND); if (cleanCmd != null && !cleanCmd.trim().isEmpty()) { - cleanCommand = cleanCmd.split(" "); //$NON-NLS-1$ + cleanCommand = CommandLineUtil.argumentsToArray(cleanCmd); } else { cleanCommand = DEFAULT_CLEAN_COMMAND; } @@ -164,7 +165,7 @@ public void setBuildContainer(IContainer buildContainer) { public void setBuildCommand(String[] buildCommand) { if (buildCommand != null) { this.buildCommand = buildCommand; - setProperty(BUILD_COMMAND, String.join(" ", buildCommand)); //$NON-NLS-1$ + setProperty(BUILD_COMMAND, CommandLineUtil.argumentsToString(buildCommand, false)); } else { this.buildCommand = DEFAULT_BUILD_COMMAND; removeProperty(BUILD_COMMAND); @@ -174,7 +175,7 @@ public void setBuildCommand(String[] buildCommand) { public void setCleanCommand(String[] cleanCommand) { if (cleanCommand != null) { this.cleanCommand = cleanCommand; - setProperty(CLEAN_COMMAND, String.join(" ", cleanCommand)); //$NON-NLS-1$ + setProperty(CLEAN_COMMAND, CommandLineUtil.argumentsToString(cleanCommand, false)); } else { this.cleanCommand = DEFAULT_CLEAN_COMMAND; removeProperty(CLEAN_COMMAND); @@ -212,9 +213,9 @@ public String getProperty(String name) { return null; } case BUILD_COMMAND: - return String.join(" ", buildCommand); //$NON-NLS-1$ + return CommandLineUtil.argumentsToString(buildCommand, false); case CLEAN_COMMAND: - return String.join(" ", cleanCommand); //$NON-NLS-1$ + return CommandLineUtil.argumentsToString(cleanCommand, false); } return null; @@ -260,7 +261,8 @@ public IProject[] build(int kind, Map args, IConsole console, IP getToolChain().getErrorParserIds())) { epm.setOutputStream(console.getOutputStream()); // 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( getBuildDirectory().toString()); @@ -321,7 +323,7 @@ public void clean(IConsole console, IProgressMonitor monitor) throws CoreExcepti } // 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( getBuildDirectory().toString()); diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CommandLineUtil.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CommandLineUtil.java index 5d91d7faa10..29db47ba0f8 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CommandLineUtil.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CommandLineUtil.java @@ -15,6 +15,7 @@ package org.eclipse.cdt.utils; import java.util.ArrayList; +import java.util.Collection; import org.eclipse.core.runtime.Platform; import org.eclipse.osgi.service.environment.Constants; @@ -269,6 +270,26 @@ public static String[] argumentsToArrayWindowsStyle(String line) { 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 + * true if newline (\r or + * \n) 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 args, boolean encodeNewline) { + return argumentsToString(args.toArray(String[]::new), encodeNewline); + } + /** * Converts argument array to a string suitable for passing to Bash like: * @@ -346,20 +367,33 @@ public static String argumentsToStringBash(String[] args, boolean encodeNewline) builder.append(' '); } - builder.append('\''); + StringBuilder argSb = new StringBuilder(); + boolean argNeedsQuotes = false; for (int j = 0; j < arg.length(); j++) { char c = arg.charAt(j); if (c == '\'') { - builder.append("'\"'\"'"); //$NON-NLS-1$ + argNeedsQuotes = true; + argSb.append("'\"'\"'"); //$NON-NLS-1$ } else if (c == '\r' && encodeNewline) { - builder.append("'$'\\r''"); //$NON-NLS-1$ + argNeedsQuotes = true; + argSb.append("'$'\\r''"); //$NON-NLS-1$ } else if (c == '\n' && encodeNewline) { - builder.append("'$'\\n''"); //$NON-NLS-1$ + argNeedsQuotes = true; + argSb.append("'$'\\n''"); //$NON-NLS-1$ } else { - builder.append(c); + if (Character.isWhitespace(c)) { + argNeedsQuotes = true; + } + argSb.append(c); } } - builder.append('\''); + if (argNeedsQuotes) { + builder.append('\''); + } + builder.append(argSb); + if (argNeedsQuotes) { + builder.append('\''); + } } return builder.toString();