From d8fd70e9efeb5ab3c7df40a354d7f31d2d795540 Mon Sep 17 00:00:00 2001 From: Mikhail Novoseltsev <51940183+Sameri11@users.noreply.github.com> Date: Sat, 12 Sep 2026 19:51:03 +0500 Subject: [PATCH 1/2] promotion: reduce the public BUILD API surface --- flutter/defs.bzl | 34 +++++++++++++++++----------------- tests/consumer/BUILD.bazel | 27 +++++++++++++++++++++------ tests/consumer/README.md | 8 +++++--- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/flutter/defs.bzl b/flutter/defs.bzl index 3040268..465b7bc 100644 --- a/flutter/defs.bzl +++ b/flutter/defs.bzl @@ -1,19 +1,18 @@ """The supported BUILD-file API for Flutter Consumer Modules. Consumer BUILD files load this one entrypoint rather than the implementation -under ``//flutter/private``. The public names below are the complete contract -exercised by the consumer API fixture; implementation files can move without -another consumer migration. +under ``//flutter/private``. Every name here is either written by hand in a +Consumer Module or named by a BUILD file these rules generate; nothing is +exported merely because it exists. Rules composed by the macros below -- +``dart_kernel``, ``flutter_android_libs``, ``jni_lib_jar``, +``strip_native_libs`` -- and the ``ABIS`` table stay private, so their +attributes remain free to change without a consumer migration. """ -load("//flutter/private:abis.bzl", _ABIS = "ABIS") load( "//flutter/private:android.bzl", _android_native_lib_jar = "android_native_lib_jar", _flutter_android_binary = "flutter_android_binary", - _flutter_android_libs = "flutter_android_libs", - _jni_lib_jar = "jni_lib_jar", - _strip_native_libs = "strip_native_libs", ) load( "//flutter/private:embedding.bzl", @@ -27,7 +26,6 @@ load( ) load( "//flutter/private:rules.bzl", - _dart_kernel = "dart_kernel", _flutter_aot_library = "flutter_aot_library", _flutter_app = "flutter_app", _flutter_assets = "flutter_assets", @@ -37,19 +35,21 @@ load( # Explicit assignments make the curated names exports of this module. Merely # importing names with load() does not re-export them to downstream BUILD files. -ABIS = _ABIS -android_native_lib_jar = _android_native_lib_jar -dart_kernel = _dart_kernel -flutter_android_binary = _flutter_android_binary -flutter_android_libs = _flutter_android_libs -flutter_aot_library = _flutter_aot_library +# +# Written by hand in a Consumer Module. flutter_app = _flutter_app -flutter_assets = _flutter_assets +flutter_android_binary = _flutter_android_binary flutter_embedding_library = _flutter_embedding_library flutter_native_contribution = _flutter_native_contribution + +# Named by the BUILD files the plugin extension generates, so they are loaded +# across a repository boundary and have to resolve from this entrypoint. +android_native_lib_jar = _android_native_lib_jar flutter_native_libs = _flutter_native_libs + +# The Dart half on its own, for an app whose Dart layout `flutter_app` refuses. flutter_pubspec = _flutter_pubspec -jni_lib_jar = _jni_lib_jar +flutter_aot_library = _flutter_aot_library +flutter_assets = _flutter_assets pub_path_deps_check = _pub_path_deps_check pub_plugins_check = _pub_plugins_check -strip_native_libs = _strip_native_libs diff --git a/tests/consumer/BUILD.bazel b/tests/consumer/BUILD.bazel index 4e2ccc9..b4fcd40 100644 --- a/tests/consumer/BUILD.bazel +++ b/tests/consumer/BUILD.bazel @@ -1,28 +1,43 @@ """The supported BUILD API for a Consumer Module. -All supported symbols load from @rules_flutter//flutter:defs.bzl. Internal -implementation helpers are exercised indirectly through the supported macros. +Supported symbols load from @rules_flutter//flutter:defs.bzl. The rules those +macros compose are not supported API; the loads below name them through +@rules_flutter//flutter/private so this fixture keeps its load-and-analysis +coverage of them without implying a consumer may do the same. """ load("@bazel_skylib//rules:build_test.bzl", "build_test") load( "@rules_flutter//flutter:defs.bzl", - "ABIS", "android_native_lib_jar", - "dart_kernel", "flutter_android_binary", - "flutter_android_libs", "flutter_aot_library", "flutter_assets", "flutter_embedding_library", "flutter_native_contribution", "flutter_native_libs", "flutter_pubspec", - "jni_lib_jar", "pub_path_deps_check", "pub_plugins_check", +) + +# Internal coverage: composed by the macros above and deliberately absent from +# defs.bzl. Reaching into //flutter/private is exactly what a real Consumer +# Module must not do, so the warning is correct and suppressed only here, in +# the fixture whose job is to notice when these rules' attributes change. +# buildifier: disable=bzl-visibility +load("@rules_flutter//flutter/private:abis.bzl", "ABIS") + +# buildifier: disable=bzl-visibility +load( + "@rules_flutter//flutter/private:android.bzl", + "flutter_android_libs", + "jni_lib_jar", "strip_native_libs", ) + +# buildifier: disable=bzl-visibility +load("@rules_flutter//flutter/private:rules.bzl", "dart_kernel") load("@rules_java//java:defs.bzl", "java_import") load(":assertions.bzl", "expect_equal", "expect_label_equal") diff --git a/tests/consumer/README.md b/tests/consumer/README.md index 494f267..19182d4 100644 --- a/tests/consumer/README.md +++ b/tests/consumer/README.md @@ -63,11 +63,13 @@ Loading and analysis — `--nobuild` — of every supported BUILD symbol through | entry point | symbols | | --- | --- | -| `defs.bzl` | `ABIS`, `dart_kernel`, `flutter_aot_library`, `flutter_assets`, `pub_path_deps_check`, `pub_plugins_check`, `flutter_app`, `jni_lib_jar`, `android_native_lib_jar`, `strip_native_libs`, `flutter_android_libs`, `flutter_android_binary`, `flutter_embedding_library`, `flutter_native_contribution`, `flutter_native_libs`, `flutter_pubspec` | +| `defs.bzl` | `flutter_app`, `flutter_android_binary`, `flutter_embedding_library`, `flutter_native_contribution`, `android_native_lib_jar`, `flutter_native_libs`, `flutter_pubspec`, `flutter_aot_library`, `flutter_assets`, `pub_path_deps_check`, `pub_plugins_check` | +| `flutter/private` | `ABIS`, `dart_kernel`, `flutter_android_libs`, `jni_lib_jar`, `strip_native_libs` — internal coverage only; the supported macros compose these, and no Consumer Module may load them | | `extensions.bzl` | `flutter_plugins_ext` (`plugins.project()`/`plugins.package()`) over a real, checked-in external plugin graph — `:fake_plugin_deps_check`, `:fake_plugin_test` | -Implementation-only rules and helpers are covered indirectly by these supported -macros; this Consumer Module does not load specialist implementation files. +Remaining implementation rules and helpers are covered indirectly by the +supported macros; this Consumer Module loads no specialist implementation file +beyond the internal row above. That catches the two things a refactor of these rules actually breaks: a symbol moving between files (load phase) and an attribute renamed, removed or made From e28435b9d1c02537df8974a00288c38307d7abbc Mon Sep 17 00:00:00 2001 From: Mikhail Novoseltsev <51940183+Sameri11@users.noreply.github.com> Date: Sat, 12 Sep 2026 20:18:16 +0500 Subject: [PATCH 2/2] promotion: enforce the private implementation boundary --- MODULE.bazel.lock | 4 +- examples/demo_app/MODULE.bazel.lock | 6 +- examples/local_plugin/MODULE.bazel.lock | 6 +- examples/no_plugins/MODULE.bazel.lock | 4 +- examples/pub_plugins/MODULE.bazel.lock | 6 +- flutter/private/BUILD.bazel | 89 +++++++++++++--- flutter/private/abis.bzl | 2 + flutter/private/android.bzl | 8 ++ flutter/private/archive.bzl | 2 + flutter/private/bundle.bzl | 2 + flutter/private/embedding.bzl | 2 + flutter/private/maven.bzl | 2 + flutter/private/ndk.bzl | 2 + flutter/private/plugins.bzl | 2 + flutter/private/pubspec.bzl | 2 + flutter/private/recipe.bzl | 2 + flutter/private/rules.bzl | 2 + tests/consumer/BUILD.bazel | 134 +++--------------------- tests/consumer/MODULE.bazel.lock | 6 +- tests/consumer/README.md | 4 +- tests/consumer/flutter/BUILD.bazel | 2 +- tools/ci/assertions.bzl | 9 ++ 22 files changed, 141 insertions(+), 157 deletions(-) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index dbb0a01..005485a 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -260,7 +260,7 @@ "moduleExtensions": { "//flutter:extensions.bzl%android_ndk": { "general": { - "bzlTransitiveDigest": "PbHufQ8Ef0dxRku/+V8j/hIWIdUoSzsJVSDuoykOXkQ=", + "bzlTransitiveDigest": "CCDnxxDPQWIOYLzO+5q4koM9rag6DwD7j1zgxAxjWeI=", "usagesDigest": "u+HEkcGg21uv1v1Y5n7OFzVXl5/8Fi8W5y561YLsmWA=", "recordedInputs": [ "REPO_MAPPING:,platforms platforms", @@ -299,7 +299,7 @@ }, "//flutter/private:repo.bzl%flutter": { "general": { - "bzlTransitiveDigest": "d0akA1llff6BLmlVnXIvFQO70c00GoPx6Qps3UswgoY=", + "bzlTransitiveDigest": "vgynOpv4LBdHrZyNmJGA6SkQT9/Dd8uEI1lVEEox6+k=", "usagesDigest": "jrBaZOcWDOcKabJnjwy68BVDrd46XjcPFZOpHFqt7ZE=", "recordedInputs": [ "REPO_MAPPING:,bazel_tools bazel_tools", diff --git a/examples/demo_app/MODULE.bazel.lock b/examples/demo_app/MODULE.bazel.lock index c4eaa23..290124f 100644 --- a/examples/demo_app/MODULE.bazel.lock +++ b/examples/demo_app/MODULE.bazel.lock @@ -557,7 +557,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%android_ndk": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "zX96yfJW4/h1cfrBMvBaUg9hTRGQp0ZuwjmqXN/HquQ=", "recordedInputs": [ "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", @@ -596,7 +596,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%flutter_plugins_ext": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "frgjMNjXCjd7j75y9p+LFe3RH+RtcxxOnaCzq3dakik=", "recordedInputs": [ "REPO_MAPPING:,flutter_maven rules_jvm_external++maven+flutter_maven", @@ -655,7 +655,7 @@ }, "@@sameri11_rules_flutter+//flutter/private:repo.bzl%flutter": { "general": { - "bzlTransitiveDigest": "d0akA1llff6BLmlVnXIvFQO70c00GoPx6Qps3UswgoY=", + "bzlTransitiveDigest": "vgynOpv4LBdHrZyNmJGA6SkQT9/Dd8uEI1lVEEox6+k=", "usagesDigest": "9JJGb3s90dw7aP1J/ALzWN+mv7TCBGSvZtZjU0/9yS8=", "recordedInputs": [ "REPO_MAPPING:sameri11_rules_flutter+,bazel_tools bazel_tools", diff --git a/examples/local_plugin/MODULE.bazel.lock b/examples/local_plugin/MODULE.bazel.lock index 176d16f..381de11 100644 --- a/examples/local_plugin/MODULE.bazel.lock +++ b/examples/local_plugin/MODULE.bazel.lock @@ -557,7 +557,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%android_ndk": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "c6Q7xXhVgobmcU8bDM+vxe4f5nLrPx8SVE7jZZJGerQ=", "recordedInputs": [ "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", @@ -596,7 +596,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%flutter_plugins_ext": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "ZniNXWl6OiVCASrWeGxNNsIQlgh4uDdHgYxug69NNWw=", "recordedInputs": [ "REPO_MAPPING:,flutter_maven rules_jvm_external++maven+flutter_maven", @@ -650,7 +650,7 @@ }, "@@sameri11_rules_flutter+//flutter/private:repo.bzl%flutter": { "general": { - "bzlTransitiveDigest": "d0akA1llff6BLmlVnXIvFQO70c00GoPx6Qps3UswgoY=", + "bzlTransitiveDigest": "vgynOpv4LBdHrZyNmJGA6SkQT9/Dd8uEI1lVEEox6+k=", "usagesDigest": "9JJGb3s90dw7aP1J/ALzWN+mv7TCBGSvZtZjU0/9yS8=", "recordedInputs": [ "REPO_MAPPING:sameri11_rules_flutter+,bazel_tools bazel_tools", diff --git a/examples/no_plugins/MODULE.bazel.lock b/examples/no_plugins/MODULE.bazel.lock index 3fc3891..65205c4 100644 --- a/examples/no_plugins/MODULE.bazel.lock +++ b/examples/no_plugins/MODULE.bazel.lock @@ -557,7 +557,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%android_ndk": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "kiRgwS+Co+SVG39rQ6d/0TSTi0aPlNWC8w8fxg1J0UE=", "recordedInputs": [ "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", @@ -596,7 +596,7 @@ }, "@@sameri11_rules_flutter+//flutter/private:repo.bzl%flutter": { "general": { - "bzlTransitiveDigest": "d0akA1llff6BLmlVnXIvFQO70c00GoPx6Qps3UswgoY=", + "bzlTransitiveDigest": "vgynOpv4LBdHrZyNmJGA6SkQT9/Dd8uEI1lVEEox6+k=", "usagesDigest": "9JJGb3s90dw7aP1J/ALzWN+mv7TCBGSvZtZjU0/9yS8=", "recordedInputs": [ "REPO_MAPPING:sameri11_rules_flutter+,bazel_tools bazel_tools", diff --git a/examples/pub_plugins/MODULE.bazel.lock b/examples/pub_plugins/MODULE.bazel.lock index c037323..52bcbf2 100644 --- a/examples/pub_plugins/MODULE.bazel.lock +++ b/examples/pub_plugins/MODULE.bazel.lock @@ -557,7 +557,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%android_ndk": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "BVQSiaq0xrv//PzqHk1mfLYCXhD/oOSxnp1+ldQM4N8=", "recordedInputs": [ "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", @@ -596,7 +596,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%flutter_plugins_ext": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "YHpUoRs5EUMqVpMzUL4GczEbTmnqwnkljjI69j4wkZo=", "recordedInputs": [ "REPO_MAPPING:,flutter_maven rules_jvm_external++maven+flutter_maven", @@ -650,7 +650,7 @@ }, "@@sameri11_rules_flutter+//flutter/private:repo.bzl%flutter": { "general": { - "bzlTransitiveDigest": "d0akA1llff6BLmlVnXIvFQO70c00GoPx6Qps3UswgoY=", + "bzlTransitiveDigest": "vgynOpv4LBdHrZyNmJGA6SkQT9/Dd8uEI1lVEEox6+k=", "usagesDigest": "9JJGb3s90dw7aP1J/ALzWN+mv7TCBGSvZtZjU0/9yS8=", "recordedInputs": [ "REPO_MAPPING:sameri11_rules_flutter+,bazel_tools bazel_tools", diff --git a/flutter/private/BUILD.bazel b/flutter/private/BUILD.bazel index 8ea6d44..3a6fa48 100644 --- a/flutter/private/BUILD.bazel +++ b/flutter/private/BUILD.bazel @@ -1,24 +1,79 @@ """Implementation of the Flutter rules. -Nothing here is supported API. Consumer Modules load //flutter:defs.bzl and -//flutter:extensions.bzl; these files are exported only because generated -repositories and the ruleset's own CI guards name them by label. +Nothing here is supported API: Consumer Modules load //flutter:defs.bzl and +//flutter:extensions.bzl, and every `.bzl` beside this file declares +`visibility(["//flutter"])` so Bazel rejects any other load, in this repository +or a consumer's. Two mechanical exceptions need a label, and only those: + + * The Python helpers are attribute defaults of rules defined here. Bazel + resolves an implicit dependency against the package of the `.bzl` that + defines the rule, so `//flutter:__subpackages__` is enough even though the + rules are instantiated in another module's packages. + * The five `.bzl` files //tools/ci:key_portability_check reads as `srcs`. + That guard parses their source for action-key portability contracts, which + requires a label, not a load. + +`repo.bzl` carries no `visibility()` declaration: tests/consumer's +`android/config.MODULE.bazel` uses its module extension directly, which is that +fixture's only coverage of the explicit embedding debug and release labels. """ -package(default_visibility = ["//visibility:public"]) - -exports_files([ - "check_path_deps.py", - "check_native_assets.py", - "inject_version.py", - "merge_native_assets.py", - "read_pubspec.py", - "repo.bzl", - "rules.bzl", - "android.bzl", - "plugins.bzl", - "ndk.bzl", -]) +load("//tools/ci:assertions.bzl", "expect_equal", "expect_label_equal") +load(":abis.bzl", "ABIS") + +package(default_visibility = ["//visibility:private"]) + +exports_files( + [ + "check_path_deps.py", + "check_native_assets.py", + "inject_version.py", + "merge_native_assets.py", + "read_pubspec.py", + ], + visibility = ["//flutter:__subpackages__"], +) + +exports_files( + [ + "android.bzl", + "ndk.bzl", + "plugins.bzl", + "repo.bzl", + "rules.bzl", + ], + visibility = ["//tools/ci:__pkg__"], +) + +# The ABI table is implementation, so these assertions live beside it rather +# than in the Consumer Module fixture: a wrong snapshot flag or CPU constraint +# mislabels a platform, and nothing else in the build would notice. +expect_equal( + ABIS["armeabi-v7a"].snapshot_flags, + [ + "--no-sim-use-hardfp", + "--no-use-integer-division", + ], + "armeabi-v7a snapshot_flags", +) + +expect_label_equal( + ABIS["arm64-v8a"].cpu_constraint, + "@platforms//cpu:arm64", + "arm64-v8a cpu_constraint", +) + +expect_label_equal( + ABIS["x86_64"].cpu_constraint, + "@platforms//cpu:x86_64", + "x86_64 cpu_constraint", +) + +expect_label_equal( + ABIS["armeabi-v7a"].cpu_constraint, + "@platforms//cpu:armv7", + "armeabi-v7a cpu_constraint", +) # Excluded from wildcard checks because resolving it requires @androidsdk. alias( diff --git a/flutter/private/abis.bzl b/flutter/private/abis.bzl index c570b6e..b34e411 100644 --- a/flutter/private/abis.bzl +++ b/flutter/private/abis.bzl @@ -15,6 +15,8 @@ there is no `gen_snapshot` to pair with an x86 library however many a package publishes. """ +visibility(["//flutter"]) + MODES = ["release", "debug"] # Modes that require gen_snapshot. diff --git a/flutter/private/android.bzl b/flutter/private/android.bzl index f3eee79..5d9e111 100644 --- a/flutter/private/android.bzl +++ b/flutter/private/android.bzl @@ -44,6 +44,14 @@ load(":bundle.bzl", "ASSETS", "CLASSES", "FlutterBundleContributionInfo", "NATIV load(":embedding.bzl", "flutter_embedding_deps") load(":pubspec.bzl", "FlutterPubspecInfo") +# `//flutter` holds the public facades. `//` is the repository root package, +# which asserts `flutter_assets_dir` there because the root is the one package +# with no path separator and the helper is deliberately not public API. +visibility([ + "//", + "//flutter", +]) + _MODE_DEBUG = Label("//flutter:mode_debug") _MODE_RELEASE = Label("//flutter:mode_release") diff --git a/flutter/private/archive.bzl b/flutter/private/archive.bzl index 4235be1..b07487c 100644 --- a/flutter/private/archive.bzl +++ b/flutter/private/archive.bzl @@ -5,6 +5,8 @@ Uses Bazel's declared `zipper`, which fixes metadata and follows argv order. `StripNativeLibs` preserves input order because it discovers entries at execution. """ +visibility(["//flutter"]) + ZIPPER_ATTRS = { "_zipper": attr.label( default = Label("@bazel_tools//tools/zip:zipper"), diff --git a/flutter/private/bundle.bzl b/flutter/private/bundle.bzl index f13d45d..d80421a 100644 --- a/flutter/private/bundle.bzl +++ b/flutter/private/bundle.bzl @@ -22,6 +22,8 @@ Two things this deliberately does not do: that assembles plus a rule that checks. """ +visibility(["//flutter"]) + # Where a contribution's files land -- named for the destination, not for the # contribution, so a platform putting two in the same place says so. # diff --git a/flutter/private/embedding.bzl b/flutter/private/embedding.bzl index 943f4a2..9befb99 100644 --- a/flutter/private/embedding.bzl +++ b/flutter/private/embedding.bzl @@ -23,6 +23,8 @@ load("@rules_java//java:defs.bzl", "java_import") load(":abis.bzl", "embedding_repo") load(":maven.bzl", "maven_label") +visibility(["//flutter"]) + _MODE_DEBUG = Label("//flutter:mode_debug") _MODE_RELEASE = Label("//flutter:mode_release") diff --git a/flutter/private/maven.bzl b/flutter/private/maven.bzl index 264442a..a05f42b 100644 --- a/flutter/private/maven.bzl +++ b/flutter/private/maven.bzl @@ -5,6 +5,8 @@ generates for it, and both feed the same artifact list, so the mangling and the version comparison live in one place rather than being reimplemented per caller. """ +visibility(["//flutter"]) + def maven_label(coordinate, repo): """`group:artifact[:version]` -> the target rules_jvm_external generates.""" parts = coordinate.split(":") diff --git a/flutter/private/ndk.bzl b/flutter/private/ndk.bzl index 4ae88a8..5f4605c 100644 --- a/flutter/private/ndk.bzl +++ b/flutter/private/ndk.bzl @@ -8,6 +8,8 @@ fetched and fails with an actionable diagnostic if no NDK is present. load("@rules_android_ndk//:rules.bzl", "android_ndk_repository") +visibility(["//flutter"]) + _MIN_NDK_MAJOR = 28 _CMAKE_STUB_BUILD = """# Generated by //flutter:extensions.bzl -- do not edit. diff --git a/flutter/private/plugins.bzl b/flutter/private/plugins.bzl index 7bf13e5..381033d 100644 --- a/flutter/private/plugins.bzl +++ b/flutter/private/plugins.bzl @@ -15,6 +15,8 @@ load(":abis.bzl", "MIN_SDK", "check_abis", "plugin_repo_target") load(":embedding.bzl", "FLUTTER_EMBEDDING_ARTIFACTS") load(":maven.bzl", "highest_versions", "maven_label") +visibility(["//flutter"]) + # Plugin reason codes. Ungated plugins build from source. # # external_native_build CMake/ndk-build configuration. diff --git a/flutter/private/pubspec.bzl b/flutter/private/pubspec.bzl index 69a5490..8605886 100644 --- a/flutter/private/pubspec.bzl +++ b/flutter/private/pubspec.bzl @@ -15,6 +15,8 @@ invalidate the kernel -- Bazel keys an action on the content of its inputs, and the package-name file is unchanged. """ +visibility(["//flutter"]) + FlutterPubspecInfo = provider( doc = "Facts read out of an app's pubspec.yaml.", fields = { diff --git a/flutter/private/recipe.bzl b/flutter/private/recipe.bzl index 60eb52f..1b52515 100644 --- a/flutter/private/recipe.bzl +++ b/flutter/private/recipe.bzl @@ -42,6 +42,8 @@ library. load(":archive.bzl", "ZIPPER_ATTRS", "deterministic_jar") +visibility(["//flutter"]) + # `dart_kernel`'s `target_os` names, not a second vocabulary. The list grows # with the platform table; macOS is absent until there is something to build for # it, and is named separately rather than folded into an `apple` -- flutter_tools diff --git a/flutter/private/rules.bzl b/flutter/private/rules.bzl index 8bf123a..c463f9f 100644 --- a/flutter/private/rules.bzl +++ b/flutter/private/rules.bzl @@ -28,6 +28,8 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load(":abis.bzl", "ABIS", "aot_gen_snapshot", "aot_target_compatible_with", "check_abis") load(":pubspec.bzl", "FlutterPubspecInfo", "flutter_pubspec") +visibility(["//flutter"]) + # Release actions may be shared through a remote cache. # # no-sandbox: package_config.json reaches into ~/.pub-cache, which is not a diff --git a/tests/consumer/BUILD.bazel b/tests/consumer/BUILD.bazel index b4fcd40..66bcde6 100644 --- a/tests/consumer/BUILD.bazel +++ b/tests/consumer/BUILD.bazel @@ -1,9 +1,6 @@ """The supported BUILD API for a Consumer Module. -Supported symbols load from @rules_flutter//flutter:defs.bzl. The rules those -macros compose are not supported API; the loads below name them through -@rules_flutter//flutter/private so this fixture keeps its load-and-analysis -coverage of them without implying a consumer may do the same. +All supported symbols load from @rules_flutter//flutter:defs.bzl. """ load("@bazel_skylib//rules:build_test.bzl", "build_test") @@ -20,26 +17,7 @@ load( "pub_path_deps_check", "pub_plugins_check", ) - -# Internal coverage: composed by the macros above and deliberately absent from -# defs.bzl. Reaching into //flutter/private is exactly what a real Consumer -# Module must not do, so the warning is correct and suppressed only here, in -# the fixture whose job is to notice when these rules' attributes change. -# buildifier: disable=bzl-visibility -load("@rules_flutter//flutter/private:abis.bzl", "ABIS") - -# buildifier: disable=bzl-visibility -load( - "@rules_flutter//flutter/private:android.bzl", - "flutter_android_libs", - "jni_lib_jar", - "strip_native_libs", -) - -# buildifier: disable=bzl-visibility -load("@rules_flutter//flutter/private:rules.bzl", "dart_kernel") load("@rules_java//java:defs.bzl", "java_import") -load(":assertions.bzl", "expect_equal", "expect_label_equal") package(default_visibility = ["//visibility:private"]) @@ -54,53 +32,6 @@ flutter_pubspec( src = "fixtures/pubspec.yaml", ) -dart_kernel( - name = "kernel", - srcs = ["lib/main.dart"], - entrypoint = "lib/main.dart", - package_config = "fixtures/package_config.json", - pubspec = ":pubspec", -) - -# target_os is the 0.3 attribute. Named explicitly rather than left default, so -# renaming or removing it fails here. -dart_kernel( - name = "kernel_ios", - srcs = ["lib/main.dart"], - entrypoint = "lib/main.dart", - package_config = "fixtures/package_config.json", - pubspec = ":pubspec", - target_os = "ios", -) - -expect_equal( - ABIS["armeabi-v7a"].snapshot_flags, - [ - "--no-sim-use-hardfp", - "--no-use-integer-division", - ], - "armeabi-v7a snapshot_flags", -) - -# Keep each ABI's explicit CPU constraint aligned with the table. -expect_label_equal( - ABIS["arm64-v8a"].cpu_constraint, - "@platforms//cpu:arm64", - "arm64-v8a cpu_constraint", -) - -expect_label_equal( - ABIS["x86_64"].cpu_constraint, - "@platforms//cpu:x86_64", - "x86_64 cpu_constraint", -) - -expect_label_equal( - ABIS["armeabi-v7a"].cpu_constraint, - "@platforms//cpu:armv7", - "armeabi-v7a cpu_constraint", -) - # The macro, with every named parameter supplied -- it is the public entry point # most consumers use, and its signature is the thing most likely to drift. flutter_aot_library( @@ -122,6 +53,19 @@ flutter_aot_library( target_os = "android", ) +# The public macro accepts non-Android target_os values too. Keep this +# analysis-only and single-ABI so the platform branch stays cheap. +flutter_aot_library( + name = "aot_library_ios", + srcs = ["lib/main.dart"], + abis = ["arm64-v8a"], + entrypoint = "lib/main.dart", + package_config = "fixtures/package_config.json", + pub_stamp = ["fixtures/pubspec.lock"], + pubspec = ":pubspec", + target_os = "ios", +) + flutter_assets( name = "assets", srcs = ["lib/main.dart"], @@ -146,22 +90,6 @@ pub_plugins_check( ) # --- android.bzl: the Android half ------------------------------------------- - -jni_lib_jar( - name = "jni_jar", - src = "fixtures/libfake.so", - # Mandatory: it decides which lib// a library loads from. - abi = "arm64-v8a", -) - -strip_native_libs( - name = "stripped", - # Mandatory: it selects the cross-strip that matches the jar's libraries, - # and the build platform is derived from it rather than restated. - abi = "arm64-v8a", - jar = "fixtures/fake_native_libs.jar", -) - # `src` takes rule targets, not source files -- in real use it is a # rules_foreign_cc cmake(). A filegroup is the cheapest stand-in that satisfies # that shape. @@ -276,40 +204,6 @@ java_import( jars = ["fixtures/fake_native_libs.jar"], ) -# Two ABIs, so the per-ABI shape is exercised rather than degenerating to one -# entry, and `aot` is the real flutter_aot_library above -- the join derives -# `_` from it, and a rename breaks that. -# -# `engine_jars` only because this test must not fetch: the ABI table would name -# the real engine repositories, and analysing one downloads ~150 MB. -flutter_android_libs( - name = "bundle", - abis = [ - "arm64-v8a", - "x86_64", - ], - aot = "aot_library", - assets = ":assets", - embedding = ":fake_embedding", - embedding_deps = [], - engine_jars = { - "arm64-v8a": "fixtures/fake_native_libs.jar", - "x86_64": "fixtures/fake_native_libs_x86_64.jar", - }, - native_libs = { - "arm64-v8a": ":fake_recipe_libs", - "x86_64": ":fake_recipe_libs_x86_64", - }, - # Populated rather than `{}`: the empty form is what a consumer reaches by - # accident, so the populated one is what needs pinning. - plugin_native_libs = { - "arm64-v8a": ":fake_plugin_libs", - "x86_64": ":fake_plugin_libs_x86_64", - }, - plugins = ":fake_plugins", - registrant = ":fake_registrant", -) - # The macro on top of the join: it emits `` plus `_`, so a # consumer's APK targets are named by it and a rename here is a rename in their # CI scripts. Two ABIs, because the per-ABI variants only exist above one. diff --git a/tests/consumer/MODULE.bazel.lock b/tests/consumer/MODULE.bazel.lock index 89adb6e..8568be7 100644 --- a/tests/consumer/MODULE.bazel.lock +++ b/tests/consumer/MODULE.bazel.lock @@ -557,7 +557,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%android_ndk": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "CE2Z/tOTJqwioicux0yXg4nzWLIvZDfcM/KtRNy1Og4=", "recordedInputs": [ "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", @@ -596,7 +596,7 @@ }, "@@sameri11_rules_flutter+//flutter:extensions.bzl%flutter_plugins_ext": { "general": { - "bzlTransitiveDigest": "ZJKKDZwqEchXeR0Vc2+H8meCWFRAv/62JcM4MQ6CVKQ=", + "bzlTransitiveDigest": "GgTgzwnVCVmS8C+TpYCirEYrl9SrY4dDdeXgNugEYz4=", "usagesDigest": "Ledc+BavJyeReHRqHvz5/Wcm+5OIAQF8UJuGmSbzKpI=", "recordedInputs": [ "REPO_MAPPING:,fake_plugin_metadata +fake_plugin_metadata+fake_plugin_metadata", @@ -653,7 +653,7 @@ }, "@@sameri11_rules_flutter+//flutter/private:repo.bzl%flutter": { "general": { - "bzlTransitiveDigest": "d0akA1llff6BLmlVnXIvFQO70c00GoPx6Qps3UswgoY=", + "bzlTransitiveDigest": "vgynOpv4LBdHrZyNmJGA6SkQT9/Dd8uEI1lVEEox6+k=", "usagesDigest": "Sk6Cc5WB7WvuCu4kD4WBlrApj6MiqRVWqpOdLMQHtd0=", "recordedInputs": [ "REPO_MAPPING:sameri11_rules_flutter+,bazel_tools bazel_tools", diff --git a/tests/consumer/README.md b/tests/consumer/README.md index 19182d4..c5c6d3b 100644 --- a/tests/consumer/README.md +++ b/tests/consumer/README.md @@ -64,12 +64,10 @@ Loading and analysis — `--nobuild` — of every supported BUILD symbol through | entry point | symbols | | --- | --- | | `defs.bzl` | `flutter_app`, `flutter_android_binary`, `flutter_embedding_library`, `flutter_native_contribution`, `android_native_lib_jar`, `flutter_native_libs`, `flutter_pubspec`, `flutter_aot_library`, `flutter_assets`, `pub_path_deps_check`, `pub_plugins_check` | -| `flutter/private` | `ABIS`, `dart_kernel`, `flutter_android_libs`, `jni_lib_jar`, `strip_native_libs` — internal coverage only; the supported macros compose these, and no Consumer Module may load them | | `extensions.bzl` | `flutter_plugins_ext` (`plugins.project()`/`plugins.package()`) over a real, checked-in external plugin graph — `:fake_plugin_deps_check`, `:fake_plugin_test` | Remaining implementation rules and helpers are covered indirectly by the -supported macros; this Consumer Module loads no specialist implementation file -beyond the internal row above. +supported macros; the Consumer BUILD file loads no private implementation file. That catches the two things a refactor of these rules actually breaks: a symbol moving between files (load phase) and an attribute renamed, removed or made diff --git a/tests/consumer/flutter/BUILD.bazel b/tests/consumer/flutter/BUILD.bazel index fce842a..51a3c08 100644 --- a/tests/consumer/flutter/BUILD.bazel +++ b/tests/consumer/flutter/BUILD.bazel @@ -13,7 +13,7 @@ # release build -- dropping the `aot_library` contribution while # `flutter_bundle_check`'s own `_mode` (a rule attribute, resolved against # `@rules_flutter` regardless of this decoy) still expects it, and every -# `:apk*`/`:bundle` target's bundle check in this module fails loudly. +# `:apk*` target's bundle check in this module fails loudly. package(default_visibility = ["//visibility:public"]) config_setting( diff --git a/tools/ci/assertions.bzl b/tools/ci/assertions.bzl index 011f94b..3e801f1 100644 --- a/tools/ci/assertions.bzl +++ b/tools/ci/assertions.bzl @@ -9,3 +9,12 @@ def expect_equal(actual, expected, what): """Fails the load if `actual` differs from `expected`.""" if actual != expected: fail("{}: got {}, expected {}".format(what, actual, expected)) + +def expect_label_equal(actual, expected, what): + """Fails the load if `actual` differs from `Label(expected)`. + + Builds the expected label here because BUILD files cannot call `Label()`. + """ + want = Label(expected) + if actual != want: + fail("{}: got {}, expected {}".format(what, actual, want))