diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java')
-rw-r--r-- | core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java | 261 |
1 files changed, 82 insertions, 179 deletions
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java index d0b6c275aa6..039e1a4518b 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2019 QNX Software Systems and others. + * Copyright (c) 2015, 2022 QNX Software Systems and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,16 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.core.build; -import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.lang.reflect.Type; import java.net.URI; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -28,16 +22,17 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Map.Entry; +import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CommandLauncherManager; +import org.eclipse.cdt.core.ICommandLauncher; import org.eclipse.cdt.core.IConsoleParser; import org.eclipse.cdt.core.IConsoleParser2; import org.eclipse.cdt.core.IMarkerGenerator; @@ -61,12 +56,14 @@ import org.eclipse.cdt.core.parser.ExtendedScannerInfo; import org.eclipse.cdt.core.parser.IExtendedScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; -import org.eclipse.cdt.core.parser.IncludeExportPatterns; import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.internal.core.BuildRunnerHelper; +import org.eclipse.cdt.internal.core.ConsoleOutputSniffer; import org.eclipse.cdt.internal.core.build.Messages; import org.eclipse.cdt.internal.core.model.BinaryRunner; import org.eclipse.cdt.internal.core.model.CModelManager; -import org.eclipse.cdt.internal.core.parser.ParserSettings2; +import org.eclipse.cdt.internal.core.scannerinfo.ExtendedScannerInfoSerializer; +import org.eclipse.cdt.internal.core.scannerinfo.IExtendedScannerInfoDeserializer; import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.cdt.utils.spawner.EnvironmentReader; import org.eclipse.core.filesystem.URIUtil; @@ -92,12 +89,6 @@ import org.osgi.service.prefs.Preferences; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; /** * Root class for CDT build configurations. Provides access to the build @@ -124,6 +115,8 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu private final Map<IResource, List<IScannerInfoChangeListener>> scannerInfoListeners = new HashMap<>(); private ScannerInfoCache scannerInfoCache; + private ICommandLauncher launcher; + protected CBuildConfiguration(IBuildConfiguration config, String name) throws CoreException { this.config = config; this.name = name; @@ -496,7 +489,8 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu .write(String.format(Messages.CBuildConfiguration_CommandNotFound, commands.get(0))); return null; } - commands.set(0, commandPath.toString()); + IPath cmd = new org.eclipse.core.runtime.Path(commandPath.toString()); + List<String> args = commands.subList(1, commands.size()); // check if includes have been removed/refreshed and scanner info refresh is needed boolean needRefresh = CommandLauncherManager.getInstance().checkIfIncludesChanged(this); @@ -505,18 +499,28 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu t.setProperty(NEED_REFRESH, Boolean.valueOf(needRefresh).toString()); } - ProcessBuilder processBuilder = new ProcessBuilder(commands).directory(buildDirectory.toFile()); - // Override environment variables - Map<String, String> environment = processBuilder.environment(); + // Generate environment block before launching process + launcher = CommandLauncherManager.getInstance().getCommandLauncher(this); + Properties envProps = launcher.getEnvironment(); + HashMap<String, String> environment = envProps.entrySet().stream() + .collect(Collectors.toMap(e -> String.valueOf(e.getKey()), e -> String.valueOf(e.getValue()), + (prev, next) -> next, HashMap::new)); for (IEnvironmentVariable envVar : envVars) { environment.put(envVar.getName(), envVar.getValue()); } setBuildEnvironment(environment); - process = processBuilder.start(); + launcher.setProject(getProject()); + process = launcher.execute(cmd, args.toArray(new String[0]), BuildRunnerHelper.envMapToEnvp(environment), + buildDirectory, monitor); } return process; } + /** + * @return The exit code of the build process. + * + * @deprecated use {@link #watchProcess(IConsole, IProgressMonitor)} or {@link #watchProcess(IConsoleParser[], IProgressMonitor)} instead + */ @Deprecated protected int watchProcess(Process process, IConsoleParser[] consoleParsers, IConsole console) throws CoreException { @@ -528,110 +532,42 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu } /** + * @return The exit code of the build process. * @since 6.4 + * + * @deprecated use {@link #watchProcess(IConsole, IProgressMonitor)} instead and pass in a monitor */ + @Deprecated protected int watchProcess(Process process, IConsole console) throws CoreException { - Thread t1 = new ReaderThread(process.getInputStream(), console.getOutputStream()); - t1.start(); - Thread t2 = new ReaderThread(process.getErrorStream(), console.getErrorStream()); - t2.start(); - try { - int rc = process.waitFor(); - // Allow reader threads the chance to process all output to console - while (t1.isAlive()) { - Thread.sleep(100); - } - while (t2.isAlive()) { - Thread.sleep(100); - } - return rc; - } catch (InterruptedException e) { - CCorePlugin.log(e); - return -1; - } + return watchProcess(console, new NullProgressMonitor()); } /** + * @return The exit code of the build process. + * @since 7.5 + */ + protected int watchProcess(IConsole console, IProgressMonitor monitor) throws CoreException { + return launcher.waitAndRead(console.getInfoStream(), console.getErrorStream(), monitor); + } + + /** + * @return The exit code of the build process. * @since 6.4 + * + * @deprecated use {@link #watchProcess(IConsoleParser[], IProgressMonitor)} instead and pass in a monitor */ + @Deprecated protected int watchProcess(Process process, IConsoleParser[] consoleParsers) throws CoreException { - Thread t1 = new ReaderThread(this, process.getInputStream(), consoleParsers); - t1.start(); - Thread t2 = new ReaderThread(this, process.getErrorStream(), consoleParsers); - t2.start(); - try { - int rc = process.waitFor(); - // Allow reader threads the chance to process all output to console - while (t1.isAlive()) { - Thread.sleep(100); - } - while (t2.isAlive()) { - Thread.sleep(100); - } - return rc; - } catch (InterruptedException e) { - CCorePlugin.log(e); - return -1; - } + return watchProcess(consoleParsers, new NullProgressMonitor()); } - private static class ReaderThread extends Thread { - CBuildConfiguration config; - private final BufferedReader in; - private final IConsoleParser[] consoleParsers; - private final PrintStream out; - - public ReaderThread(CBuildConfiguration config, InputStream in, IConsoleParser[] consoleParsers) { - this.config = config; - this.in = new BufferedReader(new InputStreamReader(in)); - this.out = null; - this.consoleParsers = consoleParsers; - } - - public ReaderThread(InputStream in, OutputStream out) { - this.in = new BufferedReader(new InputStreamReader(in)); - this.out = new PrintStream(out); - this.consoleParsers = null; - this.config = null; - } - - @Override - public void run() { - List<Job> jobList = new ArrayList<>(); - try { - for (String line = in.readLine(); line != null; line = in.readLine()) { - if (consoleParsers != null) { - for (IConsoleParser consoleParser : consoleParsers) { - // Synchronize to avoid interleaving of lines - synchronized (consoleParser) { - // if we have an IConsoleParser2, use the processLine method that - // takes a job list (Container Build support) - if (consoleParser instanceof IConsoleParser2) { - ((IConsoleParser2) consoleParser).processLine(line, jobList); - } else { - consoleParser.processLine(line); - } - } - } - } - if (out != null) { - out.println(line); - } - } - for (Job j : jobList) { - try { - j.join(); - } catch (InterruptedException e) { - // ignore - } - } - if (config != null) { - config.shutdown(); - } - } catch (IOException e) { - CCorePlugin.log(e); - } - } + /** + * @return The exit code of the build process. + * @since 7.5 + */ + protected int watchProcess(IConsoleParser[] consoleParsers, IProgressMonitor monitor) throws CoreException { + ConsoleOutputSniffer sniffer = new ConsoleOutputSniffer(consoleParsers); + return launcher.waitAndRead(sniffer.getOutputStream(), sniffer.getErrorStream(), monitor); } private File getScannerInfoCacheFile() { @@ -639,63 +575,6 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu .append(getProject().getName()).append(name + ".json").toFile(); //$NON-NLS-1$ } - private static class IExtendedScannerInfoCreator implements JsonDeserializer<IExtendedScannerInfo> { - @Override - public IExtendedScannerInfo deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) - throws JsonParseException { - JsonObject infoObj = element.getAsJsonObject(); - - Map<String, String> definedSymbols = null; - if (infoObj.has("definedSymbols")) { //$NON-NLS-1$ - JsonObject definedSymbolsObj = infoObj.get("definedSymbols").getAsJsonObject(); //$NON-NLS-1$ - definedSymbols = new HashMap<>(); - for (Entry<String, JsonElement> entry : definedSymbolsObj.entrySet()) { - definedSymbols.put(entry.getKey(), entry.getValue().getAsString()); - } - } - - String[] includePaths = null; - if (infoObj.has("includePaths")) { //$NON-NLS-1$ - JsonArray includePathsArray = infoObj.get("includePaths").getAsJsonArray(); //$NON-NLS-1$ - List<String> includePathsList = new ArrayList<>(includePathsArray.size()); - for (Iterator<JsonElement> i = includePathsArray.iterator(); i.hasNext();) { - includePathsList.add(i.next().getAsString()); - } - includePaths = includePathsList.toArray(new String[includePathsList.size()]); - } - - IncludeExportPatterns includeExportPatterns = null; - if (infoObj.has("includeExportPatterns")) { //$NON-NLS-1$ - JsonObject includeExportPatternsObj = infoObj.get("includeExportPatterns").getAsJsonObject(); //$NON-NLS-1$ - String exportPattern = null; - if (includeExportPatternsObj.has("includeExportPattern")) { //$NON-NLS-1$ - exportPattern = includeExportPatternsObj.get("includeExportPattern") //$NON-NLS-1$ - .getAsJsonObject().get("pattern").getAsString(); //$NON-NLS-1$ - } - - String beginExportsPattern = null; - if (includeExportPatternsObj.has("includeBeginExportPattern")) { //$NON-NLS-1$ - beginExportsPattern = includeExportPatternsObj.get("includeBeginExportPattern") //$NON-NLS-1$ - .getAsJsonObject().get("pattern").getAsString(); //$NON-NLS-1$ - } - - String endExportsPattern = null; - if (includeExportPatternsObj.has("includeEndExportPattern")) { //$NON-NLS-1$ - endExportsPattern = includeExportPatternsObj.get("includeEndExportPattern") //$NON-NLS-1$ - .getAsJsonObject().get("pattern").getAsString(); //$NON-NLS-1$ - } - - includeExportPatterns = new IncludeExportPatterns(exportPattern, beginExportsPattern, - endExportsPattern); - } - - ExtendedScannerInfo info = new ExtendedScannerInfo(definedSymbols, includePaths); - info.setIncludeExportPatterns(includeExportPatterns); - info.setParserSettings(new ParserSettings2()); - return info; - } - } - /** * @since 6.1 */ @@ -705,15 +584,14 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu File cacheFile = getScannerInfoCacheFile(); if (cacheFile.exists()) { try (FileReader reader = new FileReader(cacheFile)) { - GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(IExtendedScannerInfo.class, new IExtendedScannerInfoCreator()); - Gson gson = gsonBuilder.create(); + Gson gson = createGson(); scannerInfoCache = gson.fromJson(reader, ScannerInfoCache.class); } catch (IOException e) { CCorePlugin.log(e); - scannerInfoCache = new ScannerInfoCache(); } - } else { + } + + if (scannerInfoCache == null) { scannerInfoCache = new ScannerInfoCache(); } scannerInfoCache.initCache(); @@ -721,6 +599,14 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu } } + private Gson createGson() { + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(IExtendedScannerInfo.class, new IExtendedScannerInfoDeserializer()); + gsonBuilder.registerTypeAdapter(ExtendedScannerInfo.class, new ExtendedScannerInfoSerializer()); + Gson gson = gsonBuilder.create(); + return gson; + } + /** * @since 6.1 */ @@ -736,7 +622,7 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu } try (FileWriter writer = new FileWriter(getScannerInfoCacheFile())) { - Gson gson = new Gson(); + Gson gson = createGson(); synchronized (scannerInfoLock) { gson.toJson(scannerInfoCache, writer); } @@ -787,7 +673,24 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu synchronized (scannerInfoLock) { info = scannerInfoCache.getScannerInfo(resource); } - if (info == null || info.getIncludePaths().length == 0) { + // Following is a kludge to fix Bug 579668 whereby sometimes a timing + // bug occurs and scanner info for a project that specifies a container target + // has not initialized the include paths correctly to point to copied includes + // from the image target. We check to see if org.eclipse.cdt.docker.launcher is + // found in the include paths which is the .plugin directory where we copy headers + // to in the .metadata folder. + boolean needsFixing = false; + if (info != null && info.getIncludePaths().length > 0 && toolChain != null + && toolChain.getId().startsWith("gcc-img-sha")) { //$NON-NLS-1$ + needsFixing = true; + for (String includePath : info.getIncludePaths()) { + if (includePath.contains("org.eclipse.cdt.docker.launcher")) { //$NON-NLS-1$ + needsFixing = false; + break; + } + } + } + if (info == null || info.getIncludePaths().length == 0 || needsFixing) { ICElement celement = CCorePlugin.getDefault().getCoreModel().create(resource); if (celement instanceof ITranslationUnit) { try { |