Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][modules] Print library module manifest path. #76451

Merged
merged 13 commits into from
Jan 22, 2024
10 changes: 10 additions & 0 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,16 @@ class Driver {
// FIXME: This should be in CompilationInfo.
std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;

/// Lookup the path to the Standard library module manifest.
///
/// \param C - The compilation.
/// \param TC - The tool chain for additional information on
/// directories to search.
//
// FIXME: This should be in CompilationInfo.
mordante marked this conversation as resolved.
Show resolved Hide resolved
std::string GetStdModuleManifestPath(const Compilation &C,
const ToolChain &TC) const;

/// HandleAutocompletions - Handle --autocomplete by searching and printing
/// possible flags, descriptions, and its arguments.
void HandleAutocompletions(StringRef PassedFlags) const;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5280,6 +5280,9 @@ def print_resource_dir : Flag<["-", "--"], "print-resource-dir">,
def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
HelpText<"Print the paths used for finding libraries and programs">,
Visibility<[ClangOption, CLOption]>;
def print_std_module_manifest_path : Flag<["-", "--"], "print-library-module-manifest-path">,
HelpText<"Print the path for the C++ Standard library module manifest">,
Visibility<[ClangOption, CLOption]>;
def print_targets : Flag<["-", "--"], "print-targets">,
HelpText<"Print the registered targets">,
Visibility<[ClangOption, CLOption]>;
Expand Down
44 changes: 44 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2164,6 +2164,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}

if (C.getArgs().hasArg(options::OPT_print_std_module_manifest_path)) {
llvm::outs() << GetStdModuleManifestPath(C, C.getDefaultToolChain())
<< '\n';
return false;
}

if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
if (std::optional<std::string> RuntimePath = TC.getRuntimePath())
llvm::outs() << *RuntimePath << '\n';
Expand Down Expand Up @@ -6135,6 +6141,44 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
return std::string(Name);
}

std::string Driver::GetStdModuleManifestPath(const Compilation &C,
const ToolChain &TC) const {
std::string error = "<NOT PRESENT>";

switch (TC.GetCXXStdlibType(C.getArgs())) {
case ToolChain::CST_Libcxx: {
std::string lib = GetFilePath("libc++.so", TC);

// Note when there are multiple flavours of libc++ the module json needs to
// look at the command-line arguments for the proper json.
mordante marked this conversation as resolved.
Show resolved Hide resolved
// These flavours do not exist at the moment, but there are plans to
// provide a variant that is built with sanitizer instrumentation enabled.

// For example
// StringRef modules = [&] {
// const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs());
// if (Sanitize.needsAsanRt())
// return "modules-asan.json";
// return "modules.json";
// }();

SmallString<128> path(lib.begin(), lib.end());
llvm::sys::path::remove_filename(path);
llvm::sys::path::append(path, "modules.json");
if (TC.getVFS().exists(path))
return static_cast<std::string>(path);

return error;
}

case ToolChain::CST_Libstdcxx:
// libstdc++ does not provide Standard library modules yet.
return error;
}

return error;
}

std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
SmallString<128> Path;
std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
Expand Down
36 changes: 36 additions & 0 deletions clang/test/Driver/modules-print-library-module-manifest-path.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Test that -print-library-module-manifest-path finds the correct file.

// RUN: rm -rf %t && split-file %s %t && cd %t
// RUN: mkdir -p %t/Inputs/usr/lib/x86_64-linux-gnu
// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so

// RUN: %clang -print-library-module-manifest-path \
// RUN: -stdlib=libc++ \
// RUN: --sysroot=%t/Inputs \
// RUN: --target=x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck libcxx-no-module-json.cpp

// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/modules.json
// RUN: %clang -print-library-module-manifest-path \
// RUN: -stdlib=libc++ \
// RUN: --sysroot=%t/Inputs \
// RUN: --target=x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck libcxx.cpp

// RUN: %clang -print-library-module-manifest-path \
// RUN: -stdlib=libstdc++ \
// RUN: --sysroot=%t/Inputs \
// RUN: --target=x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck libstdcxx.cpp

//--- libcxx-no-module-json.cpp

// CHECK: <NOT PRESENT>

//--- libcxx.cpp

// CHECK: {{.*}}/Inputs/usr/lib/x86_64-linux-gnu{{/|\\}}modules.json

//--- libstdcxx.cpp

// CHECK: <NOT PRESENT>
Loading