NVIDIA/Dependency-Patterns
Starlark
Captured source
source ↗NVIDIA/Dependency-Patterns
Description: Example dependency patterns for OSS build tools to support
Language: Starlark
License: NOASSERTION
Stars: 1
Forks: 5
Open issues: 0
Created: 2025-10-01T13:46:10Z
Pushed: 2026-07-06T19:44:29Z
Default branch: main
Fork: no
Archived: no
README: SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: MIT
Dependency Patterns Demo Project
A demonstration C project with 5 modular libraries that build into shared objects (.so files) and link into a final main binary. The useful part of this demonstration is the various code generation dependency patterns in each library. Each Makefile has the full set of dependencies manually written. The desire is for them to all be automatically inferred.
Project Structure
public_demo/ ├── main.c # Main executable that uses all modules ├── Makefile # Root Makefile to build everything ├── README.md # This file ├── strutils/ # String utilities module (renamed from string) │ ├── strutils.h # String function declarations │ ├── strutils.c # String function implementations │ └── Makefile # Builds libstrutils.so ├── utils/ # Utility functions module │ ├── utils.h # Utility function declarations │ ├── memory.c # Memory and array operations │ ├── validation.c # Validation and conversion functions │ └── Makefile # Builds libutils.so ├── mathutils/ # Math operations module │ ├── gen_mathutils_h.pl # Generates mathutils.h │ ├── gen_mathutils_c.pl # Generates mathutils.c │ └── Makefile # Builds libmathutils.so ├── io/ # Input/Output operations module │ ├── io.h # IO function declarations │ ├── generate_io.py # Generates io_impl/*.c files │ └── Makefile # Builds libio.so └── protocol/ # Protocol encoding/decoding module ├── protocol.spec # Protocol message definitions ├── generate_protocol.py # Generates protocol.h and proto_impl/*.c files └── Makefile # Builds libprotocol.so
Modules
String Utilities Module (libstrutils.so)
- Build Pattern: Single static source file, header dependency inferable from primary source
digraph strutils {
rankdir = LR
cpp [shape=box]
gcc [shape=box]
ld [shape=box]
"strutils.c" [shape=cylinder]
"strutils.h" [shape=cylinder]
"strutils.c" -> cpp -> "strutils.i" -> gcc -> "strutils.o" -> ld -> "libstrutils.so"
"strutils.h" -> cpp
subgraph dep {
rank="same"
edge [color=red, label=dependency]
"strutils.c" -> "strutils.h"
}
}Utils Module (libutils.so)
- Build Pattern: Multi-source static files into a single library, header dependency inferable from primary source
digraph utils {
rankdir = LR
cpp1 [shape=box label=cpp]
cpp2 [shape=box label=cpp]
gcc1 [shape=box label=gcc]
gcc2 [shape=box label=gcc]
ld [shape=box]
"memory.c" [shape=cylinder]
"validation.c" [shape=cylinder]
"utils.h" [shape=cylinder]
"memory.c" -> cpp1 -> "memory.i" -> gcc1 -> "memory.o" -> ld
"validation.c" -> cpp2 -> "validation.i" -> gcc2 -> "validation.o" -> ld
"utils.h" -> { cpp1 cpp2 }
ld -> "libutils.so"
subgraph dep {
rank="same"
edge [color=red, label=dependency]
"memory.c" -> "utils.h"
"validation.c" -> "utils.h"
}
}Mathutils Module (libmathutils.so)
- Build Pattern: Source and header generation, header dependency not inferable from primary sources
digraph mathutils {
rankdir = LR
cpp [shape=box]
gcc [shape=box]
ld [shape=box]
"gen_mathutils_c.pl" [shape=cylinder, style=filled, fillcolor=lightblue]
"gen_mathutils_h.pl" [shape=cylinder, style=filled, fillcolor=lightblue]
"gen_mathutils_c.pl" -> "mathutils.c"
"gen_mathutils_h.pl" -> "mathutils.h"
"mathutils.c" -> cpp -> "mathutils.i" -> gcc -> "mathutils.o" -> ld
"mathutils.h" -> cpp
ld -> "libmathutils.so"
subgraph dep {
rank="same"
edge [color=red, label=dependency]
"mathutils.c" -> "mathutils.h"
}
}IO Module (libio.so)
- Build Pattern: Source generation, static header, unpredictable generated file names, header dependency inferable from primary source
digraph io {
rankdir = LR
cpp [shape=box]
gcc [shape=box]
ld [shape=box]
"generate_io.py" [shape=cylinder, style=filled, fillcolor=lightblue]
"io.h" [shape=cylinder]
"io_impl_*.c" [style=dashed]
"io_impl_*.i" [style=dashed]
"io_impl_*.o" [style=dashed]
"generate_io.py" -> "io_impl_*.c"
"io_impl_*.c" -> cpp -> "io_impl_*.i" -> gcc -> "io_impl_*.o" -> ld
"io.h" -> cpp
ld -> "libio.so"
subgraph dep {
rank="same"
edge [color=red, label=dependency]
"io_impl_*.c" -> "io.h"
}
}Protocol Module (libprotocol.so)
- Build Pattern: Generated header and sources with unpredictable names, header dependency not inferable from primary sources
digraph protocol {
rankdir = LR
cpp [shape=box]
gcc [shape=box]
ld [shape=box]
"generate_protocol.py" [shape=cylinder, style=filled, fillcolor=lightblue]
"protocol.spec" [shape=cylinder, style=filled, fillcolor=lightyellow]
"protocol_*.h" [style=dashed]
"proto_impl_*.c" [style=dashed]
"proto_impl_*.i" [style=dashed]
"proto_impl_*.o" [style=dashed]
"protocol.spec" -> "generate_protocol.py"
"generate_protocol.py" -> "protocol_*.h"
"generate_protocol.py" -> "proto_impl_*.c"
"proto_impl_*.c" -> cpp -> "proto_impl_*.i" -> gcc -> "proto_impl_*.o" -> ld
"protocol_*.h" -> cpp
ld -> "libprotocol.so"
subgraph dep {
rank="same"
edge [color=red, label=dependency]
"proto_impl_*.c" -> "protocol_*.h"
}
}Build Patterns
Each library demonstrates different dependency inference challenges:
1. Strutils Module - Header Dependency Inferable
- Build Pattern: Single static source file, header dependency inferable from primary source
- Dependency Challenge: The Makefile can automatically infer that
strutils.cdepends onstrutils.hby scanning the source file for#includestatements - Applicable Inference Strategy: Automatic inference from source scanning
- Build Graph Implications: Simple single-file pipeline that should be reasonably easy to represent
2. Utils Module - Multi-Source with Shared Header
- Build Pattern: Multi-source static files into a single library, header dependency inferable from primary source
- Dependency Challenge: Both
memory.candvalidation.cdepend onutils.h, and this can be inferred by scanning each source file - Applicable Inference Strategy: Automatic inference from source scanning for each file
- Build Graph Implications: How to have the top-level depend on libutils.so when it's not describable as a derived product from a single Target...
Excerpt shown — open the source for the full document.