This is an automated email from the ASF dual-hosted git repository.

leginee pushed a commit to branch bazel-migration
in repository https://gitbox.apache.org/repos/asf/openoffice.git

commit 77ac3d9ca1a440d96c86a27c2e1f23f802127621
Author: Peter Kovacs <[email protected]>
AuthorDate: Fri Jun 5 20:08:59 2026 +0200

    adding the multiproposal plan for later.
---
 platform-axis-proposal.md | 313 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 313 insertions(+)

diff --git a/platform-axis-proposal.md b/platform-axis-proposal.md
new file mode 100644
index 0000000000..c3d5e364b4
--- /dev/null
+++ b/platform-axis-proposal.md
@@ -0,0 +1,313 @@
+# Opening a Platform Axis in the Bazel Build
+
+**Status:** investigation / design proposal (no build graph changes)
+**Trigger:** trunk commit `5e139d9fe4` — *Native Apple Silicon (arm64) support 
and
+bundled Python 3.10 baseline* — the first real second-platform data point for 
AOO
+since the Bazel migration began.
+**Audience:** anyone deciding whether the Bazel branch should grow from a 
single
+Windows/x86 target into a multi-platform matrix.
+
+---
+
+## 0. TL;DR
+
+The current Bazel branch builds exactly **one** point in what is naturally a
+three-dimensional space:
+
+```
+        OS  ×  CPU      ×  "age" (toolchain / deployment target / dep ABI)
+   ┌───────────────────────────────────────────────────────────────────┐
+   │ windows   x86_64      VS2008 / WinSDK 7.0 / Python 2.7   ◀── today  │
+   │ macos     arm64       clang  / macOS 11   / Python 3.10  ◀── trunk  │
+   │ macos     x86_64      clang  / macOS …     …                        │
+   │ linux     x86_64      gcc    / …                                    │
+   └───────────────────────────────────────────────────────────────────┘
+```
+
+Bazel was built to drive this matrix from one graph. The migration so far has
+*hardcoded* the single cell (MSVC flags inline in every BUILD file, one 
toolchain
+registered unconditionally, zero `select()` on OS). The arm64 commit is the
+forcing function to factor that one cell into a coordinate system.
+
+**The key realization:** the trunk commit does not need to be "ported." It is a
+*reference spec* telling us exactly what the second matrix cell looks like
+(arch names, deployment target, ABI bridge, dep flags). Opening the axis is a
+build-system refactor; the commit supplies the answers it must encode.
+
+---
+
+## 1. The three axes, and why "chips / ages" matters
+
+Bazel models a build target along **constraints**. Two come for free from
+`@platforms`; the third we define ourselves.
+
+### Axis 1 — OS  (`@platforms//os`)
+`windows`, `macos`, `linux`, … Selects: source sets (`osl/w32` vs `osl/unx`),
+the cpp_uno bridge family, the VCL backend (win vs aqua/quartz), packaging.
+
+### Axis 2 — CPU / "chip"  (`@platforms//cpu`)
+`x86_64`, `arm64`, … Selects: the *ABI bridge* (the calling-convention
+trampoline — the single most arch-specific component in the whole tree),
+assembler dialect, atomics, and external-lib build flags (openssl
+`darwin64-arm64-cc`, icu endianness).
+
+This is where Apple Silicon lands: same OS (macos), **new chip** (arm64). The
+trunk commit's `s5abi_macosx_aarch64/` bridge is precisely "the macos cell,
+arm64 column."
+
+### Axis 3 — "age" / generation  (custom constraints + flags)
+The dimension people forget. It is not OS and not CPU — it's *which generation
+of toolchain, OS floor, and dependency ABI* you target:
+
+- **deployment target / OS floor** — the commit sets macOS 11 as the minimum
+  (`LSMinimumSystemVersion 11.0`, `-mmacosx-version-min=11.0`). The same source
+  builds differently against a 10.13 floor vs an 11.0 floor.
+- **dependency generation** — Python **2.7 → 3.10** (the commit's second half),
+  **NSS 3.39 too old for arm64** (deferred in the commit). These are 
ABI/version
+  knobs independent of OS+CPU.
+- **compiler generation** — VS2008 today; a clang version on mac.
+
+Modeling "age" as a first-class axis is what lets one branch say *"build the
+arm64 mac against the macOS-11 / Python-3.10 generation"* without forking the
+tree. It is the difference between a matrix and a pile of `#ifdef`s.
+
+---
+
+## 2. How Bazel drives the matrix (the four primitives)
+
+All four already exist in this repo — we just use them for ATL/lang/debug 
today,
+not for platforms.
+
+### 2.1 `platform()` — a named point in the matrix
+```python
+# build/platforms/BUILD.bazel  (new)
+platform(
+    name = "windows_x86",
+    constraint_values = ["@platforms//os:windows", "@platforms//cpu:x86_32"],
+)
+platform(
+    name = "macos_arm64",
+    constraint_values = [
+        "@platforms//os:macos",
+        "@platforms//cpu:arm64",
+        "//build/constraints:macos_11",   # axis-3 "age" constraint
+    ],
+)
+```
+Select a cell at the command line: `bazel build 
--platforms=//build/platforms:macos_arm64 //main/bridges:s5abi_uno`.
+
+### 2.2 `toolchain()` — auto-resolved per target platform
+You already do this. Today's 
[build/toolchain/BUILD.bazel](build/toolchain/BUILD.bazel)
+registers the VS2008 toolchain with `target_compatible_with = [windows, 
x86_64]`.
+Add a sibling and Bazel's toolchain resolution picks the right one 
automatically
+based on `--platforms`:
+```python
+toolchain(
+    name = "cc_toolchain_macos_arm64_def",
+    exec_compatible_with  = ["@platforms//os:macos", "@platforms//cpu:arm64"],
+    target_compatible_with = ["@platforms//os:macos", "@platforms//cpu:arm64"],
+    toolchain      = ":cc_toolchain_macos_clang_arm64",
+    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
+```
+`register_toolchains(...)` in MODULE.bazel lists both. **The Windows build is
+untouched** — when `--platforms` is windows, the macos toolchain is simply not
+compatible and never selected.
+
+> **Native vs cross.** The mac toolchain's `exec_compatible_with` is `macos`,
+> meaning those actions must *run on a Mac* (a CI runner or dev box, or a 
remote
+> executor). You cannot emit Mach-O/arm64 from the Windows VS2008 host. This is
+> a logistics fact, not a Bazel limitation: the same `bazel build` invocation 
on
+> a Mac produces the mac artifacts; on Windows it produces the win artifacts.
+> Remote execution (`--remote_executor`) can later let one machine drive both.
+
+### 2.3 `config_setting` — turn a platform into something `select()` can read
+Mirror the existing `has_atl` / `build_de` idiom:
+```python
+# build/BUILD.bazel  (extend)
+config_setting(name = "on_windows", constraint_values = 
["@platforms//os:windows"])
+config_setting(name = "on_macos",   constraint_values = 
["@platforms//os:macos"])
+config_setting(name = "macos_arm64",
+    constraint_values = ["@platforms//os:macos", "@platforms//cpu:arm64"])
+```
+
+### 2.4 `select()` — the per-package payload
+This is the bulk of the work, but it's mechanical. See §3.
+
+---
+
+## 3. The refactor pattern, concretely (bridges as the worked example)
+
+[main/bridges/BUILD.bazel](main/bridges/BUILD.bazel) is the perfect specimen
+because the bridge is *the* most platform-specific module. Today it is
+unconditionally MSVC/x86:
+
+```python
+# TODAY — one hardcoded cell
+_COPTS   = ["/Zm500", "/EHsc", "/Dsnprintf=_snprintf",
+            "/Imain/bridges/source/cpp_uno/msvc_win32_intel", ...]
+_DEFINES = ["WNT", "WIN32", "CPPU_ENV=msci", "_X86_=1", ...]
+
+cc_binary(
+    name = "msci_uno",
+    srcs = [ ...shared..., "source/cpp_uno/msvc_win32_intel/cpp2uno.cxx", ... 
],
+    win_def_file = "util/msci_uno.def",
+)
+```
+
+The platform-axis form keeps the shared sources common and `select()`s the 
rest:
+
+```python
+# REFACTORED — coordinate-driven
+_SHARED_SRCS = [ "source/cpp_uno/shared/bridge.cxx", ... ]   # platform-neutral
+
+cc_binary(
+    name = "cpp_uno_bridge",                         # one logical target
+    srcs = _SHARED_SRCS + select({
+        "//build:on_windows": glob(["source/cpp_uno/msvc_win32_intel/*.cxx",
+                                     "source/cpp_uno/msvc_win32_intel/*.hxx"]),
+        "//build:macos_arm64": 
glob(["source/cpp_uno/s5abi_macosx_aarch64/*.cxx",
+                                     
"source/cpp_uno/s5abi_macosx_aarch64/*.hxx",
+                                     
"source/cpp_uno/s5abi_macosx_aarch64/*.s"]),
+    }),
+    copts = _COMMON_COPTS + select({
+        "//build:on_windows": _MSVC_COPTS,     # /EHsc /Zc:wchar_t- 
/Imsvc_win32_intel ...
+        "//build:on_macos":   _CLANG_COPTS,    # -fexceptions 
-mmacosx-version-min=11.0 -I.../s5abi_macosx_aarch64
+    }),
+    defines = select({
+        "//build:on_windows": ["WNT", "WIN32", "CPPU_ENV=msci", "_X86_=1"],
+        "//build:macos_arm64": ["MACOSX", "AARCH64", "CPPU_ENV=s5abi"],
+    }),
+    # MSVC needs a .def; Mach-O uses an exported-symbols list passed via 
linkopts.
+    win_def_file = select({
+        "//build:on_windows": "util/msci_uno.def",
+        "//conditions:default": None,
+    }),
+    linkopts = select({
+        "//build:on_windows": [...implibs...],
+        "//build:on_macos":   ["-Wl,-exported_symbols_list,$(location 
util/s5abi_uno.exp)"],
+    }),
+)
+```
+
+The recurring translation table (applies to ~every module, not just bridges):
+
+| Concern              | Windows (today)                       | macOS (to 
add)                              |
+|----------------------|---------------------------------------|---------------------------------------------|
+| Exception model      | `/EHsc`                               | 
`-fexceptions`                              |
+| `sal_Unicode` ABI    | `/Zc:wchar_t-`                        | (native, no 
flag)                           |
+| Symbol export        | `win_def_file = *.def`                | 
`-exported_symbols_list *.exp`              |
+| Assembler            | `ml.exe` `.asm` (toolchain `assemble`)| clang `.s` 
(GAS) — already a `.s` in commit |
+| `snprintf` shim      | `/Dsnprintf=_snprintf`                | (none)        
                              |
+| Defines              | `WNT WIN32 _X86_=1 CPPU_ENV=msci`     | `MACOSX 
AARCH64 CPPU_ENV=s5abi`             |
+| C runtime            | `/MD` + SxS manifest staging          | 
`-stdlib=libc++`                            |
+
+None of this changes the Windows output: every `select()` keeps the existing
+Windows arm verbatim and *adds* a macOS arm. The factoring is the cost; the
+Windows cell is byte-stable if the windows branch is copied exactly.
+
+---
+
+## 4. What each part of commit 5e139d9fe4 becomes under the axis
+
+| Commit file(s)                                   | Axis role                 
         | Bazel action |
+|--------------------------------------------------|------------------------------------|--------------|
+| `bridges/source/cpp_uno/s5abi_macosx_aarch64/*` (7 src) | macos × arm64 ABI 
bridge   | new `srcs` arm in the bridge `select()` (§3) |
+| `bridges/Library_cpp_uno.mk`, `makefile.mk`      | dmake — being deleted     
         | **ignore** (reference only) |
+| `sal/osl/unx/interlck.c`, `jvmfwk/.../util.cxx`  | macos source sets         
         | enter `osl/unx` / jvmfwk `select()` arms (don't exist yet) |
+| `sal/rtl/source/macro.hxx`                       | AARCH64 arch string       
         | already harmless; no action |
+| `openssl/makefile.mk`, `icu/*.patch`             | external build, per-chip  
         | arm64 Configure variant in the openssl/icu bzlmod/foreign_cc 
wrappers |
+| `set_soenv.in`, `source_soenv.sh`, `solenv/inc/unx*.mk`, 
`gbuild/platform/macosx.mk`, `configure.ac` | dmake/autoconf env | **ignore** — 
these are exactly the layer Bazel replaces; read them as the *spec* for the 
axis-3 constants (CPU=R, OUTPATH=unxmaccr, deploy 11.0) |
+| `solenv/bin/modules/installer/*.pm`, `osarch.pm`, 
`update_module_ignore_lists.pl` | Perl installer | ignore (post-build 
packaging, separately deferred) |
+| `setup_native/.../Info.plist*`, `sysui/.../Info.plist` | mac packaging       
   | feeds a future mac staging/bundle rule |
+| `python/pyversion*.mk`                           | axis-3 "age" knob (dmake) 
         | becomes a Bazel `--//build:python_gen` flag / dep version |
+| `pyuno/.../pythonloader.py`, `scripting/.../pythonscript.py`, `mailmerge.py` 
| **shipped Py3 source** | **the only cross-platform-relevant files** — see §5 |
+
+---
+
+## 5. The Python "age" axis — the one piece that touches *today's* build
+
+Everything else above is dormant until a mac target exists. The three `.py`
+files are different: they are **staged into the install on every platform**, 
and
+the commit rewrites them for **Python 3.10** (`imp`→`types.ModuleType`,
+`file()`→`open()`, Py3 `email` imports).
+
+Today's Bazel branch bundles **Python 2.7** — 
[main/pyuno/BUILD.bazel](main/pyuno/BUILD.bazel)
+links `@python//:python27_implib` and `MODULE.bazel` pins `python 2.7.18`.
+The commit explicitly does **not** do the Windows Python-3 build. So:
+
+> Merging those three files in isolation = Py3-only loader scripts shipped 
against
+> a Py2.7 interpreter = broken pyuno/scripting on Windows.
+
+This is the cleanest illustration of why "age" must be an explicit axis: the
+`.py` content is a function of the *Python generation*, which is independent of
+OS and CPU. The correct model is a `python_gen` selector that picks **both** 
the
+interpreter dep (`@python//:...` 2.7 vs 3.10 implib) **and** the matching 
loader
+sources — so you never ship py3 scripts against a py2 runtime. Until that knob
+exists, the `.py` changes stay out of the Windows build.
+
+---
+
+## 6. Why this is worth doing — what the axis unlocks
+
+1. **One graph, every target.** `bazel build 
--platforms=//build/platforms:macos_arm64 //main/sal`
+   builds sal for mac; flip the flag for Windows. No second checkout, no fork.
+2. **Incremental, module-by-module ports.** Because each `select()` defaults to
+   the Windows arm, you can land mac arms one package at a time (sal → cppu →
+   bridges → …) with the Windows build green the entire way. The migration
+   frontier in CLAUDE.md gains a *second column* instead of a second branch.
+3. **CI matrix for free.** A GitHub Actions matrix of {windows-runner,
+   macos-arm64-runner} each runs `bazel test //...` against its `--platforms`.
+   The bridge especially becomes *unit-testable* (bridgetest) per arch — the
+   commit notes bridgetest was never run; under Bazel it's a `cc_test`.
+4. **"Ages" become switchable, not forked.** Python 2.7↔3.10, macOS-11 floor,
+   future compiler bumps — each a flag, not a code fork. You can prove a
+   Python-3 migration on a branch flag while trunk-equivalent stays on 2.7.
+5. **Universal binaries later, cheaply.** Once macos×{x86_64,arm64} both build,
+   a Bazel *transition* + `lipo` action produces a fat binary from the same
+   targets — a natural extension of the axis, not new architecture.
+6. **Hermetic cross-builds down the road.** Splitting exec vs target platforms
+   (already expressed in every `toolchain()`) is the same lever that, with a
+   clang cross-toolchain + macOS SDK sysroot, eventually lets Linux/remote
+   executors build mac artifacts — removing the "must own a Mac" constraint.
+7. **It documents the platform contract.** The translation table in §3 is
+   currently tribal knowledge buried in CLAUDE.md's cross-cutting-flags 
section.
+   Making it a `select()` turns the contract into enforced, reviewable code.
+
+---
+
+## 7. Suggested sequence (each step keeps Windows green)
+
+```
+0. Scaffold (no compile): build/platforms/, build/constraints/ (os_version,
+   python_gen), config_settings in build/BUILD.bazel. Windows build identical.
+1. Register a macos clang/arm64 cc_toolchain (target_compatible_with 
macos+arm64).
+   Verify Windows toolchain resolution is unaffected (it is — incompatible).
+2. Pilot one leaf with no platform divergence to prove the select() plumbing.
+3. Port sal: introduce the osl/w32 ↔ osl/unx srcs select(); add interlck.c 
arm64.
+4. Port the bridge (§3) — the headline arm64 deliverable; add cpp2uno/uno2cpp/
+   call.s/abi.cxx as the macos_arm64 arm. Stand up bridgetest as a cc_test.
+5. Externals: openssl darwin64-arm64-cc + icu arm64 arms in their wrappers.
+6. Decide the Python "age" axis (§5) independently of mac — it's the only piece
+   with Windows-build consequences.
+7. Everything past the bridge (VCL aqua backend, packaging .app bundle,
+   code-signing) is genuinely new module work — track as a second frontier
+   column, not a port.
+```
+
+The honest scope: steps 0–2 are days. Steps 3–5 are the real refactor (touching
+many BUILD files, but mechanically). Step 7 (aqua VCL + signing) is the large,
+genuinely-new platform bring-up the commit itself flags as out of scope
+("Code-signing infra … NOT included", aqua backend untouched).
+
+---
+
+## 8. What does *not* change
+
+- The Windows/x86 build output — every `select()` preserves the current arm; 
the
+  VS2008 toolchain stays the registered default; nothing in the 31-file commit 
is
+  in today's Bazel graph.
+- The "no source changes" rule — opening the axis is pure build-system work. 
The
+  arm64 bridge sources are *new files from upstream*, not edits to existing 
code.
+- The migration philosophy — this extends the dmake-elimination goal to a 
second
+  platform; it does not reintroduce gmake/dmake (those `.mk` files stay 
ignored).

Reply via email to