Skip to content

Commit aa256d5

Browse files
authored
Exposes cache ids as ARGs in +RUN_WITH_CACHE (#32)
Exposes cache ids as ARGs in `+RUN_WITH_CACHE`, this enables running different commands on the cache mounts of choice. Additionally: - Stores INIT config as ENV entries, simplifying previous approach - Adds new section "Mount caches and parallelization" to the documentation
1 parent 4bc404d commit aa256d5

File tree

2 files changed

+61
-32
lines changed

2 files changed

+61
-32
lines changed

rust/Earthfile

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
VERSION --global-cache 0.7
22

3-
# INIT installs some required dependencies and stores in the filesystem the configuration that will be available for the rest of functions.
4-
# - cache_id: Overrides default ID of the global $CARGO_HOME cache. Its value is exported to the build environment under the entry: $CARGO_HOME_CACHE_ID
3+
# INIT stores the configuration required for the other functions in the filesystem, and installs required dependencies.
4+
# - cache_id: Overrides default ID of the global $CARGO_HOME cache. Its value is exported to the build environment under the entry: $EARTHLY_CARGO_HOME_CACHE_ID
55
# - keep_fingerprints (false): Instructs the following +CARGO calls to don't remove the Cargo fingerprints of the source packages. Use only when source packages have been COPYed with --keep-ts option.
66
# - sweep_days (4): +CARGO uses cargo-sweep to clean build artifacts that haven't been accessed for this number of days.
77
INIT:
88
COMMAND
9-
RUN if [ -f /tmp/earthly/cfg/cache_id ]; then \
9+
RUN if [ -n "$EARTHLY_CARGO_HOME_CACHE_ID" ]; then \
1010
echo "+INIT has already been called in this build environment" ; \
1111
exit 1; \
1212
fi
@@ -19,38 +19,34 @@ INIT:
1919
DO +INSTALL_CARGO_SWEEP
2020
RUN mkdir -p /tmp/earthly/cfg
2121

22-
# cache_id
22+
# EARTHLY_CARGO_HOME_CACHE_ID
2323
ARG EARTHLY_TARGET_PROJECT_NO_TAG
2424
ARG OS_RELEASE=$(md5sum /etc/os-release | cut -d ' ' -f 1)
25-
ARG cache_id="${EARTHLY_TARGET_PROJECT_NO_TAG}#${OS_RELEASE}#earthly-cargo-cache"
26-
RUN echo "$cache_id">/tmp/earthly/cfg/cache_id
27-
ENV CARGO_HOME_CACHE_ID=$cache_id
25+
ENV EARTHLY_CARGO_HOME_CACHE_ID="${EARTHLY_TARGET_PROJECT_NO_TAG}#${OS_RELEASE}#earthly-cargo-cache"
2826

29-
#keep_fingerprints
27+
# $EARTHLY_KEEP_FINGERPRINTS
3028
ARG keep_fingerprints=false
31-
RUN echo "$keep_fingerprints">/tmp/earthly/cfg/keep_fingerprints
29+
ENV EARTHLY_KEEP_FINGERPRINTS=$keep_fingerprints
3230

33-
#sweep_days
31+
# $EARTHLY_SWEEP_DAYS
3432
ARG sweep_days=4
35-
RUN echo "$sweep_days">/tmp/earthly/cfg/sweep_days
33+
ENV EARTHLY_SWEEP_DAYS=$sweep_days
3634

3735
# CARGO runs the cargo command "cargo $args".
3836
# This function is thread safe. Parallel builds of targets calling this function should be free of race conditions.
3937
# Notice that in order to run this function, +INIT must be called first.
4038
# Arguments:
4139
# - args: Cargo subcommand and its arguments. Required.
42-
# - output: Regex to match the files within the target folder to be copied from the cache to the caller filesystem (image layers).
40+
# - output: Regex matching output artifacts files to be copied to ./target folder in the caller filesystem (image layers).
4341
# Use this argument when you want to SAVE an ARTIFACT from the target folder (mounted cache), always trying to minimize the total size of the copied fileset.
4442
# For example --output="release/[^\./]+" would keep all the files in /target/release that don't have any extension.
4543
CARGO:
4644
COMMAND
4745
DO +CHECK_INITED
4846
ARG --required args
49-
ARG keep_fingerprints=$(cat /tmp/earthly/cfg/keep_fingerprints)
50-
ARG sweep_days=$(cat /tmp/earthly/cfg/sweep_days)
5147
ARG output
5248
ARG TMP_FOLDER="/tmp/earthly/lib/rust"
53-
IF [ "$keep_fingerprints" = "false" ]
49+
IF [ "$EARTHLY_KEEP_FINGERPRINTS" = "false" ]
5450
DO +REMOVE_SOURCE_FINGERPRINTS
5551
END
5652
DO +RUN_WITH_CACHE --command="set -e;
@@ -63,8 +59,8 @@ CARGO:
6359
find . -type f -regextype posix-egrep -regex \"./$output\" -exec cp --parents \{\} $TMP_FOLDER \; ;
6460
cd ..;
6561
fi;
66-
echo \"Running cargo sweep -r -t $sweep_days\" ;
67-
cargo sweep -r -t $sweep_days;
62+
echo \"Running cargo sweep -r -t $EARTHLY_SWEEP_DAYS\" ;
63+
cargo sweep -r -t $EARTHLY_SWEEP_DAYS;
6864
echo \"Running cargo sweep -r -i\" ;
6965
cargo sweep -r -i;"
7066
IF [ "$output" != "" ]
@@ -73,33 +69,37 @@ CARGO:
7369
END
7470

7571
# RUN_WITH_CACHE runs the passed command with the CARGO caches mounted.
76-
# Notice that in order to run this function, +INIT must be called first.
72+
# Notice that in order to run this function, +INIT must be called first. This function exports the target cache mount ID under the env entry: $TARGET_CACHE_ID.
7773
# Arguments:
7874
# - command (required): Command to run, can be any expression.
75+
# - cargo_home_cache_id: ID of the cargo home cache mount. By default: $CARGO_HOME_CACHE_ID as exported by +INIT
76+
# - target_cache_id: ID of the target cache mount. By default: ${CARGO_HOME_CACHE_ID}#${EARTHLY_TARGET_NAME}
7977
#
8078
RUN_WITH_CACHE:
8179
COMMAND
8280
DO +CHECK_INITED
83-
ARG EARTHLY_TARGET_NAME
8481
ARG --required command
85-
ARG cache_id = $(cat /tmp/earthly/cfg/cache_id)
82+
ARG EARTHLY_TARGET_NAME
83+
ARG cargo_home_cache_id = $CARGO_HOME_CACHE_ID
84+
ARG target_cache_id="${CARGO_HOME_CACHE_ID}#${EARTHLY_TARGET_NAME}"
8685
# Save to restore at the end.
8786
ARG ORIGINAL_CARGO_HOME=$CARGO_HOME
8887
ARG ORIGINAL_CARGO_INSTALL_ROOT=$CARGO_INSTALL_ROOT
89-
# Make sure that crates installed though this function are stored in the original cargo home, and not in the cargo home within the mount cache.
88+
# Make sure that crates installed through this function are stored in the original cargo home, and not in the cargo home within the mount cache.
9089
# This way, if BK garbage-collects them, the build is not broken.
9190
ENV CARGO_INSTALL_ROOT=$ORIGINAL_CARGO_HOME
9291
# We change $CARGO_HOME while keeping $ORIGINAL_CARGO_HOME/bin directory in the path. This way, the Cargo binary is still accessible and the whole $CARGO_HOME is within the global cache
9392
# ($CARGO_HOME/.package-cache has to be in the cache so Cargo can properly synchronize parallel access to $CARGO_HOME resources).
9493
ENV CARGO_HOME="/tmp/earthly/.cargo"
95-
RUN --mount=type=cache,mode=0777,id=$cache_id,sharing=shared,target=$CARGO_HOME \
96-
--mount=type=cache,mode=0777,id="${cache_id}#${EARTHLY_TARGET_NAME}",target=target \
94+
RUN --mount=type=cache,mode=0777,id=$cargo_home_cache_id,sharing=shared,target=$CARGO_HOME \
95+
--mount=type=cache,mode=0777,id=$target_cache_id,sharing=locked,target=target \
9796
set -e; \
9897
mkdir -p $CARGO_HOME; \
9998
printf "Running:\n $command\n"; \
10099
eval $command
101100
ENV CARGO_HOME=$ORIGINAL_CARGO_HOME
102101
ENV CARGO_INSTALL_ROOT=$ORIGINAL_CARGO_INSTALL_ROOT
102+
ENV TARGET_CACHE_ID=$target_cache_id
103103

104104
get-tomljson:
105105
FROM alpine:3.18.3
@@ -143,7 +143,7 @@ REMOVE_SOURCE_FINGERPRINTS:
143143

144144
CHECK_INITED:
145145
COMMAND
146-
RUN if [ ! -f /tmp/earthly/cfg/cache_id ]; then \
146+
RUN if [ ! -n "$EARTHLY_CARGO_HOME_CACHE_ID" ]; then \
147147
echo "+INIT has not been called yet in this build environment" ; \
148148
exit 1; \
149-
fi;
149+
fi;

rust/README.md

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ IMPORT github.com/earthly/lib/rust:<version/commit> AS rust
1313

1414
This function stores the configuration required by the other functions in the build environment filesystem, and installs required dependencies.
1515

16-
It must be called once per build environment, to avoid passing repetitive arguments to the functions called after it, and to install required dependencies before the source files are copied from the build context.
16+
It must be called once per build environment, to avoid passing repetitive arguments to the functions called after it, and to install required dependencies before the source files are copied from the build context.
1717

1818
### Usage
1919

@@ -24,7 +24,7 @@ DO rust+INIT ...
2424

2525
### Arguments
2626
#### `cache_id`
27-
Overrides default ID of the global `$CARGO_HOME` cache. Its value is exported to the build environment under the entry: `$CARGO_HOME_CACHE_ID`.
27+
Overrides default ID of the global `$CARGO_HOME` cache. Its value is exported to the build environment under the entry: `$EARTHLY_CARGO_HOME_CACHE_ID`.
2828

2929
#### `keep_fingerprints (false)`
3030
Instructs the following `+CARGO` calls to don't remove the Cargo fingerprints of the source packages. Use only when source packages have been COPYed with `--keep-ts `option.
@@ -36,7 +36,7 @@ By default, this function removes the fingerprints of the packages found in the
3636

3737
## +CARGO
3838

39-
This function runs the cargo command `cargo $args` caching the contents of `$CARGO_HOME` and `target` for future builds of the same calling target.
39+
This function runs the cargo command `cargo $args` caching the contents of `$CARGO_HOME` and `target` for future builds of the same calling target. See #mount-caches-and-parallelization below for more details.
4040

4141
Notice that in order to run this function, [+INIT](#init) must be called first.
4242

@@ -53,9 +53,9 @@ DO rust+CARGO ...
5353
Cargo subcommand and its arguments. Required.
5454

5555
#### `output`
56-
Regex to match the files within the target folder to be copied from the cache to the caller filesystem (image layers).
56+
Regex to match the files within the target folder to be copied from the cache to the caller filesystem (image layers).
5757

58-
Use this argument when you want to `SAVE ARTIFACT` from the target folder (mounted cache), always trying to minimize the total size of the copied fileset.
58+
Use this argument when you want to `SAVE ARTIFACT` from the target folder (mounted cache), always trying to minimize the total size of the copied fileset.
5959

6060
For example `--output="release/[^\./]+"` would keep all the files in `/target/release` that don't have any extension.
6161

@@ -66,12 +66,18 @@ This function is thread safe. Parallel builds of targets calling this function s
6666

6767
`+RUN_WITH_CACHE` runs the passed command with the CARGO caches mounted.
6868

69-
Notice that in order to run this function, [+INIT](#init) must be called first.
69+
Notice that in order to run this function, [+INIT](#init) must be called first. This function exports the target cache mount ID under the env entry: `$TARGET_CACHE_ID`.
7070

7171
### Arguments
72-
#### `command (required)`
72+
#### `command (required)`
7373
Command to run, can be any expression.
7474

75+
#### `cargo_home_cache_id`
76+
ID of the cargo home cache mount. By default: `$CARGO_HOME_CACHE_ID` as exported by `+INIT`
77+
78+
#### `target_cache_id`
79+
ID of the target cache mount. By default: `${CARGO_HOME_CACHE_ID}#${EARTHLY_TARGET_NAME}`
80+
7581
### Example
7682
Show `$CARGO_HOME` cached-entries size:
7783

@@ -148,4 +154,27 @@ lint:
148154
check-dependencies:
149155
FROM +source
150156
DO rust+CARGO --args="deny --all-features check --deny warnings bans license sources"
157+
158+
# all runs all other targets in parallel
159+
all:
160+
BUILD +lint
161+
BUILD +build
162+
BUILD +test
163+
BUILD +fmt
164+
BUILD +check-dependencies
151165
```
166+
167+
## Mount caches and parallelization
168+
169+
This library uses several mount caches per tuple of `{project, os_release}`:
170+
- One cache mount for `$CARGO_HOME`, shared across all target builds without any locking involved.
171+
- A family of locked cache mounts for `$CARGO_TARGET_DIR`. One per target.
172+
173+
Notice that:
174+
- the previous targets builds might belong to one or multiple Earthly builds.
175+
- builds will only be blocked by concurrent ones of the same target
176+
177+
For example, running `earthly +all` in the previous example will:
178+
- run all targets (`+lint,+build,+test,+fmt,+check-dependencies`) in parallel without any blocking involved
179+
- use a common cache mount for `$CARGO_HOME`
180+
- use one individual `$CARGO_TARGET_DIR` cache mount per target

0 commit comments

Comments
 (0)