mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 16:11:08 +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)
|
- 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)
|
- 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)
|
- 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
|
#### Platform support
|
||||||
|
|
||||||
|
|
|
@ -486,6 +486,21 @@ public:
|
||||||
return FileName.exists(proposed) ? proposed : null;
|
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
|
* get the path to the universal CRT libraries
|
||||||
* Params:
|
* Params:
|
||||||
|
@ -546,6 +561,33 @@ version (IN_LLVM) {} else
|
||||||
return null;
|
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:
|
private:
|
||||||
extern(D):
|
extern(D):
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,14 @@ struct VSOptions
|
||||||
void initialize();
|
void initialize();
|
||||||
const char *getVCBinDir(bool x64, const char *&addpath) const;
|
const char *getVCBinDir(bool x64, const char *&addpath) const;
|
||||||
const char *getVCLibDir(bool x64) const;
|
const char *getVCLibDir(bool x64) const;
|
||||||
|
#if IN_LLVM
|
||||||
|
const char *getVCIncludeDir() const;
|
||||||
|
#endif
|
||||||
const char *getUCRTLibPath(bool x64) const;
|
const char *getUCRTLibPath(bool x64) const;
|
||||||
const char *getSDKLibPath(bool x64) const;
|
const char *getSDKLibPath(bool x64) const;
|
||||||
|
#if IN_LLVM
|
||||||
|
const char *getSDKIncludePath() const;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
|
@ -73,11 +73,10 @@ FileName runCPreprocessor(FileName csrcfile, const Loc &loc, bool &ifile,
|
||||||
const auto &triple = *global.params.targetTriple;
|
const auto &triple = *global.params.targetTriple;
|
||||||
const bool isMSVC = triple.isWindowsMSVCEnvironment();
|
const bool isMSVC = triple.isWindowsMSVCEnvironment();
|
||||||
|
|
||||||
#if 0 //ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO: INCLUDE env var etc.?
|
|
||||||
windows::MsvcEnvironmentScope msvcEnv;
|
windows::MsvcEnvironmentScope msvcEnv;
|
||||||
if (isMSVC)
|
if (isMSVC)
|
||||||
msvcEnv.setup();
|
msvcEnv.setup(/*forPreprocessingOnly=*/true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FileName ipath = getOutputPath(loc, csrcfile.toChars());
|
FileName ipath = getOutputPath(loc, csrcfile.toChars());
|
||||||
|
|
|
@ -265,7 +265,10 @@ int executeToolAndWait(const Loc &loc, const std::string &tool_,
|
||||||
namespace windows {
|
namespace windows {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
VSOptions vsOptions; // cache, as this can be expensive
|
||||||
|
|
||||||
bool setupMsvcEnvironmentImpl(
|
bool setupMsvcEnvironmentImpl(
|
||||||
|
bool forPreprocessingOnly,
|
||||||
std::vector<std::pair<std::wstring, wchar_t *>> *rollback) {
|
std::vector<std::pair<std::wstring, wchar_t *>> *rollback) {
|
||||||
const bool x64 = global.params.targetTriple->isArch64Bit();
|
const bool x64 = global.params.targetTriple->isArch64Bit();
|
||||||
|
|
||||||
|
@ -280,19 +283,13 @@ bool setupMsvcEnvironmentImpl(
|
||||||
|
|
||||||
const auto begin = std::chrono::steady_clock::now();
|
const auto begin = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
VSOptions vsOptions;
|
if (!vsOptions.VSInstallDir) {
|
||||||
vsOptions.initialize();
|
vsOptions.initialize();
|
||||||
if (!vsOptions.VSInstallDir)
|
if (!vsOptions.VSInstallDir)
|
||||||
return false;
|
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);
|
|
||||||
|
|
||||||
|
// PATH
|
||||||
llvm::SmallVector<const char *, 2> binPaths;
|
llvm::SmallVector<const char *, 2> binPaths;
|
||||||
const char *secondaryBindir = nullptr;
|
const char *secondaryBindir = nullptr;
|
||||||
if (auto bindir = vsOptions.getVCBinDir(x64, secondaryBindir)) {
|
if (auto bindir = vsOptions.getVCBinDir(x64, secondaryBindir)) {
|
||||||
|
@ -300,20 +297,52 @@ bool setupMsvcEnvironmentImpl(
|
||||||
if (secondaryBindir)
|
if (secondaryBindir)
|
||||||
binPaths.push_back(secondaryBindir);
|
binPaths.push_back(secondaryBindir);
|
||||||
}
|
}
|
||||||
|
if (binPaths.empty())
|
||||||
const bool success = libPaths.size() == 3 && !binPaths.empty();
|
|
||||||
if (!success)
|
|
||||||
return false;
|
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
|
if (!rollback) // check for availability only
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
message("Prepending to environment variables:");
|
message("Prepending to environment variables:");
|
||||||
|
|
||||||
const auto preprendToEnvVar =
|
const auto prependToEnvVar =
|
||||||
[rollback](const char *key, const wchar_t *wkey,
|
[rollback](const char *key, const wchar_t *wkey,
|
||||||
const llvm::SmallVectorImpl<const char *> &entries) {
|
const llvm::SmallVectorImpl<const char *> &entries) {
|
||||||
|
if (entries.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
wchar_t *originalValue = _wgetenv(wkey);
|
wchar_t *originalValue = _wgetenv(wkey);
|
||||||
|
|
||||||
llvm::SmallString<256> head;
|
llvm::SmallString<256> head;
|
||||||
|
@ -343,8 +372,9 @@ bool setupMsvcEnvironmentImpl(
|
||||||
};
|
};
|
||||||
|
|
||||||
rollback->reserve(2);
|
rollback->reserve(2);
|
||||||
preprendToEnvVar("LIB", L"LIB", libPaths);
|
prependToEnvVar("INCLUDE", L"INCLUDE", includePaths);
|
||||||
preprendToEnvVar("PATH", L"PATH", binPaths);
|
prependToEnvVar("LIB", L"LIB", libPaths);
|
||||||
|
prependToEnvVar("PATH", L"PATH", binPaths);
|
||||||
|
|
||||||
if (global.params.verbose) {
|
if (global.params.verbose) {
|
||||||
const auto end = std::chrono::steady_clock::now();
|
const auto end = std::chrono::steady_clock::now();
|
||||||
|
@ -357,11 +387,11 @@ bool setupMsvcEnvironmentImpl(
|
||||||
}
|
}
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
bool isMsvcAvailable() { return setupMsvcEnvironmentImpl(nullptr); }
|
bool isMsvcAvailable() { return setupMsvcEnvironmentImpl(false, nullptr); }
|
||||||
|
|
||||||
bool MsvcEnvironmentScope::setup() {
|
bool MsvcEnvironmentScope::setup(bool forPreprocessingOnly) {
|
||||||
rollback.clear();
|
rollback.clear();
|
||||||
return setupMsvcEnvironmentImpl(&rollback);
|
return setupMsvcEnvironmentImpl(forPreprocessingOnly, &rollback);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsvcEnvironmentScope::~MsvcEnvironmentScope() {
|
MsvcEnvironmentScope::~MsvcEnvironmentScope() {
|
||||||
|
|
|
@ -53,7 +53,7 @@ struct MsvcEnvironmentScope {
|
||||||
// Tries to set up the MSVC environment variables for the current process and
|
// Tries to set up the MSVC environment variables for the current process and
|
||||||
// returns true if successful. The original environment is restored on
|
// returns true if successful. The original environment is restored on
|
||||||
// destruction.
|
// destruction.
|
||||||
bool setup();
|
bool setup(bool forPreprocessingOnly = false);
|
||||||
|
|
||||||
~MsvcEnvironmentScope();
|
~MsvcEnvironmentScope();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue