diff options
author | Doug Schaefer | 2015-09-25 21:01:37 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2015-09-28 17:24:41 +0000 |
commit | 64bf3c4f69e00d4246552505d67521ce2167178c (patch) | |
tree | c25a42b9c579136a03be4c3e3eb896b040f70c9a /qt | |
parent | 7ba4959cf4293cbd17726f22b49d89c6bc444b04 (diff) | |
download | org.eclipse.cdt-64bf3c4f69e00d4246552505d67521ce2167178c.tar.gz org.eclipse.cdt-64bf3c4f69e00d4246552505d67521ce2167178c.tar.xz org.eclipse.cdt-64bf3c4f69e00d4246552505d67521ce2167178c.zip |
Starting to put Qt onto the new build system and launch.
Change-Id: I3e65f5d69bfb35d16b2d1135f99517c7a2b2c437
Diffstat (limited to 'qt')
14 files changed, 716 insertions, 16 deletions
diff --git a/qt/org.eclipse.cdt.qt.core/.classpath b/qt/org.eclipse.cdt.qt.core/.classpath index 27ef2aeea4f..9ace5bdb161 100644 --- a/qt/org.eclipse.cdt.qt.core/.classpath +++ b/qt/org.eclipse.cdt.qt.core/.classpath @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry exported="true" kind="lib" path="libs/freemarker-2.3.22.jar"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="src" path="src"/> + <classpathentry exported="true" kind="lib" path="libs/freemarker-2.3.22.jar"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/qt/org.eclipse.cdt.qt.core/.settings/org.eclipse.jdt.core.prefs b/qt/org.eclipse.cdt.qt.core/.settings/org.eclipse.jdt.core.prefs index f42de363afa..0c68a61dca8 100644 --- a/qt/org.eclipse.cdt.qt.core/.settings/org.eclipse.jdt.core.prefs +++ b/qt/org.eclipse.cdt.qt.core/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF index 49518054b12..1c950642c58 100644 --- a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF +++ b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF @@ -11,8 +11,12 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.cdt.core, org.eclipse.cdt.codan.core, org.eclipse.cdt.codan.core.cxx, - org.eclipse.core.filesystem -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 + org.eclipse.core.filesystem, + org.eclipse.launchbar.core;bundle-version="1.0.1", + org.eclipse.remote.core;bundle-version="2.0.0", + org.eclipse.debug.core;bundle-version="3.10.0", + org.eclipse.cdt.debug.core +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Localization: plugin Export-Package: org.eclipse.cdt.internal.qt.core;x-friends:="org.eclipse.cdt.qt.ui,org.eclipse.cdt.qt.tests", diff --git a/qt/org.eclipse.cdt.qt.core/build.properties b/qt/org.eclipse.cdt.qt.core/build.properties index 9773163cbb8..f2748e1059a 100644 --- a/qt/org.eclipse.cdt.qt.core/build.properties +++ b/qt/org.eclipse.cdt.qt.core/build.properties @@ -5,7 +5,6 @@ bin.includes = META-INF/,\ plugin.xml,\ templates/,\ about.html,\ - plugin.properties,\ - libs/freemarker-2.3.22.jar + plugin.properties src.includes = about.html,\ schema/ diff --git a/qt/org.eclipse.cdt.qt.core/plugin.xml b/qt/org.eclipse.cdt.qt.core/plugin.xml index 6815519847a..b99dd5f513f 100644 --- a/qt/org.eclipse.cdt.qt.core/plugin.xml +++ b/qt/org.eclipse.cdt.qt.core/plugin.xml @@ -134,4 +134,54 @@ class="org.eclipse.cdt.internal.qt.core.build.QtBuilder"> </run></builder> </extension> + <extension + point="org.eclipse.launchbar.core.launchBarContributions"> + <descriptorType + class="org.eclipse.cdt.internal.qt.core.launch.QtLaunchDescriptorType" + id="org.eclipse.cdt.qt.core.launchDescriptorType" + priority="10"> + <enablement> + <instanceof + value="org.eclipse.core.resources.IProject"> + </instanceof> + <test + forcePluginActivation="true" + property="org.eclipse.core.resources.projectNature" + value="org.eclipse.cdt.qt.core.qtNature"> + </test> + </enablement> + </descriptorType> + <configProvider + class="org.eclipse.cdt.internal.qt.core.launch.QtLocalLaunchConfigProvider" + descriptorType="org.eclipse.cdt.qt.core.launchDescriptorType" + priority="10"> + </configProvider> + </extension> + <extension + point="org.eclipse.cdt.core.ScannerInfoProvider2"> + <provider + builder="org.eclipse.cdt.qt.core.qtBuilder" + class="org.eclipse.cdt.internal.qt.core.build.QtScannerInfoProvider"> + </provider> + </extension> + <extension + point="org.eclipse.debug.core.launchConfigurationTypes"> + <launchConfigurationType + delegate="org.eclipse.cdt.internal.qt.core.launch.QtLocalRunLaunchConfigDelegate" + id="org.eclipse.cdt.qt.core.launchConfigurationType" + modes="run" + name="Qt Local Application" + public="true"> + </launchConfigurationType> + </extension> + <extension + point="org.eclipse.core.runtime.adapters"> + <factory + adaptableType="org.eclipse.core.resources.IBuildConfiguration" + class="org.eclipse.cdt.internal.qt.core.build.QtBuildConfiguration$Factory"> + <adapter + type="org.eclipse.cdt.internal.qt.core.build.QtBuildConfiguration"> + </adapter> + </factory> + </extension> </plugin> diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java index 8b79e1c3729..5f07cca71d1 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java @@ -7,15 +7,40 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.core.build; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.build.CBuildConfiguration; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.LanguageManager; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.internal.qt.core.QtPlugin; import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.IProgressMonitor; public class QtBuildConfiguration extends CBuildConfiguration { + private QtInstall qtInstall; + private String launchMode; + private Map<String, String> properties; + public QtBuildConfiguration(IBuildConfiguration config) { super(config); } @@ -46,4 +71,157 @@ public class QtBuildConfiguration extends CBuildConfiguration { } } + public static QtBuildConfiguration getConfig(IProject project, String os, String arch, String launchMode, + IProgressMonitor monitor) throws CoreException { + // return it if it exists already + for (IBuildConfiguration config : project.getBuildConfigs()) { + QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class); + QtInstall qtInstall = qtConfig.getQtInstall(); + if (qtInstall != null && qtInstall.supports(os, arch) && launchMode.equals(qtConfig.getLaunchMode())) { + return qtConfig; + } + } + + // Nope, create it + for (QtInstall qtInstall : QtInstallManager.instance.getInstalls()) { + if (qtInstall.supports(os, arch)) { + Set<String> configNames = new HashSet<>(); + for (IBuildConfiguration config : project.getBuildConfigs()) { + configNames.add(config.getName()); + } + String baseName = qtInstall.getSpec() + ":" + launchMode; //$NON-NLS-1$ + String newName = baseName; + int n = 0; + while (configNames.contains(newName)) { + newName = baseName + (++n); + } + configNames.add(newName); + IProjectDescription projectDesc = project.getDescription(); + projectDesc.setBuildConfigs(configNames.toArray(new String[configNames.size()])); + project.setDescription(projectDesc, monitor); + + QtBuildConfiguration qtConfig = project.getBuildConfig(newName).getAdapter(QtBuildConfiguration.class); + qtConfig.setup(qtInstall, launchMode); + return qtConfig; + } + } + return null; + } + + public QtInstall getQtInstall() { + if (qtInstall == null) { + // TODO set based on settings + } + return qtInstall; + } + + private String getLaunchMode() { + if (launchMode != null) { + // TODO set based on settings + } + return launchMode; + } + + private void setup(QtInstall qtInstall, String launchMode) { + this.qtInstall = qtInstall; + this.launchMode = launchMode; + // TODO save settings + } + + public String getQmakeCommand() { + return qtInstall.getQmakePath().toString(); + } + + public String getQmakeConfig() { + switch (launchMode) { + case "run": //$NON-NLS-1$ + return "CONFIG+=release"; //$NON-NLS-1$ + case "debug": //$NON-NLS-1$ + return "CONFIG+=debug"; //$NON-NLS-1$ + default: + // TODO probably need an extension point for guidance + return null; + } + } + + public Path getProjectFile() { + File projectDir = getProject().getLocation().toFile(); + File[] proFiles = projectDir.listFiles((dir, name) -> name.endsWith(".pro")); //$NON-NLS-1$ + if (proFiles.length > 0) { + // TODO what if there are more than one. + return proFiles[0].toPath(); + } else { + return null; + } + } + + public IFolder getBuildFolder() { + return getProject().getFolder("build").getFolder(getBuildConfiguration().getName()); //$NON-NLS-1$ + } + + public Path getBuildDirectory() { + return getBuildFolder().getLocation().toFile().toPath(); + } + + public String getProperty(String key) { + if (properties == null) { + List<String> cmd = new ArrayList<>(); + cmd.add(getQmakeCommand()); + cmd.add("-E"); //$NON-NLS-1$ + + String config = getQmakeConfig(); + if (config != null) { + cmd.add(config); + } + + cmd.add(getProjectFile().toString()); + + try { + Process proc = new ProcessBuilder(cmd).directory(getBuildDirectory().toFile()).start(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { + properties = new HashMap<>(); + for (String line = reader.readLine(); line != null; line = reader.readLine()) { + if (line.contains("=")) { //$NON-NLS-1$ + String[] parts = line.split("="); //$NON-NLS-1$ + if (parts.length == 2) { + properties.put(parts[0].trim(), parts[1].trim()); + } + } + } + } + } catch (IOException e) { + QtPlugin.log(e); + } + } + + return properties != null ? properties.get(key) : null; + } + + @Override + public IScannerInfo getScannerInfo(IResource resource) throws CoreException { + IScannerInfo info = super.getScannerInfo(resource); + if (info == null) { + List<String> cmd = new ArrayList<>(); + cmd.add(getProperty("QMAKE_CXX")); //$NON-NLS-1$ + cmd.addAll(Arrays.asList(getProperty("QMAKE_CXXFLAGS").split(" "))); //$NON-NLS-1$ //$NON-NLS-2$ + + for (String include : getProperty("INCLUDEPATH").split(" ")) { //$NON-NLS-1$ //$NON-NLS-2$ + cmd.add("-I"); //$NON-NLS-1$ + cmd.add(include); + } + + cmd.add("-o"); //$NON-NLS-1$ + cmd.add("-"); //$NON-NLS-1$ + + // TODO need to make sure this path is valid + // The gcc toolchain uses IFile to make sure it exists + cmd.add(resource.getFullPath().toPortableString()); + + ILanguage language = LanguageManager.getInstance() + .getLanguage(CCorePlugin.getContentType(getProject(), resource.getName()), getProject()); // $NON-NLS-1$ + putScannerInfo(language, getToolChain().getScannerInfo(getBuildFolder(), cmd)); + } + return info; + } + } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java index 6050c620264..56c3d739553 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java @@ -9,10 +9,13 @@ package org.eclipse.cdt.internal.qt.core.build; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.eclipse.cdt.core.build.IConsoleService; import org.eclipse.cdt.internal.qt.core.QtPlugin; +import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -27,23 +30,30 @@ public class QtBuilder extends IncrementalProjectBuilder { public static final String ID = QtPlugin.ID + ".qtBuilder"; //$NON-NLS-1$ - private static final String qmake = "/Users/dschaefer/Qt/5.5/clang_64/bin/qmake"; //$NON-NLS-1$ - @Override protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException { IProject project = getProject(); try { IConsoleService console = QtPlugin.getService(IConsoleService.class); + QtBuildConfiguration qtConfig = getBuildConfig().getAdapter(QtBuildConfiguration.class); - IFolder buildFolder = project.getFolder("build"); //$NON-NLS-1$ - if (!buildFolder.exists()) { - buildFolder.create(IResource.FORCE | IResource.DERIVED, true, monitor); - } + IFolder buildFolder = qtConfig.getBuildFolder(); + createFolder(buildFolder, monitor); IFile makeFile = buildFolder.getFile("Makefile"); //$NON-NLS-1$ if (!makeFile.exists()) { // Need to run qmake - String[] command = new String[] { qmake, "../main.pro", "CONFIG+=debug" }; //$NON-NLS-1$ //$NON-NLS-2$ + List<String> command = new ArrayList<>(); + command.add(qtConfig.getQmakeCommand()); + + String config = qtConfig.getQmakeConfig(); + if (config != null) { + command.add(config); + } + + IFile projectFile = qtConfig.getProject().getFile("main.pro"); + command.add(projectFile.getLocation().toOSString()); + Process process = new ProcessBuilder(command).directory(new File(buildFolder.getLocationURI())).start(); StringBuffer msg = new StringBuffer(); for (String arg : command) { @@ -56,6 +66,7 @@ public class QtBuilder extends IncrementalProjectBuilder { // run make Process process = new ProcessBuilder("make").directory(new File(buildFolder.getLocationURI())).start(); //$NON-NLS-1$ + console.writeOutput("make\n"); //$NON-NLS-1$ console.monitor(process, null, buildFolder); buildFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor); @@ -65,4 +76,13 @@ public class QtBuilder extends IncrementalProjectBuilder { } } + private void createFolder(IFolder folder, IProgressMonitor monitor) throws CoreException { + IContainer parent = folder.getParent(); + if (!parent.exists()) { + createFolder((IFolder) parent, monitor); + } + if (!folder.exists()) { + folder.create(IResource.FORCE | IResource.DERIVED, true, monitor); + } + } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstall.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstall.java new file mode 100644 index 00000000000..ae4306aae51 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstall.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.build; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Path; + +import org.eclipse.cdt.internal.qt.core.QtPlugin; +import org.eclipse.core.runtime.Platform; + +public class QtInstall { + + private final Path qmakePath; + private String spec; + + public QtInstall(Path qmakePath) { + this.qmakePath = qmakePath; + } + + public Path getQmakePath() { + return qmakePath; + } + + public Path getLibPath() { + return qmakePath.resolve("../lib"); //$NON-NLS-1$ + } + + public boolean supports(String os, String arch) { + switch (getSpec()) { + case "macx-clang": //$NON-NLS-1$ + return Platform.OS_MACOSX.equals(os) && Platform.ARCH_X86_64.equals(arch); + } + return false; + } + + public String getSpec() { + if (spec == null) { + try { + Process proc = new ProcessBuilder(getQmakePath().toString(), "-query", "QMAKE_XSPEC").start(); //$NON-NLS-1$ //$NON-NLS-2$ + try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { + String line = reader.readLine(); + if (line != null) { + spec = line.trim(); + } + } + } catch (IOException e) { + QtPlugin.log(e); + } + } + return spec; + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java new file mode 100644 index 00000000000..1074dc387e2 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.build; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class QtInstallManager { + + public static final QtInstallManager instance = new QtInstallManager(); + + private List<QtInstall> installs; + + public List<QtInstall> getInstalls() { + if (installs == null) { + installs = new ArrayList<>(); + // TODO hack to get going + File qtDir = new File(System.getProperty("user.home"), "Qt/5.5"); + if (qtDir.isDirectory()) { + for (File dir : qtDir.listFiles()) { + Path qmakePath = dir.toPath().resolve("bin/qmake"); + if (qmakePath.toFile().canExecute()) { + installs.add(new QtInstall(qmakePath)); + } + } + } + } + + return installs; + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtScannerInfoProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtScannerInfoProvider.java new file mode 100644 index 00000000000..e17d379b744 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtScannerInfoProvider.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.build; + +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.internal.qt.core.QtPlugin; +import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; + +public class QtScannerInfoProvider implements IScannerInfoProvider { + + @Override + public IScannerInfo getScannerInformation(IResource resource) { + try { + IProject project = resource.getProject(); + IBuildConfiguration config = project.getActiveBuildConfig(); + QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class); + return qtConfig.getScannerInfo(resource); + } catch (CoreException e) { + QtPlugin.log(e); + return null; + } + } + + @Override + public void subscribe(IResource resource, IScannerInfoChangeListener listener) { + } + + @Override + public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) { + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLaunchDescriptor.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLaunchDescriptor.java new file mode 100644 index 00000000000..9ff56e4c490 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLaunchDescriptor.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.launch; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.launchbar.core.ILaunchDescriptor; +import org.eclipse.launchbar.core.ILaunchDescriptorType; + +public class QtLaunchDescriptor extends PlatformObject implements ILaunchDescriptor { + + private final QtLaunchDescriptorType type; + private final IProject project; + + public QtLaunchDescriptor(QtLaunchDescriptorType type, IProject project) { + this.type = type; + this.project = project; + } + + @Override + public String getName() { + return project.getName(); + } + + @Override + public ILaunchDescriptorType getType() { + return type; + } + + public IProject getProject() { + return project; + } + + @SuppressWarnings("unchecked") + @Override + public <T> T getAdapter(Class<T> adapter) { + if (adapter.equals(IProject.class)) { + return (T) project; + } else { + return super.getAdapter(adapter); + } + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLaunchDescriptorType.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLaunchDescriptorType.java new file mode 100644 index 00000000000..41f8cbdbe13 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLaunchDescriptorType.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.launch; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.internal.qt.core.QtNature; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.launchbar.core.ILaunchDescriptor; +import org.eclipse.launchbar.core.ILaunchDescriptorType; + +public class QtLaunchDescriptorType implements ILaunchDescriptorType { + + private Map<IProject, QtLaunchDescriptor> descriptors = new HashMap<>(); + + @Override + public ILaunchDescriptor getDescriptor(Object launchObject) throws CoreException { + // TODO also check to make sure it's an application project and not a library. + // qmake -E will give the TEMPLATE variable + if (launchObject instanceof IProject) { + IProject project = (IProject) launchObject; + if (QtNature.hasNature(project)) { + QtLaunchDescriptor desc = descriptors.get(project); + if (desc == null) { + desc = new QtLaunchDescriptor(this, project); + descriptors.put(project, desc); + } + return desc; + } + } + return null; + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalLaunchConfigProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalLaunchConfigProvider.java new file mode 100644 index 00000000000..bceb0a7a841 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalLaunchConfigProvider.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.launch; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.launchbar.core.AbstractLaunchConfigProvider; +import org.eclipse.launchbar.core.ILaunchDescriptor; +import org.eclipse.remote.core.IRemoteConnection; + +/** + * Launch config provider for Qt projects running on the Local connection. Simply uses the C++ Application launch config + * type. + */ +public class QtLocalLaunchConfigProvider extends AbstractLaunchConfigProvider { + + private static final String localConnectionTypeId = "org.eclipse.remote.LocalServices"; //$NON-NLS-1$ + + private Map<IProject, ILaunchConfiguration> configs = new HashMap<>(); + + @Override + public boolean supports(ILaunchDescriptor descriptor, IRemoteConnection target) throws CoreException { + return localConnectionTypeId.equals(target.getConnectionType().getId()); + } + + @Override + public ILaunchConfigurationType getLaunchConfigurationType(ILaunchDescriptor descriptor, IRemoteConnection target) + throws CoreException { + return DebugPlugin.getDefault().getLaunchManager() + .getLaunchConfigurationType(QtLocalRunLaunchConfigDelegate.TYPE_ID); + } + + @Override + public ILaunchConfiguration getLaunchConfiguration(ILaunchDescriptor descriptor, IRemoteConnection target) + throws CoreException { + ILaunchConfiguration config = configs.get(descriptor); + if (config == null) { + config = createLaunchConfiguration(descriptor, target); + configs.put(descriptor.getAdapter(IProject.class), config); + } + return config; + } + + @Override + protected void populateLaunchConfiguration(ILaunchDescriptor descriptor, IRemoteConnection target, + ILaunchConfigurationWorkingCopy workingCopy) throws CoreException { + super.populateLaunchConfiguration(descriptor, target, workingCopy); + + // Set the project and the connection + QtLaunchDescriptor qtDesc = (QtLaunchDescriptor) descriptor; + workingCopy.setMappedResources(new IResource[] { qtDesc.getProject() }); + } + + @Override + public boolean launchConfigurationAdded(ILaunchConfiguration configuration) throws CoreException { + if (ownsLaunchConfiguration(configuration)) { + + } + return false; + } + + @Override + public boolean launchConfigurationRemoved(ILaunchConfiguration configuration) throws CoreException { + for (Entry<IProject, ILaunchConfiguration> entry : configs.entrySet()) { + if (configuration.equals(entry.getValue())) { + configs.remove(entry.getKey()); + return true; + } + } + return false; + } + + @Override + public boolean launchConfigurationChanged(ILaunchConfiguration configuration) throws CoreException { + // TODO not sure I care + return false; + } + + @Override + public void launchDescriptorRemoved(ILaunchDescriptor descriptor) throws CoreException { + IProject project = descriptor.getAdapter(IProject.class); + if (project != null) { + configs.remove(project); + } + } + + @Override + public void launchTargetRemoved(IRemoteConnection target) throws CoreException { + // nothing to do since the Local connection can't be removed + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java new file mode 100644 index 00000000000..88dabf5073a --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 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.internal.qt.core.launch; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; + +import org.eclipse.cdt.internal.qt.core.QtPlugin; +import org.eclipse.cdt.internal.qt.core.build.QtBuildConfiguration; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.LaunchConfigurationDelegate; + +public class QtLocalRunLaunchConfigDelegate extends LaunchConfigurationDelegate { + + public static final String TYPE_ID = QtPlugin.ID + ".launchConfigurationType"; //$NON-NLS-1$ + + @Override + public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) + throws CoreException { + new Job("Running Qt App") { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, monitor); + + // get the executable + IFolder buildFolder = qtBuildConfig.getBuildFolder(); + // TODO this is mac local specific and really should be in the config + // TODO also need to pull the app name out of the pro file name + IFolder appFolder = buildFolder.getFolder("main.app"); + IFolder contentsFolder = appFolder.getFolder("Contents"); + IFolder macosFolder = contentsFolder.getFolder("MacOS"); + IFile exeFile = macosFolder.getFile("main"); + + ProcessBuilder builder = new ProcessBuilder(exeFile.getLocation().toFile().getAbsolutePath()) + .directory(qtBuildConfig.getProject().getLocation().toFile()); + + // need to add the Qt libraries to the env + Map<String, String> env = builder.environment(); + String libPathEnv = env.get("DYLD_LIBRARY_PATH"); + Path libPath = qtBuildConfig.getQtInstall().getLibPath(); + if (libPathEnv == null) { + libPathEnv = libPath.toString(); + } else { + libPathEnv = libPath.toString() + File.pathSeparator + libPathEnv; + } + env.put("DYLD_LIBRARY_PATH", libPathEnv); + + Process process = builder.start(); + DebugPlugin.newProcess(launch, process, "main.app"); + } catch (IOException e) { + return new Status(IStatus.ERROR, QtPlugin.ID, "running", e); + } catch (CoreException e) { + return e.getStatus(); + } + return Status.OK_STATUS; + } + }.schedule(); + } + + @Override + public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) + throws CoreException { + QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, monitor); + + // Set it as active + IProject project = qtBuildConfig.getProject(); + IProjectDescription desc = project.getDescription(); + desc.setActiveBuildConfig(qtBuildConfig.getBuildConfiguration().getName()); + project.setDescription(desc, monitor); + + // And build + return super.buildForLaunch(configuration, mode, monitor); + } + + @Override + protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException { + // 1. Extract project from configuration + // TODO dependencies too. + IProject project = configuration.getMappedResources()[0].getProject(); + return new IProject[] { project }; + } + + private QtBuildConfiguration getQtBuildConfiguration(ILaunchConfiguration configuration, String mode, + IProgressMonitor monitor) throws CoreException { + // Find the Qt build config + IProject project = configuration.getMappedResources()[0].getProject(); + String os = Platform.getOS(); + String arch = Platform.getOSArch(); + return QtBuildConfiguration.getConfig(project, os, arch, mode, monitor); + } + +} |