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

Conversation

mordante
Copy link
Member

This implements a way for the compiler to find the modules.json associated with the C++23 Standard library modules.

This is based on a discussion in SG15. At the moment no Standard library installs this manifest. #75741 adds this feature in libc++.

This implements a way for the compiler to find the modules.json
associated with the C++23 Standard library modules.

This is based on a discussion in SG15. At the moment no Standard library
installs this manifest. llvm#75741 adds this feature in libc++.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Dec 27, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 27, 2023

@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-clang

Author: Mark de Wever (mordante)

Changes

This implements a way for the compiler to find the modules.json associated with the C++23 Standard library modules.

This is based on a discussion in SG15. At the moment no Standard library installs this manifest. #75741 adds this feature in libc++.


Full diff: https://github.com/llvm/llvm-project/pull/76451.diff

7 Files Affected:

  • (modified) clang/include/clang/Driver/Driver.h (+10)
  • (modified) clang/include/clang/Driver/Options.td (+3)
  • (modified) clang/lib/Driver/Driver.cpp (+40)
  • (added) clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/libc++.so ()
  • (added) clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json ()
  • (added) clang/test/Driver/cxx23-modules-print-library-module-manifest-path.c (+15)
  • (added) clang/test/Driver/darwin-print-library-module-manifest-path.c (+9)
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 3ee1bcf2a69c9b..2e1e3b128744ff 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -602,6 +602,16 @@ class Driver {
   // FIXME: This should be in CompilationInfo.
   std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;
 
+  /// GetModuleManifestPath - Lookup the name of the Standard library manifest.
+  ///
+  /// \param C - The compilation.
+  /// \param TC - The tool chain for additional information on
+  /// directories to search.
+  //
+  // FIXME: This should be in CompilationInfo.
+  std::string GetModuleManifestPath(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;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 2b93ddf033499c..890257e11485b6 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -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_library_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]>;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ff95c899c5f3d4..8d682f9238c6b8 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2164,6 +2164,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
     return false;
   }
 
+  if (C.getArgs().hasArg(options::OPT_print_library_module_manifest_path)) {
+    llvm::outs() << "module: ="
+                 << GetModuleManifestPath(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';
@@ -6135,6 +6141,40 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
   return std::string(Name);
 }
 
+std::string Driver::GetModuleManifestPath(const Compilation &C,
+                                          const ToolChain &TC) const {
+
+  switch (TC.GetCXXStdlibType(C.getArgs())) {
+  case ToolChain::CST_Libcxx: {
+    std::string lib = "libc++.so";
+    std::string path = GetFilePath(lib, TC);
+
+    // Note when there are multiple flavours of libc++ the module json needs to
+    // look at the command-line arguments for the proper json.
+
+    // For example
+    /*
+        const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs());
+        if (Sanitize.needsAsanRt())
+          return path.replace(path.size() - lib.size(), lib.size(),
+                              "modules-asan.json");
+    */
+
+    path = path.replace(path.size() - lib.size(), lib.size(), "modules.json");
+    if (TC.getVFS().exists(path))
+      return path;
+
+    return "";
+  }
+
+  case ToolChain::CST_Libstdcxx:
+    // libstdc++ does not provide Standard library modules yet.
+    return "";
+  }
+
+  return "";
+}
+
 std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
   SmallString<128> Path;
   std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
diff --git a/clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/libc++.so b/clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/libc++.so
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json b/clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/clang/test/Driver/cxx23-modules-print-library-module-manifest-path.c b/clang/test/Driver/cxx23-modules-print-library-module-manifest-path.c
new file mode 100644
index 00000000000000..7ad2b10081bc5b
--- /dev/null
+++ b/clang/test/Driver/cxx23-modules-print-library-module-manifest-path.c
@@ -0,0 +1,15 @@
+// Test that -print-library-module-manifest-path finds the correct file.
+
+// RUN: %clang -print-library-module-manifest-path \
+// RUN:     -stdlib=libc++ \
+// RUN:     --sysroot=%S/Inputs/cxx23_modules \
+// RUN:     --target=x86_64-linux-gnu 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LIBCXX %s
+// CHECK-LIBCXX: module: ={{.*}}/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json
+
+// RUN: %clang -print-library-module-manifest-path \
+// RUN:     -stdlib=libstdc++ \
+// RUN:     --sysroot=%S/Inputs/cxx23_modules \
+// RUN:     --target=x86_64-linux-gnu 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LIBSTDCXX %s
+// CHECK-LIBSTDCXX: module: =
diff --git a/clang/test/Driver/darwin-print-library-module-manifest-path.c b/clang/test/Driver/darwin-print-library-module-manifest-path.c
new file mode 100644
index 00000000000000..39d28589b146ae
--- /dev/null
+++ b/clang/test/Driver/darwin-print-library-module-manifest-path.c
@@ -0,0 +1,9 @@
+// Test that -print-library-module-manifest-path finds the correct file.
+//
+// Note this file is currently not available on Apple platforms
+
+// RUN: %clang -print-library-module-manifest-path \
+// RUN:     -resource-dir=%S/Inputs/resource_dir \
+// RUN:     --target=x86_64-unknown-linux-gnu 2>&1 \
+// RUN:   | FileCheck %s
+// CHECK: module: =

clang/include/clang/Driver/Driver.h Outdated Show resolved Hide resolved
clang/include/clang/Driver/Driver.h Show resolved Hide resolved
clang/include/clang/Driver/Driver.h Outdated Show resolved Hide resolved
clang/include/clang/Driver/Options.td Outdated Show resolved Hide resolved
clang/lib/Driver/Driver.cpp Outdated Show resolved Hide resolved
// RUN: --target=x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX %s
// CHECK-LIBCXX: module: ={{.*}}/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a path for libc++ like --gcc-toolchain= so that we can choose the different locations for libstdc++?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure, I've never used --gcc-toolchain either.

@boris-kolpackov
Copy link
Contributor

If I understand correctly, this invents a new option just to print the std modules path. Is there a reason why we cannot just print this information as part of -print-search-dirs? The benefit of this will be saving an extra compiler invocation in case the build system already uses this option, for example, to extract the library search paths (build2 does this). BTW, this would also allow you to sidestep the whole "what to print if there is no path" issue -- just omit the entry from the output.

If for some reason a separate option is desirable, can we then also print this information as part of -print-search-dirs?

@mordante
Copy link
Member Author

I had looked at -print-search-dirs but it seems buggy. For example, it ignores the -stdlib flag to the compiler invocation. Solving this seems a lot of work. So didn't want to add new features to that code.

@boris-kolpackov
Copy link
Contributor

I had looked at -print-search-dirs but it seems buggy. For example, it ignores the -stdlib flag to the compiler invocation.

True. I couldn't find a bug report for this so I filed one: #76614

Solving this seems a lot of work. So didn't want to add new features to that code.

If this is the right thing to do (i.e., printing this information as part of -print-search-dirs), then perhaps it's still worth it to try and fix? Once you add a separate option, you will have to drag it forever (for backwards compatibility).

@mordante
Copy link
Member Author

mordante commented Jan 3, 2024

If this is the right thing to do (i.e., printing this information as part of -print-search-dirs), then perhaps it's still worth it to try and fix? Once you add a separate option, you will have to drag it forever (for backwards compatibility).
I have a feeling how deep that rabbit hole is. This is not something I really want to dive into. Especially since I'm unfamiliar with this part of the code.

@mordante
Copy link
Member Author

@ChuanqiXu9 can you do a full review? I'd like to have this reviewed so we can land it when the libc++ side is ready.

Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM generally.

clang/lib/Driver/Driver.cpp Outdated Show resolved Hide resolved
clang/lib/Driver/Driver.cpp Show resolved Hide resolved
// RUN: --sysroot=%S/Inputs/cxx23_modules \
// RUN: --target=x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX %s
// CHECK-LIBCXX: {{.*}}/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to avoid use Inputs pattern nowadays. We can use split-file to multiple files into a single lit test. You can find the use example by searching split-file in clang/test/Modules

Copy link

github-actions bot commented Jan 12, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

We need to delete clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/libc++.so and clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json, we should generate them with split-file

@mordante
Copy link
Member Author

LGTM.

We need to delete clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/libc++.so and clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json, we should generate them with split-file

Are you sure that is the proper way? Should these tests not use a complete installation to make sure it works on installations?

@ChuanqiXu9
Copy link
Member

LGTM.
We need to delete clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/libc++.so and clang/test/Driver/Inputs/cxx23_modules/usr/lib/x86_64-linux-gnu/modules.json, we should generate them with split-file

Are you sure that is the proper way? Should these tests not use a complete installation to make sure it works on installations?

We can use mkdir to generate more complex paths. For example,

// RUN: split-file %s %t
//
// RUN: mkdir %t/....
// RUN: touch %t/.../libc++.so

The intention is to remove the use of Inputs in test. It is really hard to read.


// RUN: %clang -print-library-module-manifest-path \
// RUN: -stdlib=libstdc++ \
// RUN: --sysroot=%S/Inputs/cxx23_modules \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does %S/Inputs/cxx23_modules exist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this is a left-over when it used on-disc files. Nice catch.

clang/include/clang/Driver/Driver.h Outdated Show resolved Hide resolved
clang/lib/Driver/Driver.cpp Outdated Show resolved Hide resolved
clang/lib/Driver/Driver.cpp Outdated Show resolved Hide resolved
mordante added a commit that referenced this pull request Jan 21, 2024
Installs the source files of the experimental libc++ modules. These
source files (.cppm) are used by the Clang to build the std and 
std.compat modules.

The design of this patch is based on a discussing in SG-15 on
12.12.2023. (SG-15 is the ISO C++ Tooling study group):

- The modules are installed at a location, that is not known to build 
  systems and compilers.
- Next to the library there will be a module manifest json file.
  This json file contains the information to build the module from the
  libraries sources. This information includes the location where the
  sources are installed. @ruoso supplied the specification of this json
  file.
- If possible, the compiler has an option to give the location of the
  module manifest file
  (#76451).

Currently there is no build system support, but it expected to be added
in the future.

Fixes: #73089
@mordante
Copy link
Member Author

@MaskRay can you have another look, it would be great to land this before LLVM 18 branches, thanks!

// return "modules-asan.json";
// return "modules.json";
// }();
StringRef modules = "modules.json";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modules is only used once. inline it

Copy link
Member

@MaskRay MaskRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a few nits. Can you double check modules.json is inside lib/ (usr/lib/x86_64-linux-gnu{{/|\\}}modules.json) instead of some directory under include?

@mordante
Copy link
Member Author

LGTM with a few nits. Can you double check modules.json is inside lib/ (usr/lib/x86_64-linux-gnu{{/|\\}}modules.json) instead of some directory under include?

Thanks for the review. The json will indeed be installed in the lib dir in libc++.

@mordante mordante merged commit a301fb1 into llvm:main Jan 22, 2024
3 of 4 checks passed
@mordante mordante deleted the print-library-module-manifest-path branch January 22, 2024 18:42
@kaz7
Copy link
Contributor

kaz7 commented Jan 23, 2024

Hi @mordante,

Does this test, Driver/modules-print-library-module-manifest-path.cpp, work on other than x86? It is failing on VE build bot like below.

https://lab.llvm.org/buildbot/#/builders/91/builds/22189

AaronBallman added a commit that referenced this pull request Jan 23, 2024
@AaronBallman
Copy link
Collaborator

The build is still failing, so I've reverted these changes in 82f424f

@mordante
Copy link
Member Author

mordante commented Feb 4, 2024

Thanks for reverting @AaronBallman I somehow missed this comment.

@kaz7 it should work on all platforms AFAIK. I don't have access to a VE system. Looking at some VE tests I wonder whether the following patch would work.
patch.txt

@mordante
Copy link
Member Author

@kaz7 ping

@mordante
Copy link
Member Author

@kaz7 ping, can you have a look at the patch, I really like to reland this patch.

@ChuanqiXu9
Copy link
Member

(This is another example that the github review can't work well with the reverted patches...)

@mordante I think you can add // REQUIRES: x86-registered-target to the test if @kaz7 can't respond quickly. It will skip the test on targets other than x86. And it should keep the CI green and enable us to backport this clang18.

We can still improve this later.

@mordante
Copy link
Member Author

(This is another example that the github review can't work well with the reverted patches...)

@mordante I think you can add // REQUIRES: x86-registered-target to the test if @kaz7 can't respond quickly. It will skip the test on targets other than x86. And it should keep the CI green and enable us to backport this clang18.

We can still improve this later.

I've created #82160 as you suggested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants