# How to allocate in build.zig?

**URL:** <https://ziggit.dev/t/how-to-allocate-in-build-zig/1044>\
**Category:** Help\
**Tags:** build-system\
**Created:** [July 4, 2023, 12:00pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044 "2023-07-04T12:00:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [July 4, 2023, 12:00pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044/1 "2023-07-04T12:00:18Z")

</div>

It’s not quite clear to me what’s the intended allocation pattern when writing build.zig. Let’s say I am writing an

```zig
pub fn build(b: *std.build.Builder) void {
   // my code here
}

```

Is the following correct:

1. I can use `b.allocator` as my general purpose allocator, I don’t need to create my own `var gpa = std.heap.GeneralPurposeAllocator(.{}){};`
2. The scope of `b.allocator` covers both construction of build graph (the `fn build`) as well as the execution of actual steps. That is, that steps can “close over” b.allocator and use it at runtime, it is _not_ an arena scoped purely to the `build`
3. In general, I don’t have to worry about freeing things. Steps don’t have `deinit` function, and that’s ok and by design.

---

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [July 4, 2023, 12:08pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044/2 "2023-07-04T12:08:14Z")

</div>

Looking at the implementation:

> <https://github.com/ziglang/zig/blob/ba6e5e65a0f84b803fffe4dd26b6e71417cab616/lib/build_runner.zig#L15-L25>

It looks the answer is “yes, on all three counts” at least for what’s currently implemented.

---

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [July 4, 2023, 12:57pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044/3 "2023-07-04T12:57:37Z")

</div>

And I guess the fourth “yes” question: Is `a.create(T) catch @panic("OOM")` the correct way to handle allocation failure in build.zig?

---

<div class="post-metadata">

**Author:** ![squeek502](https://ziggit.dev/user_avatar/ziggit.dev/squeek502/32/409_2.png) [@squeek502](https://ziggit.dev/u/squeek502)\
**Post date:** [July 4, 2023, 11:14pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044/4 "2023-07-04T23:14:16Z")

</div>

The relevant issue is [improve std.build to set a good example of proper error handling on out of memory · Issue #8350 · ziglang/zig · GitHub](https://github.com/ziglang/zig/issues/8350) which has been closed with `catch @panic("OOM");` seeming to be the preferred way to handle allocation errors in `build.zig`.

---

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [July 24, 2023, 5:09pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044/5 "2023-07-24T17:09:45Z")

</div>

Looked again at this today, and noticed that the `Build` struct is itself confused about memory management (or I am misreading the code).

There’s a `destroy` method, so it sorta tries to cleanup after itself:

> <https://github.com/ziglang/zig/blob/77b96231a6bc195cc482d05599e8c20ee01645a6/lib/std/Build.zig#L427-L431>

But then there’s a bunch of data it forgets to cleanup:

> <https://github.com/ziglang/zig/blob/77b96231a6bc195cc482d05599e8c20ee01645a6/lib/std/Build.zig#L235-L237>

And we are not handling allocation failure here:

> <https://github.com/ziglang/zig/blob/77b96231a6bc195cc482d05599e8c20ee01645a6/lib/std/Build.zig#L272-L273>

I wonder if we should just go and:

- Rename `Build.allocator` to `Build.arena`
- Clearly document that the arena is permanent
- Remove `destroy` method.

---

<div class="post-metadata">

**Author:** ![andrewrk](https://ziggit.dev/user_avatar/ziggit.dev/andrewrk/32/7011_2.png) [@andrewrk](https://ziggit.dev/u/andrewrk)\
**Post date:** [July 24, 2023, 11:50pm UTC](https://ziggit.dev/t/how-to-allocate-in-build-zig/1044/6 "2023-07-24T23:50:25Z")

</div>

> [@matklad](#):
>
> - Rename `Build.allocator` to `Build.arena`
> - Clearly document that the arena is permanent
> - Remove `destroy` method.

Agreed.

Here are a couple relevant issues:

> <https://github.com/ziglang/zig/issues/14941>
>
> Extracted from #14647.
> 
> I've seen quite a bit of build.zig code in the wild th…at does inappropriate things, such as call make() during build(), or create steps during make(). This issue is to set a global enum state to which phase is currently happening, and enforce that the API is only used in the intended phase.

> <https://github.com/ziglang/zig/issues/14286>
>
> Extracted from #14265.
> 
> build.zig is handy for adding build logic, but it's no…t handy to trust a lot of different people's code running natively on the host. A deep dependency tree has the problem that many different build.zig scripts are all running, and the chance of insufficient auditing grows quickly the more dependencies there are.
> 
> This issue is to make the zig build system compile build.zig to wasm32-wasi instead of natively, and merely output its build graph, based on the user-provided build options, to stdout. At this point a separate build\_runner can execute the requested build steps (or not, depending on the permissions granted).
> 
> Perhaps a middle ground, here, would be to run the make() steps directly in the WASI code. But eventually the idea would be that make() steps happen by a separate build runner, not by the wasm guest.
> 
> I can foresee a potential escape hatch for opting into running build.zig directly on the host. As an example, the Android SDK package wants to access the Windows registry in some cases. However, I would like to avoid even having this escape hatch if possible.
> 
> This issue will require Zig to gain a WASI interpreter, written in Zig. Whereever will we find one?

These two phases will see some separation introduced, including potentially being executed in different processes or contexts. Point being it’s fine to use the same allocator in both, but you should not rely on the allocator being the same instance. I think it’s unlikely this constraint will ever be a problem.
