2019-03-01 14:49:51 +08:00
|
|
|
//===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===//
|
2011-12-18 07:10:01 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-12-18 07:10:01 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
#include "MSVC.h"
|
|
|
|
#include "CommonArgs.h"
|
2017-03-16 00:07:35 +08:00
|
|
|
#include "Darwin.h"
|
2013-02-09 06:30:41 +08:00
|
|
|
#include "clang/Basic/CharInfo.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Basic/Version.h"
|
2021-03-19 21:37:19 +08:00
|
|
|
#include "clang/Config/config.h"
|
2011-12-18 07:10:01 +08:00
|
|
|
#include "clang/Driver/Compilation.h"
|
|
|
|
#include "clang/Driver/Driver.h"
|
2013-03-24 23:06:53 +08:00
|
|
|
#include "clang/Driver/DriverDiagnostic.h"
|
2011-12-18 07:10:01 +08:00
|
|
|
#include "clang/Driver/Options.h"
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
#include "clang/Driver/SanitizerArgs.h"
|
2014-10-23 04:40:28 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2013-06-15 01:17:23 +08:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
2016-05-14 07:20:11 +08:00
|
|
|
#include "llvm/Support/ConvertUTF.h"
|
2011-12-18 07:10:01 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2014-10-23 04:40:28 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2017-03-16 00:07:35 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2016-07-19 03:02:11 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2014-10-23 04:40:28 +08:00
|
|
|
#include "llvm/Support/Process.h"
|
2021-02-25 11:58:40 +08:00
|
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
2015-01-24 03:16:25 +08:00
|
|
|
#include <cstdio>
|
|
|
|
|
2018-04-30 21:47:04 +08:00
|
|
|
#ifdef _WIN32
|
2011-12-18 07:10:01 +08:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#define NOGDI
|
2014-12-05 05:46:50 +08:00
|
|
|
#ifndef NOMINMAX
|
|
|
|
#define NOMINMAX
|
|
|
|
#endif
|
2014-06-25 00:18:10 +08:00
|
|
|
#include <windows.h>
|
2017-03-16 01:09:36 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
// Don't support SetupApi on MinGW.
|
|
|
|
#define USE_MSVC_SETUP_API
|
2017-03-16 00:07:35 +08:00
|
|
|
|
|
|
|
// Make sure this comes before MSVCSetupApi.h
|
|
|
|
#include <comdef.h>
|
|
|
|
|
|
|
|
#include "MSVCSetupApi.h"
|
|
|
|
#include "llvm/Support/COM.h"
|
|
|
|
_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
|
|
|
|
_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
|
|
|
|
_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
|
|
|
|
_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
|
|
|
|
_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
|
|
|
|
_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
|
2011-12-18 07:10:01 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace clang::driver;
|
|
|
|
using namespace clang::driver::toolchains;
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
using namespace clang::driver::tools;
|
2011-12-18 07:10:01 +08:00
|
|
|
using namespace clang;
|
2013-06-15 01:17:23 +08:00
|
|
|
using namespace llvm::opt;
|
2011-12-18 07:10:01 +08:00
|
|
|
|
2021-02-25 11:58:40 +08:00
|
|
|
static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
|
|
|
|
auto Status = VFS.status(Path);
|
|
|
|
if (!Status)
|
|
|
|
return false;
|
|
|
|
return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
|
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
// Defined below.
|
|
|
|
// Forward declare this so there aren't too many things above the constructor.
|
|
|
|
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
|
|
|
|
std::string &value, std::string *phValue);
|
|
|
|
|
2021-02-25 11:58:40 +08:00
|
|
|
static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS,
|
|
|
|
StringRef Directory) {
|
2021-01-28 00:01:59 +08:00
|
|
|
std::string Highest;
|
|
|
|
llvm::VersionTuple HighestTuple;
|
|
|
|
|
|
|
|
std::error_code EC;
|
2021-02-25 11:58:40 +08:00
|
|
|
for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
|
|
|
|
DirEnd;
|
2021-01-28 00:01:59 +08:00
|
|
|
!EC && DirIt != DirEnd; DirIt.increment(EC)) {
|
2021-02-25 11:58:40 +08:00
|
|
|
auto Status = VFS.status(DirIt->path());
|
|
|
|
if (!Status || !Status->isDirectory())
|
2021-01-28 00:01:59 +08:00
|
|
|
continue;
|
|
|
|
StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
|
|
|
|
llvm::VersionTuple Tuple;
|
|
|
|
if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
|
|
|
|
continue;
|
|
|
|
if (Tuple > HighestTuple) {
|
|
|
|
HighestTuple = Tuple;
|
|
|
|
Highest = CandidateName.str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Highest;
|
|
|
|
}
|
|
|
|
|
2020-08-26 20:58:39 +08:00
|
|
|
// Check command line arguments to try and find a toolchain.
|
|
|
|
static bool
|
2021-02-25 11:58:40 +08:00
|
|
|
findVCToolChainViaCommandLine(llvm::vfs::FileSystem &VFS, const ArgList &Args,
|
|
|
|
std::string &Path,
|
2020-08-26 20:58:39 +08:00
|
|
|
MSVCToolChain::ToolsetLayout &VSLayout) {
|
|
|
|
// Don't validate the input; trust the value supplied by the user.
|
|
|
|
// The primary motivation is to prevent unnecessary file and registry access.
|
2021-01-28 00:01:59 +08:00
|
|
|
if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir,
|
|
|
|
options::OPT__SLASH_winsysroot)) {
|
|
|
|
if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
|
|
|
|
llvm::SmallString<128> ToolsPath(A->getValue());
|
|
|
|
llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
|
|
|
|
std::string VCToolsVersion;
|
|
|
|
if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
|
|
|
|
VCToolsVersion = A->getValue();
|
|
|
|
else
|
2021-02-25 11:58:40 +08:00
|
|
|
VCToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
|
2021-01-28 00:01:59 +08:00
|
|
|
llvm::sys::path::append(ToolsPath, VCToolsVersion);
|
|
|
|
Path = std::string(ToolsPath.str());
|
|
|
|
} else {
|
|
|
|
Path = A->getValue();
|
|
|
|
}
|
2020-08-26 20:58:39 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
// Check various environment variables to try and find a toolchain.
|
2021-01-27 04:21:12 +08:00
|
|
|
static bool
|
2021-02-25 11:58:40 +08:00
|
|
|
findVCToolChainViaEnvironment(llvm::vfs::FileSystem &VFS, std::string &Path,
|
2021-01-27 04:21:12 +08:00
|
|
|
MSVCToolChain::ToolsetLayout &VSLayout) {
|
2017-03-16 00:07:35 +08:00
|
|
|
// These variables are typically set by vcvarsall.bat
|
|
|
|
// when launching a developer command prompt.
|
|
|
|
if (llvm::Optional<std::string> VCToolsInstallDir =
|
|
|
|
llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
|
|
|
|
// This is only set by newer Visual Studios, and it leads straight to
|
|
|
|
// the toolchain directory.
|
|
|
|
Path = std::move(*VCToolsInstallDir);
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
2017-03-16 00:07:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (llvm::Optional<std::string> VCInstallDir =
|
|
|
|
llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
|
|
|
|
// If the previous variable isn't set but this one is, then we've found
|
|
|
|
// an older Visual Studio. This variable is set by newer Visual Studios too,
|
|
|
|
// so this check has to appear second.
|
|
|
|
// In older Visual Studios, the VC directory is the toolchain.
|
|
|
|
Path = std::move(*VCInstallDir);
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
2017-03-16 00:07:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We couldn't find any VC environment variables. Let's walk through PATH and
|
|
|
|
// see if it leads us to a VC toolchain bin directory. If it does, pick the
|
|
|
|
// first one that we find.
|
|
|
|
if (llvm::Optional<std::string> PathEnv =
|
|
|
|
llvm::sys::Process::GetEnv("PATH")) {
|
|
|
|
llvm::SmallVector<llvm::StringRef, 8> PathEntries;
|
|
|
|
llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
|
|
|
|
for (llvm::StringRef PathEntry : PathEntries) {
|
|
|
|
if (PathEntry.empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
llvm::SmallString<256> ExeTestPath;
|
|
|
|
|
|
|
|
// If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
|
|
|
|
ExeTestPath = PathEntry;
|
|
|
|
llvm::sys::path::append(ExeTestPath, "cl.exe");
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!VFS.exists(ExeTestPath))
|
2017-03-16 00:07:35 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// cl.exe existing isn't a conclusive test for a VC toolchain; clang also
|
|
|
|
// has a cl.exe. So let's check for link.exe too.
|
|
|
|
ExeTestPath = PathEntry;
|
|
|
|
llvm::sys::path::append(ExeTestPath, "link.exe");
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!VFS.exists(ExeTestPath))
|
2017-03-16 00:07:35 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
|
2017-05-17 23:27:44 +08:00
|
|
|
llvm::StringRef TestPath = PathEntry;
|
2021-06-23 19:52:36 +08:00
|
|
|
bool IsBin =
|
|
|
|
llvm::sys::path::filename(TestPath).equals_insensitive("bin");
|
2017-05-17 23:27:44 +08:00
|
|
|
if (!IsBin) {
|
|
|
|
// Strip any architecture subdir like "amd64".
|
|
|
|
TestPath = llvm::sys::path::parent_path(TestPath);
|
2021-06-23 19:52:36 +08:00
|
|
|
IsBin = llvm::sys::path::filename(TestPath).equals_insensitive("bin");
|
2017-05-17 23:27:44 +08:00
|
|
|
}
|
|
|
|
if (IsBin) {
|
|
|
|
llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
|
2021-06-23 19:52:36 +08:00
|
|
|
if (ParentFilename.equals_insensitive("VC")) {
|
2020-01-29 03:23:46 +08:00
|
|
|
Path = std::string(ParentPath);
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
|
|
|
return true;
|
|
|
|
}
|
2021-06-23 19:52:36 +08:00
|
|
|
if (ParentFilename.equals_insensitive("x86ret") ||
|
|
|
|
ParentFilename.equals_insensitive("x86chk") ||
|
|
|
|
ParentFilename.equals_insensitive("amd64ret") ||
|
|
|
|
ParentFilename.equals_insensitive("amd64chk")) {
|
2020-01-29 03:23:46 +08:00
|
|
|
Path = std::string(ParentPath);
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
|
2017-03-16 00:07:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// This could be a new (>=VS2017) toolchain. If it is, we should find
|
|
|
|
// path components with these prefixes when walking backwards through
|
|
|
|
// the path.
|
|
|
|
// Note: empty strings match anything.
|
|
|
|
llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
|
|
|
|
"MSVC", "Tools", "VC"};
|
|
|
|
|
|
|
|
auto It = llvm::sys::path::rbegin(PathEntry);
|
|
|
|
auto End = llvm::sys::path::rend(PathEntry);
|
|
|
|
for (llvm::StringRef Prefix : ExpectedPrefixes) {
|
|
|
|
if (It == End)
|
|
|
|
goto NotAToolChain;
|
2021-06-23 19:52:36 +08:00
|
|
|
if (!It->startswith_insensitive(Prefix))
|
2017-03-16 00:07:35 +08:00
|
|
|
goto NotAToolChain;
|
|
|
|
++It;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We've found a new toolchain!
|
|
|
|
// Back up 3 times (/bin/Host/arch) to get the root path.
|
|
|
|
llvm::StringRef ToolChainPath(PathEntry);
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
|
|
ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
|
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
Path = std::string(ToolChainPath);
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
2017-03-16 00:07:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
NotAToolChain:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Query the Setup Config server for installs, then pick the newest version
|
|
|
|
// and find its default VC toolchain.
|
|
|
|
// This is the preferred way to discover new Visual Studios, as they're no
|
|
|
|
// longer listed in the registry.
|
2021-02-25 11:58:40 +08:00
|
|
|
static bool
|
|
|
|
findVCToolChainViaSetupConfig(llvm::vfs::FileSystem &VFS, std::string &Path,
|
|
|
|
MSVCToolChain::ToolsetLayout &VSLayout) {
|
2017-03-16 01:09:36 +08:00
|
|
|
#if !defined(USE_MSVC_SETUP_API)
|
2017-03-16 00:07:35 +08:00
|
|
|
return false;
|
|
|
|
#else
|
|
|
|
// FIXME: This really should be done once in the top-level program's main
|
|
|
|
// function, as it may have already been initialized with a different
|
|
|
|
// threading model otherwise.
|
|
|
|
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
|
|
|
|
HRESULT HR;
|
|
|
|
|
|
|
|
// _com_ptr_t will throw a _com_error if a COM calls fail.
|
|
|
|
// The LLVM coding standards forbid exception handling, so we'll have to
|
|
|
|
// stop them from being thrown in the first place.
|
|
|
|
// The destructor will put the regular error handler back when we leave
|
|
|
|
// this scope.
|
|
|
|
struct SuppressCOMErrorsRAII {
|
|
|
|
static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
|
|
|
|
|
|
|
|
SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
|
|
|
|
|
|
|
|
~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
|
|
|
|
|
|
|
|
} COMErrorSuppressor;
|
|
|
|
|
|
|
|
ISetupConfigurationPtr Query;
|
|
|
|
HR = Query.CreateInstance(__uuidof(SetupConfiguration));
|
|
|
|
if (FAILED(HR))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
IEnumSetupInstancesPtr EnumInstances;
|
|
|
|
HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
|
|
|
|
if (FAILED(HR))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ISetupInstancePtr Instance;
|
|
|
|
HR = EnumInstances->Next(1, &Instance, nullptr);
|
|
|
|
if (HR != S_OK)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ISetupInstancePtr NewestInstance;
|
|
|
|
Optional<uint64_t> NewestVersionNum;
|
|
|
|
do {
|
|
|
|
bstr_t VersionString;
|
|
|
|
uint64_t VersionNum;
|
|
|
|
HR = Instance->GetInstallationVersion(VersionString.GetAddress());
|
|
|
|
if (FAILED(HR))
|
|
|
|
continue;
|
|
|
|
HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
|
|
|
|
if (FAILED(HR))
|
|
|
|
continue;
|
|
|
|
if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
|
|
|
|
NewestInstance = Instance;
|
|
|
|
NewestVersionNum = VersionNum;
|
|
|
|
}
|
|
|
|
} while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
|
|
|
|
|
|
|
|
if (!NewestInstance)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bstr_t VCPathWide;
|
|
|
|
HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
|
|
|
|
if (FAILED(HR))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::string VCRootPath;
|
|
|
|
llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
|
|
|
|
|
|
|
|
llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
|
|
|
|
llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
|
|
|
|
"Microsoft.VCToolsVersion.default.txt");
|
|
|
|
|
|
|
|
auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
|
|
|
|
if (!ToolsVersionFile)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
llvm::SmallString<256> ToolchainPath(VCRootPath);
|
|
|
|
llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
|
|
|
|
ToolsVersionFile->get()->getBuffer().rtrim());
|
2021-02-25 11:58:40 +08:00
|
|
|
auto Status = VFS.status(ToolchainPath);
|
|
|
|
if (!Status || !Status->isDirectory())
|
2017-03-16 00:07:35 +08:00
|
|
|
return false;
|
|
|
|
|
2020-01-29 07:18:16 +08:00
|
|
|
Path = std::string(ToolchainPath.str());
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
|
2017-03-16 00:07:35 +08:00
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look in the registry for Visual Studio installs, and use that to get
|
|
|
|
// a toolchain path. VS2017 and newer don't get added to the registry.
|
|
|
|
// So if we find something here, we know that it's an older version.
|
|
|
|
static bool findVCToolChainViaRegistry(std::string &Path,
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
MSVCToolChain::ToolsetLayout &VSLayout) {
|
2017-03-16 00:07:35 +08:00
|
|
|
std::string VSInstallPath;
|
|
|
|
if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
|
|
|
|
"InstallDir", VSInstallPath, nullptr) ||
|
|
|
|
getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
|
|
|
|
"InstallDir", VSInstallPath, nullptr)) {
|
|
|
|
if (!VSInstallPath.empty()) {
|
|
|
|
llvm::SmallString<256> VCPath(llvm::StringRef(
|
|
|
|
VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
|
|
|
|
llvm::sys::path::append(VCPath, "VC");
|
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
Path = std::string(VCPath.str());
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
|
2017-03-16 00:07:35 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
// Try to find Exe from a Visual Studio distribution. This first tries to find
|
|
|
|
// an installed copy of Visual Studio and, failing that, looks in the PATH,
|
|
|
|
// making sure that whatever executable that's found is not a same-named exe
|
|
|
|
// from clang itself to prevent clang from falling back to itself.
|
|
|
|
static std::string FindVisualStudioExecutable(const ToolChain &TC,
|
2017-03-16 00:07:35 +08:00
|
|
|
const char *Exe) {
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
|
2017-03-16 00:07:35 +08:00
|
|
|
SmallString<128> FilePath(MSVC.getSubDirectoryPath(
|
|
|
|
toolchains::MSVCToolChain::SubDirectoryType::Bin));
|
|
|
|
llvm::sys::path::append(FilePath, Exe);
|
2021-02-25 11:58:40 +08:00
|
|
|
return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|
|
|
const InputInfo &Output,
|
|
|
|
const InputInfoList &Inputs,
|
|
|
|
const ArgList &Args,
|
|
|
|
const char *LinkingOutput) const {
|
|
|
|
ArgStringList CmdArgs;
|
2017-03-16 00:07:35 +08:00
|
|
|
|
|
|
|
auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
|
|
|
|
assert((Output.isFilename() || Output.isNothing()) && "invalid output");
|
|
|
|
if (Output.isFilename())
|
|
|
|
CmdArgs.push_back(
|
|
|
|
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
|
|
|
|
|
|
|
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
|
2020-10-19 21:10:18 +08:00
|
|
|
!C.getDriver().IsCLMode()) {
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
CmdArgs.push_back("-defaultlib:libcmt");
|
2020-10-19 21:10:18 +08:00
|
|
|
CmdArgs.push_back("-defaultlib:oldnames");
|
|
|
|
}
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
|
2021-01-27 21:52:23 +08:00
|
|
|
// If the VC environment hasn't been configured (perhaps because the user
|
|
|
|
// did not run vcvarsall), try to build a consistent link environment. If
|
|
|
|
// the environment variable is set however, assume the user knows what
|
|
|
|
// they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
|
|
|
|
// over env vars.
|
|
|
|
if (!llvm::sys::Process::GetEnv("LIB") ||
|
2021-01-28 00:01:59 +08:00
|
|
|
Args.getLastArg(options::OPT__SLASH_vctoolsdir,
|
|
|
|
options::OPT__SLASH_winsysroot)) {
|
2017-03-16 00:07:35 +08:00
|
|
|
CmdArgs.push_back(Args.MakeArgString(
|
|
|
|
Twine("-libpath:") +
|
|
|
|
TC.getSubDirectoryPath(
|
|
|
|
toolchains::MSVCToolChain::SubDirectoryType::Lib)));
|
2019-10-11 04:25:54 +08:00
|
|
|
CmdArgs.push_back(Args.MakeArgString(
|
|
|
|
Twine("-libpath:") +
|
|
|
|
TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib,
|
|
|
|
"atlmfc")));
|
2021-01-27 21:52:23 +08:00
|
|
|
}
|
|
|
|
if (!llvm::sys::Process::GetEnv("LIB") ||
|
2021-01-28 00:01:59 +08:00
|
|
|
Args.getLastArg(options::OPT__SLASH_winsdkdir,
|
|
|
|
options::OPT__SLASH_winsysroot)) {
|
2017-03-16 00:07:35 +08:00
|
|
|
if (TC.useUniversalCRT()) {
|
|
|
|
std::string UniversalCRTLibPath;
|
2021-01-27 04:21:12 +08:00
|
|
|
if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
|
2017-03-16 00:07:35 +08:00
|
|
|
CmdArgs.push_back(
|
|
|
|
Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
}
|
|
|
|
std::string WindowsSdkLibPath;
|
2021-01-27 04:21:12 +08:00
|
|
|
if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
CmdArgs.push_back(
|
|
|
|
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
|
|
|
|
}
|
|
|
|
|
[Windows] Autolink with basenames and add libdir to libpath
Prior to this change, for a few compiler-rt libraries such as ubsan and
the profile library, Clang would embed "-defaultlib:path/to/rt-arch.lib"
into the .drective section of every object compiled with
-finstr-profile-generate or -fsanitize=ubsan as appropriate.
These paths assume that the link step will run from the same working
directory as the compile step. There is also evidence that sometimes the
paths become absolute, such as when clang is run from a different drive
letter from the current working directory. This is fragile, and I'd like
to get away from having paths embedded in the object if possible. Long
ago it was suggested that we use this for ASan, and apparently I felt
the same way back then:
https://reviews.llvm.org/D4428#56536
This is also consistent with how all other autolinking usage works for
PS4, Mac, and Windows: they all use basenames, not paths.
To keep things working for people using the standard GCC driver
workflow, the driver now adds the resource directory to the linker
library search path when it calls the linker. This is enough to make
check-ubsan pass, and seems like a generally good thing.
Users that invoke the linker directly (most clang-cl users) will have to
add clang's resource library directory to their linker search path in
their build system. I'm not sure where I can document this. Ideally I'd
also do it in the MSBuild files, but I can't figure out where they go.
I'd like to start with this for now.
Reviewed By: hans
Differential Revision: https://reviews.llvm.org/D65543
2019-08-01 05:52:00 +08:00
|
|
|
// Add the compiler-rt library directories to libpath if they exist to help
|
|
|
|
// the linker find the various sanitizer, builtin, and profiling runtimes.
|
|
|
|
for (const auto &LibPath : TC.getLibraryPaths()) {
|
|
|
|
if (TC.getVFS().exists(LibPath))
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
|
|
|
|
}
|
|
|
|
auto CRTPath = TC.getCompilerRTPath();
|
|
|
|
if (TC.getVFS().exists(CRTPath))
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
|
|
|
|
for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
|
|
|
|
|
|
|
|
CmdArgs.push_back("-nologo");
|
|
|
|
|
2020-12-17 22:23:02 +08:00
|
|
|
if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
CmdArgs.push_back("-debug");
|
|
|
|
|
2018-09-07 20:47:02 +08:00
|
|
|
// Pass on /Brepro if it was passed to the compiler.
|
|
|
|
// Note that /Brepro maps to -mno-incremental-linker-compatible.
|
|
|
|
bool DefaultIncrementalLinkerCompatible =
|
|
|
|
C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
|
|
|
|
if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
|
|
|
|
options::OPT_mno_incremental_linker_compatible,
|
|
|
|
DefaultIncrementalLinkerCompatible))
|
|
|
|
CmdArgs.push_back("-Brepro");
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
|
|
|
|
options::OPT_shared);
|
|
|
|
if (DLL) {
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-dll"));
|
|
|
|
|
|
|
|
SmallString<128> ImplibName(Output.getFilename());
|
|
|
|
llvm::sys::path::replace_extension(ImplibName, "lib");
|
2017-10-12 07:54:34 +08:00
|
|
|
CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
}
|
|
|
|
|
[libFuzzer] Port to Windows
Summary:
Port libFuzzer to windows-msvc.
This patch allows libFuzzer targets to be built and run on Windows, using -fsanitize=fuzzer and/or fsanitize=fuzzer-no-link. It allows these forms of coverage instrumentation to work on Windows as well.
It does not fix all issues, such as those with -fsanitize-coverage=stack-depth, which is not usable on Windows as of this patch.
It also does not fix any libFuzzer integration tests. Nearly all of them fail to compile, fixing them will come in a later patch, so libFuzzer tests are disabled on Windows until them.
Patch By: metzman
Reviewers: morehouse, rnk
Reviewed By: morehouse, rnk
Subscribers: #sanitizers, delcypher, morehouse, kcc, eraman
Differential Revision: https://reviews.llvm.org/D51022
llvm-svn: 341082
2018-08-30 23:54:44 +08:00
|
|
|
if (TC.getSanitizerArgs().needsFuzzer()) {
|
|
|
|
if (!Args.hasArg(options::OPT_shared))
|
|
|
|
CmdArgs.push_back(
|
|
|
|
Args.MakeArgString(std::string("-wholearchive:") +
|
2019-01-21 09:34:09 +08:00
|
|
|
TC.getCompilerRTArgString(Args, "fuzzer")));
|
[libFuzzer] Port to Windows
Summary:
Port libFuzzer to windows-msvc.
This patch allows libFuzzer targets to be built and run on Windows, using -fsanitize=fuzzer and/or fsanitize=fuzzer-no-link. It allows these forms of coverage instrumentation to work on Windows as well.
It does not fix all issues, such as those with -fsanitize-coverage=stack-depth, which is not usable on Windows as of this patch.
It also does not fix any libFuzzer integration tests. Nearly all of them fail to compile, fixing them will come in a later patch, so libFuzzer tests are disabled on Windows until them.
Patch By: metzman
Reviewers: morehouse, rnk
Reviewed By: morehouse, rnk
Subscribers: #sanitizers, delcypher, morehouse, kcc, eraman
Differential Revision: https://reviews.llvm.org/D51022
llvm-svn: 341082
2018-08-30 23:54:44 +08:00
|
|
|
CmdArgs.push_back(Args.MakeArgString("-debug"));
|
|
|
|
// Prevent the linker from padding sections we use for instrumentation
|
|
|
|
// arrays.
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
|
|
|
|
}
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
if (TC.getSanitizerArgs().needsAsanRt()) {
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-debug"));
|
|
|
|
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
|
2017-10-06 04:14:00 +08:00
|
|
|
if (TC.getSanitizerArgs().needsSharedRt() ||
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
|
|
|
|
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
|
|
|
|
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
|
|
|
|
// Make sure the dynamic runtime thunk is not optimized out at link time
|
|
|
|
// to ensure proper SEH handling.
|
|
|
|
CmdArgs.push_back(Args.MakeArgString(
|
|
|
|
TC.getArch() == llvm::Triple::x86
|
|
|
|
? "-include:___asan_seh_interceptor"
|
|
|
|
: "-include:__asan_seh_interceptor"));
|
|
|
|
// Make sure the linker consider all object files from the dynamic runtime
|
|
|
|
// thunk.
|
|
|
|
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
|
|
|
|
TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
|
|
|
|
} else if (DLL) {
|
|
|
|
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
|
|
|
|
} else {
|
|
|
|
for (const auto &Lib : {"asan", "asan_cxx"}) {
|
|
|
|
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
|
|
|
|
// Make sure the linker consider all object files from the static lib.
|
|
|
|
// This is necessary because instrumented dlls need access to all the
|
|
|
|
// interface exported by the static lib in the main executable.
|
|
|
|
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
|
|
|
|
TC.getCompilerRT(Args, Lib)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
|
|
|
|
|
Add Windows Control Flow Guard checks (/guard:cf).
Summary:
A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on
indirect function calls, using either the check mechanism (X86, ARM, AArch64) or
or the dispatch mechanism (X86-64). The check mechanism requires a new calling
convention for the supported targets. The dispatch mechanism adds the target as
an operand bundle, which is processed by SelectionDAG. Another pass
(CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as
required by /guard:cf. This feature is enabled using the `cfguard` CC1 option.
Reviewers: thakis, rnk, theraven, pcc
Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D65761
2019-10-28 21:22:19 +08:00
|
|
|
// Control Flow Guard checks
|
|
|
|
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
|
|
|
|
StringRef GuardArgs = A->getValue();
|
2021-06-23 19:52:36 +08:00
|
|
|
if (GuardArgs.equals_insensitive("cf") ||
|
|
|
|
GuardArgs.equals_insensitive("cf,nochecks")) {
|
Add Windows Control Flow Guard checks (/guard:cf).
Summary:
A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on
indirect function calls, using either the check mechanism (X86, ARM, AArch64) or
or the dispatch mechanism (X86-64). The check mechanism requires a new calling
convention for the supported targets. The dispatch mechanism adds the target as
an operand bundle, which is processed by SelectionDAG. Another pass
(CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as
required by /guard:cf. This feature is enabled using the `cfguard` CC1 option.
Reviewers: thakis, rnk, theraven, pcc
Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D65761
2019-10-28 21:22:19 +08:00
|
|
|
// MSVC doesn't yet support the "nochecks" modifier.
|
|
|
|
CmdArgs.push_back("-guard:cf");
|
2021-06-23 19:52:36 +08:00
|
|
|
} else if (GuardArgs.equals_insensitive("cf-")) {
|
Add Windows Control Flow Guard checks (/guard:cf).
Summary:
A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on
indirect function calls, using either the check mechanism (X86, ARM, AArch64) or
or the dispatch mechanism (X86-64). The check mechanism requires a new calling
convention for the supported targets. The dispatch mechanism adds the target as
an operand bundle, which is processed by SelectionDAG. Another pass
(CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as
required by /guard:cf. This feature is enabled using the `cfguard` CC1 option.
Reviewers: thakis, rnk, theraven, pcc
Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D65761
2019-10-28 21:22:19 +08:00
|
|
|
CmdArgs.push_back("-guard:cf-");
|
2021-06-23 19:52:36 +08:00
|
|
|
} else if (GuardArgs.equals_insensitive("ehcont")) {
|
2021-03-03 10:38:21 +08:00
|
|
|
CmdArgs.push_back("-guard:ehcont");
|
2021-06-23 19:52:36 +08:00
|
|
|
} else if (GuardArgs.equals_insensitive("ehcont-")) {
|
2021-03-03 10:38:21 +08:00
|
|
|
CmdArgs.push_back("-guard:ehcont-");
|
Add Windows Control Flow Guard checks (/guard:cf).
Summary:
A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on
indirect function calls, using either the check mechanism (X86, ARM, AArch64) or
or the dispatch mechanism (X86-64). The check mechanism requires a new calling
convention for the supported targets. The dispatch mechanism adds the target as
an operand bundle, which is processed by SelectionDAG. Another pass
(CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as
required by /guard:cf. This feature is enabled using the `cfguard` CC1 option.
Reviewers: thakis, rnk, theraven, pcc
Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D65761
2019-10-28 21:22:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
|
|
|
|
options::OPT_fno_openmp, false)) {
|
|
|
|
CmdArgs.push_back("-nodefaultlib:vcomp.lib");
|
|
|
|
CmdArgs.push_back("-nodefaultlib:vcompd.lib");
|
|
|
|
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
|
|
|
|
TC.getDriver().Dir + "/../lib"));
|
|
|
|
switch (TC.getDriver().getOpenMPRuntime(Args)) {
|
|
|
|
case Driver::OMPRT_OMP:
|
|
|
|
CmdArgs.push_back("-defaultlib:libomp.lib");
|
|
|
|
break;
|
|
|
|
case Driver::OMPRT_IOMP5:
|
|
|
|
CmdArgs.push_back("-defaultlib:libiomp5md.lib");
|
|
|
|
break;
|
|
|
|
case Driver::OMPRT_GOMP:
|
|
|
|
break;
|
|
|
|
case Driver::OMPRT_Unknown:
|
|
|
|
// Already diagnosed.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add compiler-rt lib in case if it was explicitly
|
|
|
|
// specified as an argument for --rtlib option.
|
|
|
|
if (!Args.hasArg(options::OPT_nostdlib)) {
|
|
|
|
AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add filenames, libraries, and other linker inputs.
|
|
|
|
for (const auto &Input : Inputs) {
|
|
|
|
if (Input.isFilename()) {
|
|
|
|
CmdArgs.push_back(Input.getFilename());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Arg &A = Input.getInputArg();
|
|
|
|
|
|
|
|
// Render -l options differently for the MSVC linker.
|
|
|
|
if (A.getOption().matches(options::OPT_l)) {
|
|
|
|
StringRef Lib = A.getValue();
|
|
|
|
const char *LinkLibArg;
|
|
|
|
if (Lib.endswith(".lib"))
|
|
|
|
LinkLibArg = Args.MakeArgString(Lib);
|
|
|
|
else
|
|
|
|
LinkLibArg = Args.MakeArgString(Lib + ".lib");
|
|
|
|
CmdArgs.push_back(LinkLibArg);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, this is some other kind of linker input option like -Wl, -z,
|
|
|
|
// or -L. Render it, even if MSVC doesn't understand it.
|
|
|
|
A.renderAsInput(Args, CmdArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
TC.addProfileRTLibs(Args, CmdArgs);
|
|
|
|
|
2017-03-18 00:24:34 +08:00
|
|
|
std::vector<const char *> Environment;
|
|
|
|
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
// We need to special case some linker paths. In the case of lld, we need to
|
|
|
|
// translate 'lld' into 'lld-link', and in the case of the regular msvc
|
|
|
|
// linker, we need to use a special search algorithm.
|
|
|
|
llvm::SmallString<128> linkPath;
|
2021-03-19 21:37:19 +08:00
|
|
|
StringRef Linker
|
|
|
|
= Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
|
|
|
|
if (Linker.empty())
|
|
|
|
Linker = "link";
|
2021-06-23 19:52:36 +08:00
|
|
|
if (Linker.equals_insensitive("lld"))
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
Linker = "lld-link";
|
|
|
|
|
2021-06-23 19:52:36 +08:00
|
|
|
if (Linker.equals_insensitive("link")) {
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
// If we're using the MSVC linker, it's not sufficient to just use link
|
|
|
|
// from the program PATH, because other environments like GnuWin32 install
|
|
|
|
// their own link.exe which may come first.
|
2017-03-16 00:07:35 +08:00
|
|
|
linkPath = FindVisualStudioExecutable(TC, "link.exe");
|
2017-03-18 00:24:34 +08:00
|
|
|
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) {
|
2019-04-20 03:04:22 +08:00
|
|
|
llvm::SmallString<128> ClPath;
|
|
|
|
ClPath = TC.GetProgramPath("cl.exe");
|
2021-02-25 11:58:40 +08:00
|
|
|
if (canExecute(TC.getVFS(), ClPath)) {
|
2019-04-20 03:04:22 +08:00
|
|
|
linkPath = llvm::sys::path::parent_path(ClPath);
|
|
|
|
llvm::sys::path::append(linkPath, "link.exe");
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!canExecute(TC.getVFS(), linkPath))
|
2019-04-20 03:04:22 +08:00
|
|
|
C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
|
|
|
|
} else {
|
|
|
|
C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
|
|
|
|
}
|
|
|
|
}
|
2018-07-17 23:07:40 +08:00
|
|
|
|
2018-04-30 21:47:04 +08:00
|
|
|
#ifdef _WIN32
|
2017-03-18 00:24:34 +08:00
|
|
|
// When cross-compiling with VS2017 or newer, link.exe expects to have
|
|
|
|
// its containing bin directory at the top of PATH, followed by the
|
|
|
|
// native target bin directory.
|
|
|
|
// e.g. when compiling for x86 on an x64 host, PATH should start with:
|
2019-04-18 21:27:31 +08:00
|
|
|
// /bin/Hostx64/x86;/bin/Hostx64/x64
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
// This doesn't attempt to handle ToolsetLayout::DevDivInternal.
|
2017-03-18 00:24:34 +08:00
|
|
|
if (TC.getIsVS2017OrNewer() &&
|
|
|
|
llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
|
|
|
|
auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
|
|
|
|
|
|
|
|
auto EnvBlockWide =
|
|
|
|
std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
|
|
|
|
GetEnvironmentStringsW(), FreeEnvironmentStringsW);
|
|
|
|
if (!EnvBlockWide)
|
|
|
|
goto SkipSettingEnvironment;
|
|
|
|
|
|
|
|
size_t EnvCount = 0;
|
|
|
|
size_t EnvBlockLen = 0;
|
|
|
|
while (EnvBlockWide[EnvBlockLen] != L'\0') {
|
|
|
|
++EnvCount;
|
|
|
|
EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
|
|
|
|
1 /*string null-terminator*/;
|
|
|
|
}
|
|
|
|
++EnvBlockLen; // add the block null-terminator
|
|
|
|
|
|
|
|
std::string EnvBlock;
|
|
|
|
if (!llvm::convertUTF16ToUTF8String(
|
|
|
|
llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
|
|
|
|
EnvBlockLen * sizeof(EnvBlockWide[0])),
|
|
|
|
EnvBlock))
|
|
|
|
goto SkipSettingEnvironment;
|
|
|
|
|
|
|
|
Environment.reserve(EnvCount);
|
|
|
|
|
|
|
|
// Now loop over each string in the block and copy them into the
|
|
|
|
// environment vector, adjusting the PATH variable as needed when we
|
|
|
|
// find it.
|
|
|
|
for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
|
|
|
|
llvm::StringRef EnvVar(Cursor);
|
2021-06-23 19:52:36 +08:00
|
|
|
if (EnvVar.startswith_insensitive("path=")) {
|
2017-03-18 00:24:34 +08:00
|
|
|
using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
|
|
|
|
constexpr size_t PrefixLen = 5; // strlen("path=")
|
|
|
|
Environment.push_back(Args.MakeArgString(
|
|
|
|
EnvVar.substr(0, PrefixLen) +
|
|
|
|
TC.getSubDirectoryPath(SubDirectoryType::Bin) +
|
|
|
|
llvm::Twine(llvm::sys::EnvPathSeparator) +
|
2019-10-11 04:25:54 +08:00
|
|
|
TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) +
|
2017-03-18 00:24:34 +08:00
|
|
|
(EnvVar.size() > PrefixLen
|
|
|
|
? llvm::Twine(llvm::sys::EnvPathSeparator) +
|
|
|
|
EnvVar.substr(PrefixLen)
|
|
|
|
: "")));
|
|
|
|
} else {
|
|
|
|
Environment.push_back(Args.MakeArgString(EnvVar));
|
|
|
|
}
|
|
|
|
Cursor += EnvVar.size() + 1 /*null-terminator*/;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SkipSettingEnvironment:;
|
|
|
|
#endif
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
} else {
|
2017-06-06 10:06:28 +08:00
|
|
|
linkPath = TC.GetProgramPath(Linker.str().c_str());
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
}
|
|
|
|
|
2020-04-24 01:27:14 +08:00
|
|
|
auto LinkCmd = std::make_unique<Command>(
|
|
|
|
JA, *this, ResponseFileSupport::AtFileUTF16(),
|
|
|
|
Args.MakeArgString(linkPath), CmdArgs, Inputs, Output);
|
2017-03-18 00:24:34 +08:00
|
|
|
if (!Environment.empty())
|
|
|
|
LinkCmd->setEnvironment(Environment);
|
|
|
|
C.addCommand(std::move(LinkCmd));
|
[Driver] Consolidate tools and toolchains by target platform. (NFC)
Summary:
(This is a move-only refactoring patch. There are no functionality changes.)
This patch splits apart the Clang driver's tool and toolchain implementation
files. Each target platform toolchain is moved to its own file, along with the
closest-related tools. Each target platform toolchain has separate headers and
implementation files, so the hierarchy of classes is unchanged.
There are some remaining shared free functions, mostly from Tools.cpp. Several
of these move to their own architecture-specific files, similar to r296056. Some
of them are only used by a single target platform; since the tools and
toolchains are now together, some helpers now live in a platform-specific file.
The balance are helpers related to manipulating argument lists, so they are now
in a new file pair, CommonArgs.h and .cpp.
I've tried to cluster the code logically, which is fairly straightforward for
most of the target platforms and shared architectures. I think I've made
reasonable choices for these, as well as the various shared helpers; but of
course, I'm happy to hear feedback in the review.
There are some particular things I don't like about this patch, but haven't been
able to find a better overall solution. The first is the proliferation of files:
there are several files that are tiny because the toolchain is not very
different from its base (usually the Gnu tools/toolchain). I think this is
mostly a reflection of the true complexity, though, so it may not be "fixable"
in any reasonable sense. The second thing I don't like are the includes like
"../Something.h". I've avoided this largely by clustering into the current file
structure. However, a few of these includes remain, and in those cases it
doesn't make sense to me to sink an existing file any deeper.
Reviewers: rsmith, mehdi_amini, compnerd, rnk, javed.absar
Subscribers: emaste, jfb, danalbert, srhines, dschuff, jyknight, nemanjai, nhaehnle, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30372
llvm-svn: 297250
2017-03-08 09:02:16 +08:00
|
|
|
}
|
|
|
|
|
2017-02-03 03:36:22 +08:00
|
|
|
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
|
2014-10-22 10:37:29 +08:00
|
|
|
const ArgList &Args)
|
2020-06-06 04:49:38 +08:00
|
|
|
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
|
|
|
|
RocmInstallation(D, Triple, Args) {
|
2014-12-02 07:06:47 +08:00
|
|
|
getProgramPaths().push_back(getDriver().getInstalledDir());
|
|
|
|
if (getDriver().getInstalledDir() != getDriver().Dir)
|
|
|
|
getProgramPaths().push_back(getDriver().Dir);
|
2017-03-16 00:07:35 +08:00
|
|
|
|
2020-08-26 20:58:39 +08:00
|
|
|
// Check the command line first, that's the user explicitly telling us what to
|
|
|
|
// use. Check the environment next, in case we're being invoked from a VS
|
|
|
|
// command prompt. Failing that, just try to find the newest Visual Studio
|
|
|
|
// version we can and use its default VC toolchain.
|
2021-02-25 11:58:40 +08:00
|
|
|
findVCToolChainViaCommandLine(getVFS(), Args, VCToolChainPath, VSLayout) ||
|
|
|
|
findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, VSLayout) ||
|
|
|
|
findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, VSLayout) ||
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
|
2013-08-30 17:42:06 +08:00
|
|
|
}
|
|
|
|
|
2014-10-22 10:37:29 +08:00
|
|
|
Tool *MSVCToolChain::buildLinker() const {
|
2015-06-24 04:42:09 +08:00
|
|
|
return new tools::visualstudio::Linker(*this);
|
2013-08-30 17:42:06 +08:00
|
|
|
}
|
|
|
|
|
2014-10-22 10:37:29 +08:00
|
|
|
Tool *MSVCToolChain::buildAssembler() const {
|
2014-03-28 06:50:18 +08:00
|
|
|
if (getTriple().isOSBinFormatMachO())
|
2015-06-24 04:42:09 +08:00
|
|
|
return new tools::darwin::Assembler(*this);
|
2013-11-22 16:27:46 +08:00
|
|
|
getDriver().Diag(clang::diag::err_no_external_assembler);
|
2014-05-18 00:56:41 +08:00
|
|
|
return nullptr;
|
2013-08-30 17:42:06 +08:00
|
|
|
}
|
|
|
|
|
2014-10-22 10:37:29 +08:00
|
|
|
bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
|
2013-08-30 17:42:06 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-08-04 07:55:42 +08:00
|
|
|
bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
|
2016-05-05 09:41:07 +08:00
|
|
|
// Don't emit unwind tables by default for MachO targets.
|
|
|
|
if (getTriple().isOSBinFormatMachO())
|
|
|
|
return false;
|
|
|
|
|
2018-11-01 05:39:41 +08:00
|
|
|
// All non-x86_32 Windows targets require unwind tables. However, LLVM
|
|
|
|
// doesn't know how to generate them for all targets, so only enable
|
|
|
|
// the ones that are actually implemented.
|
|
|
|
return getArch() == llvm::Triple::x86_64 ||
|
|
|
|
getArch() == llvm::Triple::aarch64;
|
2016-12-29 01:41:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MSVCToolChain::isPICDefault() const {
|
|
|
|
return getArch() == llvm::Triple::x86_64;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MSVCToolChain::isPIEDefault() const {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MSVCToolChain::isPICDefaultForced() const {
|
|
|
|
return getArch() == llvm::Triple::x86_64;
|
2013-08-30 17:42:06 +08:00
|
|
|
}
|
|
|
|
|
2017-01-06 00:52:29 +08:00
|
|
|
void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
|
|
|
|
ArgStringList &CC1Args) const {
|
|
|
|
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
|
2020-06-06 04:49:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
|
|
|
|
ArgStringList &CC1Args) const {
|
|
|
|
RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
|
2017-01-06 00:52:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
|
|
|
|
CudaInstallation.print(OS);
|
2020-07-01 12:00:04 +08:00
|
|
|
RocmInstallation.print(OS);
|
2017-01-06 00:52:29 +08:00
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
// Windows SDKs and VC Toolchains group their contents into subdirectories based
|
|
|
|
// on the target architecture. This function converts an llvm::Triple::ArchType
|
|
|
|
// to the corresponding subdirectory name.
|
|
|
|
static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
|
|
|
|
using ArchType = llvm::Triple::ArchType;
|
|
|
|
switch (Arch) {
|
|
|
|
case ArchType::x86:
|
|
|
|
return "x86";
|
|
|
|
case ArchType::x86_64:
|
|
|
|
return "x64";
|
|
|
|
case ArchType::arm:
|
|
|
|
return "arm";
|
2018-03-06 05:36:23 +08:00
|
|
|
case ArchType::aarch64:
|
|
|
|
return "arm64";
|
2017-03-16 00:07:35 +08:00
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Similar to the above function, but for Visual Studios before VS2017.
|
|
|
|
static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
|
|
|
|
using ArchType = llvm::Triple::ArchType;
|
|
|
|
switch (Arch) {
|
|
|
|
case ArchType::x86:
|
|
|
|
// x86 is default in legacy VC toolchains.
|
|
|
|
// e.g. x86 libs are directly in /lib as opposed to /lib/x86.
|
|
|
|
return "";
|
|
|
|
case ArchType::x86_64:
|
|
|
|
return "amd64";
|
|
|
|
case ArchType::arm:
|
|
|
|
return "arm";
|
2018-03-06 05:36:23 +08:00
|
|
|
case ArchType::aarch64:
|
|
|
|
return "arm64";
|
2017-03-16 00:07:35 +08:00
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
// Similar to the above function, but for DevDiv internal builds.
|
|
|
|
static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
|
|
|
|
using ArchType = llvm::Triple::ArchType;
|
|
|
|
switch (Arch) {
|
|
|
|
case ArchType::x86:
|
|
|
|
return "i386";
|
|
|
|
case ArchType::x86_64:
|
|
|
|
return "amd64";
|
|
|
|
case ArchType::arm:
|
|
|
|
return "arm";
|
2018-03-06 05:36:23 +08:00
|
|
|
case ArchType::aarch64:
|
|
|
|
return "arm64";
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
// Get the path to a specific subdirectory in the current toolchain for
|
|
|
|
// a given target architecture.
|
|
|
|
// VS2017 changed the VC toolchain layout, so this should be used instead
|
|
|
|
// of hardcoding paths.
|
|
|
|
std::string
|
|
|
|
MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
|
2019-10-11 04:25:54 +08:00
|
|
|
llvm::StringRef SubdirParent,
|
2017-03-16 00:07:35 +08:00
|
|
|
llvm::Triple::ArchType TargetArch) const {
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
const char *SubdirName;
|
|
|
|
const char *IncludeName;
|
|
|
|
switch (VSLayout) {
|
|
|
|
case ToolsetLayout::OlderVS:
|
|
|
|
SubdirName = llvmArchToLegacyVCArch(TargetArch);
|
|
|
|
IncludeName = "include";
|
|
|
|
break;
|
|
|
|
case ToolsetLayout::VS2017OrNewer:
|
|
|
|
SubdirName = llvmArchToWindowsSDKArch(TargetArch);
|
|
|
|
IncludeName = "include";
|
|
|
|
break;
|
|
|
|
case ToolsetLayout::DevDivInternal:
|
|
|
|
SubdirName = llvmArchToDevDivInternalArch(TargetArch);
|
|
|
|
IncludeName = "inc";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
llvm::SmallString<256> Path(VCToolChainPath);
|
2019-10-11 04:25:54 +08:00
|
|
|
if (!SubdirParent.empty())
|
|
|
|
llvm::sys::path::append(Path, SubdirParent);
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
switch (Type) {
|
|
|
|
case SubDirectoryType::Bin:
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
if (VSLayout == ToolsetLayout::VS2017OrNewer) {
|
|
|
|
const bool HostIsX64 =
|
2017-03-16 00:07:35 +08:00
|
|
|
llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
|
2019-04-18 21:27:31 +08:00
|
|
|
const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
llvm::sys::path::append(Path, "bin", HostName, SubdirName);
|
|
|
|
} else { // OlderVS or DevDivInternal
|
|
|
|
llvm::sys::path::append(Path, "bin", SubdirName);
|
2017-03-16 00:07:35 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SubDirectoryType::Include:
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
llvm::sys::path::append(Path, IncludeName);
|
2017-03-16 00:07:35 +08:00
|
|
|
break;
|
|
|
|
case SubDirectoryType::Lib:
|
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.
This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.
The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.
After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.
This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.
Fixes D36860.
llvm-svn: 311391
2017-08-22 06:19:33 +08:00
|
|
|
llvm::sys::path::append(Path, "lib", SubdirName);
|
2017-03-16 00:07:35 +08:00
|
|
|
break;
|
|
|
|
}
|
2020-01-29 03:23:46 +08:00
|
|
|
return std::string(Path.str());
|
2017-03-16 00:07:35 +08:00
|
|
|
}
|
|
|
|
|
2018-04-30 21:47:04 +08:00
|
|
|
#ifdef _WIN32
|
2014-10-23 04:40:28 +08:00
|
|
|
static bool readFullStringValue(HKEY hkey, const char *valueName,
|
|
|
|
std::string &value) {
|
2016-06-23 22:33:53 +08:00
|
|
|
std::wstring WideValueName;
|
|
|
|
if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
|
|
|
|
return false;
|
|
|
|
|
2014-10-23 04:40:28 +08:00
|
|
|
DWORD result = 0;
|
|
|
|
DWORD valueSize = 0;
|
|
|
|
DWORD type = 0;
|
|
|
|
// First just query for the required size.
|
2016-06-23 22:33:53 +08:00
|
|
|
result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
|
|
|
|
&valueSize);
|
|
|
|
if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
|
2014-10-23 04:40:28 +08:00
|
|
|
return false;
|
|
|
|
std::vector<BYTE> buffer(valueSize);
|
2016-06-23 22:33:53 +08:00
|
|
|
result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
|
|
|
|
&valueSize);
|
|
|
|
if (result == ERROR_SUCCESS) {
|
|
|
|
std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
|
|
|
|
valueSize / sizeof(wchar_t));
|
2016-07-29 01:13:32 +08:00
|
|
|
if (valueSize && WideValue.back() == L'\0') {
|
2016-08-31 02:38:25 +08:00
|
|
|
WideValue.pop_back();
|
2016-07-29 01:13:32 +08:00
|
|
|
}
|
2016-06-23 22:33:53 +08:00
|
|
|
// The destination buffer must be empty as an invariant of the conversion
|
|
|
|
// function; but this function is sometimes called in a loop that passes in
|
|
|
|
// the same buffer, however. Simply clear it out so we can overwrite it.
|
|
|
|
value.clear();
|
|
|
|
return llvm::convertWideToUTF8(WideValue, value);
|
|
|
|
}
|
|
|
|
return false;
|
2014-10-23 04:40:28 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Read registry string.
|
2011-12-18 07:10:01 +08:00
|
|
|
/// This also supports a means to look for high-versioned keys by use
|
|
|
|
/// of a $VERSION placeholder in the key path.
|
|
|
|
/// $VERSION in the key path is a placeholder for the version number,
|
|
|
|
/// causing the highest value path to be searched for and used.
|
2014-10-23 04:40:28 +08:00
|
|
|
/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
|
|
|
|
/// There can be additional characters in the component. Only the numeric
|
|
|
|
/// characters are compared. This function only searches HKLM.
|
2011-12-18 07:10:01 +08:00
|
|
|
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
|
2014-10-23 04:40:28 +08:00
|
|
|
std::string &value, std::string *phValue) {
|
2018-04-30 21:47:04 +08:00
|
|
|
#ifndef _WIN32
|
2014-06-22 11:27:45 +08:00
|
|
|
return false;
|
|
|
|
#else
|
2014-10-23 04:40:28 +08:00
|
|
|
HKEY hRootKey = HKEY_LOCAL_MACHINE;
|
2011-12-18 07:10:01 +08:00
|
|
|
HKEY hKey = NULL;
|
|
|
|
long lResult;
|
|
|
|
bool returnValue = false;
|
|
|
|
|
2014-10-23 04:40:28 +08:00
|
|
|
const char *placeHolder = strstr(keyPath, "$VERSION");
|
|
|
|
std::string bestName;
|
2011-12-18 07:10:01 +08:00
|
|
|
// If we have a $VERSION placeholder, do the highest-version search.
|
|
|
|
if (placeHolder) {
|
|
|
|
const char *keyEnd = placeHolder - 1;
|
|
|
|
const char *nextKey = placeHolder;
|
|
|
|
// Find end of previous key.
|
2014-10-23 04:40:28 +08:00
|
|
|
while ((keyEnd > keyPath) && (*keyEnd != '\\'))
|
2011-12-18 07:10:01 +08:00
|
|
|
keyEnd--;
|
|
|
|
// Find end of key containing $VERSION.
|
|
|
|
while (*nextKey && (*nextKey != '\\'))
|
|
|
|
nextKey++;
|
2014-10-23 04:40:28 +08:00
|
|
|
size_t partialKeyLength = keyEnd - keyPath;
|
2011-12-18 07:10:01 +08:00
|
|
|
char partialKey[256];
|
2016-01-27 15:33:50 +08:00
|
|
|
if (partialKeyLength >= sizeof(partialKey))
|
|
|
|
partialKeyLength = sizeof(partialKey) - 1;
|
2014-10-23 04:40:28 +08:00
|
|
|
strncpy(partialKey, keyPath, partialKeyLength);
|
2011-12-18 07:10:01 +08:00
|
|
|
partialKey[partialKeyLength] = '\0';
|
|
|
|
HKEY hTopKey = NULL;
|
2016-06-23 22:33:53 +08:00
|
|
|
lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
|
|
|
|
&hTopKey);
|
2011-12-18 07:10:01 +08:00
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
char keyName[256];
|
|
|
|
double bestValue = 0.0;
|
|
|
|
DWORD index, size = sizeof(keyName) - 1;
|
2016-06-23 22:33:53 +08:00
|
|
|
for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
|
|
|
|
NULL, NULL) == ERROR_SUCCESS;
|
|
|
|
index++) {
|
2011-12-18 07:10:01 +08:00
|
|
|
const char *sp = keyName;
|
2013-02-09 06:30:41 +08:00
|
|
|
while (*sp && !isDigit(*sp))
|
2011-12-18 07:10:01 +08:00
|
|
|
sp++;
|
|
|
|
if (!*sp)
|
|
|
|
continue;
|
|
|
|
const char *ep = sp + 1;
|
2013-02-09 06:30:41 +08:00
|
|
|
while (*ep && (isDigit(*ep) || (*ep == '.')))
|
2011-12-18 07:10:01 +08:00
|
|
|
ep++;
|
|
|
|
char numBuf[32];
|
|
|
|
strncpy(numBuf, sp, sizeof(numBuf) - 1);
|
|
|
|
numBuf[sizeof(numBuf) - 1] = '\0';
|
2013-10-11 02:03:08 +08:00
|
|
|
double dvalue = strtod(numBuf, NULL);
|
|
|
|
if (dvalue > bestValue) {
|
|
|
|
// Test that InstallDir is indeed there before keeping this index.
|
|
|
|
// Open the chosen key path remainder.
|
2014-10-23 04:40:28 +08:00
|
|
|
bestName = keyName;
|
2013-10-11 02:03:08 +08:00
|
|
|
// Append rest of key.
|
2014-10-23 04:40:28 +08:00
|
|
|
bestName.append(nextKey);
|
2016-06-23 22:33:53 +08:00
|
|
|
lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
|
|
|
|
KEY_READ | KEY_WOW64_32KEY, &hKey);
|
2013-10-11 02:03:08 +08:00
|
|
|
if (lResult == ERROR_SUCCESS) {
|
2016-07-29 01:13:32 +08:00
|
|
|
if (readFullStringValue(hKey, valueName, value)) {
|
2013-10-11 02:03:08 +08:00
|
|
|
bestValue = dvalue;
|
2014-10-23 04:40:28 +08:00
|
|
|
if (phValue)
|
|
|
|
*phValue = bestName;
|
2013-10-11 02:03:08 +08:00
|
|
|
returnValue = true;
|
|
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
}
|
2011-12-18 07:10:01 +08:00
|
|
|
}
|
|
|
|
size = sizeof(keyName) - 1;
|
|
|
|
}
|
|
|
|
RegCloseKey(hTopKey);
|
|
|
|
}
|
|
|
|
} else {
|
2014-10-23 04:40:28 +08:00
|
|
|
lResult =
|
2016-06-23 22:33:53 +08:00
|
|
|
RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
|
2011-12-18 07:10:01 +08:00
|
|
|
if (lResult == ERROR_SUCCESS) {
|
2016-07-29 01:13:32 +08:00
|
|
|
if (readFullStringValue(hKey, valueName, value))
|
2011-12-18 07:10:01 +08:00
|
|
|
returnValue = true;
|
2014-10-23 04:40:28 +08:00
|
|
|
if (phValue)
|
|
|
|
phValue->clear();
|
2011-12-18 07:10:01 +08:00
|
|
|
RegCloseKey(hKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return returnValue;
|
2018-04-30 21:47:04 +08:00
|
|
|
#endif // _WIN32
|
2011-12-18 07:10:01 +08:00
|
|
|
}
|
|
|
|
|
2015-09-24 13:16:36 +08:00
|
|
|
// Find the most recent version of Universal CRT or Windows 10 SDK.
|
|
|
|
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
|
|
|
|
// directory by name and uses the last one of the list.
|
|
|
|
// So we compare entry names lexicographically to find the greatest one.
|
2021-02-25 11:58:40 +08:00
|
|
|
static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS,
|
|
|
|
const std::string &SDKPath,
|
2017-03-16 00:07:35 +08:00
|
|
|
std::string &SDKVersion) {
|
2015-09-24 13:16:36 +08:00
|
|
|
llvm::SmallString<128> IncludePath(SDKPath);
|
|
|
|
llvm::sys::path::append(IncludePath, "Include");
|
2021-02-25 11:58:40 +08:00
|
|
|
SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
|
2015-09-24 13:16:36 +08:00
|
|
|
return !SDKVersion.empty();
|
|
|
|
}
|
|
|
|
|
2021-02-25 11:58:40 +08:00
|
|
|
static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS,
|
|
|
|
const ArgList &Args,
|
2021-01-27 04:21:12 +08:00
|
|
|
std::string &Path, int &Major,
|
|
|
|
std::string &Version) {
|
2021-01-28 00:01:59 +08:00
|
|
|
if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir,
|
|
|
|
options::OPT__SLASH_winsysroot)) {
|
2021-01-27 04:21:12 +08:00
|
|
|
// Don't validate the input; trust the value supplied by the user.
|
|
|
|
// The motivation is to prevent unnecessary file and registry access.
|
2021-01-28 00:01:59 +08:00
|
|
|
llvm::VersionTuple SDKVersion;
|
|
|
|
if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
|
|
|
|
SDKVersion.tryParse(A->getValue());
|
|
|
|
|
|
|
|
if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
|
|
|
|
llvm::SmallString<128> SDKPath(A->getValue());
|
|
|
|
llvm::sys::path::append(SDKPath, "Windows Kits");
|
|
|
|
if (!SDKVersion.empty())
|
|
|
|
llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor()));
|
|
|
|
else
|
2021-02-25 11:58:40 +08:00
|
|
|
llvm::sys::path::append(
|
|
|
|
SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
|
2021-01-28 00:01:59 +08:00
|
|
|
Path = std::string(SDKPath.str());
|
|
|
|
} else {
|
|
|
|
Path = A->getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SDKVersion.empty()) {
|
|
|
|
Major = SDKVersion.getMajor();
|
|
|
|
Version = SDKVersion.getAsString();
|
2021-02-25 11:58:40 +08:00
|
|
|
} else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
|
2021-01-27 04:21:12 +08:00
|
|
|
Major = 10;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Get Windows SDK installation directory.
|
2021-02-25 11:58:40 +08:00
|
|
|
static bool getWindowsSDKDir(llvm::vfs::FileSystem &VFS, const ArgList &Args,
|
|
|
|
std::string &Path, int &Major,
|
2017-03-16 00:07:35 +08:00
|
|
|
std::string &WindowsSDKIncludeVersion,
|
|
|
|
std::string &WindowsSDKLibVersion) {
|
2021-01-27 21:52:23 +08:00
|
|
|
// Trust /winsdkdir and /winsdkversion if present.
|
2021-02-25 11:58:40 +08:00
|
|
|
if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major,
|
|
|
|
WindowsSDKIncludeVersion)) {
|
2021-01-27 04:21:12 +08:00
|
|
|
WindowsSDKLibVersion = WindowsSDKIncludeVersion;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry.
|
|
|
|
|
2011-12-18 07:10:01 +08:00
|
|
|
// Try the Windows registry.
|
2021-01-27 04:21:12 +08:00
|
|
|
std::string RegistrySDKVersion;
|
2015-09-24 13:16:36 +08:00
|
|
|
if (!getSystemRegistryString(
|
|
|
|
"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
|
|
|
|
"InstallationFolder", Path, &RegistrySDKVersion))
|
|
|
|
return false;
|
|
|
|
if (Path.empty() || RegistrySDKVersion.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
WindowsSDKIncludeVersion.clear();
|
|
|
|
WindowsSDKLibVersion.clear();
|
|
|
|
Major = 0;
|
|
|
|
std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
|
|
|
|
if (Major <= 7)
|
|
|
|
return true;
|
|
|
|
if (Major == 8) {
|
|
|
|
// Windows SDK 8.x installs libraries in a folder whose names depend on the
|
|
|
|
// version of the OS you're targeting. By default choose the newest, which
|
|
|
|
// usually corresponds to the version of the OS you've installed the SDK on.
|
|
|
|
const char *Tests[] = {"winv6.3", "win8", "win7"};
|
|
|
|
for (const char *Test : Tests) {
|
|
|
|
llvm::SmallString<128> TestPath(Path);
|
|
|
|
llvm::sys::path::append(TestPath, "Lib", Test);
|
2021-02-25 11:58:40 +08:00
|
|
|
if (VFS.exists(TestPath)) {
|
2015-09-24 13:16:36 +08:00
|
|
|
WindowsSDKLibVersion = Test;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !WindowsSDKLibVersion.empty();
|
|
|
|
}
|
|
|
|
if (Major == 10) {
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
|
2015-09-24 13:16:36 +08:00
|
|
|
return false;
|
|
|
|
WindowsSDKLibVersion = WindowsSDKIncludeVersion;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Unsupported SDK version
|
|
|
|
return false;
|
2014-10-23 04:40:28 +08:00
|
|
|
}
|
|
|
|
|
2014-10-23 04:40:43 +08:00
|
|
|
// Gets the library path required to link against the Windows SDK.
|
2021-01-27 04:21:12 +08:00
|
|
|
bool MSVCToolChain::getWindowsSDKLibraryPath(
|
|
|
|
const ArgList &Args, std::string &path) const {
|
2014-10-23 04:40:43 +08:00
|
|
|
std::string sdkPath;
|
|
|
|
int sdkMajor = 0;
|
2015-09-24 13:16:36 +08:00
|
|
|
std::string windowsSDKIncludeVersion;
|
|
|
|
std::string windowsSDKLibVersion;
|
2014-10-23 04:40:43 +08:00
|
|
|
|
|
|
|
path.clear();
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!getWindowsSDKDir(getVFS(), Args, sdkPath, sdkMajor,
|
|
|
|
windowsSDKIncludeVersion, windowsSDKLibVersion))
|
2014-10-23 04:40:43 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
llvm::SmallString<128> libPath(sdkPath);
|
|
|
|
llvm::sys::path::append(libPath, "Lib");
|
2017-03-16 00:07:35 +08:00
|
|
|
if (sdkMajor >= 8) {
|
|
|
|
llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
|
|
|
|
llvmArchToWindowsSDKArch(getArch()));
|
|
|
|
} else {
|
2014-10-23 04:40:43 +08:00
|
|
|
switch (getArch()) {
|
2017-02-03 03:36:22 +08:00
|
|
|
// In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
|
2014-10-23 04:40:43 +08:00
|
|
|
case llvm::Triple::x86:
|
|
|
|
break;
|
|
|
|
case llvm::Triple::x86_64:
|
|
|
|
llvm::sys::path::append(libPath, "x64");
|
|
|
|
break;
|
|
|
|
case llvm::Triple::arm:
|
|
|
|
// It is not necessary to link against Windows SDK 7.x when targeting ARM.
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
path = std::string(libPath.str());
|
2014-10-23 04:40:43 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-11 08:09:39 +08:00
|
|
|
// Check if the Include path of a specified version of Visual Studio contains
|
|
|
|
// specific header files. If not, they are probably shipped with Universal CRT.
|
2017-03-16 00:07:35 +08:00
|
|
|
bool MSVCToolChain::useUniversalCRT() const {
|
|
|
|
llvm::SmallString<128> TestPath(
|
|
|
|
getSubDirectoryPath(SubDirectoryType::Include));
|
|
|
|
llvm::sys::path::append(TestPath, "stdlib.h");
|
2021-02-25 11:58:40 +08:00
|
|
|
return !getVFS().exists(TestPath);
|
2015-09-11 08:09:39 +08:00
|
|
|
}
|
|
|
|
|
2021-02-25 11:58:40 +08:00
|
|
|
static bool getUniversalCRTSdkDir(llvm::vfs::FileSystem &VFS,
|
|
|
|
const ArgList &Args, std::string &Path,
|
2021-01-27 04:21:12 +08:00
|
|
|
std::string &UCRTVersion) {
|
2021-01-27 21:52:23 +08:00
|
|
|
// If /winsdkdir is passed, use it as location for the UCRT too.
|
|
|
|
// FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
|
2021-01-27 04:21:12 +08:00
|
|
|
int Major;
|
2021-02-25 11:58:40 +08:00
|
|
|
if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, UCRTVersion))
|
2021-01-27 04:21:12 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
// FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
|
|
|
|
// registry.
|
|
|
|
|
2015-09-11 08:09:39 +08:00
|
|
|
// vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
|
|
|
|
// for the specific key "KitsRoot10". So do we.
|
|
|
|
if (!getSystemRegistryString(
|
2017-02-03 03:36:22 +08:00
|
|
|
"SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
|
|
|
|
Path, nullptr))
|
2015-09-11 08:09:39 +08:00
|
|
|
return false;
|
|
|
|
|
2021-02-25 11:58:40 +08:00
|
|
|
return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
|
2015-09-11 08:09:39 +08:00
|
|
|
}
|
|
|
|
|
2021-01-27 04:21:12 +08:00
|
|
|
bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
|
|
|
|
std::string &Path) const {
|
2015-09-11 08:09:39 +08:00
|
|
|
std::string UniversalCRTSdkPath;
|
|
|
|
std::string UCRTVersion;
|
|
|
|
|
|
|
|
Path.clear();
|
2021-02-25 11:58:40 +08:00
|
|
|
if (!getUniversalCRTSdkDir(getVFS(), Args, UniversalCRTSdkPath, UCRTVersion))
|
2015-09-11 08:09:39 +08:00
|
|
|
return false;
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
|
2015-09-11 08:09:39 +08:00
|
|
|
if (ArchName.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
|
|
|
|
llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
|
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
Path = std::string(LibPath.str());
|
2015-09-11 08:09:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
unsigned Major, Minor, Micro;
|
2017-03-16 00:07:35 +08:00
|
|
|
Triple.getEnvironmentVersion(Major, Minor, Micro);
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
if (Major || Minor || Micro)
|
|
|
|
return VersionTuple(Major, Minor, Micro);
|
|
|
|
return VersionTuple();
|
|
|
|
}
|
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
|
2016-05-14 07:20:11 +08:00
|
|
|
VersionTuple Version;
|
2018-04-30 21:47:04 +08:00
|
|
|
#ifdef _WIN32
|
2017-03-16 00:07:35 +08:00
|
|
|
SmallString<128> ClExe(BinDir);
|
2016-05-14 07:20:11 +08:00
|
|
|
llvm::sys::path::append(ClExe, "cl.exe");
|
|
|
|
|
|
|
|
std::wstring ClExeWide;
|
|
|
|
if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
|
|
|
|
return Version;
|
|
|
|
|
|
|
|
const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
|
|
|
|
nullptr);
|
|
|
|
if (VersionSize == 0)
|
|
|
|
return Version;
|
|
|
|
|
|
|
|
SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
|
|
|
|
if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
|
|
|
|
VersionBlock.data()))
|
|
|
|
return Version;
|
|
|
|
|
|
|
|
VS_FIXEDFILEINFO *FileInfo = nullptr;
|
|
|
|
UINT FileInfoSize = 0;
|
|
|
|
if (!::VerQueryValueW(VersionBlock.data(), L"\\",
|
|
|
|
reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
|
|
|
|
FileInfoSize < sizeof(*FileInfo))
|
|
|
|
return Version;
|
|
|
|
|
|
|
|
const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
|
|
|
|
const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
|
|
|
|
const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
|
|
|
|
|
|
|
|
Version = VersionTuple(Major, Minor, Micro);
|
|
|
|
#endif
|
|
|
|
return Version;
|
|
|
|
}
|
|
|
|
|
2015-09-24 13:16:36 +08:00
|
|
|
void MSVCToolChain::AddSystemIncludeWithSubfolder(
|
|
|
|
const ArgList &DriverArgs, ArgStringList &CC1Args,
|
|
|
|
const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
|
|
|
|
const Twine &subfolder3) const {
|
2014-10-23 04:40:28 +08:00
|
|
|
llvm::SmallString<128> path(folder);
|
2015-09-24 13:16:36 +08:00
|
|
|
llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
|
2015-03-18 18:17:07 +08:00
|
|
|
addSystemInclude(DriverArgs, CC1Args, path);
|
2014-10-23 04:40:28 +08:00
|
|
|
}
|
|
|
|
|
2014-10-22 10:37:29 +08:00
|
|
|
void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|
|
|
ArgStringList &CC1Args) const {
|
2012-09-05 01:29:52 +08:00
|
|
|
if (DriverArgs.hasArg(options::OPT_nostdinc))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
|
2015-09-24 13:16:36 +08:00
|
|
|
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
|
|
|
|
"include");
|
2012-09-05 01:29:52 +08:00
|
|
|
}
|
|
|
|
|
2016-04-13 03:04:37 +08:00
|
|
|
// Add %INCLUDE%-like directories from the -imsvc flag.
|
|
|
|
for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
|
|
|
|
addSystemInclude(DriverArgs, CC1Args, Path);
|
|
|
|
|
2021-06-16 21:22:17 +08:00
|
|
|
auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool {
|
|
|
|
if (auto Val = llvm::sys::Process::GetEnv(Var)) {
|
2021-06-21 23:18:00 +08:00
|
|
|
SmallVector<StringRef, 8> Dirs;
|
2021-06-16 21:22:17 +08:00
|
|
|
StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
|
|
|
|
if (!Dirs.empty()) {
|
|
|
|
addSystemIncludes(DriverArgs, CC1Args, Dirs);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Add %INCLUDE%-like dirs via /external:env: flags.
|
|
|
|
for (const auto &Var :
|
|
|
|
DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) {
|
|
|
|
AddSystemIncludesFromEnv(Var);
|
|
|
|
}
|
|
|
|
|
2012-09-05 01:29:52 +08:00
|
|
|
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
|
|
|
|
return;
|
2011-12-18 07:10:01 +08:00
|
|
|
|
2021-06-16 21:22:17 +08:00
|
|
|
// Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search
|
|
|
|
// paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir.
|
2021-01-28 00:01:59 +08:00
|
|
|
if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
|
|
|
|
options::OPT__SLASH_winsysroot)) {
|
2021-06-21 23:18:00 +08:00
|
|
|
bool Found = AddSystemIncludesFromEnv("INCLUDE");
|
|
|
|
Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
|
|
|
|
if (Found)
|
2021-06-16 21:22:17 +08:00
|
|
|
return;
|
2012-03-13 08:02:21 +08:00
|
|
|
}
|
|
|
|
|
2011-12-18 07:10:01 +08:00
|
|
|
// When built with access to the proper Windows APIs, try to actually find
|
|
|
|
// the correct include paths first.
|
2017-03-16 00:07:35 +08:00
|
|
|
if (!VCToolChainPath.empty()) {
|
|
|
|
addSystemInclude(DriverArgs, CC1Args,
|
|
|
|
getSubDirectoryPath(SubDirectoryType::Include));
|
2019-10-11 04:25:54 +08:00
|
|
|
addSystemInclude(DriverArgs, CC1Args,
|
|
|
|
getSubDirectoryPath(SubDirectoryType::Include, "atlmfc"));
|
2014-10-23 04:40:28 +08:00
|
|
|
|
2017-03-16 00:07:35 +08:00
|
|
|
if (useUniversalCRT()) {
|
2015-09-11 08:09:39 +08:00
|
|
|
std::string UniversalCRTSdkPath;
|
|
|
|
std::string UCRTVersion;
|
2021-02-25 11:58:40 +08:00
|
|
|
if (getUniversalCRTSdkDir(getVFS(), DriverArgs, UniversalCRTSdkPath,
|
|
|
|
UCRTVersion)) {
|
2015-09-24 13:16:36 +08:00
|
|
|
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
|
|
|
|
"Include", UCRTVersion, "ucrt");
|
2015-09-11 08:09:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-23 04:40:28 +08:00
|
|
|
std::string WindowsSDKDir;
|
2021-06-21 23:18:00 +08:00
|
|
|
int major = 0;
|
2015-09-24 13:16:36 +08:00
|
|
|
std::string windowsSDKIncludeVersion;
|
|
|
|
std::string windowsSDKLibVersion;
|
2021-02-25 11:58:40 +08:00
|
|
|
if (getWindowsSDKDir(getVFS(), DriverArgs, WindowsSDKDir, major,
|
2021-01-27 04:21:12 +08:00
|
|
|
windowsSDKIncludeVersion, windowsSDKLibVersion)) {
|
2014-10-23 04:40:28 +08:00
|
|
|
if (major >= 8) {
|
2015-09-24 13:16:36 +08:00
|
|
|
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
|
|
|
|
// Anyway, llvm::sys::path::append is able to manage it.
|
2014-10-23 04:40:28 +08:00
|
|
|
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
|
2021-01-27 04:21:12 +08:00
|
|
|
"Include", windowsSDKIncludeVersion,
|
2015-09-24 13:16:36 +08:00
|
|
|
"shared");
|
2014-10-23 04:40:28 +08:00
|
|
|
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
|
2021-01-27 04:21:12 +08:00
|
|
|
"Include", windowsSDKIncludeVersion,
|
2015-09-24 13:16:36 +08:00
|
|
|
"um");
|
2014-10-23 04:40:28 +08:00
|
|
|
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
|
2021-01-27 04:21:12 +08:00
|
|
|
"Include", windowsSDKIncludeVersion,
|
2015-09-24 13:16:36 +08:00
|
|
|
"winrt");
|
2014-10-23 04:40:28 +08:00
|
|
|
} else {
|
|
|
|
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
|
2021-01-27 04:21:12 +08:00
|
|
|
"Include");
|
2014-10-23 04:40:28 +08:00
|
|
|
}
|
2014-04-23 08:15:01 +08:00
|
|
|
}
|
2017-03-16 00:07:35 +08:00
|
|
|
|
2012-09-05 01:29:52 +08:00
|
|
|
return;
|
2011-12-18 07:10:01 +08:00
|
|
|
}
|
|
|
|
|
2018-04-28 03:11:14 +08:00
|
|
|
#if defined(_WIN32)
|
2011-12-18 07:10:01 +08:00
|
|
|
// As a fallback, select default install paths.
|
2014-06-22 11:27:45 +08:00
|
|
|
// FIXME: Don't guess drives and paths like this on Windows.
|
2012-09-05 01:29:52 +08:00
|
|
|
const StringRef Paths[] = {
|
2011-12-18 07:10:01 +08:00
|
|
|
"C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
|
|
|
|
"C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
|
|
|
|
"C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
|
|
|
|
"C:/Program Files/Microsoft Visual Studio 8/VC/include",
|
|
|
|
"C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
|
|
|
|
};
|
2012-09-05 01:29:52 +08:00
|
|
|
addSystemIncludes(DriverArgs, CC1Args, Paths);
|
2016-07-25 12:47:44 +08:00
|
|
|
#endif
|
2011-12-18 07:10:01 +08:00
|
|
|
}
|
|
|
|
|
2014-10-22 10:37:29 +08:00
|
|
|
void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
|
|
|
|
ArgStringList &CC1Args) const {
|
2021-06-11 15:43:52 +08:00
|
|
|
// FIXME: There should probably be logic here to find libc++ on Windows.
|
2011-12-18 07:10:01 +08:00
|
|
|
}
|
2015-06-08 08:22:46 +08:00
|
|
|
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
|
|
|
|
const ArgList &Args) const {
|
|
|
|
bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
|
|
|
|
VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
|
2017-03-16 00:07:35 +08:00
|
|
|
if (MSVT.empty())
|
|
|
|
MSVT = getMSVCVersionFromTriple(getTriple());
|
|
|
|
if (MSVT.empty() && IsWindowsMSVC)
|
|
|
|
MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
if (MSVT.empty() &&
|
|
|
|
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
|
|
|
|
IsWindowsMSVC)) {
|
2021-05-28 07:38:09 +08:00
|
|
|
// -fms-compatibility-version=19.14 is default, aka 2017, 15.7
|
|
|
|
MSVT = VersionTuple(19, 14);
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
}
|
|
|
|
return MSVT;
|
|
|
|
}
|
|
|
|
|
2015-06-08 08:22:46 +08:00
|
|
|
std::string
|
|
|
|
MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
|
|
|
|
types::ID InputType) const {
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
// The MSVC version doesn't care about the architecture, even though it
|
|
|
|
// may look at the triple internally.
|
|
|
|
VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
|
2015-06-08 08:22:46 +08:00
|
|
|
MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
|
|
|
|
MSVT.getSubminor().getValueOr(0));
|
|
|
|
|
Refactor how the MSVC toolchain searches for a compatibility version.
Summary:
The MSVC toolchain and Clang driver combination currently uses a fairly complex
sequence of steps to determine the MS compatibility version to pass to cc1.
There is some oddness in this sequence currently, with some code which inspects
flags in the toolchain, and some code which inspects the triple and local
environment in the driver code.
This change is an attempt to consolidate most of this logic so that
Win32-specific code lives in MSVCToolChain.cpp. I'm not 100% happy with the
split, so any suggestions are welcome.
There are a few things you might want to watch for for specifically:
- On all platforms, if MSVC compatibility flags are provided (and valid), use
those.
- The fallback sequence should be the same as before, but is now consolidated
into MSVCToolChain::getMSVCVersion:
- Otherwise, try to use the Triple.
- Otherwise, on Windows, check the executable.
- Otherwise, on Windows or with --fms-extensions, default to 18.
- Otherwise, we can't determine the version.
- MSVCToolChain::ComputeEffectiveTriple no longer calls the base
ToolChain::ComputeEffectiveClangTriple. The only thing it would change for
Windows the architecture, which we don't care about for the compatibility
version.
- I'm not sure whether this is philosophically correct (but it should
be easy to add back to MSVCToolChain::getMSVCVersionFromTriple if not).
- Previously, Tools.cpp just called getTriple() anyhow, so it doesn't look
like the effective triple was always being used previously anyhow.
Reviewers: hans, compnerd, llvm-commits, rnk
Subscribers: amccarth
Differential Revision: https://reviews.llvm.org/D27477
llvm-svn: 288998
2016-12-08 07:41:58 +08:00
|
|
|
// For the rest of the triple, however, a computed architecture name may
|
|
|
|
// be needed.
|
|
|
|
llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
|
2015-06-09 14:30:01 +08:00
|
|
|
if (Triple.getEnvironment() == llvm::Triple::MSVC) {
|
|
|
|
StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
|
|
|
|
if (ObjFmt.empty())
|
|
|
|
Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
|
|
|
|
else
|
|
|
|
Triple.setEnvironmentName(
|
|
|
|
(Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
|
|
|
|
}
|
2015-06-08 08:22:46 +08:00
|
|
|
return Triple.getTriple();
|
|
|
|
}
|
2015-06-20 05:36:47 +08:00
|
|
|
|
|
|
|
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
|
|
|
|
SanitizerMask Res = ToolChain::getSupportedSanitizers();
|
|
|
|
Res |= SanitizerKind::Address;
|
2019-04-12 22:14:58 +08:00
|
|
|
Res |= SanitizerKind::PointerCompare;
|
|
|
|
Res |= SanitizerKind::PointerSubtract;
|
[libFuzzer] Port to Windows
Summary:
Port libFuzzer to windows-msvc.
This patch allows libFuzzer targets to be built and run on Windows, using -fsanitize=fuzzer and/or fsanitize=fuzzer-no-link. It allows these forms of coverage instrumentation to work on Windows as well.
It does not fix all issues, such as those with -fsanitize-coverage=stack-depth, which is not usable on Windows as of this patch.
It also does not fix any libFuzzer integration tests. Nearly all of them fail to compile, fixing them will come in a later patch, so libFuzzer tests are disabled on Windows until them.
Patch By: metzman
Reviewers: morehouse, rnk
Reviewed By: morehouse, rnk
Subscribers: #sanitizers, delcypher, morehouse, kcc, eraman
Differential Revision: https://reviews.llvm.org/D51022
llvm-svn: 341082
2018-08-30 23:54:44 +08:00
|
|
|
Res |= SanitizerKind::Fuzzer;
|
|
|
|
Res |= SanitizerKind::FuzzerNoLink;
|
2018-06-26 10:15:47 +08:00
|
|
|
Res &= ~SanitizerKind::CFIMFCall;
|
2015-06-20 05:36:47 +08:00
|
|
|
return Res;
|
|
|
|
}
|
2015-07-27 15:32:11 +08:00
|
|
|
|
2016-01-13 07:17:03 +08:00
|
|
|
static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
|
|
|
|
bool SupportsForcingFramePointer,
|
|
|
|
const char *ExpandChar, const OptTable &Opts) {
|
|
|
|
assert(A->getOption().matches(options::OPT__SLASH_O));
|
|
|
|
|
|
|
|
StringRef OptStr = A->getValue();
|
|
|
|
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
|
|
|
|
const char &OptChar = *(OptStr.data() + I);
|
|
|
|
switch (OptChar) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case 'x':
|
|
|
|
case 'd':
|
2017-10-03 08:14:03 +08:00
|
|
|
// Ignore /O[12xd] flags that aren't the last one on the command line.
|
|
|
|
// Only the last one gets expanded.
|
|
|
|
if (&OptChar != ExpandChar) {
|
|
|
|
A->claim();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (OptChar == 'd') {
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
|
|
|
|
} else {
|
|
|
|
if (OptChar == '1') {
|
|
|
|
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
|
|
|
|
} else if (OptChar == '2' || OptChar == 'x') {
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
|
|
|
|
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
|
2016-01-13 07:17:03 +08:00
|
|
|
}
|
2017-10-03 08:14:03 +08:00
|
|
|
if (SupportsForcingFramePointer &&
|
|
|
|
!DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
|
|
|
|
if (OptChar == '1' || OptChar == '2')
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
|
2016-01-13 07:17:03 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'b':
|
2016-05-25 05:23:29 +08:00
|
|
|
if (I + 1 != E && isdigit(OptStr[I + 1])) {
|
|
|
|
switch (OptStr[I + 1]) {
|
|
|
|
case '0':
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
|
|
|
|
break;
|
|
|
|
case '1':
|
2016-06-23 00:56:16 +08:00
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
|
2016-05-25 05:23:29 +08:00
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
|
|
|
|
break;
|
|
|
|
}
|
2016-01-13 07:17:03 +08:00
|
|
|
++I;
|
2016-05-25 05:23:29 +08:00
|
|
|
}
|
2016-01-13 07:17:03 +08:00
|
|
|
break;
|
|
|
|
case 'g':
|
2018-09-25 22:10:26 +08:00
|
|
|
A->claim();
|
2016-01-13 07:17:03 +08:00
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if (I + 1 != E && OptStr[I + 1] == '-') {
|
|
|
|
++I;
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
|
|
|
|
} else {
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
|
|
|
|
break;
|
|
|
|
case 'y': {
|
|
|
|
bool OmitFramePointer = true;
|
|
|
|
if (I + 1 != E && OptStr[I + 1] == '-') {
|
|
|
|
OmitFramePointer = false;
|
|
|
|
++I;
|
|
|
|
}
|
|
|
|
if (SupportsForcingFramePointer) {
|
|
|
|
if (OmitFramePointer)
|
|
|
|
DAL.AddFlagArg(A,
|
|
|
|
Opts.getOption(options::OPT_fomit_frame_pointer));
|
|
|
|
else
|
|
|
|
DAL.AddFlagArg(
|
|
|
|
A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
|
2016-03-23 23:37:41 +08:00
|
|
|
} else {
|
2019-02-07 20:46:49 +08:00
|
|
|
// Don't warn about /Oy- in x86-64 builds (where
|
2016-03-23 23:37:41 +08:00
|
|
|
// SupportsForcingFramePointer is false). The flag having no effect
|
|
|
|
// there is a compiler-internal optimization, and people shouldn't have
|
2019-02-07 20:46:49 +08:00
|
|
|
// to special-case their build files for x86-64 clang-cl.
|
2016-03-23 23:37:41 +08:00
|
|
|
A->claim();
|
2016-01-13 07:17:03 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
|
|
|
|
const OptTable &Opts) {
|
|
|
|
assert(A->getOption().matches(options::OPT_D));
|
|
|
|
|
|
|
|
StringRef Val = A->getValue();
|
|
|
|
size_t Hash = Val.find('#');
|
|
|
|
if (Hash == StringRef::npos || Hash > Val.find('=')) {
|
|
|
|
DAL.append(A);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
std::string NewVal = std::string(Val);
|
2016-01-13 07:17:03 +08:00
|
|
|
NewVal[Hash] = '=';
|
|
|
|
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
|
|
|
|
}
|
|
|
|
|
2021-06-10 23:06:19 +08:00
|
|
|
static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL,
|
|
|
|
const OptTable &Opts) {
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
|
|
|
|
const OptTable &Opts) {
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
|
|
|
|
DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
|
|
|
|
}
|
|
|
|
|
2015-07-27 15:32:11 +08:00
|
|
|
llvm::opt::DerivedArgList *
|
|
|
|
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
|
2020-03-12 04:40:28 +08:00
|
|
|
StringRef BoundArch,
|
|
|
|
Action::OffloadKind OFK) const {
|
2015-07-27 15:32:11 +08:00
|
|
|
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
|
|
|
|
const OptTable &Opts = getDriver().getOpts();
|
|
|
|
|
2019-02-07 20:46:49 +08:00
|
|
|
// /Oy and /Oy- don't have an effect on X86-64
|
|
|
|
bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
|
2015-08-25 08:46:45 +08:00
|
|
|
|
2015-07-27 15:32:11 +08:00
|
|
|
// The -O[12xd] flag actually expands to several flags. We must desugar the
|
|
|
|
// flags so that options embedded can be negated. For example, the '-O2' flag
|
|
|
|
// enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
|
|
|
|
// correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
|
|
|
|
// aspect of '-O2'.
|
|
|
|
//
|
|
|
|
// Note that this expansion logic only applies to the *last* of '[12xd]'.
|
|
|
|
|
|
|
|
// First step is to search for the character we'd like to expand.
|
|
|
|
const char *ExpandChar = nullptr;
|
2017-10-03 08:14:03 +08:00
|
|
|
for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
|
2015-07-27 15:32:11 +08:00
|
|
|
StringRef OptStr = A->getValue();
|
|
|
|
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
|
2016-05-25 08:43:45 +08:00
|
|
|
char OptChar = OptStr[I];
|
|
|
|
char PrevChar = I > 0 ? OptStr[I - 1] : '0';
|
|
|
|
if (PrevChar == 'b') {
|
|
|
|
// OptChar does not expand; it's an argument to the previous char.
|
|
|
|
continue;
|
|
|
|
}
|
2015-07-27 15:32:11 +08:00
|
|
|
if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
|
|
|
|
ExpandChar = OptStr.data() + I;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Arg *A : Args) {
|
2016-01-13 07:17:03 +08:00
|
|
|
if (A->getOption().matches(options::OPT__SLASH_O)) {
|
|
|
|
// The -O flag actually takes an amalgam of other options. For example,
|
|
|
|
// '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
|
|
|
|
TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
|
|
|
|
} else if (A->getOption().matches(options::OPT_D)) {
|
|
|
|
// Translate -Dfoo#bar into -Dfoo=bar.
|
|
|
|
TranslateDArg(A, *DAL, Opts);
|
2021-06-10 23:06:19 +08:00
|
|
|
} else if (A->getOption().matches(options::OPT__SLASH_permissive)) {
|
|
|
|
// Expand /permissive
|
|
|
|
TranslatePermissive(A, *DAL, Opts);
|
|
|
|
} else if (A->getOption().matches(options::OPT__SLASH_permissive_)) {
|
|
|
|
// Expand /permissive-
|
|
|
|
TranslatePermissiveMinus(A, *DAL, Opts);
|
2020-03-12 04:40:28 +08:00
|
|
|
} else if (OFK != Action::OFK_HIP) {
|
|
|
|
// HIP Toolchain translates input args by itself.
|
2015-07-27 15:32:11 +08:00
|
|
|
DAL->append(A);
|
|
|
|
}
|
|
|
|
}
|
2016-01-13 07:17:03 +08:00
|
|
|
|
2015-07-27 15:32:11 +08:00
|
|
|
return DAL;
|
|
|
|
}
|
2021-06-10 23:02:44 +08:00
|
|
|
|
|
|
|
void MSVCToolChain::addClangTargetOptions(
|
|
|
|
const ArgList &DriverArgs, ArgStringList &CC1Args,
|
|
|
|
Action::OffloadKind DeviceOffloadKind) const {
|
|
|
|
// MSVC STL kindly allows removing all usages of typeid by defining
|
|
|
|
// _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
|
|
|
|
if (DriverArgs.hasArg(options::OPT_fno_rtti, options::OPT_frtti,
|
|
|
|
/*Default=*/false))
|
|
|
|
CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
|
|
|
|
}
|