Skip to content

Commit

Permalink
Trying to implement P1689R5
Browse files Browse the repository at this point in the history
  • Loading branch information
ChuanqiXu9 committed Sep 23, 2022
1 parent 327141f commit fd809e8
Show file tree
Hide file tree
Showing 22 changed files with 646 additions and 125 deletions.
20 changes: 20 additions & 0 deletions P1689Examples/Simple/CMakeLists.txt
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.24)
project(cxx_modules_simple CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include("${CMake_TEST_MODULE_COMPILATION_RULES}")

add_executable(simple)
target_sources(simple
PRIVATE
main.cxx
PRIVATE
FILE_SET CXX_MODULES
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
importable.cxx)
target_compile_features(simple PUBLIC cxx_std_20)
27 changes: 27 additions & 0 deletions P1689Examples/Simple/README.txt
@@ -0,0 +1,27 @@
# (WIP) How to run

- Compiler: the in-tree clang
- Cmake: cmake master with the following patch:
> https://gitlab.kitware.com/ben.boeckel/cmake/-/commit/3d1e6afed1c5e3b33f2f5b31a3a87c6d02e158e4

Command line option

```
CC=clang CXX=clang++ cmake -DCMake_TEST_MODULE_COMPILATION=named \
-DCMake_TEST_MODULE_COMPILATION_RULES=cxx_modules_rules_clang.cmake \
-DCMake_TEST_HOST_CMAKE=ON -S . -B build -GNinja
```

Currently, it will meet the following error:

```
$ninja
[1/3] Building CXX object CMakeFiles/simple.dir/importable.cxx.o
FAILED: CMakeFiles/simple.dir/importable.cxx.o CMakeFiles/simple.dir/importable.pcm
clang++ -std=c++20 -MD -MT CMakeFiles/simple.dir/importable.cxx.o -MF CMakeFiles/simple.dir/importable.cxx.o.d @CMakeFiles/simple.dir/importable.cxx.o.modmap -fdep-format=trtbd -x c++ -std=c++20 -o CMakeFiles/simple.dir/importable.cxx.o -c Simple/importable.cxx
error: -fdep-format= requires -fdep-file=
error: -fdep-format= requires -fdep-output=
ninja: build stopped: subcommand failed.
```


11 changes: 11 additions & 0 deletions P1689Examples/Simple/cxx_modules_rules_clang.cmake
@@ -0,0 +1,11 @@
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
set(CMake_TEST_CXXModules_UUID "a246741c-d067-4019-a8fb-3d16b0c9d1d3")

set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
"<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E -x c++ <SOURCE>"
" -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
" -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT> -fdep-format=trtbd"
" -o <PREPROCESSED_SOURCE>")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE> -fdep-format=trtbd -x c++ -std=c++20")
6 changes: 6 additions & 0 deletions P1689Examples/Simple/importable.cxx
@@ -0,0 +1,6 @@
export module importable;

export int from_import()
{
return 0;
}
6 changes: 6 additions & 0 deletions P1689Examples/Simple/main.cxx
@@ -0,0 +1,6 @@
import importable;

int main(int argc, char* argv[])
{
return from_import();
}
176 changes: 54 additions & 122 deletions README.md
@@ -1,122 +1,54 @@
# The LLVM Compiler Infrastructure

This directory and its sub-directories contain the source code for LLVM,
a toolkit for the construction of highly optimized compilers,
optimizers, and run-time environments.

The README briefly describes how to get started with building LLVM.
For more information on how to contribute to the LLVM project, please
take a look at the
[Contributing to LLVM](https://llvm.org/docs/Contributing.html) guide.

## Getting Started with the LLVM System

Taken from [here](https://llvm.org/docs/GettingStarted.html).

### Overview

Welcome to the LLVM project!

The LLVM project has multiple components. The core of the project is
itself called "LLVM". This contains all of the tools, libraries, and header
files needed to process intermediate representations and convert them into
object files. Tools include an assembler, disassembler, bitcode analyzer, and
bitcode optimizer. It also contains basic regression tests.

C-like languages use the [Clang](http://clang.llvm.org/) frontend. This
component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode
-- and from there into object files, using LLVM.

Other components include:
the [libc++ C++ standard library](https://libcxx.llvm.org),
the [LLD linker](https://lld.llvm.org), and more.

### Getting the Source Code and Building LLVM

The LLVM Getting Started documentation may be out of date. The [Clang
Getting Started](http://clang.llvm.org/get_started.html) page might have more
accurate information.

This is an example work-flow and configuration to get and build the LLVM source:

1. Checkout LLVM (including related sub-projects like Clang):

* ``git clone https://github.com/llvm/llvm-project.git``

* Or, on windows, ``git clone --config core.autocrlf=false
https://github.com/llvm/llvm-project.git``

2. Configure and build LLVM and Clang:

* ``cd llvm-project``

* ``cmake -S llvm -B build -G <generator> [options]``

Some common build system generators are:

* ``Ninja`` --- for generating [Ninja](https://ninja-build.org)
build files. Most llvm developers use Ninja.
* ``Unix Makefiles`` --- for generating make-compatible parallel makefiles.
* ``Visual Studio`` --- for generating Visual Studio projects and
solutions.
* ``Xcode`` --- for generating Xcode projects.

Some common options:

* ``-DLLVM_ENABLE_PROJECTS='...'`` and ``-DLLVM_ENABLE_RUNTIMES='...'`` ---
semicolon-separated list of the LLVM sub-projects and runtimes you'd like to
additionally build. ``LLVM_ENABLE_PROJECTS`` can include any of: clang,
clang-tools-extra, cross-project-tests, flang, libc, libclc, lld, lldb,
mlir, openmp, polly, or pstl. ``LLVM_ENABLE_RUNTIMES`` can include any of
libcxx, libcxxabi, libunwind, compiler-rt, libc or openmp. Some runtime
projects can be specified either in ``LLVM_ENABLE_PROJECTS`` or in
``LLVM_ENABLE_RUNTIMES``.

For example, to build LLVM, Clang, libcxx, and libcxxabi, use
``-DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi"``.

* ``-DCMAKE_INSTALL_PREFIX=directory`` --- Specify for *directory* the full
path name of where you want the LLVM tools and libraries to be installed
(default ``/usr/local``). Be careful if you install runtime libraries: if
your system uses those provided by LLVM (like libc++ or libc++abi), you
must not overwrite your system's copy of those libraries, since that
could render your system unusable. In general, using something like
``/usr`` is not advised, but ``/usr/local`` is fine.

* ``-DCMAKE_BUILD_TYPE=type`` --- Valid options for *type* are Debug,
Release, RelWithDebInfo, and MinSizeRel. Default is Debug.

* ``-DLLVM_ENABLE_ASSERTIONS=On`` --- Compile with assertion checks enabled
(default is Yes for Debug builds, No for all other build types).

* ``cmake --build build [-- [options] <target>]`` or your build system specified above
directly.

* The default target (i.e. ``ninja`` or ``make``) will build all of LLVM.

* The ``check-all`` target (i.e. ``ninja check-all``) will run the
regression tests to ensure everything is in working order.

* CMake will generate targets for each tool and library, and most
LLVM sub-projects generate their own ``check-<project>`` target.

* Running a serial build will be **slow**. To improve speed, try running a
parallel build. That's done by default in Ninja; for ``make``, use the option
``-j NNN``, where ``NNN`` is the number of parallel jobs to run.
In most cases, you get the best performance if you specify the number of CPU threads you have.
On some Unix systems, you can specify this with ``-j$(nproc)``.

* For more information see [CMake](https://llvm.org/docs/CMake.html).

Consult the
[Getting Started with LLVM](https://llvm.org/docs/GettingStarted.html#getting-started-with-llvm)
page for detailed information on configuring and compiling LLVM. You can visit
[Directory Layout](https://llvm.org/docs/GettingStarted.html#directory-layout)
to learn about the layout of the source code tree.

## Getting in touch

Join [LLVM Discourse forums](https://discourse.llvm.org/), [discord chat](https://discord.gg/xS7Z362) or #llvm IRC channel on [OFTC](https://oftc.net/).

The LLVM project has adopted a [code of conduct](https://llvm.org/docs/CodeOfConduct.html) for
participants to all modes of communication within the project.
Draft for implementing P1689R5 based on clang-trunk.

# Current status:

For each TU, now we can generate the direct dependency information for named modules as the P1689R5 described. We can found the result from test/Modules/P1689.cpp.

Also for the implementation (non partition) unit, currently it will provide nothing and require the corresponding primary module interface correctly.

# Possible improvement?
- In the section of `Example scanning output`, it shows

```json
{
"version": 1,
"revision": 0,
"rules": [
{
"primary-output": "duplicate.mpp.o",
"provides": [
{
"logical-name": "duplicate"
}
]
},
{
"primary-output": "another.mpp.o",
"provides": [
{
"logical-name": "another"
}
],
"requires": [
{
"logical-name": "duplicate"
}
]
},
{
"primary-output": "use.mpp.o",
"requires": [
{
"logical-name": "duplicate"
},
{
"logical-name": "another"
}
]
}
]
}
```

So it looks like the output should be for the project instead of the each TU.
But I am wondering if it will be better to merge them outside the compiler.
3 changes: 3 additions & 0 deletions clang-tools-extra/clangd/Compiler.cpp
Expand Up @@ -57,6 +57,9 @@ void disableUnsupportedOptions(CompilerInvocation &CI) {
CI.getDependencyOutputOpts().HeaderIncludeOutputFile.clear();
CI.getDependencyOutputOpts().DOTOutputFile.clear();
CI.getDependencyOutputOpts().ModuleDependencyOutputDir.clear();
CI.getDependencyOutputOpts().ModuleDepFormat = ModuleDependencyFormat::None;
CI.getDependencyOutputOpts().ModuleDepFile.clear();
CI.getDependencyOutputOpts().ModuleDepOutput.clear();

// Disable any pch generation/usage operations. Since serialized preamble
// format is unstable, using an incompatible one might result in unexpected
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticFrontendKinds.td
Expand Up @@ -128,6 +128,15 @@ def warn_fe_concepts_ts_flag : Warning<
"-fconcepts-ts is deprecated - use '-std=c++20' for Concepts support">,
InGroup<Deprecated>;

def err_fe_invalid_module_dep_format : Error<
"unknown dependency format '%0'">;
def err_fe_module_dependency_format_requires_dep_file : Error<
"-fdep-format= requires -fdep-file=">;
def err_fe_module_dependency_format_requires_dep_output : Error<
"-fdep-format= requires -fdep-output=">;
def err_fe_module_dependency_file_requires_dep_format : Error<
"-fdep-file= requires -fdep-format=">;

def err_fe_unable_to_load_basic_block_sections_file : Error<
"unable to load basic block sections function list: '%0'">;

Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -714,6 +714,16 @@ def MG : Flag<["-"], "MG">, Group<M_Group>, Flags<[CC1Option]>,
MarshallingInfoFlag<DependencyOutputOpts<"AddMissingHeaderDeps">>;
def MJ : JoinedOrSeparate<["-"], "MJ">, Group<M_Group>,
HelpText<"Write a compilation database entry per input">;
def fdep_file : Joined<["-"], "fdep-file=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"File for structured output dependency information">,
MetaVarName<"<file>">;
def fdep_format : Joined<["-"], "fdep-format=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Format for structured output dependency information (supported: 'trtbd')">,
MetaVarName<"<format>">, Values<"trtbd">,
MarshallingInfoFlag<PreprocessorOpts<"StandardModulesDepsFormat">>;
def fdep_output : Joined<["-"], "fdep-output=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Output file for the compilation step">,
MetaVarName<"<file>">;
def MP : Flag<["-"], "MP">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Create phony target for each dependency (other than main file)">,
MarshallingInfoFlag<DependencyOutputOpts<"UsePhonyTargets">>;
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Frontend/DependencyOutputOptions.h
Expand Up @@ -28,6 +28,9 @@ enum ExtraDepKind {
EDK_DepFileEntry,
};

/// ModuleDependencyFormat - Format for the module dependency file.
enum class ModuleDependencyFormat { None, Trtbd };

/// DependencyOutputOptions - Options for controlling the compiler dependency
/// file generation.
class DependencyOutputOptions {
Expand Down Expand Up @@ -76,6 +79,15 @@ class DependencyOutputOptions {
/// The directory to copy module dependencies to when collecting them.
std::string ModuleDependencyOutputDir;

/// The format for the module dependency file.
ModuleDependencyFormat ModuleDepFormat = ModuleDependencyFormat::None;

/// The output file for the module dependency file.
std::string ModuleDepFile;

/// The output path to use as the output in the module dependency file.
std::string ModuleDepOutput;

public:
DependencyOutputOptions()
: IncludeSystemHeaders(0), ShowHeaderIncludes(0), UsePhonyTargets(0),
Expand Down
29 changes: 29 additions & 0 deletions clang/include/clang/Frontend/Utils.h
Expand Up @@ -160,6 +160,35 @@ class ModuleDependencyCollector : public DependencyCollector {
virtual bool hasErrors() { return HasErrors; }
};

/// Collects dependencies for the P1689 output format.
class P1689ModuleDependencyCollector : public DependencyCollector {
ModuleDependencyFormat ModuleDepFormat = ModuleDependencyFormat::None;
std::string ModuleDepFile;
std::string ModuleDepOutput;

public:
P1689ModuleDependencyCollector(const DependencyOutputOptions &Opts);
~P1689ModuleDependencyCollector() override {}

void attachToPreprocessor(Preprocessor &PP) override;

void writeFile();

struct ModuleInfo {
enum class ModuleType {
Named,
AngleHeader,
QuoteHeader
};
std::string Name;
std::string SourcePath;
bool IsInterface = true;
ModuleType Type;
};
llvm::Optional<ModuleInfo> Provide;
std::vector<ModuleInfo> Requires;
};

/// AttachDependencyGraphGen - Create a dependency graph generator, and attach
/// it to the given preprocessor.
void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Lex/ModuleMap.h
Expand Up @@ -578,6 +578,10 @@ class ModuleMap {
Module *createShadowedModule(StringRef Name, bool IsFramework,
Module *ShadowingModule);

Module *getSourceModule() {
return SourceModule;
}

/// Creates a new declaration scope for module names, allowing
/// previously defined modules to shadow definitions from the new scope.
///
Expand Down

0 comments on commit fd809e8

Please sign in to comment.