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

Ensure full ICBuildConfiguration environment is used during scanning (#1095)

Under certain conditions*, the compiler param in the command field of
the compile_commands.json is a relative path rather than absolute. When
this happens, the built-ins detection was not successful and the
following exception was thrown:

!ENTRY org.eclipse.cdt.core 4 0 2025-02-23 20:32:10.752
!MESSAGE Error: Cannot run program "gcc": Launching failed
!STACK 0
java.io.IOException: Cannot run program "gcc": Launching failed
	at org.eclipse.cdt.utils.spawner.Spawner.exec(Spawner.java:450)
	at org.eclipse.cdt.utils.spawner.Spawner.<init>(Spawner.java:147)
	at org.eclipse.cdt.utils.spawner.Spawner.<init>(Spawner.java:134)
	at org.eclipse.cdt.utils.spawner.ProcessFactory$Builder.start(ProcessFactory.java:273)
	at org.eclipse.cdt.utils.spawner.ProcessFactory.exec(ProcessFactory.java:366)
	at org.eclipse.cdt.core.CommandLauncher.execute(CommandLauncher.java:189)
	at org.eclipse.cdt.jsoncdb.core.internal.builtins.CompilerBuiltinsDetector.detectBuiltins(CompilerBuiltinsDetector.java:111)
	at org.eclipse.cdt.jsoncdb.core.CompileCommandsJsonParser.detectBuiltins(CompileCommandsJsonParser.java:290)
	at org.eclipse.cdt.jsoncdb.core.CompileCommandsJsonParser.processJsonFile(CompileCommandsJsonParser.java:193)
	at org.eclipse.cdt.jsoncdb.core.CompileCommandsJsonParser.parse(CompileCommandsJsonParser.java:455)
	at org.eclipse.cdt.cmake.core.CMakeBuildConfiguration.processCompileCommandsFile(CMakeBuildConfiguration.java:361)
	at org.eclipse.cdt.cmake.core.CMakeBuildConfiguration.build(CMakeBuildConfiguration.java:241)

This meant that source file includes were not indexed and could not be
opened using Open Declaration (F3) and info markers of the following
type appeared in the Problems view:

  gcc -E -P -dM -Wp,-v
"...extCmakegcc\\build\\cmake.run.win32.x86_64.Local\\detect_compiler_builtins.c"
  Cannot run program "gcc": Launching failed

  Error: Program "gcc" not found in PATH
  PATH=[...]
    extCmakegcc		Unknown	Compiler Builtins Detector Problem
  gcc -E -P -dM -Wp,-v
"...extCmakegcc\\build\\cmake.run.win32.x86_64.Local\\detect_compiler_builtins.c"
  Cannot run program "gcc": Launching failed

This patch fixes the environment issue for Core Build projects, by
calling ICBuildConfiguration.setBuildEnvironment(Map<String, String>) as
part of the built-ins detection setup, thereby supporting absolute and
relative compiler paths.

Addresses Issue: CDT CMake Improvements #1000, IDE-82683-REQ-011 Source
code navigation and Built-ins detection

*: CMake produces relative compiler path

When the CMAKE_<LANG>_COMPILER variable (eg CMAKE_C_COMPILER) is set in
the CMakeLists.txt *after* the project() or language commands, it causes
a relative path to be used. For example, in the CMakeLists.txt below,
gcc is set after project() command:

  cmake_minimum_required(VERSION 3.10)
  project (track2)
  set(CMAKE_C_COMPILER gcc)
  add_executable(${PROJECT_NAME} track2.c)

The above script creates a relative compiler path in
compile_commands.json:
  "command": "gcc   -O3 -DNDEBUG -o ...

Normally the CMAKE_C_COMPILER variable should be set before the
project() comannd.

  "command": "C:\\msys64\\mingw64\\bin\\c++.exe -IC...

Co-authored-by: Jonah Graham <jonah@kichwacoders.com>
This commit is contained in:
betamax 2025-02-26 02:56:41 +00:00 committed by GitHub
parent 74c4844357
commit e138646434
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -17,10 +17,13 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.ICommandLauncher;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.ICBuildConfigurationManager;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.jsoncdb.core.IParserPreferences;
import org.eclipse.cdt.jsoncdb.core.IParserPreferencesAccess;
@ -29,6 +32,8 @@ import org.eclipse.cdt.jsoncdb.core.participant.IRawSourceFileInfo;
import org.eclipse.cdt.jsoncdb.core.participant.builtins.IBuiltinsDetectionBehavior;
import org.eclipse.cdt.jsoncdb.core.participant.builtins.IBuiltinsOutputProcessor;
import org.eclipse.cdt.jsoncdb.core.participant.builtins.OutputSniffer;
import org.eclipse.cdt.utils.spawner.EnvironmentReader;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
@ -185,25 +190,8 @@ public class CompilerBuiltinsDetector {
* return {@code null}.
*/
private String[] getEnvp(IProject project) {
var map = new HashMap<String, String>();
// The cc.exe from mingw64 (part of Msys2) on Windows needs the bin folder to be on the PATH to be executed.
// e.g. 'C:\msys64\mingw64\bin' must be part of the PATH environment variable. That's why we need PATH here:
// Fixes CDT #407
try {
final String path = "PATH"; //$NON-NLS-1$
var variables = CCorePlugin.getDefault().getBuildEnvironmentManager()
.getVariables(project.getActiveBuildConfig(), true);
for (var variable : variables) {
if (path.equalsIgnoreCase(variable.getName())) {
map.put(path, variable.getValue());
break;
}
}
} catch (CoreException e) {
Plugin.getDefault().getLog().error(
String.format(Messages.CompilerBuiltinsDetector_errmsg_determine_PATH_failed, project.getName()),
e);
}
var map = getProjectEnvp(project);
// On POSIX (Linux, UNIX) systems reset language variables to default (English)
// with UTF-8 encoding since GNU compilers can handle only UTF-8 characters.
// Include paths with locale characters will be handled properly regardless
@ -227,6 +215,44 @@ public class CompilerBuiltinsDetector {
return envArray;
}
/**
* Return the project's environment. This applies any project specific environment
* to the system environment.
*/
private HashMap<String, String> getProjectEnvp(IProject project) {
var map = new HashMap<String, String>();
Properties environmentVariables = EnvironmentReader.getEnvVars();
for (String key : environmentVariables.stringPropertyNames()) {
String value = environmentVariables.getProperty(key);
map.put(key, value);
}
IBuildConfiguration active = null;
try {
active = project.getActiveBuildConfig();
if (active == null) {
// unreachable, getActiveBuildConfig is documented as not returning null.
} else {
var manager = CCorePlugin.getService(ICBuildConfigurationManager.class);
ICBuildConfiguration cBuildConfiguration = manager.getBuildConfiguration(active);
if (cBuildConfiguration != null) {
// If this project is Core Build, use its specialisation of getBuildEnvironmentManager
// to get the environment.
cBuildConfiguration.setBuildEnvironment(map);
} else {
CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(map, active, true);
}
}
} catch (CoreException e) {
Plugin.getDefault().getLog().error(
String.format(Messages.CompilerBuiltinsDetector_errmsg_determine_PATH_failed, project.getName()),
e);
}
return map;
}
/**
* Gets a path to the source file which is the input for the compiler. The file
* will be created with no content in the build directory.