mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 15:40:55 +03:00
Set up MSVC environment for C preprocessing on Windows
This commit is contained in:
parent
d94b12500b
commit
04bcdc4d06
6 changed files with 103 additions and 26 deletions
|
@ -4,7 +4,7 @@
|
|||
- Frontend, druntime and Phobos are at version [2.103.1](https://dlang.org/changelog/2.103.0.html), incl. new command-line option `-verror-supplements`. (#4345)
|
||||
- New commandline option `-femit-local-var-lifetime` that enables variable lifetime (scope) annotation to LLVM IR codegen. Lifetime annotation enables stack memory reuse for local variables with non-overlapping scope. (#4395)
|
||||
- C files are now automatically preprocessed using the external C compiler (configurable via `-gcc` or the `CC` environment variable, and `-Xcc` for extra flags). Extra preprocessor flags (e.g., include dirs and manual defines) can be added via new command-line option `-P`. (#4417)
|
||||
- Windows: Requires an MSVC environment set up for the target (`cl.exe` on `PATH`, `INCLUDE` environment variable). If `clang-cl.exe` is on `PATH`, it is preferred over Microsoft's `cl.exe` by default (e.g., to avoid printing the C source file path to stderr during preprocessing).
|
||||
- Windows: If `clang-cl.exe` is on `PATH`, it is preferred over Microsoft's `cl.exe` by default (e.g., to avoid printing the C source file path to stderr during preprocessing).
|
||||
|
||||
#### Platform support
|
||||
|
||||
|
|
|
@ -486,6 +486,21 @@ public:
|
|||
return FileName.exists(proposed) ? proposed : null;
|
||||
}
|
||||
|
||||
version (IN_LLVM)
|
||||
{
|
||||
const(char)* getVCIncludeDir() const
|
||||
{
|
||||
const(char)* proposed;
|
||||
|
||||
if (VCToolsInstallDir !is null)
|
||||
proposed = FileName.combine(VCToolsInstallDir, "include");
|
||||
else if (VCInstallDir !is null)
|
||||
proposed = FileName.combine(VCInstallDir, "include");
|
||||
|
||||
return FileName.exists(proposed) ? proposed : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the path to the universal CRT libraries
|
||||
* Params:
|
||||
|
@ -546,6 +561,33 @@ version (IN_LLVM) {} else
|
|||
return null;
|
||||
}
|
||||
|
||||
version (IN_LLVM)
|
||||
{
|
||||
const(char)* getSDKIncludePath() const
|
||||
{
|
||||
if (WindowsSdkDir)
|
||||
{
|
||||
alias umExists = returnDirIfContainsFile!"um"; // subdir in this case
|
||||
|
||||
const sdk = FileName.combine(WindowsSdkDir.toDString, "include");
|
||||
if (WindowsSdkVersion)
|
||||
{
|
||||
if (auto p = umExists(sdk, WindowsSdkVersion.toDString)) // SDK 10.0
|
||||
return p;
|
||||
}
|
||||
// purely speculative
|
||||
if (auto p = umExists(sdk, "win8")) // SDK 8.0
|
||||
return p;
|
||||
if (auto p = umExists(sdk, "winv6.3")) // SDK 8.1
|
||||
return p;
|
||||
if (auto p = umExists(sdk)) // SDK 7.1 or earlier
|
||||
return p;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
extern(D):
|
||||
|
||||
|
|
|
@ -25,8 +25,14 @@ struct VSOptions
|
|||
void initialize();
|
||||
const char *getVCBinDir(bool x64, const char *&addpath) const;
|
||||
const char *getVCLibDir(bool x64) const;
|
||||
#if IN_LLVM
|
||||
const char *getVCIncludeDir() const;
|
||||
#endif
|
||||
const char *getUCRTLibPath(bool x64) const;
|
||||
const char *getSDKLibPath(bool x64) const;
|
||||
#if IN_LLVM
|
||||
const char *getSDKIncludePath() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _WIN32
|
||||
|
|
|
@ -73,11 +73,10 @@ FileName runCPreprocessor(FileName csrcfile, const Loc &loc, bool &ifile,
|
|||
const auto &triple = *global.params.targetTriple;
|
||||
const bool isMSVC = triple.isWindowsMSVCEnvironment();
|
||||
|
||||
#if 0 //ifdef _WIN32
|
||||
// TODO: INCLUDE env var etc.?
|
||||
#ifdef _WIN32
|
||||
windows::MsvcEnvironmentScope msvcEnv;
|
||||
if (isMSVC)
|
||||
msvcEnv.setup();
|
||||
msvcEnv.setup(/*forPreprocessingOnly=*/true);
|
||||
#endif
|
||||
|
||||
FileName ipath = getOutputPath(loc, csrcfile.toChars());
|
||||
|
|
|
@ -265,7 +265,10 @@ int executeToolAndWait(const Loc &loc, const std::string &tool_,
|
|||
namespace windows {
|
||||
|
||||
namespace {
|
||||
VSOptions vsOptions; // cache, as this can be expensive
|
||||
|
||||
bool setupMsvcEnvironmentImpl(
|
||||
bool forPreprocessingOnly,
|
||||
std::vector<std::pair<std::wstring, wchar_t *>> *rollback) {
|
||||
const bool x64 = global.params.targetTriple->isArch64Bit();
|
||||
|
||||
|
@ -280,19 +283,13 @@ bool setupMsvcEnvironmentImpl(
|
|||
|
||||
const auto begin = std::chrono::steady_clock::now();
|
||||
|
||||
VSOptions vsOptions;
|
||||
vsOptions.initialize();
|
||||
if (!vsOptions.VSInstallDir)
|
||||
return false;
|
||||
|
||||
llvm::SmallVector<const char *, 3> libPaths;
|
||||
if (auto vclibdir = vsOptions.getVCLibDir(x64))
|
||||
libPaths.push_back(vclibdir);
|
||||
if (auto ucrtlibdir = vsOptions.getUCRTLibPath(x64))
|
||||
libPaths.push_back(ucrtlibdir);
|
||||
if (auto sdklibdir = vsOptions.getSDKLibPath(x64))
|
||||
libPaths.push_back(sdklibdir);
|
||||
if (!vsOptions.VSInstallDir) {
|
||||
vsOptions.initialize();
|
||||
if (!vsOptions.VSInstallDir)
|
||||
return false;
|
||||
}
|
||||
|
||||
// PATH
|
||||
llvm::SmallVector<const char *, 2> binPaths;
|
||||
const char *secondaryBindir = nullptr;
|
||||
if (auto bindir = vsOptions.getVCBinDir(x64, secondaryBindir)) {
|
||||
|
@ -300,20 +297,52 @@ bool setupMsvcEnvironmentImpl(
|
|||
if (secondaryBindir)
|
||||
binPaths.push_back(secondaryBindir);
|
||||
}
|
||||
|
||||
const bool success = libPaths.size() == 3 && !binPaths.empty();
|
||||
if (!success)
|
||||
if (binPaths.empty())
|
||||
return false;
|
||||
|
||||
llvm::SmallVector<const char *, 3> includePaths;
|
||||
llvm::SmallVector<const char *, 3> libPaths;
|
||||
if (forPreprocessingOnly) {
|
||||
// INCLUDE
|
||||
if (auto vcincludedir = vsOptions.getVCIncludeDir()) {
|
||||
includePaths.push_back(vcincludedir);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (auto sdkincludedir = vsOptions.getSDKIncludePath()) {
|
||||
includePaths.push_back(FileName::combine(sdkincludedir, "ucrt"));
|
||||
includePaths.push_back(FileName::combine(sdkincludedir, "shared"));
|
||||
includePaths.push_back(FileName::combine(sdkincludedir, "um"));
|
||||
includePaths.push_back(FileName::combine(sdkincludedir, "winrt"));
|
||||
includePaths.push_back(FileName::combine(sdkincludedir, "cppwinrt"));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// LIB
|
||||
if (auto vclibdir = vsOptions.getVCLibDir(x64))
|
||||
libPaths.push_back(vclibdir);
|
||||
if (auto ucrtlibdir = vsOptions.getUCRTLibPath(x64))
|
||||
libPaths.push_back(ucrtlibdir);
|
||||
if (auto sdklibdir = vsOptions.getSDKLibPath(x64))
|
||||
libPaths.push_back(sdklibdir);
|
||||
|
||||
if (libPaths.size() != 3)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rollback) // check for availability only
|
||||
return true;
|
||||
|
||||
if (global.params.verbose)
|
||||
message("Prepending to environment variables:");
|
||||
|
||||
const auto preprendToEnvVar =
|
||||
const auto prependToEnvVar =
|
||||
[rollback](const char *key, const wchar_t *wkey,
|
||||
const llvm::SmallVectorImpl<const char *> &entries) {
|
||||
if (entries.empty())
|
||||
return;
|
||||
|
||||
wchar_t *originalValue = _wgetenv(wkey);
|
||||
|
||||
llvm::SmallString<256> head;
|
||||
|
@ -343,8 +372,9 @@ bool setupMsvcEnvironmentImpl(
|
|||
};
|
||||
|
||||
rollback->reserve(2);
|
||||
preprendToEnvVar("LIB", L"LIB", libPaths);
|
||||
preprendToEnvVar("PATH", L"PATH", binPaths);
|
||||
prependToEnvVar("INCLUDE", L"INCLUDE", includePaths);
|
||||
prependToEnvVar("LIB", L"LIB", libPaths);
|
||||
prependToEnvVar("PATH", L"PATH", binPaths);
|
||||
|
||||
if (global.params.verbose) {
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
|
@ -357,11 +387,11 @@ bool setupMsvcEnvironmentImpl(
|
|||
}
|
||||
} // anonymous namespace
|
||||
|
||||
bool isMsvcAvailable() { return setupMsvcEnvironmentImpl(nullptr); }
|
||||
bool isMsvcAvailable() { return setupMsvcEnvironmentImpl(false, nullptr); }
|
||||
|
||||
bool MsvcEnvironmentScope::setup() {
|
||||
bool MsvcEnvironmentScope::setup(bool forPreprocessingOnly) {
|
||||
rollback.clear();
|
||||
return setupMsvcEnvironmentImpl(&rollback);
|
||||
return setupMsvcEnvironmentImpl(forPreprocessingOnly, &rollback);
|
||||
}
|
||||
|
||||
MsvcEnvironmentScope::~MsvcEnvironmentScope() {
|
||||
|
|
|
@ -53,7 +53,7 @@ struct MsvcEnvironmentScope {
|
|||
// Tries to set up the MSVC environment variables for the current process and
|
||||
// returns true if successful. The original environment is restored on
|
||||
// destruction.
|
||||
bool setup();
|
||||
bool setup(bool forPreprocessingOnly = false);
|
||||
|
||||
~MsvcEnvironmentScope();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue