Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added feature to generate compile_commands.json file #692

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.
@@ -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("build/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("build/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("build/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("build/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("build/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
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
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
jonahgraham marked this conversation as resolved.
Show resolved Hide resolved
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: com.google.gson;version="2.8.0"
Expand Down
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
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
@@ -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>
@@ -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) {
}
@@ -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);

}