diff --git a/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF index 413d69ae823..d82ef0e4309 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF +++ b/build/org.eclipse.cdt.managedbuilder.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.core; singleton:=true -Bundle-Version: 9.6.300.qualifier +Bundle-Version: 9.7.0.qualifier Bundle-Activator: org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -12,6 +12,7 @@ Export-Package: org.eclipse.cdt.build.core.scannerconfig, org.eclipse.cdt.managedbuilder.buildmodel, org.eclipse.cdt.managedbuilder.buildproperties, org.eclipse.cdt.managedbuilder.core, + org.eclipse.cdt.managedbuilder.core.jsoncdb, org.eclipse.cdt.managedbuilder.envvar, org.eclipse.cdt.managedbuilder.internal.buildmodel;x-friends:="org.eclipse.cdt.managedbuilder.ui", org.eclipse.cdt.managedbuilder.internal.core;x-friends:="org.eclipse.cdt.managedbuilder.ui,org.eclipse.cdt.managedbuilder.headlessbuilderapp", @@ -39,7 +40,8 @@ Require-Bundle: org.eclipse.cdt.core;bundle-version="[8.3.0,9.0.0)", org.eclipse.ui;bundle-version="[3.2.0,4.0.0)", org.eclipse.core.variables;bundle-version="[3.1.100,4.0.0)", org.eclipse.cdt.make.core;visibility:=reexport, - org.eclipse.core.filesystem;bundle-version="1.2.0" + org.eclipse.core.filesystem;bundle-version="1.2.0", + org.eclipse.jdt.annotation;bundle-version="[2.2.7,3.0.0)";resolution:=optional Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: com.google.gson;version="2.8.0" diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.properties b/build/org.eclipse.cdt.managedbuilder.core/plugin.properties index 05c1695ec50..0e5591443c2 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/plugin.properties +++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.properties @@ -78,6 +78,7 @@ extension-point.name.0 = Managed Build Definitions extension-point.name.1 = Managed Build Project Converter extension-point.name.2 = Build Properties extension-point.name.3 = ToolChain Modification Info +extension-point.name.4 = Compilation Database Contributor GCCBuildOutputParser.name = CDT GCC Build Output Parser GCCBuiltinCompilerSettings.name = CDT GCC Built-in Compiler Settings diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml index f4892de8a22..076b3a70cc7 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml @@ -7,6 +7,8 @@ + + diff --git a/build/org.eclipse.cdt.managedbuilder.core/schema/compilationDatabaseContributor.exsd b/build/org.eclipse.cdt.managedbuilder.core/schema/compilationDatabaseContributor.exsd new file mode 100644 index 00000000000..5453c5de637 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/schema/compilationDatabaseContributor.exsd @@ -0,0 +1,84 @@ + + + + + + + + + This extension point allows to add specific information to compile_commands.json file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Compilation Database for C/C++ projects + + + + + + + Toolchain ID + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/CompilationDatabaseInformation.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/CompilationDatabaseInformation.java new file mode 100644 index 00000000000..10a44877e4e --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/CompilationDatabaseInformation.java @@ -0,0 +1,22 @@ +/******************************************************************************** + * Copyright (c) {date} {owner}[ and others] + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.cdt.managedbuilder.core.jsoncdb; + +/** + * The compilation database array of “command objects” members to be used for + * the extension point + * directory: The working directory of the compilation. + * command: The compile command. file: The main translation unit source + * processed by this compilation step. + * @since 9.7 + */ + +public record CompilationDatabaseInformation(String directory, String command, String file) { +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/ICompilationDatabaseContributor.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/ICompilationDatabaseContributor.java new file mode 100644 index 00000000000..9e6660a2e3c --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/ICompilationDatabaseContributor.java @@ -0,0 +1,33 @@ +/******************************************************************************** + * Copyright (c) {date} {owner}[ and others] + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.cdt.managedbuilder.core.jsoncdb; + +import java.util.List; + +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.jdt.annotation.NonNull; + +/** + * @since 9.7 + */ +public interface ICompilationDatabaseContributor { + + /** + * @param config + * Adds a new list of files to the compilation database + * Implementors should provide concrete implementations of this + * interface. IConfiguration will be taken as input, accessing the project and will generate a list of + * additional files to be added to compile_commands.json + * @return A non-null list of files that will be added to compilation database + */ + @NonNull + public List getAdditionalFiles(@NonNull IConfiguration config); + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseContributionManager.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseContributionManager.java new file mode 100644 index 00000000000..206d692e03c --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseContributionManager.java @@ -0,0 +1,126 @@ +/******************************************************************************** + * Copyright (c) {date} {owner}[ and others] + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.cdt.managedbuilder.core.jsoncdb.generator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IToolChain; +import org.eclipse.cdt.managedbuilder.core.jsoncdb.ICompilationDatabaseContributor; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.NonNull; + +public class CompilationDatabaseContributionManager { + private static final String ATTRIB_RUNNER = "runner"; //$NON-NLS-1$ + private static final String ATTRIB_TOOLCHAIN_ID = "toolchainID"; //$NON-NLS-1$ + private static final String ID_COMPILATIONDATABASE = "compilationDatabase"; //$NON-NLS-1$ + private static final String EXTENSION_ID = "compilationDatabaseContributor"; //$NON-NLS-1$ + private Map factoryExtensions; + @NonNull + private Map loadedInstances; + + private static CompilationDatabaseContributionManager instance; + + private CompilationDatabaseContributionManager() { + factoryExtensions = new HashMap<>(); + loadedInstances = new HashMap<>(); + initalise(); + } + + public static synchronized CompilationDatabaseContributionManager getInstance() { + if (CompilationDatabaseContributionManager.instance == null) { + CompilationDatabaseContributionManager.instance = new CompilationDatabaseContributionManager(); + } + return CompilationDatabaseContributionManager.instance; + } + + private void initalise() { + Map loadedExtension = new HashMap<>(); + + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint( + "org.eclipse.cdt.managedbuilder.core", CompilationDatabaseContributionManager.EXTENSION_ID); //$NON-NLS-1$ + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (IExtension extension2 : extensions) { + IConfigurationElement[] configElements = extension2.getConfigurationElements(); + for (IConfigurationElement configElement : configElements) { + if (CompilationDatabaseContributionManager.ID_COMPILATIONDATABASE.equals(configElement.getName())) { // $NON-NLS-1$ + String toolchainId = configElement + .getAttribute(CompilationDatabaseContributionManager.ATTRIB_TOOLCHAIN_ID); + String className = configElement + .getAttribute(CompilationDatabaseContributionManager.ATTRIB_RUNNER); + if (toolchainId != null && className != null) { + loadedExtension.put(toolchainId, configElement); + } + } + } + } + } + + factoryExtensions = loadedExtension; + } + + /** + * Get the Code Assist tool with the specified id + * + * @param id + * @return Tool extension or a list with no element if not found. + * @throws CoreException + */ + + @NonNull + public synchronized ICompilationDatabaseContributor getCompilationDatabaseContributor( + @NonNull IConfiguration config) { + IToolChain toolChain = config.getToolChain(); + while (toolChain != null) { + String toolchainId = toolChain.getBaseId(); + if (loadedInstances.containsKey(toolchainId)) { + ICompilationDatabaseContributor contributor = loadedInstances.get(toolchainId); + Assert.isNotNull(contributor); + return contributor; + } else if (factoryExtensions.containsKey(toolchainId)) { + return createCdbInstance(toolchainId); + } else { + toolChain = toolChain.getSuperClass(); + } + } + return x -> new ArrayList<>(); + } + + @NonNull + private ICompilationDatabaseContributor createCdbInstance(String toolchainId) { + IConfigurationElement ele = factoryExtensions.get(toolchainId); + if (ele != null) { + ICompilationDatabaseContributor loaded = null; + try { + loaded = (ICompilationDatabaseContributor) ele + .createExecutableExtension(CompilationDatabaseContributionManager.ATTRIB_RUNNER); + + } catch (CoreException e) { + Platform.getLog(getClass()).log(Status.error("Not able to create instance", e)); //$NON-NLS-1$ + } + if (loaded == null) { + loaded = x -> new ArrayList<>(); + } + loadedInstances.put(toolchainId, loaded); + return loaded; + } + return x -> new ArrayList<>(); + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseGenerator.java new file mode 100644 index 00000000000..ec6aba29e24 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseGenerator.java @@ -0,0 +1,419 @@ +/******************************************************************************** + * Copyright (c) {date} {owner}[ and others] + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.cdt.managedbuilder.core.jsoncdb.generator; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; + +import org.eclipse.cdt.core.settings.model.ICSourceEntry; +import org.eclipse.cdt.core.settings.model.util.CDataUtil; +import org.eclipse.cdt.managedbuilder.core.BuildException; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IFileInfo; +import org.eclipse.cdt.managedbuilder.core.IFolderInfo; +import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineGenerator; +import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineInfo; +import org.eclipse.cdt.managedbuilder.core.IOutputType; +import org.eclipse.cdt.managedbuilder.core.IResourceInfo; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.core.jsoncdb.CompilationDatabaseInformation; +import org.eclipse.cdt.managedbuilder.core.jsoncdb.ICompilationDatabaseContributor; +import org.eclipse.cdt.managedbuilder.internal.macros.FileContextData; +import org.eclipse.cdt.managedbuilder.macros.BuildMacroException; +import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceProxy; +import org.eclipse.core.resources.IResourceProxyVisitor; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class CompilationDatabaseGenerator { + + private static final String CDB_FILENAME = "compile_commands.json"; //$NON-NLS-1$ + private static final String BUILD_FOLDER = "build"; //$NON-NLS-1$ + private static final String ERROR_MESSAGE = "Can not set contents to compile_commands.json file"; //$NON-NLS-1$ + + private IProject project; + private IConfiguration configuration; + private ICSourceEntry[] srcEntries; + private Collection fileList; + + public CompilationDatabaseGenerator(IProject proj, IConfiguration config) { + project = proj; + configuration = config; + srcEntries = config.getSourceEntries(); + } + + /** + * @param proj + * Creates and populates compilation database file + * @param config + */ + public void generate() { + + IPath buildDirectory = project.getFullPath() + .append(IPath.SEPARATOR + CompilationDatabaseGenerator.BUILD_FOLDER); + IPath compilationDatabasePath = buildDirectory + .append(IPath.SEPARATOR + CompilationDatabaseGenerator.CDB_FILENAME); + try { + if (!buildDirectory.toFile().exists()) { + createDirectory(CompilationDatabaseGenerator.BUILD_FOLDER); + } + IFile compileCommandsFile = createFile(compilationDatabasePath); + addToCompilationdatabase(project, compileCommandsFile, configuration); + + } catch (CoreException e) { + Platform.getLog(getClass()) + .log(Status.error("Unable to initialize the creation of compile_commands.json file", e)); //$NON-NLS-1$ + } + + } + + private IFile createFile(IPath compilationDatabasePath) throws CoreException { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IFile newFile = workspace.getRoot().getFile(compilationDatabasePath); + try { + if (!newFile.exists()) { + try (InputStream inputStream = new ByteArrayInputStream("".getBytes())) { //$NON-NLS-1$ + newFile.create(inputStream, true, null); + } + } else { + try (InputStream inputStream = new ByteArrayInputStream("".getBytes())) { //$NON-NLS-1$ + newFile.setContents(inputStream, true, false, null); + } + } + + } catch (Exception e) { + IStatus status = new Status(IStatus.ERROR, getClass(), CompilationDatabaseGenerator.ERROR_MESSAGE, e); + Platform.getLog(getClass()).log(status); + } + + return newFile; + } + + private void addToCompilationdatabase(IProject project, IFile compileCommandsFile, @NonNull IConfiguration config) + throws CoreException { + List objList = new ArrayList<>(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + ResourceProxyVisitor resourceVisitor = new ResourceProxyVisitor(this, config); + project.accept(resourceVisitor, IResource.NONE); + try { + objList.addAll(populateObjList(project, config)); + objList.addAll(getRunnerForToolchain(config).getAdditionalFiles(config)); + CompilationDatabaseGenerator.save(gson.toJson(objList), compileCommandsFile); + } catch (Exception e) { + IStatus status = new Status(IStatus.ERROR, getClass(), CompilationDatabaseGenerator.ERROR_MESSAGE, e); + Platform.getLog(getClass()).log(status); + } + } + + private static void save(String buffer, IFile file) throws CoreException { + byte[] bytes = buffer.getBytes(StandardCharsets.UTF_8); + ByteArrayInputStream stream = new ByteArrayInputStream(bytes); + boolean force = true; + file.setContents(stream, force, false, null); // Don't record history + } + + @NonNull + private ICompilationDatabaseContributor getRunnerForToolchain(@NonNull IConfiguration config) throws CoreException { + return CompilationDatabaseContributionManager.getInstance().getCompilationDatabaseContributor(config); + } + + private List populateObjList(IProject project, IConfiguration config) + throws CoreException, BuildException { + List objList = new ArrayList<>(); + for (IResource resource : getFileList()) { + + IPath moduleRelativePath = resource.getParent().getProjectRelativePath(); + String relativePath = moduleRelativePath.toString(); + IFolder folder = project.getFolder(config.getName()); + IPath sourceLocation = getPathForResource(resource); + String ext = sourceLocation.getFileExtension(); + IResourceInfo rcInfo = config.getResourceInfo(resource.getProjectRelativePath(), false); + ITool tool = null; + if (rcInfo instanceof IFileInfo fi) { + ITool[] tools = fi.getToolsToInvoke(); + if (tools != null && tools.length > 0) { + tool = tools[0]; + for (ITool tool2 : tools) { + if (!tool2.getCustomBuildStep()) { + tool = tool2; + break; + } + } + } + } else if (rcInfo instanceof IFolderInfo foInfo) { + tool = foInfo.getToolFromInputExtension(ext); + } + + if (tool != null) { + + ArrayList enumeratedPrimaryOutputs = new ArrayList<>(); + calculateOutputsForSource(tool, relativePath, sourceLocation, enumeratedPrimaryOutputs); + ArrayList inputs = new ArrayList<>(); + inputs.add(resource.getLocation().toString()); + + IPath[] addlInputPaths = tool.getAdditionalDependencies(); + for (IPath addlInputPath : addlInputPaths) { + + IPath addlPath = addlInputPath; + if (!(addlPath.toString().startsWith("$(")) && !addlPath.isAbsolute()) { //$NON-NLS-1$ + IPath tempPath = getPathForResource(project).append(addlPath); + if (tempPath != null) { + addlPath = ManagedBuildManager.calculateRelativePath(folder.getLocation(), tempPath); + } + } + inputs.add(addlPath.toString()); + } + String[] inputStrings = inputs.toArray(new String[inputs.size()]); + String primaryOutputName = null; + String resourceName = sourceLocation.removeFileExtension().lastSegment(); + if (!enumeratedPrimaryOutputs.isEmpty()) { + if (enumeratedPrimaryOutputs.size() > 1) { + StringBuilder resultBuilder = new StringBuilder(); + for (IPath outputPath : enumeratedPrimaryOutputs) { + resultBuilder.append(outputPath.toString()).append(" "); //$NON-NLS-1$ + } + primaryOutputName = resultBuilder.toString().trim(); + } else { + primaryOutputName = enumeratedPrimaryOutputs.get(0).toString(); + } + } else { + primaryOutputName = relativePath + IPath.SEPARATOR + resourceName + ".o"; //$NON-NLS-1$ + } + IPath outputLocation = Path.fromOSString(primaryOutputName); + if (!outputLocation.isAbsolute()) { + outputLocation = getPathForResource(project).append(folder.getName()).append(primaryOutputName); + } + String outflag = tool.getOutputFlag(); + String outputPrefix = tool.getOutputPrefix(); + String[] flags = tool.getToolCommandFlags(sourceLocation, folder.getFullPath()); + IManagedCommandLineInfo cmdLInfo = generateToolCommandLineInfo(tool, flags, outflag, outputPrefix, + outputLocation + "", inputStrings, sourceLocation, outputLocation); //$NON-NLS-1$ + + IBuildMacroProvider provider = ManagedBuildManager.getBuildMacroProvider(); + String resolvedOptionFileContents = provider.resolveValueToMakefileFormat(cmdLInfo.getCommandLine(), "", //$NON-NLS-1$ + " ", IBuildMacroProvider.CONTEXT_FILE, //$NON-NLS-1$ + new FileContextData(sourceLocation, outputLocation, null, tool)); + + objList.add(new CompilationDatabaseInformation(project.getLocation().toString(), + resolvedOptionFileContents, resource.getLocation().toString())); + } + + } + return objList; + + } + + private IManagedCommandLineInfo generateToolCommandLineInfo(ITool tool, String[] flags, String outputFlag, + String outputPrefix, String outputName, String[] inputResources, IPath inputLocation, + IPath outputLocation) { + + String cmd = tool.getToolCommand(); + try { + String resolvedCommand = null; + + if ((inputLocation != null && inputLocation.toString().indexOf(" ") != -1) || //$NON-NLS-1$ + (outputLocation != null && outputLocation.toString().indexOf(" ") != -1)) { //$NON-NLS-1$ + resolvedCommand = ManagedBuildManager.getBuildMacroProvider().resolveValue(cmd, "", //$NON-NLS-1$ + " ", //$NON-NLS-1$ + IBuildMacroProvider.CONTEXT_FILE, + new FileContextData(inputLocation, outputLocation, null, tool)); + } else { + resolvedCommand = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat(cmd, "", //$NON-NLS-1$ + " ", //$NON-NLS-1$ + IBuildMacroProvider.CONTEXT_FILE, + new FileContextData(inputLocation, outputLocation, null, tool)); + } + if ((resolvedCommand = resolvedCommand.trim()).length() > 0) { + cmd = resolvedCommand; + } + + } catch (BuildMacroException e) { + Platform.getLog(getClass()).log(Status.error(CompilationDatabaseGenerator.ERROR_MESSAGE, e)); + } + + IManagedCommandLineGenerator gen = tool.getCommandLineGenerator(); + return gen.generateCommandLineInfo(tool, cmd, flags, outputFlag, outputPrefix, outputName, inputResources, + tool.getCommandLinePattern()); + + } + + private void calculateOutputsForSource(ITool tool, String relativePath, IPath sourceLocation, + ArrayList enumeratedPrimaryOutputs) { + + IOutputType[] outTypes = tool.getOutputTypes(); + if (outTypes != null && outTypes.length > 0) { + IOutputType type = tool.getPrimaryOutputType(); + boolean primaryOutput = (type == tool.getPrimaryOutputType()); + String[] extensions = type.getOutputExtensions(tool); + if (primaryOutput) { + for (String extension : extensions) { + String prefix = type.getOutputPrefix(); + String fileName = sourceLocation.removeFileExtension().lastSegment(); + IPath outPath = Path.fromOSString(relativePath + IPath.SEPARATOR + prefix + fileName); + outPath = outPath.addFileExtension(extension); + enumeratedPrimaryOutputs.add(0, outPath); + + } + } + } + } + + private IPath getPathForResource(IResource resource) { + return new Path(resource.getLocationURI().getPath()); + } + + private boolean isSource(IPath path) { + return !CDataUtil.isExcluded(path, srcEntries); + } + + private void appendFileList(IResource resource) { + getFileList().add(resource); + } + + private Collection getFileList() { + if (fileList == null) { + fileList = new LinkedHashSet<>(); + } + return fileList; + } + + private boolean isGeneratedResource(IResource resource) { + // Is this a generated directory ... + IPath path = resource.getProjectRelativePath(); + String[] configNames = ManagedBuildManager.getBuildInfo(project).getConfigurationNames(); + for (String name : configNames) { + IPath root = new Path(name); + // It is if it is a root of the resource pathname + if (root.isPrefixOf(path)) { + return true; + } + } + + return false; + } + + private IPath createDirectory(String dirName) throws CoreException { + // Create or get the handle for the build directory + IFolder folder = project.getFolder(dirName); + if (!folder.exists()) { + // Make sure that parent folders exist + IPath parentPath = (new Path(dirName)).removeLastSegments(1); + // Assume that the parent exists if the path is empty + if (!parentPath.isEmpty()) { + IFolder parent = project.getFolder(parentPath); + if (!parent.exists()) { + createDirectory(parentPath.toString()); + } + } + + // Now make the requested folder + try { + folder.create(true, true, null); + } catch (CoreException e) { + if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED) { + folder.refreshLocal(IResource.DEPTH_ZERO, null); + } else { + throw e; + } + } + + // Make sure the folder is marked as derived so it is not added to CM + if (!folder.isDerived()) { + folder.setDerived(true, null); + } + } + + return folder.getFullPath(); + } + + /** + * This class is used to recursively walk the project and determine which + * modules contribute buildable source files. + */ + private class ResourceProxyVisitor implements IResourceProxyVisitor { + private final CompilationDatabaseGenerator generator; + private final IConfiguration config; + + public ResourceProxyVisitor(CompilationDatabaseGenerator generator, IConfiguration cfg) { + this.generator = generator; + this.config = cfg; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core. + * resources.IResourceProxy) + */ + @Override + public boolean visit(IResourceProxy proxy) throws CoreException { + // No point in proceeding, is there + if (generator == null) { + return false; + } + + IResource resource = proxy.requestResource(); + boolean isSource = isSource(resource.getProjectRelativePath()); + + // Is this a resource we should even consider + if (proxy.getType() == IResource.FILE) { + // If this resource has a Resource Configuration and is not excluded or + // if it has a file extension that one of the tools builds, add the sudirectory + // to the list + IResourceInfo rcInfo = config.getResourceInfo(resource.getProjectRelativePath(), false); + if (isSource/* && !rcInfo.isExcluded() */) { + if (rcInfo instanceof IFolderInfo) { + String ext = resource.getFileExtension(); + boolean buildFile = ((IFolderInfo) rcInfo).buildsFileType(ext); + if (buildFile && + // If this file resource is a generated resource, then it is uninteresting + !generator.isGeneratedResource(resource)) { + + generator.appendFileList(resource); + } + } else { + generator.appendFileList(resource); + } + } + } else if (proxy.getType() == IResource.FOLDER) { + + if (!isSource || generator.isGeneratedResource(resource)) { + return false; + } + return true; + } + return true; + } + + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java index 2d6c149f7ce..e470b70ab08 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java @@ -51,6 +51,7 @@ import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.managedbuilder.core.jsoncdb.generator.CompilationDatabaseGenerator; import org.eclipse.cdt.managedbuilder.internal.buildmodel.BuildDescription; import org.eclipse.cdt.managedbuilder.internal.buildmodel.BuildStateManager; import org.eclipse.cdt.managedbuilder.internal.buildmodel.IBuildModelBuilder; @@ -505,6 +506,8 @@ private IProject[] build(int kind, IProject project, IBuilder[] builders, boolea } for (int i = 0; i < num; i++) { + CompilationDatabaseGenerator generator = new CompilationDatabaseGenerator(getProject(), activeCfg); + generator.generate(); //bug 219337 if (kind == INCREMENTAL_BUILD || kind == AUTO_BUILD) { if (buildConfigResourceChanges()) { //only build projects with project resource changes