|
| 1 | +--- |
| 2 | +name: edg-cmakedef-build-config |
| 3 | +description: >- |
| 4 | + Explains EDG macro/build configurations: the .cmakedef files under |
| 5 | + cmake/macro-conf, the edg-cmakedef resolver, EDG_MACRO_CONF selection, and |
| 6 | + CMakePresets.json. Use when adding or changing a macro for a build, creating |
| 7 | + a new configuration or variant, finding out why a macro is (not) set, or |
| 8 | + choosing a preset. For running builds and tests, use edg-cpfe-build-test. |
| 9 | +--- |
| 10 | + |
| 11 | +# EDG cmakedef build configurations |
| 12 | + |
| 13 | +A **macro configuration** is a named set of `.cmakedef` files that decide |
| 14 | +which preprocessor macros each binary is compiled with. CMake resolves them |
| 15 | +with `dev_tools/bin/edg-cmakedef`. Project root = directory containing |
| 16 | +`src/cfe.c` and `dev_tools/`. |
| 17 | + |
| 18 | +Source of truth (read these rather than trusting this summary): |
| 19 | + |
| 20 | +- `dev_tools/bin/edg-cmakedef` — the resolver / language. |
| 21 | +- `cmake/macro-conf.cmake` — CMake glue. |
| 22 | +- `cmake/host-defaults.cmake` — auto-selection when nothing is specified. |
| 23 | +- `cmake/macro-conf/` — the configurations. |
| 24 | +- `CMakePresets.json` — presets that pick a configuration. |
| 25 | + |
| 26 | +## The cmakedef language |
| 27 | + |
| 28 | +One statement per line; blank lines and `#` comments are ignored. |
| 29 | + |
| 30 | +| Line | Meaning | |
| 31 | +| --- | --- | |
| 32 | +| `NAME` | define `NAME` (emitted as `NAME=1` in `#define` output) | |
| 33 | +| `NAME=value` | define with a value (may be empty) | |
| 34 | +| `import <dir/file>` | process `cmake/macro-conf/dir/file.cmakedef` here (root-relative, no extension) | |
| 35 | +| `delete NAME` | remove a prior definition; **error** if not set | |
| 36 | +| `delete_if_set NAME` | remove a prior definition; message only if not set | |
| 37 | + |
| 38 | +- Later lines override earlier ones (including across imports), so order |
| 39 | + matters: import the base first, then add overrides. |
| 40 | +- `@VAR@` in a value is expanded by CMake (`string(CONFIGURE)`). |
| 41 | +- Any unparsable line or failing `delete` makes the file invalid; the |
| 42 | + CMake configure then fails with "Failed to process cmakedef." |
| 43 | + |
| 44 | +## Layout of `cmake/macro-conf/` |
| 45 | + |
| 46 | +- `<config>/<target>.cmakedef`, one file per target. Targets and who reads |
| 47 | + them: `base` (`src/CMakeLists.txt`, emitted as a generated |
| 48 | + `cmake_defines.h` plus `USE_CMAKE_DEFINES`), `cpfe`, `cpfe-cp`, `cdisp` |
| 49 | + (`src/cmake/<target>/CMakeLists.txt`) and `cpprtlib` |
| 50 | + (`lib_src/CMakeLists.txt`); the last four become `-D` flags. |
| 51 | +- `default/` — baseline each config imports first |
| 52 | + (e.g. `default/cpfe` sets `BACK_END_IS_C_GEN_BE`, `DO_IL_LOWERING`). |
| 53 | + `default/base.cmakedef` is a "should not be used" stub. |
| 54 | +- `support/` — reusable fragments: `platform/`, `arch/`, `compiler/`, |
| 55 | + `build-type/`, `simple-conf/`, `feature/` (`on`/`off`), `target/`. |
| 56 | + Fragments are per-target too (e.g. `support/build-type/debug/cpfe`). |
| 57 | +- Named configs (`linux-gcc`, `linux-gcc-release`, `linux-clang`, |
| 58 | + `linux-i686-gcc`, `macos-arm-clang`, `windows-msvc`, …). Variants layer on |
| 59 | + a parent: `linux-gcc-multi-thread-release/cpfe.cmakedef` imports |
| 60 | + `<linux-gcc-release/cpfe>` and then appends its own macros. |
| 61 | +- A config directory missing a target file is auto-populated by CMake with |
| 62 | + `import <default/<target>>`; don't rely on that for real configs. |
| 63 | + |
| 64 | +## Selection |
| 65 | + |
| 66 | +- Single-config generators (Ninja): cache var `EDG_MACRO_CONF`. |
| 67 | +- Multi-config generators: `EDG_DEBUG_MACRO_CONF` and |
| 68 | + `EDG_RELEASE_MACRO_CONF`. |
| 69 | +- If empty, `host-defaults.cmake` picks one from OS, arch, compiler, and |
| 70 | + build type (`detect_host_defaults`); otherwise CMake warns. |
| 71 | +- Presets set it explicitly, e.g. `linux-gcc-debug` → |
| 72 | + `EDG_MACRO_CONF=linux-gcc`, binary dir `build/gcc`. |
| 73 | +- Every cmakedef file reached is added to `CMAKE_CONFIGURE_DEPENDS`, so |
| 74 | + editing one re-runs configure on the next build. |
| 75 | + |
| 76 | +## Recipes |
| 77 | + |
| 78 | +Inspect what a config resolves to (host Python, read-only, no build): |
| 79 | + |
| 80 | +```bash |
| 81 | +edg-cmakedef cmake/macro-conf linux-gcc/cpfe.cmakedef print-values |
| 82 | +edg-cmakedef --verbose cmake/macro-conf linux-gcc/cpfe.cmakedef print-values |
| 83 | +edg-cmakedef cmake/macro-conf linux-gcc/base.cmakedef print-defines |
| 84 | +edg-cmakedef cmake/macro-conf linux-gcc/cpfe.cmakedef print-paths |
| 85 | +``` |
| 86 | + |
| 87 | +- The target is resolved against the root if relative (CMake passes |
| 88 | + absolute paths); never repeat the root in it. |
| 89 | +- `print-values` → `NAME=value` lines; `print-defines` → `#ifndef/#define` |
| 90 | + blocks (the `base` form); `print-paths` → the files visited. |
| 91 | +- `--verbose` writes the import chain and each Setting / Overwriting / |
| 92 | + Deleting step to **stderr**, which shows exactly which file last set a |
| 93 | + macro. Use it to answer "why is X set?". |
| 94 | +- Compare two configs by diffing the `print-values` output (sort first). |
| 95 | + |
| 96 | +Change a macro for one build: edit the narrowest file that covers it. |
| 97 | +Shared by everything → `default/<target>`; one platform / build type / |
| 98 | +compiler → the matching `support/…` fragment; one named config or variant → |
| 99 | +that config's `<target>.cmakedef`. Check all targets that need it |
| 100 | +(`base` vs `cpfe` vs `cpprtlib` are separate files). |
| 101 | + |
| 102 | +Add a new configuration: |
| 103 | + |
| 104 | +1. Copy the nearest sibling directory under `cmake/macro-conf/` with all |
| 105 | + its target files; keep imports of `default/` and `support/` fragments. |
| 106 | +2. If it is a variant, import the parent's file instead of copying it. |
| 107 | +3. Add a preset to `CMakePresets.json` (inherit `linux-common` or the |
| 108 | + platform's common preset; set `EDG_MACRO_CONF`, `binaryDir`). |
| 109 | +4. If it should be auto-selected, add a branch in |
| 110 | + `cmake/host-defaults.cmake` (and note release builds use the |
| 111 | + `<name>-release` directory). |
| 112 | +5. Validate with the `print-values` recipe for every target, then |
| 113 | + configure/build in Docker (see **edg-cpfe-build-test**): |
| 114 | + |
| 115 | + ```bash |
| 116 | + edg-exec -- cmake --preset <preset> |
| 117 | + edg-exec --wdir build/<dir> -- ninja |
| 118 | + ``` |
| 119 | + |
| 120 | +## Pitfalls |
| 121 | + |
| 122 | +- `import <…>` paths are relative to `cmake/macro-conf`, with no extension. |
| 123 | +- `delete` of a never-set key fails the configure; use `delete_if_set` when |
| 124 | + the key might legitimately be absent. |
| 125 | +- A macro in a cmakedef only matters if the source consumes it; the generated |
| 126 | + `cmake_defines.h` is only used when `USE_CMAKE_DEFINES` is set. Editing |
| 127 | + `src/defines.h` (BUILD.md) does not change what a CMake configuration |
| 128 | + produces. |
| 129 | +- `print-paths` output order is unspecified (set iteration). |
| 130 | +- Windows uses `dev_tools/win-bin/edg-cmakedef.bat`; the Python is |
| 131 | + type-checked by `dev_tools/typecheck-python.sh` (follow |
| 132 | + **edg-python-style** if editing the tool). |
0 commit comments