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 3ce2cfc700a2d2b5916ada5c5d44fee8585da995
Author: Peter Kovacs <[email protected]>
AuthorDate: Mon Jun 22 23:29:10 2026 +0200

    update harness
---
 CLAUDE.md     |   3 +
 STYLEGUIDE.md | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 219 insertions(+)

diff --git a/CLAUDE.md b/CLAUDE.md
index f9ecc852fe..f56f7a43cb 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -138,6 +138,9 @@ Source code is NOT being changed — only the build system.
   - BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 disables auto-detection
 
 ## Key conventions
+- BUILD-file authoring conventions (module skeleton, naming, idioms, 
anti-patterns):
+  see STYLEGUIDE.md.  The rules below are the operating/landmine notes; 
STYLEGUIDE.md
+  is the copy-paste pattern reference for new modules.
 - BUILD.bazel files live at main/<package>/BUILD.bazel (NOT prj/)
   - prj/ convention only worked for nmake() wrappers; cc_library needs
     glob() access to sources which requires the BUILD at module root
diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md
new file mode 100644
index 0000000000..10196c63fc
--- /dev/null
+++ b/STYLEGUIDE.md
@@ -0,0 +1,216 @@
+# BUILD-file Styleguide — AOO Bazel Migration
+
+How to author `BUILD.bazel` and `.bzl` files so a new module looks like the
+ones already migrated. This is the **code** styleguide for this repo — the
+actual C++/Java source is out of scope (see [CLAUDE.md](CLAUDE.md) "Goal").
+
+For *operating* rules (build commands, workflow, guardrails) see
+[CLAUDE.md](CLAUDE.md). For *why* a given pattern exists, the
+`MEMORY.md` milestone for that module is the primary record. This file is
+the **generalization** of those ~50 milestones into copy-pasteable shape.
+
+Canonical reference example to imitate: 
[main/basctl/BUILD.bazel](main/basctl/BUILD.bazel)
+(a full first-party DLL with SDI, RSC, shielded includes, implib export).
+Foundational library example: [main/sal/BUILD.bazel](main/sal/BUILD.bazel).
+
+---
+
+## 1. Module BUILD skeleton
+
+A first-party module DLL is built in this order. Copy the shape, not the names.
+
+```python
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
+# load only the pipelines this module actually uses (rsc_res, sdi_target, ...)
+
+# 1. Defines and copts as module-local _DEFINES / _COPTS lists (see §2)
+_DEFINES = [ "WNT", "GUI", "WIN32", ... , "snprintf=_snprintf", "SUPD=680" ]
+_COPTS   = [ "/Zc:wchar_t-", "/Imain/<mod>/inc", "/Imain/<mod>/source/inc", 
... ]
+
+# 2. Header / include "shield" libraries (see §3)
+cc_library(name = "<mod>_inc",        textual_hdrs = glob(["inc/**"]),        
strip_include_prefix = "inc")
+cc_library(name = "<mod>_source_inc", textual_hdrs = glob(["source/inc/**"]), 
strip_include_prefix = "source/inc")
+
+# 3. Generated inputs (SDI slots, IDL, etc.) — only if the module uses them
+sdi_target(name = "<mod>slots_sdi", ...)
+cc_library(name = "<mod>slots_headers", hdrs = [":<mod>slots_sdi"], includes = 
["<mod>slots_sdi_inc"])
+
+# 4. The DLL itself
+cc_binary(
+    name = "<mod>",
+    srcs = ["inc/pch/precompiled_<mod>.cxx"] + glob(["source/**/*.cxx", 
"source/**/*.hxx"]),
+    copts = _COPTS,
+    defines = _DEFINES,
+    linkshared = True,
+    win_def_file = "util/<mod>.def",      # see §5
+    deps = [ ":<mod>_inc", ... , "//main/sal:sal_headers", ... ],   # headers 
only
+    additional_linker_inputs = [ "//main/sal:sal_implib", ... ],    # implibs 
(see §5)
+    linkopts = [ "$(execpath //main/sal:sal_implib)", ... , "shell32.lib" ],
+)
+
+# 5. Re-export this module's own implib for downstream consumers (see §5)
+filegroup(name = "<mod>_implib", srcs = [":<mod>"], output_group = 
"interface_library")
+
+# 6. Resources / config, if any (see §6)
+rsc_res(name = "<mod>_res", ...)
+filegroup(name = "uiconfig_files", srcs = glob(["uiconfig/**/*.xml"]), 
visibility = ["//main/postprocess:__pkg__"])
+exports_files(glob(["**/*.component"]))
+```
+
+**Driving the dep graph:** parse the module's legacy `build.lst` /
+`makefile.mk` to derive `deps`. `SLOFILES`/`OBJFILES` lists tell you exactly
+which sources belong in the library — prefer matching them over a blind
+`glob`, and `exclude` the ones a glob over-collects (see `main/sal` rtl: it
+excludes `gen_makefile.cxx`, `alloc_fini.cxx`, `strtmpl.c` because they are
+not in `SLOFILES`).
+
+---
+
+## 2. Defines & copts conventions
+
+- Hoist into module-local `_DEFINES` and `_COPTS` lists at the top of the file
+  so every target in the module shares them. Don't inline per-target.
+- The cross-cutting flags (`/Zc:wchar_t-`, `snprintf=_snprintf`,
+  `stlport` dep, `Z_PREFIX`, `CURL_STATICLIB`, …) are catalogued in
+  [CLAUDE.md](CLAUDE.md) "Cross-cutting compiler flags & defines". **Check that
+  list before building any new module** — most "mysterious" link/ABI failures
+  are a missing entry from it.
+- `_HAS_ITERATOR_DEBUGGING=0` is set **globally** in the toolchain — do **not**
+  re-add it per module (redundant; see CLAUDE.md).
+- Use a `_SLO_DEFINES = _DEFINES + ["SHAREDLIB", "_DLL_"]` derived list when a
+  module builds both shared- and static-lib object sets (see `main/sal`).
+
+---
+
+## 3. Idioms to copy
+
+### Shield (`_inc`) libraries — beat header-shadowing by name
+Many modules have identically-named headers (`helpid.hrc`, `*sh.hrc`). Expose a
+module's own `inc/` and `source/inc/` as **separate** `cc_library` targets with
+`strip_include_prefix`, listed **first** in `deps`, so they resolve before any
+transitively-added same-named header. Use `textual_hdrs` (not `hdrs`) for
+`.hrc`/`.tab`/`#include`d data files so Bazel doesn't try to compile-check 
them.
+Reference: [main/basctl/BUILD.bazel](main/basctl/BUILD.bazel) `basctl_inc` /
+`basctl_source_inc`, and the cui/basctl milestones in `MEMORY.md`.
+
+### Per-subdir `/I` copts for flat sibling includes
+Source that includes a sibling header by bare name (`<baside2.hrc>`,
+`"precompiled_sal.hxx"`) needs that exact directory on the include path. Add a
+`/Imain/<mod>/<subdir>` copt per such subdir (basctl adds 
`/Imain/basctl/source/basicide`).
+
+### `_headers` libraries are the public contract
+A module exposes its API to others as `//main/<mod>:<mod>_headers` (headers +
+`strip_include_prefix` + `includes`), never by depending on its `cc_binary`.
+Downstream `deps` carry **only** `_headers`; linking is via implibs (§5).
+
+### Generated headers get a wrapper `cc_library`
+SDI/IDL/MIDL output is wrapped: `hdrs = [":<gen>"]`, `includes =
+["<gen>_inc"]` (or `includes = ["."]` / `[".."]` for generated-header dirs).
+Reference: `basslots_headers`, and the winaccessibility/writerfilter 
milestones.
+
+### `textual_hdrs` for included data tables
+`.tab` files (`main/sal` textenc), `hash.cxx` (sdext pdfimport), private
+`types.idl`-derived headers — anything `#include`d rather than compiled — goes
+in `textual_hdrs`.
+
+---
+
+## 4. Naming conventions
+
+| Target | Pattern | Example |
+|---|---|---|
+| Public header lib | `<mod>_headers` | `sal_headers`, `tools_headers` |
+| Private include shield | `<mod>_inc`, `<mod>_source_inc` | `basctl_inc` |
+| Resource-constant shield | `<mod>_source_hrc`, `<mod>_hrc` | 
`basctl_source_hrc`, `svl_hrc` |
+| The DLL | `<mod>` (bare) | `basctl`, `sal` |
+| Re-exported implib | `<mod>_implib` (or `<linkname>_implib`) | 
`basctl_implib`, `comphelpMSC_implib` |
+| SDI slot gen | `<name>slots_sdi` + `<name>slots_headers` | `basslots_sdi` |
+| RSC resource | `<mod>_res` | `basctl_res` |
+| DEF file | `util/<linkname>.def` | `util/basctl.def` |
+
+The **implib name often differs from the module name** because it matches the
+upstream link-name, not the directory (`comphelpMSC_implib`, `tl_implib`,
+`utl_implib`, `svxcore_implib`). When in doubt, check the consumer's
+`additional_linker_inputs` list.
+
+---
+
+## 5. The DLL link triad (DEF + implib in + implib out)
+
+A first-party DLL has three linking concerns that must stay consistent:
+
+1. **Exports** — convert the upstream `<name>.map` GNU-ld script to a Windows
+   `util/<name>.def` and set `win_def_file`. UNO component DLLs export exactly
+   `component_getImplementationEnvironment`, `component_getFactory`,
+   `component_canUnload`. If there is no `.map`, hand-write a minimal `.def`
+   (see starmath milestone: `sm.def`/`smd.def`, no `canUnload`).
+2. **Consuming others' implibs** — list each dependency's implib in **both**
+   `additional_linker_inputs` (so Bazel stages the file) **and** `linkopts` as
+   `$(execpath //main/<dep>:<dep>_implib)`. Both are required; the
+   `additional_linker_inputs` entry alone won't put it on the link line.
+   Plain system libs (`shell32.lib`, `user32.lib`, `ws2_32.lib`) go straight
+   in `linkopts`.
+3. **Exposing your own implib** — end the file with
+   `filegroup(name="<mod>_implib", srcs=[":<mod>"], 
output_group="interface_library")`
+   so downstream modules can link you.
+
+---
+
+## 6. Resources, config, components
+
+- **RSC** (`rsc_res`): `srcs` = `.src`, `hdrs` = `.hrc` (own + cross-module
+  `*_inc_hrc` filegroups), `includes` = every `.hrc` search dir, and
+  **`images_root = "main/default_images"`** — this exact value is mandatory for
+  any module with `Bitmap { File = "x.png" }` (see CLAUDE.md; a module-specific
+  `images_root` silently empties every `BitmapEx(ResId)`).
+- **uiconfig**: expose as a `filegroup` visible to `//main/postprocess` only;
+  it is staged as a **folder tree**, never a zip.
+- **`.component`** files: `exports_files(glob(["**/*.component"]))` so the
+  postprocess/services.rdb pipeline can read them.
+
+---
+
+## 7. `.bzl` custom rules
+
+When a build step has no `cc_*`/`genrule` fit, it gets a Starlark rule under
+`build/rules/<thing>.bzl` (existing: `idl_pipeline`, `rsc_pipeline`,
+`sdi_target`, `images`, `scp2`, `localedata_pipeline`, `gtest_test`, …).
+Conventions, by example:
+
+- Prefer `ctx.actions.run` with explicit tool inputs over `run_shell`; use
+  `ctx.actions.symlink` (pure Bazel) for staging, not a shell `cp`.
+- Tools that link `/MD` need their CRT DLLs + **external** `.manifest` staged
+  beside the EXE (the `svidl_bundle` pattern — replicated in `gtest_test.bzl`;
+  miss it and you get R6034). See the test-infra and IDL milestones.
+- A rule that emits headers must advertise the include dir via an `includes`
+  provider/attr so the wrapper `cc_library` can surface it.
+- Keep the rule's migration rationale in its module `readme.md` and a one-line
+  `MEMORY.md` pointer — that is where future-you will look.
+
+---
+
+## 8. Anti-patterns (do NOT do)
+
+- ❌ Put a BUILD file in `prj/`. First-party modules need `glob()` over sources
+  → BUILD lives at `main/<mod>/BUILD.bazel`.
+- ❌ Depend on another module's `cc_binary` to get its headers. Use `_headers`.
+- ❌ Module-specific `images_root`. Always `"main/default_images"`.
+- ❌ Re-add `_HAS_ITERATOR_DEBUGGING=0` per module (global already).
+- ❌ Put an implib only in `additional_linker_inputs` (also needs `linkopts`).
+- ❌ Stage uiconfig as a zip (must be a folder tree).
+- ❌ Manipulate the Bazel cache directly. Use
+  `bazel mod deps --lockfile_mode=refresh` or ask the user.
+- ❌ Modify C++/Java source to make a build pass. Source is out of scope; fix
+  the build description instead. (If a source bug is genuinely blocking, raise
+  it — see the latent-UAF precedent — don't silently patch.)
+
+---
+
+## 9. After a module builds
+
+Per [CLAUDE.md](CLAUDE.md) workflow: **let the user build** (don't run the 
build
+yourself), add a `readme.md` migration summary to the module, add a one-line
+`MEMORY.md` milestone pointer, and **only then** update the frontier in
+CLAUDE.md. The `MEMORY.md` entry is what makes the next similar module fast.

Reply via email to