From 62aafb9db1684e0e4b40e72daf8d881d27c28a72 Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Tue, 2 Jul 2024 14:57:49 -0400 Subject: [PATCH] docs: document describing how to update symbols map files + bugfix in the symbols generator for major versioning --- .../how-to/how-to-update-symbols-map.md | 183 ++++++++++++++++++ doc/sphinx/how-to/index.md | 1 + tools/symbols_map_generator/main.py | 23 ++- 3 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 doc/sphinx/how-to/how-to-update-symbols-map.md diff --git a/doc/sphinx/how-to/how-to-update-symbols-map.md b/doc/sphinx/how-to/how-to-update-symbols-map.md new file mode 100644 index 00000000000..0b21a6e1a94 --- /dev/null +++ b/doc/sphinx/how-to/how-to-update-symbols-map.md @@ -0,0 +1,183 @@ +# How to Update Symbols Map Files +Mir defines `symbols.map` files for the following libraries: + +- [miral](#how-to-update-miral-symbols) +- [miroil](#how-to-update-miroil-symbols) +- [mirserver](#how-to-update-mirserver-symbols-map) +- mircore +- mircommon +- mirplatform +- mirwayland + +A few different circumstances will prompt a developer to update +these files. These circumstances are: + +1. When a new symbols is added +2. When a symbols is changed or removed (e.g. a new parameter is + added to a method call, a class is removed, etc.) + +The former is an extension to the existing interface, meaning that +the new symbols can simply be put in a new stanza with a "bumped" +minor version. Note that the minor version must only be bumped once +per release cycle. This means that if I add a new symbols two months +before a release and you add a symbol 1 day before the release, then +our new symbols will go in the same stanza at the end of the +end of the `symbols.map` file. In that situation, I would have been +the one to create the new stanza. + +The latter is an ABI break, which means that _all_ of the symbols +in that library must now be in one giant stanza with a new major +version. + +## Setup +Before we can update the symbols of Mir's libraries, we'll want to set +up our environment so that the our internal tools can work correctly. + +To do this, you will first want to install clang-19. Note that it is +VERY important that you have the most recent version of clang, as that +works the best. + +```sh +sudo apt install clang-19 +``` + +Afterwards, you will want to set the following environment variables to point +at the path of `libclang.so` and `libclang.so`'s `lib` directory. Note that +these paths are likely to be the same on most Ubuntu 24.04 setups, but may +vary on other distros: + +```sh +export MIR_SYMBOLS_MAP_GENERATOR_CLANG_SO_PATH=/usr/lib/llvm-19/lib/libclang.so.1 +export MIR_SYMBOLS_MAP_GENERATOR_CLANG_LIBRARY_PATH=/usr/lib/llvm-19/lib +``` + +I just put those `export ...` commands in my `.bashrc` so that I don't have +to think about it. + +And that's it! Now we are ready to update our symbols automatically. + +## How to know if symbols need updating +Sometimes we break a symbols but don't even realize it until someone +points it out in a pull request. Nowadays, the symbols check is automated +by CI. You can find results of this check +[here](https://github.com/canonical/mir/actions/workflows/symbols-check.yml). +This check is run on each pull request. It will inform you whether or not +a `symbols.map` file needs to be updated due to your change. + +**Warning**: This check is not sophisticated to know if you change the +definition of a symbol (e.g. you changed the parameters of a method). This +check will still have to be done with your ever-wary eyes! + +## How to update miral symbols + +### Scenario 1: Adding a new symbol +1. Make the additive change to the interface (e.g. by adding a new method + to an existing class) +2. If not already bumped in this release cycle, bump `MIRAL_VERSION_MINOR` + in `src/CMakeLists.txt` +3. If not already bumped in this release cycle, bump `MIRAL_ABI` in + `src/miral/CMakeLists.txt` +4. From the root of the project, run: + ```sh + cmake --build build --target generate-miral-symbols-map + ``` +5. Check that your new symbols is in the `symbols.map` file: + ```sh + git diff src/miral/symbols.map + ``` +6. Regenerate the debian symbols: + ```sh + cmake --build build --target regenerate-miral-debian-symbols + ``` + +### Scenario 2: Removing or changing a symbol +1. Make a destructive change to the interface (e.g. remove a parameter from + a method). +2. If not already bumped in this release cycle, bump `MIRAL_VERSION_MAJOR` + in `src/CMakeLists.txt`. Set `MIRAL_VERSION_MINOR` and `MIRAL_VERSION_PATCH` + to `0` +3. If not already bumped in this release cycle, bump `MIRAL_ABI` in + `src/miral/CMakeLists.txt` +4. From the root of the project, run: + ```sh + cmake --build build --target generate-miral-symbols-map + ``` +5. Check that your symbols are reflected properly in the `symbols.map` file: + ```sh + git diff src/miral/symbols.map + ``` +6. Regenerate the debian symbols: + ```sh + cmake --build build --target regenerate-miral-debian-symbols + ``` + +## How to update miroil symbols + +### Scenario 1: Adding a new symbol +1. Make the additive change to the interface (e.g. by adding a new method + to an existing class) +2. If not already bumped in this release cycle, bump `MIROIL_VERSION_MINOR` + in `src/miroil/CMakeLists.txt` +3. If not already bumped in this release cycle, bump `MIROIL_ABI` in + `src/miroil/CMakeLists.txt` +4. From the root of the project, run: + ```sh + cmake --build build --target generate-miroil-symbols-map + ``` +5. Check that your new symbols is in the `symbols.map` file: + ```sh + git diff src/miroil/symbols.map + ``` + +### Scenario 2: Removing or changing a symbol +1. Make a destructive change to the interface (e.g. remove a parameter from + a method). +2. If not already bumped in this release cycle, bump `MIROIL_ABI`` + in `src/miroil/CMakeLists.txt`. Set `MIROIL_VERSION_MINOR` and `MIROIL_VERSION_PATCH` + to `0` +3. From the root of the project, run: + ```sh + cmake --build build --target generate-miral-symbols-map + ``` +4. Check that your symbols are reflected properly in the `symbols.map` file: + ```sh + git diff src/miral/symbols.map + ``` +5. Regenerate the debian symbols: + ```sh + cmake --build build --target regenerate-miroil-debian-symbols + ``` + +## How to update mirserver symbols map +### Scenario 1: Adding a new symbol +1. Make the additive change to the interface (e.g. by adding a new method + to an existing class) +2. If not already bumped in this release cycle, bump `MIR_VERSION_MINOR` + in `CMakeLists.txt` +3. If not already bumped in this release cycle, bump `MIRSERVER_ABI` in + `src/server/CMakeLists.txt` +4. From the root of the project, run: + ```sh + cmake --build build --target generate-mirserver-symbols-map + ``` +5. Check that your new symbols is in the `symbols.map` file: + ```sh + git diff src/server/symbols.map + ``` + +### Scenario 2: Removing or changing a symbol +1. Make a destructive change to the interface (e.g. remove a parameter from + a method). +2. If not already bumped in this release cycle, bump `MIR_VERSION_MAJOR` + in `CMakeLists.txt`. Set `MIR_VERSION_MINOR` and `MIR_VERSION_PATCH` + to `0` +3. If not already bumped in this release cycle, bump `MIRSERVER_ABI` in + `src/server/CMakeLists.txt` +4. From the root of the project, run: + ```sh + cmake --build build --target generate-mirserver-symbols-map + ``` +5. Check that your symbols are reflected properly in the `symbols.map` file: + ```sh + git diff src/server/symbols.map + ``` \ No newline at end of file diff --git a/doc/sphinx/how-to/index.md b/doc/sphinx/how-to/index.md index 5ad49116851..9a7bcd73787 100644 --- a/doc/sphinx/how-to/index.md +++ b/doc/sphinx/how-to/index.md @@ -18,4 +18,5 @@ how-to-use-checkbox-mir how-to-calibrate-a-touchscreen-device how-to-enable-graphics-core22-on-a-device how-to-test-mir-for-a-release +how-to-update-symbols-map ``` diff --git a/tools/symbols_map_generator/main.py b/tools/symbols_map_generator/main.py index cdb0d871d06..d0b5376df91 100755 --- a/tools/symbols_map_generator/main.py +++ b/tools/symbols_map_generator/main.py @@ -42,6 +42,10 @@ class LibraryInfo(TypedDict): map_file: str +def get_major_version_from_str(version: str) -> int: + return int(version.split('.')[0]) + + class Symbol: name: str version: str @@ -471,22 +475,31 @@ def main(): new_external_symbols = get_added_symbols(previous_symbols, external_symbols, False) new_internal_symbols = get_added_symbols(previous_symbols, internal_symbols, True) + next_major = get_major_version_from_str(version) next_version = f"{library.upper()}_{version}" next_internal_version = f"{library.upper()}_INTERNAL_{version}" data_to_output: OrderedDict[str, dict[str, list[str]]] = OrderedDict() # Remake the stanzas for the previous symbols for symbol in previous_symbols: - version = f"{library.upper()}_{symbol.version}" - if not version in data_to_output: - data_to_output[version] = { + major = get_major_version_from_str(symbol.version) + + # If we are going up by a major version, then we should add + # all existing symbols to the new stanza + if major == next_major: + symbol_version = f"{library.upper()}_{symbol.version}" + else: + symbol_version = f"{library.upper()}_{version}" + + if not symbol_version in data_to_output: + data_to_output[symbol_version] = { "c": [], "c++": [] } if symbol.is_c_symbol: - bisect.insort(data_to_output[version]["c"], symbol.name) + bisect.insort(data_to_output[symbol_version]["c"], symbol.name) else: - bisect.insort(data_to_output[version]["c++"], symbol.name) + bisect.insort(data_to_output[symbol_version]["c++"], symbol.name) # Add the external symbols for symbol in new_external_symbols: