Skip to content

Commit

Permalink
docs: document describing how to update symbols map files + bugfix in…
Browse files Browse the repository at this point in the history
… the symbols generator for major versioning
  • Loading branch information
mattkae committed Jul 2, 2024
1 parent 6f465ad commit 62aafb9
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 5 deletions.
183 changes: 183 additions & 0 deletions doc/sphinx/how-to/how-to-update-symbols-map.md
Original file line number Diff line number Diff line change
@@ -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
```
1 change: 1 addition & 0 deletions doc/sphinx/how-to/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
23 changes: 18 additions & 5 deletions tools/symbols_map_generator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 62aafb9

Please sign in to comment.