1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Add settings to Makefile build configs to build at project root.

Often Makefile projects are intended to be built from the project
root directory, such as ESP32 IDF projects. This adds a setting to
control that.

Change-Id: I151ebf60a7609461d24e192a9d6418fccb737055
This commit is contained in:
Doug Schaefer 2017-11-09 14:13:35 -05:00
parent 18f76e8313
commit 45019ea780
9 changed files with 280 additions and 18 deletions

View file

@ -197,7 +197,7 @@
<extension
point="org.eclipse.cdt.core.buildConfigProvider">
<provider
class="org.eclipse.cdt.make.internal.core.MakefileBuildConfigurationProvider"
class="org.eclipse.cdt.make.core.MakefileBuildConfigurationProvider"
id="org.eclipse.cdt.make.core.provider"
natureId="org.eclipse.cdt.make.core.makeNature">
</provider>

View file

@ -5,19 +5,21 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.cdt.make.internal.core;
package org.eclipse.cdt.make.core;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.ICBuildConfigurationManager;
import org.eclipse.cdt.core.build.ICBuildConfigurationProvider;
import org.eclipse.cdt.core.build.IToolChain;
import org.eclipse.cdt.core.build.StandardBuildConfiguration;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* @since 7.4
*/
public class MakefileBuildConfigurationProvider implements ICBuildConfigurationProvider {
public static final String ID = "org.eclipse.cdt.make.core.provider"; //$NON-NLS-1$

View file

@ -1,11 +1,16 @@
PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
OBJS = ${projectName}.o
all: ${projectName}
${projectName}: $(OBJS)
$(CC) -o $@ $^
$(CXX) -o $@ $^
%.o: ../../%.cpp
%.o: $(PROJECT_ROOT)%.cpp
$(CXX) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
%.o: $(PROJECT_ROOT)%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
clean:

View file

@ -37,7 +37,8 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.2.0,4.0.0)",
org.eclipse.compare;bundle-version="[3.3.0,4.0.0)",
org.eclipse.core.filesystem;bundle-version="1.2.0",
org.eclipse.tools.templates.ui;bundle-version="1.1.1",
org.eclipse.tools.templates.freemarker;bundle-version="1.0.0"
org.eclipse.tools.templates.freemarker;bundle-version="1.0.0",
org.eclipse.cdt.launch;bundle-version="9.2.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.ibm.icu.text

View file

@ -651,4 +651,11 @@
label="Make">
</tag>
</extension>
<extension
point="org.eclipse.cdt.launch.coreBuildTab">
<provider
nature="org.eclipse.cdt.make.core.makeNature"
tabClass="org.eclipse.cdt.make.internal.ui.MakeBuildSettingsTab">
</provider>
</extension>
</plugin>

View file

@ -0,0 +1,149 @@
/*******************************************************************************
* Copyright (c) 2017 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.cdt.make.internal.ui;
import java.util.Map;
import org.eclipse.cdt.core.build.ICBuildConfiguration;
import org.eclipse.cdt.core.build.StandardBuildConfiguration;
import org.eclipse.cdt.launch.ui.corebuild.CommonBuildTab;
import org.eclipse.cdt.make.core.MakefileBuildConfigurationProvider;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
public class MakeBuildSettingsTab extends CommonBuildTab {
private Button projectButton;
private Button configButton;
private boolean defaultProject;
@Override
protected String getBuildConfigProviderId() {
return MakefileBuildConfigurationProvider.ID;
}
@Override
public void createControl(Composite parent) {
Composite comp = new Composite(parent, SWT.NONE);
comp.setLayout(new GridLayout());
setControl(comp);
// Toolchain selector
Control tcControl = createToolchainSelector(comp);
tcControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
// Build Output Group
Group group = new Group(comp, SWT.NONE);
group.setText("Build Output Location");
group.setLayout(new GridLayout());
group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
projectButton = new Button(group, SWT.RADIO);
projectButton.setText("Build in project directory");
projectButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
configButton = new Button(group, SWT.RADIO);
configButton.setText("Build in configuration specific folder");
configButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
}
@Override
public String getName() {
return "Makefile";
}
@Override
protected void restoreProperties(Map<String, String> properties) {
// TODO Auto-generated method stub
super.restoreProperties(properties);
String container = properties.get(StandardBuildConfiguration.BUILD_CONTAINER);
if (container != null && !container.trim().isEmpty()) {
IPath containerLoc = new Path(container);
if (containerLoc.segmentCount() == 1) {
// TODO what if it's not the project?
projectButton.setSelection(true);
defaultProject = true;
} else {
configButton.setSelection(true);
defaultProject = false;
}
}
}
@Override
protected void saveProperties(Map<String, String> properties) {
super.saveProperties(properties);
try {
ICBuildConfiguration buildConfig = getBuildConfiguration();
if (buildConfig instanceof StandardBuildConfiguration) {
StandardBuildConfiguration stdConfig = (StandardBuildConfiguration) buildConfig;
if (defaultProject && !projectButton.getSelection()) {
properties.put(StandardBuildConfiguration.BUILD_CONTAINER,
stdConfig.getDefaultBuildContainer().getFullPath().toString());
} else if (!defaultProject && projectButton.getSelection()) {
properties.put(StandardBuildConfiguration.BUILD_CONTAINER,
stdConfig.getProject().getFullPath().toString());
}
}
} catch (CoreException e) {
MakeUIPlugin.log(e.getStatus());
}
}
@Override
public void initializeFrom(ILaunchConfiguration configuration) {
super.initializeFrom(configuration);
ICBuildConfiguration buildConfig = getBuildConfiguration();
String container = buildConfig.getProperty(StandardBuildConfiguration.BUILD_CONTAINER);
if (container != null && !container.trim().isEmpty()) {
IPath containerLoc = new Path(container);
if (containerLoc.segmentCount() == 1) {
// TODO what if it's not the project?
projectButton.setSelection(true);
defaultProject = true;
} else {
configButton.setSelection(true);
defaultProject = false;
}
}
}
@Override
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
super.performApply(configuration);
try {
ICBuildConfiguration buildConfig = getBuildConfiguration();
if (buildConfig instanceof StandardBuildConfiguration) {
StandardBuildConfiguration stdConfig = (StandardBuildConfiguration) buildConfig;
if (defaultProject && !projectButton.getSelection()) {
stdConfig.setBuildContainer(stdConfig.getDefaultBuildContainer());
} else if (!defaultProject && projectButton.getSelection()) {
stdConfig.setBuildContainer(stdConfig.getProject());
}
}
} catch (CoreException e) {
MakeUIPlugin.log(e.getStatus());
}
}
}

View file

@ -74,4 +74,12 @@
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java" type="org.eclipse.cdt.core.build.StandardBuildConfiguration">
<filter comment="No one extends this yet." id="336658481">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.build.StandardBuildConfiguration"/>
<message_argument value="BUILD_CONTAINER"/>
</message_arguments>
</filter>
</resource>
</component>

View file

@ -147,7 +147,7 @@ public abstract class CBuildConfiguration extends PlatformObject
this.launchMode = launchMode;
Preferences settings = getSettings();
settings.put(TOOLCHAIN_TYPE, toolChain.getProvider().getId());
settings.put(TOOLCHAIN_TYPE, toolChain.getTypeId());
settings.put(TOOLCHAIN_ID, toolChain.getId());
try {
settings.flush();

View file

@ -9,6 +9,10 @@ package org.eclipse.cdt.core.build;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
@ -20,11 +24,15 @@ import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.internal.core.build.Messages;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
/**
@ -35,12 +43,26 @@ import org.eclipse.core.runtime.Status;
*/
public class StandardBuildConfiguration extends CBuildConfiguration {
private String[] buildCommand = { "make", "-j", "-f", "../../Makefile", "all" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
private String[] cleanCommand = { "make", "clean" }; //$NON-NLS-1$ //$NON-NLS-2$
/**
* @since 6.4
*/
public static final String BUILD_CONTAINER = "stdbuild.build.container"; //$NON-NLS-1$
private String[] buildCommand;
private String[] cleanCommand;
private IContainer buildContainer;
public StandardBuildConfiguration(IBuildConfiguration config, String name) throws CoreException {
super(config, name);
String container = getProperty(BUILD_CONTAINER);
if (container != null && !container.trim().isEmpty()) {
IPath containerLoc = new org.eclipse.core.runtime.Path(container);
if (containerLoc.segmentCount() == 1) {
buildContainer = ResourcesPlugin.getWorkspace().getRoot().getProject(containerLoc.segment(0));
} else {
buildContainer = ResourcesPlugin.getWorkspace().getRoot().getFolder(containerLoc);
}
}
}
public StandardBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain,
@ -50,6 +72,7 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
public void setBuildContainer(IContainer buildContainer) {
this.buildContainer = buildContainer;
setProperty(BUILD_CONTAINER, buildContainer.getFullPath().toString());
}
public void setBuildCommand(String[] buildCommand) {
@ -60,11 +83,55 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
this.cleanCommand = cleanCommand;
}
private void createBuildContainer(IContainer container, IProgressMonitor monitor) throws CoreException {
IContainer parent = container.getParent();
if (!(parent instanceof IProject) && !parent.exists()) {
createBuildContainer(parent, monitor);
}
if (container instanceof IFolder) {
((IFolder) container).create(IResource.FORCE | IResource.DERIVED, true, monitor);
}
}
@Override
public IContainer getBuildContainer() throws CoreException {
if (buildContainer == null) {
return super.getBuildContainer();
} else {
if (!(buildContainer instanceof IProject) && !buildContainer.exists()) {
createBuildContainer(buildContainer, new NullProgressMonitor());
}
}
return buildContainer != null ? buildContainer : super.getBuildContainer();
}
/**
* @since 6.4
*/
public IContainer getDefaultBuildContainer() throws CoreException {
return super.getBuildContainer();
}
@Override
public String getProperty(String name) {
String prop = super.getProperty(name);
if (prop != null) {
return prop;
}
switch (name) {
case BUILD_CONTAINER:
try {
return getBuildContainer().getFullPath().toString();
} catch (CoreException e) {
CCorePlugin.log(e.getStatus());
}
}
return null;
}
@Override
public IProject[] build(int kind, Map<String, String> args, IConsole console, IProgressMonitor monitor)
throws CoreException {
@ -78,12 +145,25 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
outStream.write(String.format(Messages.StandardBuildConfiguration_0, buildDir.toString()));
String[] command = new String[buildCommand.length];
Path make = findCommand(buildCommand[0]);
command[0] = make.toString();
System.arraycopy(buildCommand, 1, command, 1, buildCommand.length - 1);
List<String> command;
if (buildCommand != null) {
command = Arrays.asList(buildCommand);
Path make = findCommand(buildCommand[0]);
command.set(0, make.toString());
} else {
command = new ArrayList<>();
command.add(findCommand("make").toString()); //$NON-NLS-1$
command.add("-j"); //$NON-NLS-1$
if (!getBuildContainer().equals(getProject())) {
Path makefile = Paths.get(getProject().getFile("Makefile").getLocationURI()); //$NON-NLS-1$
Path relative = getBuildDirectory().relativize(makefile);
command.add("-f"); //$NON-NLS-1$
command.add(relative.toString());
}
command.add("all"); //$NON-NLS-1$
}
try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this,
try (ErrorParserManager epm = new ErrorParserManager(project, getProject().getLocationURI(), this,
getToolChain().getErrorParserIds())) {
epm.setOutputStream(console.getOutputStream());
// run make
@ -115,10 +195,20 @@ public class StandardBuildConfiguration extends CBuildConfiguration {
ConsoleOutputStream outStream = console.getOutputStream();
String[] command = new String[cleanCommand.length];
Path make = findCommand(cleanCommand[0]);
command[0] = make.toString();
System.arraycopy(cleanCommand, 1, command, 1, cleanCommand.length - 1);
List<String> command;
if (cleanCommand != null) {
command = Arrays.asList(cleanCommand);
} else {
command = new ArrayList<>();
command.add(findCommand("make").toString()); //$NON-NLS-1$
if (!getBuildContainer().equals(getProject())) {
Path makefile = Paths.get(getProject().getFile("Makefile").getLocationURI()); //$NON-NLS-1$
Path relative = getBuildDirectory().relativize(makefile);
command.add("-f"); //$NON-NLS-1$
command.add(relative.toString());
}
command.add("clean"); //$NON-NLS-1$
}
// run make
outStream.write(String.format("%s\n", String.join(" ", command))); //$NON-NLS-1$ //$NON-NLS-2$