2828 id : get_c_apps
2929 run : |
3030 python .github/workflows/scripts/get_c_apps.py ${{ secrets.GITHUB_TOKEN }}
31- echo "c_apps=$(cat c_apps.json)" >> $GITHUB_OUTPUT
31+ # PoC LTO: restrict to a small set of tier-1 apps to keep the matrix cheap.
32+ python - <<'PY'
33+ import json
34+
35+ REQUIRED_APPS = [
36+ "app-bitcoin-new",
37+ "app-ethereum",
38+ "app-solana",
39+ "app-exchange",
40+ ]
41+
42+ with open("c_apps.json", encoding="utf-8") as f:
43+ all_apps = json.load(f)
44+
45+ by_name = {a.get("app-name"): a for a in all_apps if isinstance(a, dict)}
46+ selected, missing = [], []
47+ for name in REQUIRED_APPS:
48+ app = by_name.get(name)
49+ if app is None:
50+ missing.append(name)
51+ else:
52+ selected.append(app)
53+
54+ if missing:
55+ raise SystemExit("Missing required apps in matrix source: " + ", ".join(missing))
56+
57+ with open("c_apps_limited.json", "w", encoding="utf-8") as f:
58+ json.dump(selected, f)
59+ PY
60+ echo "c_apps=$(cat c_apps_limited.json)" >> $GITHUB_OUTPUT
3261
3362 print-matrix :
3463 needs : [prepare-matrix]
@@ -45,18 +74,21 @@ jobs:
4574 fail-fast : false
4675 matrix :
4776 apps : ${{ fromJSON(needs.prepare-matrix.outputs.c_apps) }}
77+ # PoC LTO: same image & SDK ref for every config, only the make flags differ,
78+ # so size and (indicative) build-time deltas are attributable to LTO.
79+ config :
80+ - name : baseline
81+ make_flags : ' '
82+ - name : lto
83+ make_flags : ' ENABLE_LINK_TIME_OPTIMIZATION=1 ENABLE_STACK_PROTECTOR=0'
84+ - name : lto-sp
85+ make_flags : ' ENABLE_LINK_TIME_OPTIMIZATION=1 ENABLE_STACK_PROTECTOR=1'
4886 runs-on : ubuntu-latest
4987 container :
5088 image : ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
5189 defaults :
5290 run :
5391 shell : bash
54- env :
55- # Some C apps embed a Rust component pinned (via rust-toolchain.toml) to a
56- # toolchain that differs from the one the builder image exports through
57- # RUSTUP_TOOLCHAIN. A set RUSTUP_TOOLCHAIN overrides that pin and breaks
58- # the build, so it is unset before make for these apps (see build steps).
59- RUSTUP_TOOLCHAIN_UNSET_APPS : " app-namada app-stacks"
6092
6193 steps :
6294 - name : Clone App
@@ -69,48 +101,87 @@ jobs:
69101 uses : actions/checkout@v6
70102 with :
71103 path : sdk
72- ref : ${{ inputs.sdk_branch || github.head_ref }}
104+ ref : ${{ inputs.sdk_branch || 'mbr/lto' }}
73105
74106 - name : Install prerequisites
75107 run : pip install --break-system-packages ledgered
76108
77109 - name : Build App for Nano X
78110 if : contains(matrix.apps.devices, 'nanox')
79- run : |
80- cd ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
81- echo "Building for Nano X"
82- if [[ " $RUSTUP_TOOLCHAIN_UNSET_APPS " == *" ${{ matrix.apps.app-name }} "* ]]; then unset RUSTUP_TOOLCHAIN; fi
83- make clean
84- make TARGET=nanox BOLOS_SDK=$GITHUB_WORKSPACE/sdk
111+ run : bash "$GITHUB_WORKSPACE/sdk/.github/workflows/scripts/poc_lto_build_target.sh" nanox '${{ matrix.config.make_flags }}'
112+ working-directory : ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
113+ - name : Upload Nano X build
114+ if : always() && contains(matrix.apps.devices, 'nanox')
115+ uses : actions/upload-artifact@v4
116+ with :
117+ name : elf-${{ matrix.apps.app-name }}-nanox-${{ matrix.config.name }}
118+ path : poc_out/nanox
119+
85120 - name : Build App for Nano S+
86121 if : contains(matrix.apps.devices, 'nanos+')
87- run : |
88- cd ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
89- echo "Building for Nano S+"
90- if [[ " $RUSTUP_TOOLCHAIN_UNSET_APPS " == *" ${{ matrix.apps.app-name }} "* ]]; then unset RUSTUP_TOOLCHAIN; fi
91- make clean
92- make TARGET=nanos2 BOLOS_SDK=$GITHUB_WORKSPACE/sdk
122+ run : bash "$GITHUB_WORKSPACE/sdk/.github/workflows/scripts/poc_lto_build_target.sh" nanos2 '${{ matrix.config.make_flags }}'
123+ working-directory : ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
124+ - name : Upload Nano S+ build
125+ if : always() && contains(matrix.apps.devices, 'nanos+')
126+ uses : actions/upload-artifact@v4
127+ with :
128+ name : elf-${{ matrix.apps.app-name }}-nanos2-${{ matrix.config.name }}
129+ path : poc_out/nanos2
130+
93131 - name : Build App for Stax
94132 if : contains(matrix.apps.devices, 'stax')
95- run : |
96- cd ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
97- echo "Building for Stax"
98- if [[ " $RUSTUP_TOOLCHAIN_UNSET_APPS " == *" ${{ matrix.apps.app-name }} "* ]]; then unset RUSTUP_TOOLCHAIN; fi
99- make clean
100- make TARGET=stax BOLOS_SDK=$GITHUB_WORKSPACE/sdk
133+ run : bash "$GITHUB_WORKSPACE/sdk/.github/workflows/scripts/poc_lto_build_target.sh" stax '${{ matrix.config.make_flags }}'
134+ working-directory : ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
135+ - name : Upload Stax build
136+ if : always() && contains(matrix.apps.devices, 'stax')
137+ uses : actions/upload-artifact@v4
138+ with :
139+ name : elf-${{ matrix.apps.app-name }}-stax-${{ matrix.config.name }}
140+ path : poc_out/stax
141+
101142 - name : Build App for Flex
102143 if : contains(matrix.apps.devices, 'flex')
103- run : |
104- cd ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
105- echo "Building for Flex"
106- if [[ " $RUSTUP_TOOLCHAIN_UNSET_APPS " == *" ${{ matrix.apps.app-name }} "* ]]; then unset RUSTUP_TOOLCHAIN; fi
107- make clean
108- make TARGET=flex BOLOS_SDK=$GITHUB_WORKSPACE/sdk
144+ run : bash "$GITHUB_WORKSPACE/sdk/.github/workflows/scripts/poc_lto_build_target.sh" flex '${{ matrix.config.make_flags }}'
145+ working-directory : ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
146+ - name : Upload Flex build
147+ if : always() && contains(matrix.apps.devices, 'flex')
148+ uses : actions/upload-artifact@v4
149+ with :
150+ name : elf-${{ matrix.apps.app-name }}-flex-${{ matrix.config.name }}
151+ path : poc_out/flex
152+
109153 - name : Build App for Apex+
110154 if : contains(matrix.apps.devices, 'apex_p')
111- run : |
112- cd ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
113- echo "Building for Apex+"
114- if [[ " $RUSTUP_TOOLCHAIN_UNSET_APPS " == *" ${{ matrix.apps.app-name }} "* ]]; then unset RUSTUP_TOOLCHAIN; fi
115- make clean
116- make TARGET=apex_p BOLOS_SDK=$GITHUB_WORKSPACE/sdk
155+ run : bash "$GITHUB_WORKSPACE/sdk/.github/workflows/scripts/poc_lto_build_target.sh" apex_p '${{ matrix.config.make_flags }}'
156+ working-directory : ${{ matrix.apps.app-name }}/${{ matrix.apps.build-directory }}
157+ - name : Upload Apex+ build
158+ if : always() && contains(matrix.apps.devices, 'apex_p')
159+ uses : actions/upload-artifact@v4
160+ with :
161+ name : elf-${{ matrix.apps.app-name }}-apex_p-${{ matrix.config.name }}
162+ path : poc_out/apex_p
163+
164+ compare-builds :
165+ name : Compare builds (size & time)
166+ needs : [test-build]
167+ if : always()
168+ runs-on : ubuntu-latest
169+ steps :
170+ - name : Checkout repository
171+ uses : actions/checkout@v6
172+ - name : Download all artifacts
173+ uses : actions/download-artifact@v4
174+ with :
175+ pattern : elf-*-*-*
176+ path : downloaded_artifacts
177+ - name : Install dependencies
178+ run : sudo apt-get update && sudo apt-get install -y --no-install-recommends binutils
179+ - name : Build comparison tables
180+ run : python3 .github/workflows/scripts/poc_lto_compare.py downloaded_artifacts poc_lto.md
181+ - name : Publish to summary
182+ run : cat poc_lto.md >> $GITHUB_STEP_SUMMARY
183+ - name : Upload comparison
184+ uses : actions/upload-artifact@v4
185+ with :
186+ name : poc-lto-comparison
187+ path : poc_lto.md
0 commit comments