Skip to content

Commit dc4524b

Browse files
committed
runfiles
1 parent 37375e8 commit dc4524b

File tree

8 files changed

+788
-2
lines changed

8 files changed

+788
-2
lines changed

ada/private/common.bzl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ def _bind(
191191
args.add("--rename")
192192
args.add(binder_cwd_name + ".ads")
193193
args.add(binder_ads)
194+
args.add("--rename")
195+
args.add(binder_cwd_name + ".o")
196+
args.add(binder_obj)
194197
args.add("--")
195198

196199
# Command 1: gnatbind
@@ -202,14 +205,16 @@ def _bind(
202205
args.add(binder_cwd_name + ".adb")
203206
args.add(main_ali)
204207

205-
# Command 2: compile the binder output
208+
# Command 2: compile the binder output.
209+
# GNAT requires the object filename to match the compilation unit name,
210+
# so we output to the CWD-relative name and let process_wrapper rename.
206211
args.add("++")
207212
args.add(compiler)
208213
args.add("-c")
209214
args.add("-I.")
210215
args.add(binder_cwd_name + ".adb")
211216
args.add("-o")
212-
args.add(binder_obj)
217+
args.add(binder_cwd_name + ".o")
213218

214219
actions.run(
215220
executable = process_wrapper,

ada/runfiles/BUILD.bazel

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
load("//ada:defs.bzl", "ada_library")
2+
3+
ada_library(
4+
name = "runfiles",
5+
srcs = [
6+
"runfiles.adb",
7+
"runfiles.ads",
8+
],
9+
visibility = ["//visibility:public"],
10+
)

ada/runfiles/README.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Ada Runfiles Library
2+
3+
Resolve [Bazel runfile](https://bazel.build/extending/rules#runfiles) paths at
4+
runtime from Ada binaries and tests.
5+
6+
## Setup
7+
8+
Add `@rules_ada//ada/runfiles` as a dependency and list any runtime data files
9+
in the `data` attribute:
10+
11+
```python
12+
load("@rules_ada//ada:defs.bzl", "ada_binary")
13+
14+
ada_binary(
15+
name = "my_binary",
16+
srcs = ["main.adb"],
17+
data = ["//path/to:data.txt"],
18+
deps = ["@rules_ada//ada/runfiles"],
19+
)
20+
```
21+
22+
## Usage
23+
24+
```ada
25+
with Ada.Text_IO;
26+
with Runfiles;
27+
28+
procedure Main is
29+
R : constant Runfiles.Context := Runfiles.Create;
30+
Path : constant String :=
31+
R.Rlocation ("my_workspace/path/to/data.txt");
32+
begin
33+
Ada.Text_IO.Put_Line ("File is at: " & Path);
34+
end Main;
35+
```
36+
37+
### Bzlmod repo mapping
38+
39+
When using [Bzlmod](https://bazel.build/external/overview#bzlmod), repository
40+
names seen at build time (apparent names) may differ from the canonical names
41+
used in the runfiles tree. Use the `Rlocation` overload with `Source_Repo` to
42+
apply the `_repo_mapping` translations automatically:
43+
44+
```ada
45+
Path : constant String :=
46+
R.Rlocation ("my_dep/data/config.json",
47+
Source_Repo => "");
48+
```
49+
50+
`Source_Repo` identifies the repository that is performing the lookup. For the
51+
root module this is `""` (empty string). The library reads the `_repo_mapping`
52+
file produced by Bazel and translates the apparent repo name (first path
53+
component) to its canonical name before resolving.
54+
55+
## API reference
56+
57+
### `Runfiles.Create`
58+
59+
```ada
60+
function Create return Context;
61+
```
62+
63+
Creates a runfiles context by examining, in order:
64+
65+
1. `RUNFILES_MANIFEST_FILE` environment variable (manifest mode)
66+
2. `RUNFILES_DIR` environment variable (directory mode)
67+
3. `TEST_SRCDIR` environment variable (directory mode, set by Bazel test runner)
68+
4. `argv[0].runfiles` sibling directory
69+
5. Ancestor directories ending in `.runfiles`
70+
71+
If a `MANIFEST` file exists inside the discovered directory, manifest mode is
72+
used instead of directory mode.
73+
74+
Raises `Runfiles_Error` if no runfiles can be located.
75+
76+
### `Runfiles.Rlocation`
77+
78+
```ada
79+
function Rlocation (Self : Context; Path : String) return String;
80+
```
81+
82+
Resolves an rlocation path (e.g. `"my_repo/path/to/file"`) to a real filesystem
83+
path. Absolute paths are returned unchanged.
84+
85+
- **Manifest mode**: looks up the path in the parsed manifest. Raises
86+
`Runfiles_Error` if not found.
87+
- **Directory mode**: joins the runfiles directory with the path. Does not check
88+
whether the file exists on disk.
89+
90+
### `Runfiles.Rlocation` (bzlmod-aware)
91+
92+
```ada
93+
function Rlocation
94+
(Self : Context;
95+
Path : String;
96+
Source_Repo : String) return String;
97+
```
98+
99+
Same as above, but first applies the `_repo_mapping` to translate the apparent
100+
repository name (first path component) using the given `Source_Repo` as the
101+
lookup key. Falls back to the unmapped path if no mapping entry exists.
102+
103+
Supports both the standard and compact repo mapping formats, including the
104+
wildcard prefix entries from
105+
[`--incompatible_compact_repo_mapping_manifest`](https://github.com/bazelbuild/bazel/issues/26262)
106+
(Bazel 9+).
107+
108+
### `Runfiles_Error`
109+
110+
```ada
111+
Runfiles_Error : exception;
112+
```
113+
114+
Raised when runfiles cannot be located (`Create`) or a specific path cannot be
115+
resolved in manifest mode (`Rlocation`).

0 commit comments

Comments
 (0)