Skip to content

Commit 969dd42

Browse files
feat: add RECURSE option for subdirectory scanning
1 parent 28db818 commit 969dd42

5 files changed

Lines changed: 80 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
### Added
66

7-
- NIL
7+
- `RECURSE` option for `nfx_embed_resources()` to enable recursive subdirectory scanning
8+
- Automatic relative path preservation for resources in subdirectories when `RECURSE` is enabled
9+
- Optional 4th parameter for resource generator CLI to specify custom resource names
810

911
### Changed
1012

11-
- NIL
13+
- Resource naming: with `RECURSE`, resources now use relative paths (e.g., `"shaders/vertex.glsl"`) instead of just filenames
14+
- Pattern handling: `RECURSE` mode uses `**` glob patterns to properly match files in subdirectories
1215

1316
### Deprecated
1417

README.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ nfx_embed_resources(
320320
NAMESPACE <namespace>
321321
REGISTRY_NAME <registry_name>
322322
[PATTERN pattern1 pattern2 ...]
323+
[RECURSE]
323324
)
324325
```
325326

@@ -330,6 +331,7 @@ nfx_embed_resources(
330331
- `NAMESPACE` - C++ namespace (supports nested namespaces like `my::app::resources`)
331332
- `REGISTRY_NAME` - Name for generated files (creates `<name>.h` and `<name>.cpp`)
332333
- `PATTERN` - Optional file glob patterns (default: `*` for all files)
334+
- `RECURSE` - Optional flag to enable recursive subdirectory scanning
333335

334336
**Generated Functions:**
335337

@@ -359,12 +361,37 @@ nfx_embed_resources(
359361
```
360362

361363
This will:
362-
1. Scan `${CMAKE_SOURCE_DIR}/assets` for files matching the patterns
364+
1. Scan `${CMAKE_SOURCE_DIR}/assets` for files matching the patterns (current directory only)
363365
2. Generate `assets.h` and `assets.cpp` in `${CMAKE_BINARY_DIR}/generated`
364366
3. Create `myapp::assets::all()` and `myapp::assets::find()` functions
365367
4. Add generated files to the `myapp` target
366368
5. Include directory automatically added so you can `#include <assets.h>`
367369

370+
**Example with Recursive Scanning:**
371+
372+
```cmake
373+
nfx_embed_resources(
374+
TARGET myapp
375+
RESOURCE_DIR "${CMAKE_SOURCE_DIR}/assets"
376+
OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated"
377+
NAMESPACE "myapp::assets"
378+
REGISTRY_NAME "assets"
379+
PATTERN "*.json" "*.xml" "*.png"
380+
RECURSE # Scan subdirectories recursively
381+
)
382+
```
383+
384+
With `RECURSE`, resources in subdirectories are named with their relative paths:
385+
- `assets/config.json` → resource name: `"config.json"`
386+
- `assets/shaders/vertex.glsl` → resource name: `"shaders/vertex.glsl"`
387+
- `assets/textures/ui/icon.png` → resource name: `"textures/ui/icon.png"`
388+
389+
```cpp
390+
// Find resources by their relative paths
391+
auto* shader = myapp::assets::find("shaders/vertex.glsl");
392+
auto* icon = myapp::assets::find("textures/ui/icon.png");
393+
```
394+
368395
## Project Structure
369396

370397
```
@@ -466,13 +493,17 @@ nfx_embed_resources(
466493
NAMESPACE "myapp::shaders"
467494
REGISTRY_NAME "shaders"
468495
PATTERN "*.glsl" "*.hlsl"
496+
RECURSE # Include shaders from subdirectories
469497
)
470498
```
471499

472500
Then include the appropriate headers:
473501
```cpp
474502
#include <config.h> // Includes nfx::Resource, provides myapp::config::find()
475503
#include <shaders.h> // Includes nfx::Resource, provides myapp::shaders::find()
504+
505+
// Access shader with subdirectory path
506+
auto* vertShader = myapp::shaders::find("pbr/vertex.glsl");
476507
```
477508

478509
### Custom Resource Registry
@@ -515,4 +546,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
515546
516547
---
517548
518-
_Updated on January 22, 2026_
549+
_Updated on January 25, 2026_

cmake/nfxResourceFunctions.cmake

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function(nfx_embed_resources)
66
cmake_parse_arguments(
77
PARSE_ARGV 0
88
ARG
9-
""
9+
"RECURSE"
1010
"TARGET;RESOURCE_DIR;OUTPUT_DIR;NAMESPACE;REGISTRY_NAME"
1111
"PATTERN"
1212
)
@@ -36,10 +36,20 @@ function(nfx_embed_resources)
3636

3737
set(GLOB_PATTERNS "")
3838
foreach(PATTERN ${FILE_PATTERN})
39-
list(APPEND GLOB_PATTERNS "${ARG_RESOURCE_DIR}/${PATTERN}")
39+
if(ARG_RECURSE)
40+
# For recursive search, use ** to match subdirectories
41+
list(APPEND GLOB_PATTERNS "${ARG_RESOURCE_DIR}/**/${PATTERN}")
42+
else()
43+
list(APPEND GLOB_PATTERNS "${ARG_RESOURCE_DIR}/${PATTERN}")
44+
endif()
4045
endforeach()
4146

42-
file(GLOB RESOURCE_FILES CONFIGURE_DEPENDS ${GLOB_PATTERNS})
47+
# Use GLOB_RECURSE if RECURSE option is set
48+
if(ARG_RECURSE)
49+
file(GLOB_RECURSE RESOURCE_FILES CONFIGURE_DEPENDS ${GLOB_PATTERNS})
50+
else()
51+
file(GLOB RESOURCE_FILES CONFIGURE_DEPENDS ${GLOB_PATTERNS})
52+
endif()
4353

4454
if(NOT RESOURCE_FILES)
4555
message(WARNING "No resources found in ${ARG_RESOURCE_DIR} matching: ${FILE_PATTERN}")
@@ -52,13 +62,23 @@ function(nfx_embed_resources)
5262
set(ALL_IDS "")
5363

5464
foreach(RESOURCE_FILE ${RESOURCE_FILES})
55-
get_filename_component(RESOURCE_NAME "${RESOURCE_FILE}" NAME)
56-
string(MAKE_C_IDENTIFIER "${RESOURCE_NAME}" RESOURCE_ID)
65+
# Get resource name (relative path for RECURSE, just filename otherwise)
66+
if(ARG_RECURSE)
67+
file(RELATIVE_PATH RESOURCE_NAME "${ARG_RESOURCE_DIR}" "${RESOURCE_FILE}")
68+
# Convert path separators to underscores for unique identifier
69+
string(REPLACE "/" "_" RESOURCE_ID_BASE "${RESOURCE_NAME}")
70+
string(MAKE_C_IDENTIFIER "${RESOURCE_ID_BASE}" RESOURCE_ID)
71+
else()
72+
get_filename_component(RESOURCE_NAME "${RESOURCE_FILE}" NAME)
73+
string(MAKE_C_IDENTIFIER "${RESOURCE_NAME}" RESOURCE_ID)
74+
endif()
75+
5776
set(OUTPUT_CPP "${ARG_OUTPUT_DIR}/resource_${RESOURCE_ID}.cpp")
5877

78+
# Pass the resource name explicitly to maintain path information
5979
add_custom_command(
6080
OUTPUT "${OUTPUT_CPP}"
61-
COMMAND $<TARGET_FILE:nfx-resourcegenerator-cli> "${RESOURCE_FILE}" "${OUTPUT_CPP}" "${ARG_NAMESPACE}"
81+
COMMAND $<TARGET_FILE:nfx-resourcegenerator-cli> "${RESOURCE_FILE}" "${OUTPUT_CPP}" "${ARG_NAMESPACE}" "${RESOURCE_NAME}"
6282
DEPENDS "${RESOURCE_FILE}" nfx-resourcegenerator-cli
6383
COMMENT "Embedding: ${RESOURCE_NAME}"
6484
VERBATIM

cmake/nfxResourceTarget.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ add_executable(nfx-resourcegenerator-cli
1212
set_target_properties(nfx-resourcegenerator-cli PROPERTIES
1313
CXX_STANDARD 20
1414
CXX_STANDARD_REQUIRED ON
15-
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
15+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
1616
)
1717
add_executable(nfx::resourcegen ALIAS nfx-resourcegenerator-cli)
1818

src/resourcefenerator-cli.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,26 +248,28 @@ bool generateCppFile(
248248
*
249249
* @details This tool converts binary files into C++ source files containing
250250
* byte arrays. The generated code is placed in a specified namespace.
251-
* The identifier and filename are automatically derived from the input path.
251+
* The identifier is automatically derived from the input path, but
252+
* the resource name can be explicitly specified.
252253
*
253-
* @param argc Argument count (must be 4)
254+
* @param argc Argument count (must be 4 or 5)
254255
* @param argv Command-line arguments:
255-
* [1] input_file - Path to the binary file to embed
256-
* [2] output_cpp - Path for the generated .cpp file
257-
* [3] namespace - C++ namespace for the generated code
256+
* [1] input_file - Path to the binary file to embed
257+
* [2] output_cpp - Path for the generated .cpp file
258+
* [3] namespace - C++ namespace for the generated code
259+
* [4] resource_name (optional) - Name for the resource (defaults to filename)
258260
*
259261
* @return 0 on success, 1 on error
260262
*
261263
* Generated code structure:
262264
* - {identifier}_data: const uint8_t array containing the binary data
263265
* - {identifier}_size: const size_t containing the data size
264-
* - {identifier}_name: const char array containing the filename
266+
* - {identifier}_name: const char array containing the resource name
265267
*/
266268
int main( int argc, char* argv[] )
267269
{
268-
if( argc != 4 )
270+
if( argc != 4 && argc != 5 )
269271
{
270-
std::cerr << "Usage: " << argv[0] << " <input_file> <output_cpp> <namespace>\n";
272+
std::cerr << "Usage: " << argv[0] << " <input_file> <output_cpp> <namespace> [resource_name]\n";
271273
return 1;
272274
}
273275

@@ -294,12 +296,13 @@ int main( int argc, char* argv[] )
294296
return 1;
295297
}
296298

297-
const std::string filename = inPath.filename().string();
298-
const std::string identifier = makeIdentifier( filename );
299+
// Use provided resource name or default to filename
300+
const std::string resourceName = ( argc == 5 ) ? argv[4] : inPath.filename().string();
301+
const std::string identifier = makeIdentifier( resourceName );
299302

300303
if( !isValidIdentifier( identifier ) )
301304
{
302-
std::cerr << "Error: Could not generate valid C++ identifier from filename: " << filename << "\n";
305+
std::cerr << "Error: Could not generate valid C++ identifier from resource name: " << resourceName << "\n";
303306
return 1;
304307
}
305308

@@ -309,7 +312,7 @@ int main( int argc, char* argv[] )
309312
return 1;
310313
}
311314

312-
if( !generateCppFile( outPath, identifier, filename, ns, data ) )
315+
if( !generateCppFile( outPath, identifier, resourceName, ns, data ) )
313316
{
314317
return 1;
315318
}

0 commit comments

Comments
 (0)