Skip to content

Conversation

cyphar
Copy link
Member

@cyphar cyphar commented Aug 28, 2025

Making runc a .PHONY target means that we rebuild it each time, even if
the source code does not change. This can cause issues if you are trying
attach uprobes a binary that then gets replaced when you try to run
integration tests with it.

The "static" target needed to be adjusted a little, but now it's just a
special case of the standard "runc" target.

Also, the "runc-bin" and "static-bin" rules were really not necessary in
the first place...

Signed-off-by: Aleksa Sarai [email protected]

@cyphar
Copy link
Member Author

cyphar commented Aug 28, 2025

We can also do this for the test binaries and/or memfd-bind but it would require messing around with more target names, so I'm not sure if it's worth the effort.

Making runc a .PHONY target means that we rebuild it each time, even if
the source code does not change. This can cause issues if you are trying
attach uprobes a binary that then gets replaced when you try to run
integration tests with it.

The "static" target needed to be adjusted a little, but now it's just a
special case of the standard "runc" target.

Also, the "runc-bin" and "static-bin" rules were really not necessary in
the first place...

Signed-off-by: Aleksa Sarai <[email protected]>
runc: runc-bin
GO_SRC := \
go.mod go.sum \
$(shell find . -type f -name '*.go' -or -name '*.c')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And //go:embed files

runc/main.go

Line 25 in d845c4a

//go:embed VERSION

Copy link
Member Author

@cyphar cyphar Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me cook up some awk-foo to make this work without hardcoding them...

Copy link
Member

@rata rata Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyphar I'm not convinced we want to stop relying on the compiler for this on every runc compilation.

I'm not very familiar with uprobes, how are you attaching them?

If you really need the binary to not change, I think something like: cp runc runc-uprobes; make; <overwrite runc-uprobes only if md5 is different> is a simpler alternative that doesn't put the price of this limitation (discover files we need to trigger a recompile) on everyone else not using uprobes.

It would be great if go provided, like gcc, a feature to list the dependencies in a makefile-style fashion. Or if we can say to go build: only overwrite if there are changes. These might be good issues for go, though? I haven't searched if they already rejected something like this or what.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very familiar with uprobes, how are you attaching them?

bpftrace -e 'uprobe:./runc:symbol { ... }'

I was wrong though -- the Go compiler doesn't replace the binary if it would be identical (the inode number is unchanged after make) so this patch is unnecessary. I'm not sure why it didn't work when I was testing it before...

Copy link
Contributor

@akhilerm akhilerm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch also does not rebuild, if the target has changed.

akhil@akhil-ThinkPad-L14:~/g/s/g/o/runc (makefile-deps)$ make runc
go build -trimpath "-buildmode=pie"  -tags "seccomp urfave_cli_no_docs" -ldflags "-X main.gitCommit=0d6527ad  " -o runc .
akhil@akhil-ThinkPad-L14:~/g/s/g/o/runc (makefile-deps)$ make static
make: Nothing to be done for 'static'.

Did not create a static runc binary, but ideally thats the expected behaviour.

.PHONY: runc-bin
runc-bin:
$(GO_BUILD) -o runc .
.DEFAULT: runc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This DEFAULT will be a no-op since there is another target defined before.

So just calling make will trigger the static build, rather than the current existing one.

@cyphar
Copy link
Member Author

cyphar commented Aug 29, 2025

@akhilerm I would've preferred to have a runc.static target that makes a binary called runc.static but I presume some people depend on static to produce a binary called runc...

The "dumb" solution would be to just rebuild static every time like we do today.

@tianon
Copy link
Member

tianon commented Aug 29, 2025

I presume some people depend on static to produce a binary called runc...

I mean, they should get a pretty obvious 404 from doing so and update their packaging, right? 😇

Copy link
Contributor

@kolyshkin kolyshkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One other issue I see is when GO= is explicitly specified, runc won't be rebuilt. This will break one of my usual scenarios, in a hard-to-notice way.

Similar for GOEXPERIMENT= although I rarely use it.

Are there alternative solutions for the issue described? I'd really like go to worry about dependencies, not us.

# "static" just maps to runc with a different "go build" invocation. This lets
# us avoid rebuilding if the sources haven't changed -- even with .PHONY.
.PHONY: static
static: export GO_BUILD=$(GO_BUILD_STATIC)
Copy link
Contributor

@kolyshkin kolyshkin Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is export really needed here? Looks like not, since we don't use sub-make, but maybe I'm missing something.

@cyphar
Copy link
Member Author

cyphar commented Sep 6, 2025

This is not actually necessary -- I just tested this and the Go compiler doesn't actually replace the binary if there are no changes, and so uprobes do actually work. I'm not sure why it was failing when I tried this before but it's actually fine.

@cyphar cyphar closed this Sep 6, 2025
@cyphar cyphar deleted the makefile-deps branch September 6, 2025 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants