Skip to content

[clang] Support layering checks for C++ modules #144981

Open
@matts1

Description

@matts1

One highly useful feature of build systems is the ability to ensure strict dependencies. For more details, see this blog post.

What are strict deps

TLDR: Strict deps enforce that code can only depend on its direct dependencies, and not transitive dependencies.

Consider the following code:

// foo.cppm
import bar;
import baz;
// bar.cppm
import baz
# BUILD

cc_module(
  name = "foo",
  interface = "foo.cppm",
  deps = [":bar"]
)

cc_module(
  name = "bar",
  interface = "bar.cppm",
  deps = [":baz"]
)

This code should not compile. foo imports baz, but does not declare a dependency on baz. However, build systems have no easy mechanism to enforce this, as they have to output compile steps along the lines of:

clang++ --precompile baz.cppm -o baz.pcm
clang++ --precompile bar.cppm -fmodule-file=baz=baz.pcm -o bar.pcm
clang++ --precompile foo.cppm -fmodule-file=baz=baz.pcm -fmodule-file=bar=bar.pcm -o foo.pcm

Note that we cannot simply remove the -fmodule-file=baz=..., otherwise we would get an error if the module bar ever tried to return a value of a type declared in baz.

Proposal

I propose that clang adds a new option -findirect-module-file. This has the same semantics as -fmodule-file, with the only difference being that if you ever attempt to import the module from the main TU, you get an error.

It might also be a good idea to add -Wstrict-module-deps or similar, so that this option can be first applied as warnings to an existing codebase, instead of errors.

This would allow the build system to generate:

clang++ --precompile baz.cppm -o baz.pcm
clang++ --precompile bar.cppm -fmodule-file=baz=baz.pcm -o bar.pcm
clang++ --precompile foo.cppm -findirect-module-file=baz=baz.pcm -fmodule-file=bar=bar.pcm -o foo.pcm

Thus allowing foo to fail to compile in the first place.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:modulesC++20 modules and Clang Header Modules

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions