Skip to content

Commit 4639bc6

Browse files
committed
Support external manifest repositories
1 parent 0e7b987 commit 4639bc6

5 files changed

Lines changed: 119 additions & 18 deletions

File tree

.github/workflows/smoke.yml

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88

99
jobs:
1010
smoke:
11-
name: ${{ matrix.os }} / ${{ matrix.link_mode }}
11+
name: ${{ matrix.os }} / ${{ matrix.manifest_source }} / ${{ matrix.link_mode }}
1212
runs-on: ${{ matrix.os }}
1313
timeout-minutes: 20
1414
strategy:
@@ -21,6 +21,9 @@ jobs:
2121
- symlink
2222
- hardlink
2323
- copy
24+
manifest_source:
25+
- internal
26+
- external
2427
include:
2528
- os: ubuntu-latest
2629
native_build_arg: -j1
@@ -34,22 +37,39 @@ jobs:
3437
steps:
3538
- uses: actions/checkout@v6
3639

40+
- name: Checkout external manifests
41+
if: matrix.manifest_source == 'external'
42+
uses: actions/checkout@v6
43+
with:
44+
repository: AnastaZIuk/nam-smoke-manifests
45+
path: external-manifests
46+
3747
- name: Restore NAM cache
3848
uses: actions/cache@v5
3949
with:
4050
path: ${{ env.NAM_CACHE_ROOT }}
41-
key: nam-cache-${{ runner.os }}-${{ hashFiles('media/**/*.dvc') }}
51+
key: nam-cache-${{ runner.os }}-${{ matrix.manifest_source }}-${{ hashFiles('media/**/*.dvc', 'external-manifests/media/**/*.dvc') }}
4252
restore-keys: |
53+
nam-cache-${{ runner.os }}-${{ matrix.manifest_source }}-
4354
nam-cache-${{ runner.os }}-
4455
4556
- name: Configure smoke
4657
shell: pwsh
4758
run: |
4859
cmake -E rm -rf $env:SMOKE_BUILD_DIR
4960
cmake -E make_directory $env:NAM_CACHE_ROOT
50-
cmake -S smoke -B $env:SMOKE_BUILD_DIR `
51-
-DNAM_SMOKE_CACHE_ROOT="$env:NAM_CACHE_ROOT" `
52-
-DNAM_SMOKE_LINK_MODE=${{ matrix.link_mode }}
61+
$cmakeArgs = @(
62+
'-S', 'smoke',
63+
'-B', $env:SMOKE_BUILD_DIR,
64+
"-DNAM_SMOKE_CACHE_ROOT=$env:NAM_CACHE_ROOT",
65+
"-DNAM_SMOKE_LINK_MODE=${{ matrix.link_mode }}"
66+
)
67+
if ('${{ matrix.manifest_source }}' -eq 'external') {
68+
$cmakeArgs += "-DNAM_SMOKE_MANIFEST_ROOT=$env:GITHUB_WORKSPACE/external-manifests"
69+
$cmakeArgs += '-DNAM_SMOKE_REPO=AnastaZIuk/nam-smoke-manifests'
70+
$cmakeArgs += '-DNAM_SMOKE_TAG=media'
71+
}
72+
& cmake @cmakeArgs
5373
5474
- name: Build smoke
5575
shell: pwsh

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ At a high level this follows the same pattern used by mature package and artifac
4343
- `binaryTarget(url:, checksum:)` in `SwiftPM`
4444
- content-addressed external test data in `CMake ExternalData`, used by projects such as `VTK`
4545

46+
The same consumer module is also meant to stay reusable beyond Nabla itself.
47+
This repository is the first-party Nabla registry, but consumers can point the
48+
module at a different manifest checkout and a different `GitHub Release`
49+
channel without changing the build-graph model.
50+
4651
## Evidence
4752

4853
### Git History Pressure

cmake/NablaAssetManifests.cmake

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Consumer module for the Nabla-Asset-Manifests repository.
1+
# Consumer module with Nabla-Asset-Manifests defaults.
22
#
33
# Maintainer-side source of truth:
44
# - physical layout under channel roots such as `media/`
@@ -167,17 +167,30 @@ function(_nam_resolve_cache_root OUT_VAR)
167167
set(${OUT_VAR} "${_root}" PARENT_SCOPE)
168168
endfunction()
169169

170+
function(_nam_resolve_manifest_root OUT_VAR)
171+
set(options)
172+
set(oneValueArgs MANIFEST_ROOT)
173+
cmake_parse_arguments(NAM "${options}" "${oneValueArgs}" "" ${ARGN})
174+
175+
if (DEFINED NAM_MANIFEST_ROOT AND NOT "${NAM_MANIFEST_ROOT}" STREQUAL "")
176+
file(TO_CMAKE_PATH "${NAM_MANIFEST_ROOT}" _root)
177+
else()
178+
nam_get_repo_root(_root)
179+
endif()
180+
set(${OUT_VAR} "${_root}" PARENT_SCOPE)
181+
endfunction()
182+
170183
function(_nam_get_channel_root OUT_VAR)
171184
set(options)
172-
set(oneValueArgs CHANNEL)
185+
set(oneValueArgs CHANNEL MANIFEST_ROOT)
173186
cmake_parse_arguments(NAM "${options}" "${oneValueArgs}" "" ${ARGN})
174187

175188
if (NOT DEFINED NAM_CHANNEL OR "${NAM_CHANNEL}" STREQUAL "")
176189
set(NAM_CHANNEL "media")
177190
endif()
178191

179-
nam_get_repo_root(_repo_root)
180-
set(_channel_root "${_repo_root}/${NAM_CHANNEL}")
192+
_nam_resolve_manifest_root(_manifest_root MANIFEST_ROOT "${NAM_MANIFEST_ROOT}")
193+
set(_channel_root "${_manifest_root}/${NAM_CHANNEL}")
181194
if (NOT EXISTS "${_channel_root}")
182195
message(FATAL_ERROR "NablaAssetManifests: channel root `${_channel_root}` does not exist")
183196
endif()
@@ -186,14 +199,14 @@ endfunction()
186199

187200
function(_nam_parse_dvc_file)
188201
set(options)
189-
set(oneValueArgs DVC_FILE CHANNEL OUT_RELATIVE_PATH OUT_RELEASE_ASSET OUT_KEY)
202+
set(oneValueArgs DVC_FILE CHANNEL MANIFEST_ROOT OUT_RELATIVE_PATH OUT_RELEASE_ASSET OUT_KEY)
190203
cmake_parse_arguments(NAM "${options}" "${oneValueArgs}" "" ${ARGN})
191204

192205
if (NOT NAM_DVC_FILE)
193206
message(FATAL_ERROR "NablaAssetManifests: DVC_FILE is required")
194207
endif()
195208

196-
_nam_get_channel_root(_channel_root CHANNEL "${NAM_CHANNEL}")
209+
_nam_get_channel_root(_channel_root CHANNEL "${NAM_CHANNEL}" MANIFEST_ROOT "${NAM_MANIFEST_ROOT}")
197210
file(STRINGS "${NAM_DVC_FILE}" _lines)
198211

199212
set(_path "")
@@ -230,14 +243,14 @@ endfunction()
230243

231244
function(nam_get_channel_asset_keys OUT_VAR)
232245
set(options)
233-
set(oneValueArgs CHANNEL)
246+
set(oneValueArgs CHANNEL MANIFEST_ROOT)
234247
cmake_parse_arguments(NAM "${options}" "${oneValueArgs}" "" ${ARGN})
235248

236249
if (NOT DEFINED NAM_CHANNEL OR "${NAM_CHANNEL}" STREQUAL "")
237250
set(NAM_CHANNEL "media")
238251
endif()
239252

240-
_nam_get_channel_root(_channel_root CHANNEL "${NAM_CHANNEL}")
253+
_nam_get_channel_root(_channel_root CHANNEL "${NAM_CHANNEL}" MANIFEST_ROOT "${NAM_MANIFEST_ROOT}")
241254
file(GLOB_RECURSE _dvc_files "${_channel_root}/*.dvc")
242255
list(SORT _dvc_files)
243256

@@ -246,6 +259,7 @@ function(nam_get_channel_asset_keys OUT_VAR)
246259
_nam_parse_dvc_file(
247260
DVC_FILE "${_dvc}"
248261
CHANNEL "${NAM_CHANNEL}"
262+
MANIFEST_ROOT "${NAM_MANIFEST_ROOT}"
249263
OUT_RELATIVE_PATH _relative_path
250264
OUT_RELEASE_ASSET _release_asset
251265
OUT_KEY _key
@@ -257,7 +271,7 @@ endfunction()
257271

258272
function(_nam_find_channel_asset)
259273
set(options)
260-
set(oneValueArgs CHANNEL ASSET OUT_RELATIVE_PATH OUT_RELEASE_ASSET OUT_KEY)
274+
set(oneValueArgs CHANNEL MANIFEST_ROOT ASSET OUT_RELATIVE_PATH OUT_RELEASE_ASSET OUT_KEY)
261275
cmake_parse_arguments(NAM "${options}" "${oneValueArgs}" "" ${ARGN})
262276

263277
if (NOT DEFINED NAM_CHANNEL OR "${NAM_CHANNEL}" STREQUAL "")
@@ -267,7 +281,7 @@ function(_nam_find_channel_asset)
267281
message(FATAL_ERROR "NablaAssetManifests: ASSET is required")
268282
endif()
269283

270-
_nam_get_channel_root(_channel_root CHANNEL "${NAM_CHANNEL}")
284+
_nam_get_channel_root(_channel_root CHANNEL "${NAM_CHANNEL}" MANIFEST_ROOT "${NAM_MANIFEST_ROOT}")
271285
file(GLOB_RECURSE _dvc_files "${_channel_root}/*.dvc")
272286
list(SORT _dvc_files)
273287

@@ -276,6 +290,7 @@ function(_nam_find_channel_asset)
276290
_nam_parse_dvc_file(
277291
DVC_FILE "${_dvc}"
278292
CHANNEL "${NAM_CHANNEL}"
293+
MANIFEST_ROOT "${NAM_MANIFEST_ROOT}"
279294
OUT_RELATIVE_PATH _relative_path
280295
OUT_RELEASE_ASSET _release_asset
281296
OUT_KEY _key
@@ -427,7 +442,7 @@ endfunction()
427442

428443
function(nam_add_channel_target)
429444
set(options NO_SYMLINKS VERBOSE)
430-
set(oneValueArgs TARGET CHANNEL REPO TAG CACHE_ROOT DESTINATION_ROOT SHOW_PROGRESS)
445+
set(oneValueArgs TARGET CHANNEL MANIFEST_ROOT REPO TAG CACHE_ROOT DESTINATION_ROOT SHOW_PROGRESS)
431446
set(multiValueArgs ITEMS)
432447
cmake_parse_arguments(NAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
433448

@@ -450,17 +465,19 @@ function(nam_add_channel_target)
450465
set(NAM_SHOW_PROGRESS ON)
451466
endif()
452467

468+
_nam_resolve_manifest_root(_manifest_root MANIFEST_ROOT "${NAM_MANIFEST_ROOT}")
469+
453470
if (NAM_ITEMS)
454471
set(_items ${NAM_ITEMS})
455472
else()
456-
nam_get_channel_asset_keys(_items CHANNEL "${NAM_CHANNEL}")
473+
nam_get_channel_asset_keys(_items CHANNEL "${NAM_CHANNEL}" MANIFEST_ROOT "${_manifest_root}")
457474
endif()
458475

459476
list(LENGTH _items _item_count)
460477
_nam_get_backend_kind(_backend_kind)
461478
_nam_resolve_cache_root(_cache_root CACHE_ROOT "${NAM_CACHE_ROOT}")
462479
_nam_include_externaldata(_externaldata_provider)
463-
_nam_summary("configure channel target `${NAM_TARGET}`: channel=`${NAM_CHANNEL}`, repo=`${NAM_REPO}`, tag=`${NAM_TAG}`, backend=`${_backend_kind}`, externaldata=`${_externaldata_provider}`, cache_root=`${_cache_root}`, total=${_item_count}")
480+
_nam_summary("configure channel target `${NAM_TARGET}`: channel=`${NAM_CHANNEL}`, manifest_root=`${_manifest_root}`, repo=`${NAM_REPO}`, tag=`${NAM_TAG}`, backend=`${_backend_kind}`, externaldata=`${_externaldata_provider}`, cache_root=`${_cache_root}`, total=${_item_count}")
464481

465482
_nam_get_github_release_index_file(_index_file REPO "${NAM_REPO}" TAG "${NAM_TAG}" CACHE_ROOT "${NAM_CACHE_ROOT}")
466483

@@ -495,6 +512,7 @@ function(nam_add_channel_target)
495512
foreach(_asset IN LISTS _items)
496513
_nam_find_channel_asset(
497514
CHANNEL "${NAM_CHANNEL}"
515+
MANIFEST_ROOT "${_manifest_root}"
498516
ASSET "${_asset}"
499517
OUT_RELATIVE_PATH _relative_path
500518
OUT_RELEASE_ASSET _release_asset

cmake/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ include("${asset_manifests_repo}/nam.cmake")
4141
nam_add_channel_target(
4242
TARGET media
4343
CHANNEL media
44+
MANIFEST_ROOT "${asset_manifests_repo}"
4445
REPO Devsh-Graphics-Programming/Nabla-Asset-Manifests
4546
TAG media
4647
DESTINATION_ROOT "${CMAKE_CURRENT_BINARY_DIR}"
@@ -54,6 +55,7 @@ nam_add_channel_target(
5455
## Default arguments
5556

5657
- `CHANNEL = media`
58+
- `MANIFEST_ROOT = <root of the repository that provides nam.cmake>`
5759
- `REPO = Devsh-Graphics-Programming/Nabla-Asset-Manifests`
5860
- `TAG = media`
5961
- `DESTINATION_ROOT = ${CMAKE_CURRENT_BINARY_DIR}`
@@ -63,6 +65,42 @@ nam_add_channel_target(
6365
- `NO_SYMLINKS = OFF`
6466
- `VERBOSE = OFF`
6567

68+
## Custom manifest repository
69+
70+
The consumer module can also read manifests from a different local checkout
71+
while still reusing the same public `nam_add_channel_target(...)` entrypoint.
72+
73+
Typical setup:
74+
75+
- add this repository as a submodule or vendor it some other way so
76+
`nam.cmake` stays available locally
77+
- checkout a second repository that contains a compatible channel tree with
78+
`.dvc` files
79+
- publish the corresponding payloads from that second repository as a
80+
`GitHub Release`
81+
82+
Example:
83+
84+
```cmake
85+
include("${nam_module_repo}/nam.cmake")
86+
87+
nam_add_channel_target(
88+
TARGET custom_media
89+
MANIFEST_ROOT "${custom_manifest_repo}"
90+
CHANNEL media
91+
REPO my-user/my-manifests
92+
TAG media
93+
DESTINATION_ROOT "${CMAKE_CURRENT_BINARY_DIR}"
94+
)
95+
```
96+
97+
Current scope stays intentionally small:
98+
99+
- manifest discovery can come from a different local repository via
100+
`MANIFEST_ROOT`
101+
- remote payload resolution still uses `GitHub Release assets` only
102+
- the built-in Nabla defaults remain unchanged when `MANIFEST_ROOT` is omitted
103+
66104
`<ENTRY>` resolves per platform:
67105

68106
- Windows: `%LOCALAPPDATA%`
@@ -195,6 +233,10 @@ Its local options are:
195233

196234
- `NAM_SMOKE_LINK_MODE = auto|symlink|hardlink|copy`
197235
- `NAM_SMOKE_CACHE_ROOT = <path>`
236+
- `NAM_SMOKE_MANIFEST_ROOT = <path>`
237+
- `NAM_SMOKE_REPO = <owner>/<repo>`
238+
- `NAM_SMOKE_TAG = <release-tag>`
239+
- `NAM_SMOKE_CHANNEL = <channel>`
198240
- `NAM_SMOKE_NO_SYMLINKS = ON|OFF`
199241

200242
Those options are for smoke verification only. They are not part of the public

smoke/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ option(NAM_SMOKE_NO_SYMLINKS "Force copy materialization in the smoke consumer."
77
set(NAM_SMOKE_LINK_MODE "auto" CACHE STRING "Smoke materialization mode override.")
88
set_property(CACHE NAM_SMOKE_LINK_MODE PROPERTY STRINGS auto symlink hardlink copy)
99
set(NAM_SMOKE_CACHE_ROOT "" CACHE PATH "Shared cache root for smoke runs.")
10+
set(NAM_SMOKE_MANIFEST_ROOT "" CACHE PATH "Manifest root override for smoke runs.")
11+
set(NAM_SMOKE_REPO "" CACHE STRING "GitHub repository override for smoke runs.")
12+
set(NAM_SMOKE_TAG "" CACHE STRING "Release tag override for smoke runs.")
13+
set(NAM_SMOKE_CHANNEL "media" CACHE STRING "Channel override for smoke runs.")
1014

1115
string(TOLOWER "${NAM_SMOKE_LINK_MODE}" _nam_smoke_link_mode)
1216
if (
@@ -30,6 +34,18 @@ set(_nam_extra_args)
3034
if (NAM_SMOKE_CACHE_ROOT)
3135
list(APPEND _nam_extra_args CACHE_ROOT "${NAM_SMOKE_CACHE_ROOT}")
3236
endif()
37+
if (NAM_SMOKE_MANIFEST_ROOT)
38+
list(APPEND _nam_extra_args MANIFEST_ROOT "${NAM_SMOKE_MANIFEST_ROOT}")
39+
endif()
40+
if (NAM_SMOKE_REPO)
41+
list(APPEND _nam_extra_args REPO "${NAM_SMOKE_REPO}")
42+
endif()
43+
if (NAM_SMOKE_TAG)
44+
list(APPEND _nam_extra_args TAG "${NAM_SMOKE_TAG}")
45+
endif()
46+
if (NAM_SMOKE_CHANNEL)
47+
list(APPEND _nam_extra_args CHANNEL "${NAM_SMOKE_CHANNEL}")
48+
endif()
3349

3450
unset(NAM_INTERNAL_FORCE_FILE_LINK_MODE)
3551
if (_nam_smoke_link_mode STREQUAL "copy" OR NAM_SMOKE_NO_SYMLINKS)

0 commit comments

Comments
 (0)