Skip to content

Replace build wrapper with native meson targets#1722

Open
PeakKS wants to merge 5 commits into
containers:mainfrom
PeakKS:redo-build-system
Open

Replace build wrapper with native meson targets#1722
PeakKS wants to merge 5 commits into
containers:mainfrom
PeakKS:redo-build-system

Conversation

@PeakKS

@PeakKS PeakKS commented Sep 21, 2025

Copy link
Copy Markdown

Tentative fix for #1706

Replaces the go build wrapper and the completions wrapper with just doing the build right in meson. Essentially I am just tricking go into building as a static library, then linking that with itself. This prevents the weird go build cache issue I ran into in #1706.

Since -z now can not be used for this application, I am forcing -z lazy in the linker args. It seems like the reason this only popped up on gentoo is because we default to -z now for security reasons (see : https://packages.gentoo.org/useflags/default-znow).

Getting rid of some of the boilerplate is just a nice side benefit :)

@PeakKS

PeakKS commented Sep 21, 2025

Copy link
Copy Markdown
Author

Not sure how CI is failing, logs seem to show the binary getting compiled then not existing for completions?

@debarshiray debarshiray left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for working on this, @PeakKS ! I don't have time right now to take a very close look, but I didn't want to completely ignore your significant contribution. So some fly-by comments:

First, I think what you are suggesting is a good idea. The less shell scripts we use, the better it is! :)

Second, do you think it will be possible to have tests to check if the toolbox binary was correctly built? You have already seen what src/go-build-wrapper was doing, and you will see the background in the Git history of that file. The toolbox binary needs to be linked in a very specific way for different Toolbx containers to work across different host OSes.

If we have tests to check the important attributes of the binary, then it becomes a lot easier to make changes to the build, and review those changes, etc.. It's one of the big reasons why we never revamped src/go-build-wrapper before. Manually checking everything felt too nerve-wracking and stressful. :)

@debarshiray debarshiray left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you please use your full name and a real email address in your Git authorship information?

The Signed-off-by trailer has no meaning without a real full name and email address.

I could have made an exception for a one line change because it would be legally insignificant. However, that's not the case with this pull request, because you have done a substantial amount of great work. :)

We need a real full name and email address for tracking copyright holders in case a licensing issue crops up. Note how projects as diverse as GCC, GnuPG, Linux and Podman don't allow anonymous or pseudonymous contributions.

@PeakKS

PeakKS commented Sep 23, 2025

Copy link
Copy Markdown
Author

Could you please use your full name and a real email address in your Git authorship information?

The Signed-off-by trailer has no meaning without a real full name and email address.

I could have made an exception for a one line change because it would be legally insignificant. However, that's not the case with this pull request, because you have done a substantial amount of great work. :)

We need a real full name and email address for tracking copyright holders in case a licensing issue crops up. Note how projects as diverse as GCC, GnuPG, Linux and Podman don't allow anonymous or pseudonymous contributions.

No problem, didn't even realize I used my username lol.

@debarshiray

Copy link
Copy Markdown
Member

Hey @PeakKS ! How is it going with this pull request. I am asking because I see that the CI is failing. Do you need some help?

@PeakKS

PeakKS commented May 28, 2026

Copy link
Copy Markdown
Author

Hey @PeakKS ! How is it going with this pull request. I am asking because I see that the CI is failing. Do you need some help?

I haven't worked on this in a while but I think it's correct besides the CI. I can rebase on main to see if that magically fixes the CI, otherwise I'll need someone to take a closer look.

PeakKS added 5 commits May 28, 2026 18:45
Signed-off-by: Blake Batson <bbatson101@gmail.com>
Signed-off-by: Blake Batson <bbatson101@gmail.com>
Signed-off-by: Blake Batson <bbatson101@gmail.com>
Signed-off-by: Blake Batson <bbatson101@gmail.com>
Signed-off-by: Blake Batson <bbatson101@gmail.com>
@PeakKS PeakKS force-pushed the redo-build-system branch from fd565e8 to 3bdea06 Compare May 28, 2026 22:54
@PeakKS

PeakKS commented May 28, 2026

Copy link
Copy Markdown
Author

Okay seems like the same issue as before.

Links target? Yep: [12/15] Linking target src/toolbox
Correct dependencies in build.ninja? Seems so: build src/_toolbox: CUSTOM_COMMAND | src/toolbox
Fails anyways? Yep: FileNotFoundError: [Errno 2] No such file or directory: '/home/zuul-worker/src/github.com/containers/toolbox/builddir/src/toolbox'

I also tried running my local build of toolbox to run a fedora42 container and try building there to replicate the CI build failure but it still builds fine inside.

@debarshiray could you take a look?

@debarshiray debarshiray marked this pull request as ready for review June 11, 2026 13:33
@debarshiray

Copy link
Copy Markdown
Member

This is how the CI fails on Ubuntu hosts:

...
ninja: Entering directory `/home/runner/work/toolbox/toolbox/containers/toolbox/builddir'
[1/15] /usr/bin/go-md2man -in ../doc/toolbox-enter.1.md -out doc/toolbox-enter.1
[2/15] /usr/bin/go-md2man -in ../doc/toolbox.1.md -out doc/toolbox.1
[3/15] /usr/bin/go-md2man -in ../doc/toolbox-create.1.md -out doc/toolbox-create.1
[4/15] /usr/bin/go-md2man -in ../doc/toolbox-help.1.md -out doc/toolbox-help.1
[5/15] /usr/bin/go-md2man -in ../doc/toolbox-init-container.1.md -out doc/toolbox-init-container.1
[6/15] /usr/bin/go-md2man -in ../doc/toolbox-list.1.md -out doc/toolbox-list.1
[7/15] /usr/bin/go-md2man -in ../doc/toolbox-rmi.1.md -out doc/toolbox-rmi.1
[8/15] /usr/bin/go-md2man -in ../doc/toolbox.conf.5.md -out doc/toolbox.conf.5
[9/15] /usr/bin/go-md2man -in ../doc/toolbox-run.1.md -out doc/toolbox-run.1
[10/15] /usr/bin/go-md2man -in ../doc/toolbox-rm.1.md -out doc/toolbox-rm.1
[11/15] /usr/lib/go-1.22/bin/go build -C /home/runner/work/toolbox/toolbox/containers/toolbox/src -trimpath -buildmode=c-archive -tags '' -ldflags '-X github.com/containers/toolbox/pkg/version.currentVersion=0.3' -o /home/runner/work/toolbox/toolbox/containers/toolbox/builddir/src/toolbox.a
[12/15] cc  -o src/toolbox  -Wl,--as-needed -Wl,--no-undefined -Wl,--whole-archive -Wl,--start-group src/toolbox.a -Wl,--no-whole-archive -Wl,-rpath,/run/host/usr/lib/x86_64-linux-gnu -Wl,-z,lazy -Wl,--export-dynamic -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-dynamic-linker,/run/host/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 -Wl,--end-group
[13/15] /usr/bin/meson --internal exe --capture src/toolbox.bash -- /home/runner/work/toolbox/toolbox/containers/toolbox/builddir/src/toolbox completion bash
FAILED: [code=1] src/toolbox.bash 
/usr/bin/meson --internal exe --capture src/toolbox.bash -- /home/runner/work/toolbox/toolbox/containers/toolbox/builddir/src/toolbox completion bash
Traceback (most recent call last):
  File "/usr/bin/meson", line 29, in <module>
    sys.exit(mesonmain.main())
  File "/usr/lib/python3/dist-packages/mesonbuild/mesonmain.py", line 257, in main
    return run(sys.argv[1:], launcher)
  File "/usr/lib/python3/dist-packages/mesonbuild/mesonmain.py", line 246, in run
    return run_script_command(args[1], args[2:])
  File "/usr/lib/python3/dist-packages/mesonbuild/mesonmain.py", line 194, in run_script_command
    return module.run(script_args)
  File "/usr/lib/python3/dist-packages/mesonbuild/scripts/meson_exe.py", line 122, in run
    return run_exe(exe)
  File "/usr/lib/python3/dist-packages/mesonbuild/scripts/meson_exe.py", line 66, in run_exe
    p = subprocess.Popen(cmd_args, env=child_env, cwd=exe.workdir,
  File "/usr/lib/python3.10/subprocess.py", line 971, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.10/subprocess.py", line 1751, in _execute_child
    self._posix_spawn(args, executable, env, restore_signals,
  File "/usr/lib/python3.10/subprocess.py", line 1696, in _posix_spawn
    self.pid = os.posix_spawn(executable, args, env, **kwargs)
FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/toolbox/toolbox/containers/toolbox/builddir/src/toolbox'

As far as I can make out, step 12 generates src/toolbox and step 13 tries to use it to generate the shell completions and fails with FileNotFoundError.

@debarshiray debarshiray left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not immediately clear to me why the build breaks on the CI environment, because, like you, I can't reproduce it on my local system either. Meanwhile, here's an idea on how to move this forward:

Comment thread src/meson.build

libc_path = run_command(cc_exe, '--print-file-name=libc.so', capture: true, check: true).stdout()
libc_canon = run_command(readlink, '--canonicalize', libc_path, capture: true, check: true).stdout()
libc_dir = run_command(dirname, libc_canon, capture: true, check: true).stdout().strip()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like this approach of using Meson's run_command() to move things out of the go-build-wrapper shell script into Meson.

It seems to me that these parts can be split into a simpler commit that's less likely to break the CI.

Comment thread src/meson.build
dynamic_linker = '/lib/ld-linux-riscv64-lp64d.so.1'
else
host_machine_description = cpu_family + ' (' + endian + ' endian)'
error('Please specify dynamic linker for:', host_machine_description)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am curious about the switch from this to objcopy(1) to set the dynamic linker. In the past we used patchelf(1) to do the same thing, and we dropped it because some downstream distributors decided against shipping patchelf(1).

I see that objcopy(1) is part of GNU Binutils. So, it's more likely to be present than patchelf(1), but there's still benefit in the general principle of fewer build requirements within reason.

@debarshiray

Copy link
Copy Markdown
Member

Second, do you think it will be possible to have tests to check if the toolbox binary was correctly built? You have already seen what src/go-build-wrapper was doing, and you will see the background in the Git history of that file. The toolbox binary needs to be linked in a very specific way for different Toolbx containers to work across different host OSes.

If we have tests to check the important attributes of the binary, then it becomes a lot easier to make changes to the build, and review those changes, etc.. It's one of the big reasons why we never revamped src/go-build-wrapper before. Manually checking everything felt too nerve-wracking and stressful. :)

I found some tests hidden in #1031 Let's see if I can rescue them.

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.

2 participants