Request for Tutorial: Patching Zig

I’ve built things from source a few times, but those were really small things and a while ago. I’d like to run a patched Zig compiler, and have minimal friction upgrading to new versions (0.12 and on).

Is there a guide for creating such a setup? I’m not fluent in git but can follow instructions just fine.

EDIT: it turns out that for my case low-friction release upgrades aren’t worth the effort, so ignore that requirement. What I really want is to be able to keep my changes in a patch file, edit them there, and compile as if i had a full copy of the original source with the patch applied.

Hey @red-all-over, welcome to the forum!

If by patched, you mean updating your compiler within the same release, that’s one thing… but if you’re talking about jumping entire releases (say 11 to 12), you’re going to have friction by design at this point. For instance, there are big breaking changes coming in 13 around IO management that were described as “apocalyptic” by the core team. I don’t know what a smooth ride for that sort of change looks like.

If you’re not talking about building an old project from source that was intended for a previous compiler version, then that’s more easily accomplished. Say for example you want to clone something and build it from git to be used, that’s quite manageable and a tutorial could be created quite easily.

The easiest thing to do for major version changes is to re-clone/download a copy of updated source and compile it accordingly. Or, if you are into version control, you can use an older version of the Zig compiler depending on the project you’re attempting to build.

Can you give us some more context?

1 Like

Upgrading releases isn’t necessary if that makes it a whole 'nother class of problem, and I wasn’t planning on upgrading within releases anyway, so I suppose it doesn’t need to support any kind of upgrade at all!

As for my use-case, I want to add some syntax sugar to use while working on my hobby project.

It is.

Okay - and again, just trying to make sure we’re on the same page. When you syntax sugar, are you looking for language features between versions? It would really help to see an example.

Like, the feature is absent in Zig 0.11.0 but present in 0.11.2? No.

fn addone(x: i64) i64
    return x + 1

The patch would make this compile despite lacking ;{}.

It’s also lacking a return type. Zig is a sugar free language in many regards - I believe they are still not considering language proposals at the moment. If you’re not looking to jump major releases, I don’t see this as being something that will benefit you for quite some time. If anything, you’ll probably be more stable staying in bounds until you’re ready to make the jump (you’ll face a lot of breakage depending on the state of your code base).

Maybe someone else has further insight on the issue here, but I don’t think you’ll be gaining much ground in terms of syntax in the near future.

That was an oversight.

Sure, and I respect the decisions of the language leadership. That’s why I’m looking to make my desired changes privately, on my own computer. I am absolutely not proposing any changes to Zig proper.

Of course, and I think we’re on the same page here. What I’m saying is that (as far as I’ve researched) I don’t foresee much in the way of syntax of the sort you’re referring to on the horizon - there’s a few things that may interest you though.

If I was in your position and was trying to make the decision for myself, here’s what I would do…

First, I’d look at the upcoming milestones on github to see if there’s anything that catches my interest - here’s the 13.0 milestones: 0.13.0 Milestone · GitHub

One thing that I see is pinned memory was accepted and is slated for 13.0. At that point, I would decide “is this enough to break my code for?” and if the answer is yes, I’d make the jump.

Otherwise, I’d keep my eyes open on the future releases and pick ones that I think are worth the jump. Admittedly, this requires a bit of homework, but I’m not sure how else to weigh your options in this situtation.

To be clear, I like to stay current, so I just accept the breaks and rewrite my code.

1 Like

I think I misplaced my emphasis in my first post, sorry. I just happened to think about easy upgrades as a nice-to-have.

Since upgrades will be painful either way, I think this reduces to a question about how to use git to develop a patch locally. I’m sure there are already great tutorials for that. Thanks for fielding my question.

1 Like

Happy to help - I’d still keep an eye out here for anyone else who has an opinion on the subject. I just want to save you from writing machinery that could largely go unused and break your code when it is.

On further reflection, I think I want this:

There is the official Zig source as of some point, could be a release or not. There is a patch file. And there is a script which builds the source as if the patch file were applied, without modifying the source. It’s fine if the script makes some tmp copies to modify and delete.

That way I could hack on the patch file, and whenever I’m interested in later Zig versions, I’d have at least a snowball’s chance of producing an updated patch that works on it. And again, if not, fine.

On inspection, GNU(?) patch has a flag --output that does exactly what I want it to. This may turn out to be easier than I feared! (Heh, famous last words.)

If I was doing something like this, I would probably just clone the Zig repository, create my own branch and commit my changes in there.

Then periodically rebase that branch to replay the changes contained in this branch on top of the most recent updates of the master branch.

4 Likes

If I understand the suggestion correctly, you’re referring to swapping out the underlying Zig implementation beneath the code that that the user has written. I’m trying to picture that for the issue at hand. Maybe you can walk me through your though process here a bit more.

Let’s take a simple issue like unmutated var… in this scenario, someone wrote a bunch of code before that breaking change. At this point, they want to update their compiler to pickup the newest version of the language for any of the features they may be missing. I still foresee a lot of code breakage that’s going to occur for anything they’ve written on top of it if they didn’t obey that rule. If the language fundamentally changes, I’m not sure how that makes the transition process more smooth?

I can see using branches as a way to observe the impact of the changes. That could be helpful, sure - but I’m not sure if you’re saying there is utility beyond that?

@red-all-over, I’m not familiar with the --output flag you mentioned and I’m having trouble locating documentation that is related to this issue… can you share some resources?

Well, with 1042 issues open and only 3 closed, sometimes something shifts backwards. :wink:

2 Likes

True, it’s uncertain if something will get moved if it’s not already closed. However, it’s the only public portal I’m aware of to speculate about the future of the language from.

You can also look at it retroactively - once a release has been put out, you can look at the changes and make the decision then. That’s probably a more effective way to approach this.

2 Likes

I haven’t done a lot of rebasing but when I did it seemed helpful in managing changes in relation to other changes, it essentially allows you to pretend that old changes are just a bunch of changes you just did now (with possibly outdated assumptions about what the code should look like), then step by step you can edit certain commits which are still causing errors with the new underlying reality towards their fixed adaptation.
Especially interactive rebase is kind of fun, where you pick commits to edit, remove, reorder etc.

I would say mostly this allows you to still keep some amount of shared history between your branch and master (basically where your branch last branched off from master is shared) sometimes this is helpful. Also sometimes you do things in your branch that the master branch does too, when you then rebase your changes on top, then your changes of these things disappear, because in master it was already done, that way your change set shrinks becoming more manageable.

You are still left with adapting your changes/addons to breaking changes in master,
but I still find it helpful, because you are maintaining the minimal set of changes from master now, and later on that now.
Which means that you just have to understand the current code base, to be able to read your patch, instead of having to understand some old version of zig and then track how your patch was patched and patched and patched to arrive at current zig.

Technically the resulting code is quite similar, but one carries a complicated history that isn’t really helpful to the question “how could you implement this feature now?”.

A big patch is technically similar (lacking some conveniences), but this allows you to treat it as a series of small patches that are logically connected and where you also have the tracking of where the patches need to be applied.

1 Like