Skip to content

Commit

Permalink
Added feature to generate compile_commands.json file (#692)
Browse files Browse the repository at this point in the history
Includes:

- Created a new extension point to provide the opportunity to
incorporate additional information into the file
- New tests for the generator
- Preference page to enable/disable generator

Fixes #689
  • Loading branch information
alicetrifu committed May 16, 2024
1 parent 237c326 commit 5ca5107
Show file tree
Hide file tree
Showing 44 changed files with 2,141 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ helloworldC.zip:
Basic standard Linux GCC C HelloWorld ManagedBuild Project template.
Contains Debug + Release configurations.

helloworldCPP.zip:
Minimal standard Linux GCC C++ HelloWorld ManagedBuild Project template
Contains Debug + Release configurations.

bug_335476.zip:
Test for noticing environment variable changes.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Marc-Andre Laperle.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.core.tests;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.FileReader;

import org.eclipse.cdt.managedbuilder.core.jsoncdb.CompilationDatabaseInformation;
import org.eclipse.cdt.managedbuilder.internal.core.CommonBuilder;
import org.eclipse.cdt.managedbuilder.testplugin.AbstractBuilderTest;
import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;

public class CompilationDatabaseGenerationTest extends AbstractBuilderTest {

/**
* Tests generation of compile_commands.json in "build" folder
*/
@Test
public void testCompilationDatabaseGeneration() throws Exception {
setWorkspace("regressions");
final IProject app = loadProject("helloworldC");
setGenerateFileOptionEnabled(true);
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
IFile compilationDatabase = app.getFile("Debug/compile_commands.json");
assertTrue(compilationDatabase.exists());
}

/**
* Tests format for compile_commands.json. JSON array is expected, containing an element for the c file
*/
@Test
public void testJsonFormat() throws Exception {
setWorkspace("regressions");
final IProject app = loadProject("helloworldC");
setGenerateFileOptionEnabled(true);
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
IFile commandsFile = app.getFile("Debug/compile_commands.json");
if (commandsFile.exists()) {

try (FileReader reader = new FileReader(commandsFile.getLocation().toFile())) {
Gson gson = new Gson();
JsonArray jsonArray = gson.fromJson(reader, JsonArray.class);
for (JsonElement element : jsonArray) {
CompilationDatabaseInformation compileCommand = gson.fromJson(element,
CompilationDatabaseInformation.class);

assertTrue(compileCommand.directory() != null && !compileCommand.directory().isEmpty());
assertTrue(compileCommand.command() != null && !compileCommand.command().isEmpty());
assertTrue(compileCommand.file() != null && !compileCommand.file().isEmpty());
assertTrue(compileCommand.file().endsWith("src/helloworldC.c"));
}

}

}
}

/**
* Test that compile_commands.json is correctly generated when more than one .c file is present as a source file
*/
@Test
public void testMultipleFiles() throws Exception {
setWorkspace("regressions");
final IProject app = loadProject("helloworldC");
IFile aFile = ManagedBuildTestHelper.createFile(app, "src/newFile.c");
setGenerateFileOptionEnabled(true);
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
IFile commandsFile = app.getFile("Debug/compile_commands.json");
int numberOfElementsFound = 0;
boolean helloworldCIsPresent = false;
boolean newFileIsPresent = false;
try (FileReader reader = new FileReader(commandsFile.getLocation().toFile())) {
Gson gson = new Gson();
JsonArray jsonArray = gson.fromJson(reader, JsonArray.class);
System.out.println(jsonArray);
for (JsonElement element : jsonArray) {
CompilationDatabaseInformation compileCommand = gson.fromJson(element,
CompilationDatabaseInformation.class);
numberOfElementsFound++;
if (compileCommand.file().endsWith("helloworldC.c")) {
helloworldCIsPresent = true;
}
if (compileCommand.file().endsWith("newFile.c")) {
newFileIsPresent = true;
}
}
assertEquals(2, numberOfElementsFound);
assertTrue(helloworldCIsPresent);
assertTrue(newFileIsPresent);
}
}

/**
* Tests that cpp files are handled by compile_commands.json file generator
*/
@Test
public void isCPPFileAllowed() throws Exception {
setWorkspace("regressions");
final IProject app = loadProject("helloworldCPP");
setGenerateFileOptionEnabled(true);
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
IFile commandsFile = app.getFile("Debug/compile_commands.json");
if (commandsFile.exists()) {

try (FileReader reader = new FileReader(commandsFile.getLocation().toFile())) {
Gson gson = new Gson();
JsonArray jsonArray = gson.fromJson(reader, JsonArray.class);
for (JsonElement element : jsonArray) {
CompilationDatabaseInformation compileCommand = gson.fromJson(element,
CompilationDatabaseInformation.class);

assertTrue(compileCommand.directory() != null && !compileCommand.directory().isEmpty());
assertTrue(compileCommand.command() != null && !compileCommand.command().isEmpty());
assertTrue(compileCommand.file() != null && !compileCommand.file().isEmpty());
assertTrue(compileCommand.file().endsWith("src/helloworldCPP.cpp"));
}

}
}
}

/**
* Tests that compilation database is not generated when feature is disabled
*/
@Test
public void testCompilationDatabaseGenerationNotEnabled() throws Exception {
setWorkspace("regressions");
final IProject app = loadProject("helloworldC");
setGenerateFileOptionEnabled(false);
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
IFile compilationDatabase = app.getFile("Debug/compile_commands.json");
assertFalse(compilationDatabase.exists());
}

private static void setGenerateFileOptionEnabled(boolean value) {
IPreferenceStore preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE,
"org.eclipse.cdt.managedbuilder.ui");
preferenceStore.setValue(CommonBuilder.COMPILATION_DATABASE_ENABLEMENT, value);
}

@AfterEach
public void restoreDefaultForGenerateFile() {
IPreferenceStore preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE,
"org.eclipse.cdt.managedbuilder.ui");
preferenceStore.setToDefault(CommonBuilder.COMPILATION_DATABASE_ENABLEMENT);
}
}
5 changes: 5 additions & 0 deletions build/org.eclipse.cdt.managedbuilder.core/.project
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -12,9 +12,11 @@ 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",
org.eclipse.cdt.managedbuilder.internal.core.jsoncdb.generator;x-internal:=true,
org.eclipse.cdt.managedbuilder.internal.dataprovider;x-internal:=true,
org.eclipse.cdt.managedbuilder.internal.envvar;x-internal:=true,
org.eclipse.cdt.managedbuilder.internal.language.settings.providers;x-friends:="org.eclipse.cdt.managedbuilder.ui",
Expand All @@ -39,7 +41,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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions build/org.eclipse.cdt.managedbuilder.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<extension-point id="projectConverter" name="%extension-point.name.1" schema="schema/Converter.exsd"/>
<extension-point id="buildProperties" name="%extension-point.name.2" schema="schema/buildProperties.exsd"/>
<extension-point id="tcModificationInfo" name="%extension-point.name.3" schema="schema/tcModificationInfo.exsd"/>
<extension-point id="compilationDatabaseContributor" name="%extension-point.name.4" schema="schema/compilationDatabaseContributor.exsd"/>



<!-- =================================================================================== -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.managedbuilder.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.managedbuilder.core" id="compilationDatabaseContributor" name="Compilation Database Contributor"/>
</appInfo>
<documentation>
This extension point allows to add specific information to compile_commands.json file.
</documentation>
</annotation>

<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<choice>
<element ref="compilationDatabase"/>
</choice>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="compilationDatabase">
<annotation>
<documentation>
Compilation Database for C/C++ projects
</documentation>
</annotation>
<complexType>
<attribute name="toolchainID" type="string" use="required">
<annotation>
<documentation>
Toolchain ID
</documentation>
</annotation>
</attribute>
<attribute name="runner" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.managedbuilder.core.jsoncdb.ICompilationDatabaseContributor"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>






</schema>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/********************************************************************************
* Copyright (c) 2023, 2024 Renesas Electronics Corp. 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) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/********************************************************************************
* Copyright (c) 2023, 2024 Renesas Electronics Europe. 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<CompilationDatabaseInformation> getAdditionalFiles(@NonNull IConfiguration config);

}

0 comments on commit 5ca5107

Please sign in to comment.