diff --git a/.gitignore b/.gitignore index 0f072ef2c715..7af2b923f380 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ buck-out /.direnv .buckconfig.local .envrc.local +__pycache__/ # symlinks /examples/with_prelude/prelude diff --git a/flake.lock b/flake.lock index 899a68d26d2e..591caa440d79 100644 --- a/flake.lock +++ b/flake.lock @@ -48,11 +48,11 @@ ] }, "locked": { - "lastModified": 1748399823, - "narHash": "sha256-kahD8D5hOXOsGbNdoLLnqCL887cjHkx98Izc37nDjlA=", + "lastModified": 1766198367, + "narHash": "sha256-f1L1rCEu2Zew6zdiZ38jJDZd65ktE7UN+Gqn2LHPiFI=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "d68a69dc71bc19beb3479800392112c2f6218159", + "rev": "66bb33fdfb50b1ee724381c3f5d6012dac6c89b3", "type": "github" }, "original": { diff --git a/prelude/cxx/attr_selection.bzl b/prelude/cxx/attr_selection.bzl index 8a6897d39d24..16c59222b0aa 100644 --- a/prelude/cxx/attr_selection.bzl +++ b/prelude/cxx/attr_selection.bzl @@ -33,7 +33,7 @@ def cxx_by_language_ext(x: dict[typing.Any, typing.Any], ext: str) -> list[typin # And you can see them in java code, but somehow it works with # this one, which is seem across the repo. Find out what's happening. key_compiler = "c_cpp_output" - elif ext in (".cpp", ".cc", ".cl", ".cxx", ".c++", ".bc"): + elif ext in (".cpp", ".cc", ".cl", ".cxx", ".c++", ".bc", ".cppm", ".ixx"): key_pp = "cxx" key_compiler = "cxx_cpp_output" elif ext == ".m": diff --git a/prelude/cxx/compile.bzl b/prelude/cxx/compile.bzl index 601ef9cd4c88..e2bc161db392 100644 --- a/prelude/cxx/compile.bzl +++ b/prelude/cxx/compile.bzl @@ -1114,7 +1114,7 @@ def _validate_target_headers(label: Label, preprocessor: list[CPreprocessor]): def _get_compiler_info(toolchain: CxxToolchainInfo, ext: CxxExtension) -> typing.Any: compiler_info = None - if ext.value in (".cpp", ".cc", ".cl", ".cxx", ".c++", ".h", ".hpp", ".hh", ".h++", ".hxx", ".bc"): + if ext.value in (".cpp", ".cc", ".cl", ".cxx", ".c++", ".h", ".hpp", ".hh", ".h++", ".hxx", ".bc", ".cppm", ".ixx"): compiler_info = toolchain.cxx_compiler_info elif ext.value == ".c": compiler_info = toolchain.c_compiler_info @@ -1140,7 +1140,7 @@ def _get_compiler_info(toolchain: CxxToolchainInfo, ext: CxxExtension) -> typing return compiler_info def _get_category(ext: CxxExtension) -> str: - if ext.value in (".cpp", ".cc", ".cl", ".cxx", ".c++", ".h", ".hpp", ".hh", ".h++", ".hxx"): + if ext.value in (".cpp", ".cc", ".cl", ".cxx", ".c++", ".h", ".hpp", ".hh", ".h++", ".hxx", ".cppm", ".ixx"): return "cxx_compile" if ext.value == ".c": return "c_compile" @@ -1186,7 +1186,7 @@ def _dep_file_type(ext: CxxExtension) -> [DepFileType, None]: return None # Return the file type as well - if ext.value in (".cpp", ".cc", ".cl", ".mm", ".cxx", ".c++", ".h", ".hpp", ".hh", ".h++", ".hxx"): + if ext.value in (".cpp", ".cc", ".cl", ".mm", ".cxx", ".c++", ".h", ".hpp", ".hh", ".h++", ".hxx", ".cppm", ".ixx"): return DepFileType("cpp") elif ext.value in (".c", ".m"): return DepFileType("c") diff --git a/prelude/cxx/compile_types.bzl b/prelude/cxx/compile_types.bzl index f718b146d1bf..a156cad86b9d 100644 --- a/prelude/cxx/compile_types.bzl +++ b/prelude/cxx/compile_types.bzl @@ -37,6 +37,8 @@ CxxExtension = enum( ".h++", ".hxx", ".bc", + ".cppm", + ".ixx", *AsmExtensions.values() ) diff --git a/prelude/cxx/cxx.bzl b/prelude/cxx/cxx.bzl index d063c43528c5..87843abe2729 100644 --- a/prelude/cxx/cxx.bzl +++ b/prelude/cxx/cxx.bzl @@ -245,6 +245,7 @@ def cxx_library_generate(ctx: AnalysisContext, rule_type: str) -> list[Provider] # @oss-disable[end= ]: extra_linker_outputs_factory = get_extra_linker_outputs, # @oss-disable[end= ]: extra_linker_outputs_flags_factory = get_extra_linker_output_flags, supports_stripping = ctx.attrs.supports_stripping, + cxx_module_scanning = ctx.attrs.module_scanning, ) output = cxx_library_parameterized(ctx, params) return output.providers @@ -318,6 +319,7 @@ def cxx_binary_impl(ctx: AnalysisContext) -> list[Provider]: coverage_instrumentation_compiler_flags = ctx.attrs.coverage_instrumentation_compiler_flags, separate_debug_info = ctx.attrs.separate_debug_info, cuda_compile_style = CudaCompileStyle(ctx.attrs.cuda_compile_style), + cxx_module_scanning = ctx.attrs.module_scanning, ) output = cxx_executable(ctx, params) @@ -837,6 +839,7 @@ def cxx_test_impl(ctx: AnalysisContext) -> list[Provider]: coverage_instrumentation_compiler_flags = ctx.attrs.coverage_instrumentation_compiler_flags, separate_debug_info = ctx.attrs.separate_debug_info, cuda_compile_style = CudaCompileStyle(ctx.attrs.cuda_compile_style), + cxx_module_scanning = ctx.attrs.module_scanning, ) output = cxx_executable(ctx, params, is_cxx_test = True) diff --git a/prelude/cxx/cxx_toolchain_types.bzl b/prelude/cxx/cxx_toolchain_types.bzl index 37aeaad08a51..1389d9a504dc 100644 --- a/prelude/cxx/cxx_toolchain_types.bzl +++ b/prelude/cxx/cxx_toolchain_types.bzl @@ -229,6 +229,7 @@ CxxToolchainInfo = provider( "clang_llvm_statistics": provider_field(typing.Any, default = None), "clang_remarks": provider_field(typing.Any, default = None), "clang_trace": provider_field(typing.Any, default = None), + "clang_scan_deps": provider_field(typing.Any, default = None), "compiler_flavor_flags": provider_field(typing.Any, default = {}), "cpp_dep_tracking_mode": provider_field(typing.Any, default = None), "cuda_compiler_info": provider_field(typing.Any, default = None), diff --git a/prelude/cxx/cxx_types.bzl b/prelude/cxx/cxx_types.bzl index 04f8dd6152a2..5ac4a927a642 100644 --- a/prelude/cxx/cxx_types.bzl +++ b/prelude/cxx/cxx_types.bzl @@ -293,4 +293,8 @@ CxxRuleConstructorParams = record( # are using symlink trees. skip_exported_headers = field(bool, False), supports_stripping = field(bool, True), + # If set, the source files must be scanned for module dependencies + # prior to compilation, so we can know the correct order to compile them + # as well as additional compiler flags to pass to the compiler. + cxx_module_scanning = field(bool, False), ) diff --git a/prelude/decls/cxx_common.bzl b/prelude/decls/cxx_common.bzl index 970edc2dab5e..e00c55e3c5ff 100644 --- a/prelude/decls/cxx_common.bzl +++ b/prelude/decls/cxx_common.bzl @@ -340,6 +340,14 @@ def _use_content_based_paths_arg(): "use_content_based_paths": attrs.bool(default = True), } +def _module_scanning_arg(): + return { + "module_scanning": attrs.bool(default = False, doc = """ + If set, the source files must be scanned for module dependencies + prior to compilation. +"""), + } + cxx_common = struct( srcs_arg = _srcs_arg, deps_arg = _deps_arg, @@ -375,4 +383,5 @@ cxx_common = struct( use_fbcc_rust_wrapper_arg = _use_fbcc_rust_wrapper_arg, use_content_based_paths_arg = _use_content_based_paths_arg, supports_stripping = _supports_stripping, + module_scanning_arg = _module_scanning_arg, ) diff --git a/prelude/decls/cxx_rules.bzl b/prelude/decls/cxx_rules.bzl index dcb501b6d33a..199e15b707ca 100644 --- a/prelude/decls/cxx_rules.bzl +++ b/prelude/decls/cxx_rules.bzl @@ -145,6 +145,7 @@ cxx_binary = prelude_rule( cxx_common.runtime_dependency_handling_arg() | cxx_common.use_fbcc_rust_wrapper_arg() | cxx_common.use_content_based_paths_arg() | + cxx_common.module_scanning_arg() | { "cxx_runtime_type": attrs.option(attrs.enum(CxxRuntimeType), default = None), "default_host_platform": attrs.option(attrs.configuration_label(), default = None), @@ -484,6 +485,7 @@ library_attrs = ( cxx_common.version_arg() | cxx_common.use_fbcc_rust_wrapper_arg() | cxx_common.use_content_based_paths_arg() | + cxx_common.module_scanning_arg() | validation_common.attrs_validators_arg() | { "archive_allow_cache_upload": attrs.bool(default = False), @@ -845,6 +847,7 @@ cxx_test = prelude_rule( cxx_common.headers_arg() | cxx_common.preprocessor_flags_arg() | cxx_common.compiler_flags_arg() | + cxx_common.module_scanning_arg() | cxx_common.linker_flags_arg() | cxx_common.precompiled_header_arg() | buck.deps_query_arg() | @@ -1061,6 +1064,7 @@ cxx_toolchain = prelude_rule( "strip_debug_flags": attrs.option(attrs.list(attrs.arg()), default = None), "strip_non_global_flags": attrs.option(attrs.list(attrs.arg()), default = None), "use_header_map": attrs.bool(default = False), + "clang_scan_deps": attrs.option(attrs.source(), default = None), } | buck.licenses_arg() | buck.labels_arg() | diff --git a/prelude/toolchains/cxx.bzl b/prelude/toolchains/cxx.bzl index ec8e45c41e7a..457d4f6382df 100644 --- a/prelude/toolchains/cxx.bzl +++ b/prelude/toolchains/cxx.bzl @@ -42,6 +42,7 @@ CxxToolsInfo = provider( "linker": provider_field(typing.Any, default = None), "linker_type": LinkerType, "rc_compiler": provider_field(typing.Any, default = None), + "clang_scan_deps": provider_field(typing.Any, default = None), }, ) @@ -58,6 +59,7 @@ def _legacy_equivalent_cxx_tools_info_windows(ctx: AnalysisContext, default_tool archiver_type = default_toolchain.archiver_type, linker = default_toolchain.linker if ctx.attrs.linker == None or ctx.attrs.linker == "link.exe" else ctx.attrs.linker, linker_type = default_toolchain.linker_type, + clang_scan_deps = default_toolchain.clang_scan_deps if ctx.attrs.clang_scan_deps == None else ctx.attrs.clang_scan_deps, ) def _legacy_equivalent_cxx_tools_info_non_windows(ctx: AnalysisContext, default_toolchain: CxxToolsInfo) -> CxxToolsInfo: @@ -73,6 +75,7 @@ def _legacy_equivalent_cxx_tools_info_non_windows(ctx: AnalysisContext, default_ archiver_type = default_toolchain.archiver_type, linker = default_toolchain.linker if ctx.attrs.linker == None else ctx.attrs.linker, linker_type = default_toolchain.linker_type, + clang_scan_deps = default_toolchain.clang_scan_deps if ctx.attrs.clang_scan_deps == None else ctx.attrs.clang_scan_deps, ) def _system_cxx_toolchain_impl(ctx: AnalysisContext): @@ -224,6 +227,7 @@ def _cxx_toolchain_from_cxx_tools_info(ctx: AnalysisContext, cxx_tools_info: Cxx pic_behavior = pic_behavior, llvm_link = llvm_link, use_dep_files = True, + clang_scan_deps = _run_info(cxx_tools_info.clang_scan_deps), ), CxxPlatformInfo(name = target_name), ] @@ -239,6 +243,7 @@ system_cxx_toolchain = rule( "compiler": attrs.option(attrs.string(), default = None), "compiler_type": attrs.option(attrs.string(), default = None), # one of CxxToolProviderType "cpp_dep_tracking_mode": attrs.string(default = "makefile"), + "clang_scan_deps": attrs.option(attrs.string(), default = None), "cvtres_compiler": attrs.option(attrs.string(), default = None), "cvtres_flags": attrs.list(attrs.arg(), default = []), "cxx_compiler": attrs.option(attrs.string(), default = None), diff --git a/prelude/toolchains/cxx/clang/tools.bzl b/prelude/toolchains/cxx/clang/tools.bzl index d6ee574ed03b..6fb920a3d4a9 100644 --- a/prelude/toolchains/cxx/clang/tools.bzl +++ b/prelude/toolchains/cxx/clang/tools.bzl @@ -24,6 +24,7 @@ def _path_clang_tools_impl(_ctx) -> list[Provider]: archiver_type = "gnu", linker = "clang++", linker_type = LinkerType("gnu"), + clang_scan_deps = "clang-scan-deps", ), ] diff --git a/prelude/toolchains/msvc/tools.bzl b/prelude/toolchains/msvc/tools.bzl index a5c82e768ef4..b50ef46d459d 100644 --- a/prelude/toolchains/msvc/tools.bzl +++ b/prelude/toolchains/msvc/tools.bzl @@ -137,6 +137,8 @@ def _find_msvc_tools_impl(ctx: AnalysisContext) -> list[Provider]: archiver_type = "windows", linker = _windows_linker_wrapper(ctx, link_exe_script), linker_type = LinkerType("windows"), + # MSVC can do module scanning without needing a separate tool. + clang_scan_deps = None, ), ] diff --git a/rust-toolchain b/rust-toolchain index b2584b239291..b26ab2ac7f8b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -9,6 +9,7 @@ # * NOTE: You may have to change this ocaml file in a follow up commit as ocamlrep # has a dependency on buck2 git trunk. # * Update `../monarch/rust-toolchain` (one instance) +# * Update flake.lock via `nix flake update rust-overlay` # @rustc_version: rustc 1.91.0-nightly (02c7b1a7a 2025-09-13) channel = "nightly-2025-09-14"