Skip to content

Commit

Permalink
proof read
Browse files Browse the repository at this point in the history
  • Loading branch information
Muhmud Ahmad committed Jan 16, 2024
1 parent 61b16fd commit 3d4e2a6
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 64 deletions.
107 changes: 54 additions & 53 deletions BUILD_SYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ The build process works as follows:

1. If not already built, perform a build of `Thorvg` and it's native dependencies for the local machine architecture
2. For each target architecture, e.g. `aarch64-apple-darwin`, build `Thorvg` and, for Apple and Android targets, its native dependencies
3. Generate `uniffi` bindings for the target platform, i.e. Android, by building `uniffi-bindgen`. This relies on a local architecture build of Thorvg
3. Generate `uniffi` bindings for the target platform, e.g. Android, by first building `uniffi-bindgen`. This relies on a local architecture build of `Thorvg`
- For WASM, instead use `uniffi-bindgen-cpp` to generate C++ bindings
4. Build the Rust `dotlottie-player` library
5. Put together the final release artifacts for each platform, i.e. Android, Apple, etc. and populate the `release` directory

### Define blocks

`define` blocks act like functions and are used for various purposes, such as to dynamically create
sections of the Makefile, create output files, etc. The sections that follow following give details
sections of the Makefile, create output files, etc. The sections that follow provide details
of each of these blocks.

When these blocks are referenced, they will usually be called with a mixture of top-level make
variables and target specific ones. Examples of target-specific variables are as follows:
variables and target-specific variables. Examples of target-specific variables are as follows:

```
$(THORVG_LOCAL_ARCH_BUILD_DIR)/$(NINJA_BUILD_FILE): export PKG_CONFIG_PATH := $(PWD)/$(LOCAL_ARCH_LIB_DIR)/pkgconfig:$(PWD)/$(LOCAL_ARCH_LIB64_DIR)
Expand All @@ -30,42 +30,42 @@ $(THORVG_LOCAL_ARCH_BUILD_DIR)/$(NINJA_BUILD_FILE): THORVG_DEP_SOURCE_DIR := $(D

Both of these variables are being given values in the specific case of the build for
`$(THORVG_LOCAL_ARCH_BUILD_DIR)/$(NINJA_BUILD_FILE)`. In the first line, the value will
also be exported to the shell environment being running the make recipe. In the case of
the second, the variable value will only be visible within the context of the make file.
also be exported to the shell environment being running the associated make recipe. In the case of
the second line, the variable value will only be visible within the context of the make file.

#### Thorvg

These blocks are used to build the external dependencies for Thorvg, which are only performed
These blocks are used to build the external dependencies for `Thorvg`, which are only used
for Android and Apple build targets:

- `SETUP_CMAKE`: Perform a CMake setup for Thorvg's dependencies
- `ANDROID_CMAKE_TOOLCHAIN_FILE`: Creates a CMake Toolchain file used to build Thorvg's dependencies
- `CMAKE_BUILD`: Performs a CMake build as per a CMake specification
- `CMAKE_MAKE_BUILD`: Performs a make build as per a CMake specification
- `NEW_LOCAL_ARCH_CMAKE_BUILD`: Used to setup local architecture builds, i.e. for the local machine
- `NEW_ANDROID_CMAKE_BUILD`: Defines a CMake build for Thorvg dependencies for Android
- `NEW_APPLE_CMAKE_BUILD`: Defines a CMake build for Thorvg dependencies for Apple
- `SETUP_CMAKE`: Perform a CMake setup for `Thorvg`'s dependencies
- `ANDROID_CMAKE_TOOLCHAIN_FILE`: Creates a `CMake` Toolchain file used to build `Thorvg`'s dependencies
- `CMAKE_BUILD`: Performs a `CMake` build as per a `CMake` specification
- `CMAKE_MAKE_BUILD`: Performs a make build as per a `CMake` specification
- `NEW_LOCAL_ARCH_CMAKE_BUILD`: Used to setup local architecture builds, i.e. for the local build machine
- `NEW_ANDROID_CMAKE_BUILD`: Defines a `CMake` build for `Thorvg` dependencies for Android
- `NEW_APPLE_CMAKE_BUILD`: Defines a `CMake` build for `Thorvg` dependencies for Apple

These define blocks are used to setup Meson cross files for use with the Thorvg build. They are
The following define blocks are used to setup `Meson` cross files for use with the `Thorvg` build. They are
parameterized using Makefile variables, and their output is not yet written to file:

- `ANDROID_CROSS_FILE`: Defines an Android cross file to be used with Meson
- `APPLE_CROSS_FILE`: Defines an Apple cross file to be used with Meson
- `WASM_CROSS_FILE`: Defines an WASM cross file to be used with Meson
- `ANDROID_CROSS_FILE`: Defines an Android cross file to be used with `Meson`
- `APPLE_CROSS_FILE`: Defines an Apple cross file to be used with `Meson`
- `WASM_CROSS_FILE`: Defines an WASM cross file to be used with `Meson`

These blocks use the previous ones and output the result to a file:

- `NEW_ANDROID_CROSS_FILE`: Creates the Android cross file for use with Thorvg
- `NEW_APPLE_CROSS_FILE`: Creates the Apple cross file for use with Thorvg
- `NEW_WASM_CROSS_FILE`: Creates the WASM cross file for use with Thorvg
- `NEW_ANDROID_CROSS_FILE`: Creates an Android cross file for use with `Thorvg`
- `NEW_APPLE_CROSS_FILE`: Creates an Apple cross file for use with `Thorvg`
- `NEW_WASM_CROSS_FILE`: Creates a WASM cross file for use with `Thorvg`

The following blocks are used to build Thorvg:
The following blocks are used to build `Thorvg`:

- `SETUP_MESON`: Runs meson to setup a build using Ninja
- `NINJA_BUILD`: Performs a Ninja build, as per a Meson build specification
- `NEW_THORVG_BUILD`: Defines a new build of Thorvg
- `SETUP_MESON`: Runs `Meson` to setup a build using `Ninja`
- `NINJA_BUILD`: Performs a `Ninja` build, as per a `Meson` build specification
- `NEW_THORVG_BUILD`: Defines a new build of `Thorvg`

Finally, these blocks build on the previous ones to perform the builds for Thorvg and all of its
Finally, these blocks build on the previous ones to perform the builds for `Thorvg` and all of its
dependencies:

- `NEW_ANDROID_DEPS_BUILD`: Performs the native builds required for Android
Expand All @@ -74,9 +74,9 @@ dependencies:

#### Rust

Cargo is used to build `uniffi-bindgen` and the `dotlottie-player` library.
`Cargo` is used to build `uniffi-bindgen` and the `dotlottie-player` library:

- `CARGO_BUILD`: Performs a Cargo build for Rust code
- `CARGO_BUILD`: Performs a `Cargo` build for Rust code

The following blocks are used to create `uniffi` bindings:

Expand All @@ -98,46 +98,47 @@ For Apple, we must:

The following define blocks are used to achieve this:

- `LIPO_CREATE`: Used as part of the Apple release process
- `CREATE_FRAMEWORK`: Used as part of the Apple release process
- `LIPO_CREATE`: Creates a Lipo library artifacts
- `APPLE_MODULE_MAP_FILE`: Creates a Module Map file for an Apple release
- `CREATE_FRAMEWORK`: Creates a Framework
- `NEW_APPLE_FRAMEWORK`: Creates the Framework and XC Framework
- `APPLE_RELEASE`: Compiles the final artifacts for an Apple release

For WASM builds, we must compile the `uniffi-bindgen-cpp` generated bindings with the manually
maintained `emscripten` C++ bindings, along with the `dotlottie-player` rust library to build
the final release artifacts.

- `WASM_MESON_BUILD_FILE`: Creates the Meson file used to build the WASM release artifacts
- `SETUP_WASM_MESON`: Runs meson to setup a WASM build using Ninja
- `WASM_MESON_BUILD_FILE`: Creates the `Meson` file used to build the WASM release artifacts
- `SETUP_WASM_MESON`: Runs `Meson` to setup a WASM build using `Ninja`
- `WASM_RELEASE`: Compiles the final artifacts for a WASM release

#### Top-level

Each build operation heavily relies on Makefile variables, which help to reduce the amount of
duplication. The variables for each build target are setup using the following blocks:
Each build operation heavily relies on Makefile variables, which allows for build data to be defined
in a single place and reduces duplication. The variables for each build target are setup using the
following blocks:

- `NEW_BUILD_TARGET`: Defines to required make variables for a new target build
- `NEW_BUILD_TARGET`: Defines to required make variables for a new build target
- `NEW_APPLE_TARGET`: Defines additional variables required for Apple builds

These previous targets require access to the name of the target in SCREAMING_SNAKE case, in order
to simplify the definition of the new variables. This is achieved using the following blocks:
These previous blocks require access to the name of the target in SCREAMING_SNAKE case, in order
to aid in the definition of the new variables. This is achieved using the following blocks:

- `DEFINE_TARGET`: Simple helper function to define a new target
- `DEFINE_APPLE_TARGET`: Simple helper function to define a new apple target

After defining a target, the following top-level blocks define add necessary actions for a
After defining a target, the following top-level blocks perform all the necessary actions for a
particular build type:

- `NEW_ANDROID_BUILD`: Performs the builds Rust builds and release actions for Android
- `NEW_APPLE_BUILD`: Performs the builds Rust builds and release actions for Apple
- `NEW_WASM_BUILD`: Performs the builds Rust/C++ builds and release actions for WASM
- `NEW_ANDROID_BUILD`: Performs the Rust builds and release actions for Android
- `NEW_APPLE_BUILD`: Performs the Rust builds and release actions for Apple
- `NEW_WASM_BUILD`: Performs the Rust/C++ builds and release actions for WASM

#### Utilities

The following are general utility blocks:

- `TARGET_PREFIX`: Simple helper function to convert cucumber-case to SCREAMING_SNAKE
- `TARGET_PREFIX`: Simple helper function to convert `cucumber-case` to `SCREAMING_SNAKE`
- `CREATE_OUTPUT_FILE`: General utility to create an output file

### Delayed variable expansion
Expand All @@ -150,16 +151,16 @@ $2_THORVG_DEP_BUILD_DIR := $$($2_DEPS_BUILD_DIR)/$(THORVG)
```

This is for the purpose of using the block that contains this code with the make `eval` function, which
allows to dynamically create sections of the Makefile. This greatly reduces the amount of repetition in
allows for dynamically creating sections of the Makefile. This greatly reduces the amount of repetition in
the Makefile, and thus maintenance overhead, at the cost of a small amount of complexity.

When a `define` block is referenced, variables references contained within it are expanded, and
When a `define` block is called, variables references contained within it are expanded, and
this behaviour is usually what you would want to happen outside the context of `eval`. However, when
using `eval`, we may want certain variables to be expanded by eval instead.
using `eval`, we may want certain variables to be expanded later by `eval` instead.

In the example given above, we want `$2_THORVG_DEP_BUILD_DIR` to be expanded into the name of a variable
to be created. As `$2` in this case is defined as the SCREAMING_SNAKE_CASE version of the current target
architecture, and will be have a value such as `AARCH64_LINUX_ANDROID`, the line will be expanded to
architecture, and will be have a value such as `AARCH64_LINUX_ANDROID`, the line above will be expanded to
something like the following, _before_ being passed to `eval`:

```
Expand All @@ -178,19 +179,19 @@ result of the expansion without evaluting it, which can be useful for debugging.
### Submodule management

This repo uses git submodules for its external dependencies. Though these will normally be setup
for your by running `make mac-setup`, it can sometimes be useful to run `make deps` manually as
for you when running `make mac-setup`, it can sometimes be useful to run `make deps` manually as
well.

If the version of a submodule, such as for `Thorvg`, is updated, when you pull this change your
reference to the submodule would have been updated, however, your local clone of the submodule
would still be pointing to the old copy. To bring your local copy into line with the checked in
reference to the submodule will be updated, however, your local clone of the submodule
would still point to the old commit. To bring your local copy into line with the checked in
commit of the submodule, run `make deps`.

### Incremental builds

Performing a `make all` and building all possible targets can take a long time when performed from
scratch. However, after the initial build, the next `make all` build operation is significantly
faster, as all previous build files, such as for `Thorvg`, will be already available.
scratch. However, after the initial build, the next `make all` build operation will be significantly
faster, as all previous build files, such as for `Thorvg`, will already be available.

#### Cleanup

Expand All @@ -199,6 +200,6 @@ clean repo, and is usually not what you want to do. Run `make clean` instead to
build files. In most cases, this is also not required, and you can simply rebuild the target you are
working with to perform an incremental build.

There a small quirk with the `zlib` dependency build, which makes it submodule clone appear dirty
after a build. This does not cause any real problems, but can show up as an unncessary change by
git. If this bothers you, run `make clean-build`.
There a small quirk with the `zlib` dependency build, which makes its submodule clone appear dirty
after a build. This does not cause any real problems, but can show up in git as an unncessary change.
If this bothers you, run `make clean-build`.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Build Instructions

To build for all targets platforms, it would be best to use a Mac. You will also need GNU `make`
To build for all target platforms, it would be best to use a Mac. You will also need GNU `make`
installed, at a bare minimum. To ensure that your local machine has all the other necessary
tools installed to perform the builds, run the following from the root of the repo:
tools installed to build the project, run the following from the root of the repo:

```bash
$ make mac-setup
Expand All @@ -12,12 +12,12 @@ $ make mac-setup

Builds can be performed for the following groups of targets:

- android
- apple
- wasm
- `android`
- `apple`
- `WASM`

For `android` and `apple`, builds will be performed for all supported architectures, whereas
for `wasm`, only a single target will be built. These names refer to Makefile targets that can be
for `WASM`, only a single target will be built. These names refer to Makefile targets that can be
used to build them. For example, to build all `android` targets, execute the following:

```bash
Expand All @@ -44,11 +44,11 @@ $ make help

## Creating a Release

Manually execute the `Create Release PR` Github Action workflow to create a release PR. The will
include all changes since the last release. The repo uses [changesets](https://github.com/changesets/changesets) to determine the new release
version. The [knope](https://github.com/knope-dev/knope) tool can be installed locally and used to
simply the creation of changeset files.
Manually execute the `Create Release PR` Github Action workflow to create a release PR. This will
include all changes since the last release. This repo uses [changesets](https://github.com/changesets/changesets)
to determine the new release version. The [knope](https://github.com/knope-dev/knope) tool can be installed locally
and used to simply the creation of changeset files.

The created release PR should be checked for correctness and then merged. Once merged, the `Release`
The release PR should be checked for correctness and then merged. Once that is done, the `Release`
Github Actions workflow will be started automatically to do the work of actually creating the new
release and building & uploading the related release artifacts.

0 comments on commit 3d4e2a6

Please sign in to comment.