From 84316a4f81ab483d044b56e9143840242b7a73cd Mon Sep 17 00:00:00 2001 From: Alice Trifu Date: Thu, 10 Apr 2025 16:47:46 +0300 Subject: [PATCH] Fix for the compiler path in compile_commands.json file Compiler path was wrongly created when anything was set on the "Prefix" option from "Cross Settings". The code needs to check if anything is set there before creating the default path for the compiler. --- .../CompilationDatabaseGenerationTest.java | 26 +++++++++ .../CompilationDatabaseGenerator.java | 53 +++++++++++++------ 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/CompilationDatabaseGenerationTest.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/CompilationDatabaseGenerationTest.java index 3a0435d654a..3d058dea1b9 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/CompilationDatabaseGenerationTest.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/CompilationDatabaseGenerationTest.java @@ -16,6 +16,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.FileReader; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IConfiguration; @@ -220,4 +223,27 @@ public class CompilationDatabaseGenerationTest extends AbstractBuilderTest { app.build(IncrementalProjectBuilder.FULL_BUILD, null); assertFalse(app.getFile("Debug/compile_commands.json").exists()); } + + @Test + public void testGetCompilerArgsWithSpacesAndQuotes() { + String[] commandLine = { "gcc", "My file.c", "-o", "My file.o", "-DNAME=\"My Value\"", + "C:\\Program Files\\Lib" }; + List argsList = Arrays.asList(commandLine).subList(1, commandLine.length); + String result = escapeArgsForCompileCommand(argsList); + String expected = "\"My file.c\" -o \"My file.o\" \"-DNAME=\\\"My Value\\\"\" \"C:\\\\Program Files\\\\Lib\""; + + assertEquals(expected, result); + } + + private static String escapeArgsForCompileCommand(List args) { + return args.stream().map(arg -> { + if (arg.contains(" ") || arg.contains("\"") || arg.contains("\\")) { + String escaped = arg.replace("\\", "\\\\").replace("\"", "\\\""); + return "\"" + escaped + "\""; + } else { + return arg; + } + }).collect(Collectors.joining(" ")); + } + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/jsoncdb/generator/CompilationDatabaseGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/jsoncdb/generator/CompilationDatabaseGenerator.java index 6c144d9c01f..243a8df3bd4 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/jsoncdb/generator/CompilationDatabaseGenerator.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/jsoncdb/generator/CompilationDatabaseGenerator.java @@ -14,11 +14,13 @@ import java.io.File; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; @@ -69,8 +71,9 @@ public final class CompilationDatabaseGenerator { /** * Checked on each build * Used before we look up the environment + * Map of compiler name (as calculated by {@link #getCompilerName(String)}) to the absolute path of the compiler. */ - private Map toolMap = new HashMap<>(); + private Map toolMap = new HashMap<>(); private IProject project; private IConfiguration configuration; private ICSourceEntry[] srcEntries; @@ -229,18 +232,19 @@ public final class CompilationDatabaseGenerator { outputLocation + "", inputStrings, sourceLocation, outputLocation); //$NON-NLS-1$ IBuildMacroProvider provider = ManagedBuildManager.getBuildMacroProvider(); - String compilerName = CompilationDatabaseGenerator.getCompilerName(tool); String commandLine = cmdLInfo.getCommandLine(); - commandLine = commandLine.replace(compilerName, "").trim(); //$NON-NLS-1$ - String compilerPath = findCompilerInPath(tool, config); + String compilerName = CompilationDatabaseGenerator.getCompilerName(commandLine); + String compilerArguments = getCompilerArgs(commandLine); + String compilerPath = findCompilerInPath(config, compilerName); String resolvedOptionFileContents; if (compilerPath != null && !compilerPath.isEmpty()) { - resolvedOptionFileContents = provider.resolveValueToMakefileFormat(compilerPath + " " + commandLine, //$NON-NLS-1$ + resolvedOptionFileContents = provider.resolveValueToMakefileFormat( + compilerPath + " " + compilerArguments, //$NON-NLS-1$ "", " ", //$NON-NLS-1$//$NON-NLS-2$ IBuildMacroProvider.CONTEXT_FILE, new FileContextData(sourceLocation, outputLocation, null, tool)); } else { - resolvedOptionFileContents = provider.resolveValueToMakefileFormat(commandLine, "", " ", //$NON-NLS-1$//$NON-NLS-2$ + resolvedOptionFileContents = provider.resolveValueToMakefileFormat(compilerArguments, "", " ", //$NON-NLS-1$//$NON-NLS-2$ IBuildMacroProvider.CONTEXT_FILE, new FileContextData(sourceLocation, outputLocation, null, tool)); @@ -438,15 +442,15 @@ public final class CompilationDatabaseGenerator { } - private String findCompilerInPath(ITool tool, IConfiguration config) { - if (toolMap.containsKey(tool)) { - return "\"" + toolMap.get(tool) + "\""; //$NON-NLS-1$//$NON-NLS-2$ + private String findCompilerInPath(IConfiguration config, String compilerName) { + String cacheKey = compilerName; + if (toolMap.containsKey(cacheKey)) { + return "\"" + toolMap.get(cacheKey) + "\""; //$NON-NLS-1$//$NON-NLS-2$ } - String compilerName = CompilationDatabaseGenerator.getCompilerName(tool); File pathToCompiler = new File(compilerName); if (pathToCompiler.isAbsolute()) { - toolMap.put(tool, compilerName); + toolMap.put(cacheKey, compilerName); return "\"" + compilerName + "\""; //$NON-NLS-1$ //$NON-NLS-2$ } ICConfigurationDescription cfg = ManagedBuildManager.getDescriptionForConfiguration(config); @@ -458,7 +462,7 @@ public final class CompilationDatabaseGenerator { IPath resolvedPath = PathUtil.findProgramLocation(compilerName, variable.getValue()); if (resolvedPath != null) { String path = resolvedPath.toString(); - toolMap.put(tool, path); + toolMap.put(cacheKey, path); return "\"" + path + "\""; //$NON-NLS-1$ //$NON-NLS-2$ } else { return null; // Only one PATH so can exit early @@ -469,13 +473,32 @@ public final class CompilationDatabaseGenerator { return null; } - private static String getCompilerName(ITool tool) { - String compilerCommand = tool.getToolCommand(); - String[] arguments = CommandLineUtil.argumentsToArray(compilerCommand); + private static String getCompilerName(String commandLine) { + String[] arguments = CommandLineUtil.argumentsToArray(commandLine); if (arguments.length == 0) { return ""; //$NON-NLS-1$ } return arguments[0]; } + private static String getCompilerArgs(String commandLine) { + String[] arguments = CommandLineUtil.argumentsToArray(commandLine); + if (arguments.length <= 1) { + return ""; //$NON-NLS-1$ + } + List argsList = Arrays.asList(arguments).subList(1, arguments.length); + return escArgsForCompileCommand(argsList); + } + + private static String escArgsForCompileCommand(final List args) { + return args.stream().map(arg -> { + if (arg.contains(" ") || arg.contains("\"") || arg.contains("\\")) { //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + String escaped = arg.replace("\\", "\\\\").replace("\"", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$ + return "\"" + escaped + "\""; //$NON-NLS-1$//$NON-NLS-2$ + } else { + return arg; + } + }).collect(Collectors.joining(" ")); //$NON-NLS-1$ + } + }