mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 519190 - Get CMake working with MSVC toolchain
Adds in Core Build support for the MSVC toolchain. Fixes issue
with PATH in the core build configuration since on Windows it's often
Path.
Change-Id: I3eb201bc22bf42341207e8f3bbef999d4d174f05
(cherry picked from commit 7f3745c765
)
This commit is contained in:
parent
dd07cba37b
commit
c4990122ac
4 changed files with 378 additions and 1 deletions
|
@ -435,7 +435,14 @@ public abstract class CBuildConfiguration extends PlatformObject
|
|||
Map<String, String> env = new HashMap<>(System.getenv());
|
||||
setBuildEnvironment(env);
|
||||
|
||||
String[] path = env.get("PATH").split(File.pathSeparator); //$NON-NLS-1$
|
||||
String pathStr = env.get("PATH"); //$NON-NLS-1$
|
||||
if (pathStr == null) {
|
||||
pathStr = env.get("Path"); // for Windows //$NON-NLS-1$
|
||||
if (pathStr == null) {
|
||||
return null; // no idea
|
||||
}
|
||||
}
|
||||
String[] path = pathStr.split(File.pathSeparator);
|
||||
for (String dir : path) {
|
||||
Path commandPath = Paths.get(dir, command);
|
||||
if (Files.exists(commandPath)) {
|
||||
|
@ -635,6 +642,7 @@ public abstract class CBuildConfiguration extends PlatformObject
|
|||
String[] compileCommands = toolChain.getCompileCommands();
|
||||
loop:
|
||||
for (String arg : command) {
|
||||
// TODO we should really ask the toolchain, not all args start with '-'
|
||||
if (arg.startsWith("-")) { //$NON-NLS-1$
|
||||
// option found, missed our command
|
||||
return false;
|
||||
|
|
|
@ -735,5 +735,12 @@
|
|||
</toolChain>
|
||||
</template>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.cdt.core.toolChainProvider">
|
||||
<provider
|
||||
class="org.eclipse.cdt.msw.build.core.MSVCToolChainProvider"
|
||||
id="org.eclipse.cdt.msw.build">
|
||||
</provider>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/*******************************************************************************
|
||||
* 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.msw.build.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.build.IToolChain;
|
||||
import org.eclipse.cdt.core.build.IToolChainProvider;
|
||||
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
|
||||
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
|
||||
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
|
||||
import org.eclipse.core.resources.IBuildConfiguration;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.PlatformObject;
|
||||
import org.osgi.framework.Version;
|
||||
|
||||
public class MSVCToolChain extends PlatformObject implements IToolChain {
|
||||
|
||||
private final IToolChainProvider provider;
|
||||
private final Path path;
|
||||
private final Map<String, String> properties = new HashMap<>();
|
||||
private final String id;
|
||||
private final String arch;
|
||||
private final String version;
|
||||
private final IEnvironmentVariable pathVar;
|
||||
private final IEnvironmentVariable includeVar;
|
||||
private final IEnvironmentVariable libVar;
|
||||
private final String[] includeDirs;
|
||||
private final Map<String, String> symbols;
|
||||
|
||||
public MSVCToolChain(IToolChainProvider provider, Path path) {
|
||||
this.provider = provider;
|
||||
this.path = path;
|
||||
|
||||
// path = <version>/bin/<hostArch>/<targetArch>
|
||||
String targetArch = path.getFileName().toString();
|
||||
this.arch = targetArch.equalsIgnoreCase("x86") ? Platform.ARCH_X86 : Platform.ARCH_X86_64; //$NON-NLS-1$
|
||||
this.id = "msvc." + arch; //$NON-NLS-1$
|
||||
this.version = path.getParent().getParent().getParent().getFileName().toString();
|
||||
|
||||
Path kitRoot = Paths.get("C:", "Program Files (x86)", "Windows Kits", "10"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
List<String> versions = Arrays.asList(kitRoot.resolve("lib").toFile().list()); //$NON-NLS-1$
|
||||
Collections.sort(versions, (v1, v2) -> {
|
||||
Version ver1;
|
||||
try {
|
||||
ver1 = new Version(v1);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Version ver2;
|
||||
try {
|
||||
ver2 = new Version(v2);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ver2.compareTo(ver1);
|
||||
});
|
||||
String sdkVersion = versions.iterator().next();
|
||||
|
||||
pathVar = new EnvironmentVariable("Path", String.join(File.pathSeparator, //$NON-NLS-1$
|
||||
path.toString(),
|
||||
kitRoot.resolve("bin").resolve(sdkVersion).resolve(targetArch).toString() //$NON-NLS-1$
|
||||
), IEnvironmentVariable.ENVVAR_PREPEND, File.pathSeparator);
|
||||
|
||||
this.includeDirs = new String[] {
|
||||
path.getParent().getParent().getParent().resolve("include").toString(), //$NON-NLS-1$
|
||||
kitRoot.resolve("include").resolve(sdkVersion).resolve("ucrt").toString(), //$NON-NLS-1$ //$NON-NLS-2$
|
||||
kitRoot.resolve("include").resolve(sdkVersion).resolve("shared").toString(), //$NON-NLS-1$ //$NON-NLS-2$
|
||||
kitRoot.resolve("include").resolve(sdkVersion).resolve("um").toString(), //$NON-NLS-1$ //$NON-NLS-2$
|
||||
kitRoot.resolve("include").resolve(sdkVersion).resolve("winrt").toString() //$NON-NLS-1$ //$NON-NLS-2$
|
||||
};
|
||||
|
||||
includeVar = new EnvironmentVariable("INCLUDE", String.join(File.pathSeparator, this.includeDirs), //$NON-NLS-1$
|
||||
IEnvironmentVariable.ENVVAR_REPLACE, File.pathSeparator);
|
||||
|
||||
libVar = new EnvironmentVariable("LIB", String.join(File.pathSeparator, //$NON-NLS-1$
|
||||
path.getParent().getParent().getParent().resolve("lib").resolve(targetArch).toString(), //$NON-NLS-1$
|
||||
kitRoot.resolve("lib").resolve(sdkVersion).resolve("ucrt").resolve(targetArch).toString(), //$NON-NLS-1$ //$NON-NLS-2$
|
||||
kitRoot.resolve("lib").resolve(sdkVersion).resolve("um").resolve(targetArch).toString() //$NON-NLS-1$ //$NON-NLS-2$
|
||||
), IEnvironmentVariable.ENVVAR_REPLACE, File.pathSeparator);
|
||||
|
||||
symbols = new HashMap<>();
|
||||
symbols.put("_WIN32", "1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (this.arch.equals(Platform.ARCH_X86)) {
|
||||
symbols.put("_M_IX86", "600"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
symbols.put("_WIN64", "1"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("_M_X64", "100"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
// TODO make this more dynamic to actual version
|
||||
symbols.put("_MSC_VER", "1900"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
// Microsoft specific modifiers that can be ignored
|
||||
symbols.put("__cdecl", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__fastcall", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__restrict", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__sptr", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__stdcall", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__unaligned", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__uptr", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__w64", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
// Redefine some things so that the CDT parser can handle them, until there is a VC specific parser
|
||||
symbols.put("__forceinline", "__inline"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__int8", "char"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__int16", "short"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__int32", "int"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
symbols.put("__int64", "long long"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
@Override
|
||||
public IToolChainProvider getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Visual C++";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
String value = properties.get(key);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// By default, we're a local GCC
|
||||
switch (key) {
|
||||
case ATTR_OS:
|
||||
return Platform.OS_WIN32;
|
||||
case ATTR_ARCH:
|
||||
return arch;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String key, String value) {
|
||||
properties.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEnvironmentVariable[] getVariables() {
|
||||
return new IEnvironmentVariable[] { pathVar, includeVar, libVar };
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEnvironmentVariable getVariable(String name) {
|
||||
switch (name) {
|
||||
case "PATH": //$NON-NLS-1$
|
||||
case "Path": //$NON-NLS-1$
|
||||
return pathVar;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getErrorParserIds() {
|
||||
return new String[] { CCorePlugin.PLUGIN_ID + ".VCErrorParser" //$NON-NLS-1$
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBinaryParserId() {
|
||||
return CCorePlugin.PLUGIN_ID + ".PE"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getCommandPath(Path command) {
|
||||
if (command.isAbsolute()) {
|
||||
return command;
|
||||
} else {
|
||||
return this.path.resolve(command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCompileCommands() {
|
||||
return new String[] { "cl", "cl.exe" //$NON-NLS-1$ //$NON-NLS-2$
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public IExtendedScannerInfo getDefaultScannerInfo(IBuildConfiguration buildConfig,
|
||||
IExtendedScannerInfo baseScannerInfo, ILanguage language, URI buildDirectoryURI) {
|
||||
return new ExtendedScannerInfo(symbols, includeDirs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IExtendedScannerInfo getScannerInfo(IBuildConfiguration buildConfig, List<String> command,
|
||||
IExtendedScannerInfo baseScannerInfo, IResource resource, URI buildDirectoryURI) {
|
||||
Map<String, String> symbols = new HashMap<>(this.symbols);
|
||||
List<String> includeDirs = new ArrayList<>(Arrays.asList(this.includeDirs));
|
||||
|
||||
for (String arg : command) {
|
||||
if (arg.startsWith("-") || arg.startsWith("/")) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (arg.charAt(1) == 'I') {
|
||||
includeDirs.add(arg.substring(2));
|
||||
} else if (arg.charAt(1) == 'D') {
|
||||
String[] define = arg.substring(2).split("="); //$NON-NLS-1$
|
||||
if (define.length == 1) {
|
||||
symbols.put(define[0], "1"); //$NON-NLS-1$
|
||||
} else {
|
||||
symbols.put(define[0], define[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ExtendedScannerInfo(symbols, includeDirs.toArray(new String[includeDirs.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IResource[] getResourcesFromCommand(List<String> command, URI buildDirectoryURI) {
|
||||
// Start at the back looking for arguments
|
||||
// TODO this was copied from the GCCToolChain, good candidate for the default implementation
|
||||
List<IResource> resources = new ArrayList<>();
|
||||
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
|
||||
for (int i = command.size() - 1; i >= 0; --i) {
|
||||
String arg = command.get(i);
|
||||
if (arg.startsWith("-") || arg.startsWith("/")) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
// ran into an option, we're done.
|
||||
break;
|
||||
}
|
||||
Path srcPath = Paths.get(arg);
|
||||
URI uri;
|
||||
if (srcPath.isAbsolute()) {
|
||||
uri = srcPath.toUri();
|
||||
} else {
|
||||
try {
|
||||
uri = buildDirectoryURI.resolve(arg);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Bad URI
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (IFile resource : root.findFilesForLocationURI(uri)) {
|
||||
resources.add(resource);
|
||||
}
|
||||
}
|
||||
|
||||
return resources.toArray(new IResource[resources.size()]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*******************************************************************************
|
||||
* 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.msw.build.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.eclipse.cdt.core.build.IToolChain;
|
||||
import org.eclipse.cdt.core.build.IToolChainManager;
|
||||
import org.eclipse.cdt.core.build.IToolChainProvider;
|
||||
import org.eclipse.cdt.msw.build.Activator;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
/**
|
||||
* Toolchain provider for Microsoft's Visual C++ Compiler (MSVC).
|
||||
*
|
||||
* This implementation only supports Microsoft Build Tools 2017 and
|
||||
* the Windows 10 SDK (Kit).
|
||||
*/
|
||||
public class MSVCToolChainProvider implements IToolChainProvider {
|
||||
|
||||
public MSVCToolChainProvider() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "org.eclipse.cdt.msw.build"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IToolChainManager manager) throws CoreException {
|
||||
// See if cl is installed
|
||||
Path vsPath = Paths.get("C:", "Program Files (x86)", "Microsoft Visual Studio"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
if (!Files.exists(vsPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path vs2017Path = vsPath.resolve("2017"); //$NON-NLS-1$
|
||||
if (!Files.exists(vs2017Path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path msvcPath = vs2017Path.resolve("BuildTools").resolve("VC").resolve("Tools").resolve("MSVC"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
if (!Files.exists(msvcPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String hostPath = Platform.getOSArch().equals(Platform.ARCH_X86) ? "HostX86" : "HostX64"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
String archPath = Platform.getOSArch().equals(Platform.ARCH_X86) ? "x86" : "x64"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
try {
|
||||
Files.find(msvcPath, 6, (path, attr) -> {
|
||||
return path.getFileName().toString().equalsIgnoreCase("cl.exe") //$NON-NLS-1$
|
||||
&& path.getParent().getParent().getFileName().toString().equalsIgnoreCase(hostPath)
|
||||
&& path.getParent().getFileName().toString().equalsIgnoreCase(archPath);
|
||||
}).forEach((path) -> {
|
||||
manager.addToolChain(new MSVCToolChain(this, path.getParent()));
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Finding cl.exe", e)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IToolChain getToolChain(String id, String version) throws CoreException {
|
||||
// TODO Auto-generated method stub
|
||||
return IToolChainProvider.super.getToolChain(id, version);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue