From 45019ea7805777774f71d395e077fe36068d401f Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 9 Nov 2017 14:13:35 -0500 Subject: 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 --- build/org.eclipse.cdt.make.core/plugin.xml | 2 +- .../core/MakefileBuildConfigurationProvider.java | 68 ++++++++++ .../core/MakefileBuildConfigurationProvider.java | 66 --------- .../templates/simple/Makefile | 9 +- build/org.eclipse.cdt.make.ui/META-INF/MANIFEST.MF | 3 +- build/org.eclipse.cdt.make.ui/plugin.xml | 7 + .../cdt/make/internal/ui/MakeBuildSettingsTab.java | 149 +++++++++++++++++++++ core/org.eclipse.cdt.core/.settings/.api_filters | 8 ++ .../cdt/core/build/CBuildConfiguration.java | 2 +- .../cdt/core/build/StandardBuildConfiguration.java | 112 ++++++++++++++-- 10 files changed, 344 insertions(+), 82 deletions(-) create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakefileBuildConfigurationProvider.java delete mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakefileBuildConfigurationProvider.java create mode 100644 build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java diff --git a/build/org.eclipse.cdt.make.core/plugin.xml b/build/org.eclipse.cdt.make.core/plugin.xml index 63816b70211..5de1999d0e0 100644 --- a/build/org.eclipse.cdt.make.core/plugin.xml +++ b/build/org.eclipse.cdt.make.core/plugin.xml @@ -197,7 +197,7 @@ diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakefileBuildConfigurationProvider.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakefileBuildConfigurationProvider.java new file mode 100644 index 00000000000..1406011df48 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/MakefileBuildConfigurationProvider.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.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.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$ + + @Override + public String getId() { + return ID; + } + + @Override + public ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name) + throws CoreException { + return new StandardBuildConfiguration(config, name); + } + + @Override + public ICBuildConfiguration createBuildConfiguration(IProject project, IToolChain toolChain, + String launchMode, IProgressMonitor monitor) throws CoreException { + ICBuildConfigurationManager configManager = MakeCorePlugin.getService(ICBuildConfigurationManager.class); + + StringBuilder configName = new StringBuilder("make."); //$NON-NLS-1$ + configName.append(launchMode); + String os = toolChain.getProperty(IToolChain.ATTR_OS); + if (os != null) { + configName.append('.'); + configName.append(os); + } + String arch = toolChain.getProperty(IToolChain.ATTR_ARCH); + if (arch != null && !arch.isEmpty()) { + configName.append('.'); + configName.append(arch); + } + String name = configName.toString(); + int i = 0; + while (configManager.hasConfiguration(this, project, name)) { + name = configName.toString() + '.' + (++i); + } + + IBuildConfiguration config = configManager.createBuildConfiguration(this, project, name, monitor); + StandardBuildConfiguration makeConfig = new StandardBuildConfiguration(config, name, toolChain, + launchMode); + configManager.addBuildConfiguration(config, makeConfig); + return makeConfig; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakefileBuildConfigurationProvider.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakefileBuildConfigurationProvider.java deleted file mode 100644 index f820c4eb7e9..00000000000 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/MakefileBuildConfigurationProvider.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * 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.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; - -public class MakefileBuildConfigurationProvider implements ICBuildConfigurationProvider { - - public static final String ID = "org.eclipse.cdt.make.core.provider"; //$NON-NLS-1$ - - @Override - public String getId() { - return ID; - } - - @Override - public ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name) - throws CoreException { - return new StandardBuildConfiguration(config, name); - } - - @Override - public ICBuildConfiguration createBuildConfiguration(IProject project, IToolChain toolChain, - String launchMode, IProgressMonitor monitor) throws CoreException { - ICBuildConfigurationManager configManager = MakeCorePlugin.getService(ICBuildConfigurationManager.class); - - StringBuilder configName = new StringBuilder("make."); //$NON-NLS-1$ - configName.append(launchMode); - String os = toolChain.getProperty(IToolChain.ATTR_OS); - if (os != null) { - configName.append('.'); - configName.append(os); - } - String arch = toolChain.getProperty(IToolChain.ATTR_ARCH); - if (arch != null && !arch.isEmpty()) { - configName.append('.'); - configName.append(arch); - } - String name = configName.toString(); - int i = 0; - while (configManager.hasConfiguration(this, project, name)) { - name = configName.toString() + '.' + (++i); - } - - IBuildConfiguration config = configManager.createBuildConfiguration(this, project, name, monitor); - StandardBuildConfiguration makeConfig = new StandardBuildConfiguration(config, name, toolChain, - launchMode); - configManager.addBuildConfiguration(config, makeConfig); - return makeConfig; - } - -} diff --git a/build/org.eclipse.cdt.make.core/templates/simple/Makefile b/build/org.eclipse.cdt.make.core/templates/simple/Makefile index 02622849e17..404907713d5 100644 --- a/build/org.eclipse.cdt.make.core/templates/simple/Makefile +++ b/build/org.eclipse.cdt.make.core/templates/simple/Makefile @@ -1,11 +1,16 @@ +PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + OBJS = ${projectName}.o all: ${projectName} ${projectName}: $(OBJS) - $(CC) -o $@ $^ + $(CXX) -o $@ $^ + +%.o: $(PROJECT_ROOT)%.cpp + $(CXX) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< -%.o: ../../%.cpp +%.o: $(PROJECT_ROOT)%.c $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< clean: diff --git a/build/org.eclipse.cdt.make.ui/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.make.ui/META-INF/MANIFEST.MF index aa7adc5bd1d..02ee6cafbcf 100644 --- a/build/org.eclipse.cdt.make.ui/META-INF/MANIFEST.MF +++ b/build/org.eclipse.cdt.make.ui/META-INF/MANIFEST.MF @@ -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 diff --git a/build/org.eclipse.cdt.make.ui/plugin.xml b/build/org.eclipse.cdt.make.ui/plugin.xml index 430a7a35fd2..e4c1f7bbd09 100644 --- a/build/org.eclipse.cdt.make.ui/plugin.xml +++ b/build/org.eclipse.cdt.make.ui/plugin.xml @@ -651,4 +651,11 @@ label="Make"> + + + + diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java new file mode 100644 index 00000000000..8910088d725 --- /dev/null +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeBuildSettingsTab.java @@ -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 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 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()); + } + } + +} diff --git a/core/org.eclipse.cdt.core/.settings/.api_filters b/core/org.eclipse.cdt.core/.settings/.api_filters index cc9a57dda17..b75949e3ada 100644 --- a/core/org.eclipse.cdt.core/.settings/.api_filters +++ b/core/org.eclipse.cdt.core/.settings/.api_filters @@ -74,4 +74,12 @@ + + + + + + + + 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 b3d47a4fc5e..ce7edae66b0 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 @@ -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(); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java index 5bed805c33f..01d6e4651c5 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/StandardBuildConfiguration.java @@ -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 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 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 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$ -- cgit v1.2.3