ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
32.09k stars 2.34k forks source link

Building zig from source on Guix fails at stage3 #18434

Open tribals opened 6 months ago

tribals commented 6 months ago

Zig Version

$ ./zig2 version
thread 327725 panic: only a few subcommands are supported in a zig2.c build
Unable to dump stack trace: debug info stripped
Aborted (core dumped)

Steps to Reproduce and Observed Behavior

I'm trying to package Zig 0.11 on Guix: currently, there is only 0.10 available, and I believe 0.11 is major step forward. To what, indeed?

I've already tried to package zig when there was only 0.9 (and I was trying 0.10). That time I failed, and now, with 0.11 release out - with it comes new self-hosting compiler.

Compilers! Especially self-hosting! What would be even more interesting?

I've really enjoyed reading a blog post explaining approach Zig has been taken with self-hosting problem. (If you didn't mind, self-hosted compilers usually become a major obstacle for distro maintainers & packagers. They also create funny chain of dependency on it's "previous self", which is also major impact to problem surface packagers tries to solve.)

I also really appreciate how Zig Build System tries to integrate with the world. And, finally, building a compiler with it's build system with just one command is really pleasurable.

So, what is the bug, and how to reproduce it? Here is a Guix Package definition, which one can use to reproduce this bug:

(use-modules
  (gnu packages llvm)
  (gnu packages zig)
  (guix gexp)
  (guix git-download)
  (guix packages))

(define zig-0.11
  (package
    (inherit zig-0.10)
    (name "zig")
    (version "0.11.0")
    (source
     (origin
       (method git-fetch)
       (uri (git-reference
             (url "https://github.com/ziglang/zig.git")
             (commit version)))
       (file-name (git-file-name name version))
       (sha256
        (base32 "0qh7c27cd4wcdjj0mbpkarvwypfk1js8hkyxs0z149qv75zkbrca"))))
       ; (patches (search-patches "zig-use-baseline-cpu-by-default.patch"))))
    (inputs
     (modify-inputs (package-inputs zig-0.10)
       (replace "clang" clang-16)
       (replace "lld" lld-16)))
    (native-inputs
     (modify-inputs (package-native-inputs zig-0.10)
       (replace "llvm" llvm-16)))))

zig-0.11

Save it to any location, and then use with guix build command's --file option (note zig-0.11 variable at the end of such a file):

$ guix build --keep-failed -f zig.scm  # keep build results for further investigation

Build process will be finished successfully, but check phase will fail because of zig3 improperly linked with system libraries (command used to build zig3 just for convenience):

<...>
[100%] Building stage3
/tmp/guix-build-zig-0.11.0.drv-0/source/zig2 build --prefix /tmp/guix-build-zig-0.11.0.drv-0/source/stage3 --zig-lib-dir /tmp/guix-build-zig-0.11.0.drv-0/source/lib -Dconfig_h=/tmp/guix-build-zig-0.11.0.drv-0/source/config.h -Denable-llvm -Doptimize=ReleaseFast -Dno-langref -Dno-autodocs -Dtarget=native -Dcpu=baseline -Dversion-string=0.11.0
<...>
[100%] Built target stage3
<...>
Install the project...
/gnu/store/yh3yl7hzaa1ig3vz5gwgmbxic698nnsx-cmake-minimal-3.24.2/bin/cmake -P cmake_install.cmake
-- Install configuration: "RelWithDebInfo"
phase `install' succeeded after 1.8 seconds
starting phase `check'
/gnu/store/07qjj90yfdnpzqmfgxx7hql39sk7k8wa-zig-0.11.0/bin/zig: error while loading shared libraries: libclang-cpp.so.16: cannot open shared object file: No such file or directory
error: in phase 'check': uncaught exception:
%exception #<&invoke-error program: "/gnu/store/07qjj90yfdnpzqmfgxx7hql39sk7k8wa-zig-0.11.0/bin/zig" arguments: ("build" "test" "-Dskip-stage1" "-Dskip-stage2-tests" "-Dskip-non-native") exit-status: 127 term-signal: #f stop-signal: #f>
phase `check' failed after 0.0 seconds

Why so?

$ file /gnu/store/07qjj90yfdnpzqmfgxx7hql39sk7k8wa-zig-0.11.0/bin/zig
/gnu/store/07qjj90yfdnpzqmfgxx7hql39sk7k8wa-zig-0.11.0/bin/zig: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, with debug_info, not stripped

It is dynamically linked executable, as expected (and supposed by) Guix build process.

$ ldd /gnu/store/07qjj90yfdnpzqmfgxx7hql39sk7k8wa-zig-0.11.0/bin/zig
    linux-vdso.so.1 (0x00007ffec2dc1000)
    libclang-cpp.so.16 => not found
    libLLVM-16.so => /usr/lib/libLLVM-16.so (0x00007f1479600000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f1479200000)
    libz.so.1 => /usr/lib/glibc-hwcaps/x86-64-v3/libz.so.1.3 (0x00007f148585d000)
    libc.so.6 => /usr/lib/glibc-hwcaps/x86-64-v3/libc.so.6 (0x00007f1479003000)
    /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f1485891000)
    libffi.so.7 => /usr/lib/../lib64/libffi.so.7 (0x00007f148584f000)
    libedit.so.0 => /usr/lib/../lib64/libedit.so.0 (0x00007f1485813000)
    libm.so.6 => /usr/lib/../lib64/glibc-hwcaps/x86-64-v3/libm.so.6 (0x00007f148572d000)
    libzstd.so.1 => /usr/lib/../lib64/libzstd.so.1 (0x00007f147952d000)
    libncursesw.so.6 => /usr/lib/../lib64/libncursesw.so.6 (0x00007f14856be000)
    libxml2.so.2 => /usr/lib/../lib64/libxml2.so.2 (0x00007f1478ea4000)
    libgcc_s.so.1 => /usr/lib/../lib64/libgcc_s.so.1 (0x00007f1479504000)
    liblzma.so.5 => /usr/lib/liblzma.so.5 (0x00007f14794d6000)
    libicuuc.so.73 => /usr/lib/libicuuc.so.73 (0x00007f1478c00000)
    libicudata.so.73 => /usr/lib/libicudata.so.73 (0x00007f1476c00000)

It is not only linked against system-wide libraries, but also missing one completely (that one is from ZIG_CLANG_LIBRARIES list).

The problem is that, whenever zig2 get's built with "system compiler" - all the dependencies properly resolved thanks to cmake. But when zig build kicks in - this integration get's lost. Although I read carefully Zig Build System documentation, and there is --search-prefix option to zig build, I didn't find any way to propose those search prefix(es) from cmake part, which is actually used to build compiler: it has a bunch of options which one can set with cmake -DZIG_SHARED_LLVM=ON etc, but cmake has no any attempt to propagate discovered libraries to zig build, IIUC (from reading build.zig of 0.11.0 tag, and sporadic std.build chunks).

Although I managed to pass those --search-prefixes to ./zig2 build ... while debugging, it seems like that has no effect at this particular problem: zig3 get's linked against system libraries no matter what I pass to --search-prefix.

I did some search of similar issues before opening this one, here some examples:

All they relate in some way to proper discovery of libraries (and headers) when one do choose to build from source, but mostly system-specific: there is no problem with libraries discovery when zig2 get's built with system compiler whenever one's system compiler is able to properly discover shared libraries. There is no such problem on Guix:

$ ldd /tmp/guix-build-zig-0.11.0.drv-0/source/zig2
    linux-vdso.so.1 (0x00007fff61d28000)
    libclang-cpp.so.16 => /gnu/store/x082r2l5k5pp2pv6am059cksc69d4cgh-clang-16.0.6/lib/libclang-cpp.so.16 (0x00007f2396e00000)
    libLLVM-16.so => /gnu/store/hhvk2iflqadcqibz7m10lqjhqfljxmmj-llvm-16.0.6/lib/libLLVM-16.so (0x00007f238ec00000)
    libz.so.1 => /gnu/store/slzq3zqwj75lbrg4ly51hfhbv2vhryv5-zlib-1.2.13/lib/libz.so.1 (0x00007f239ac4a000)
    libstdc++.so.6 => /gnu/store/930nwsiysdvy2x5zv1sf6v7ym75z8ayk-gcc-11.3.0-lib/lib/libstdc++.so.6 (0x00007f238e800000)
    libm.so.6 => /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libm.so.6 (0x00007f239ab6b000)
    libgcc_s.so.1 => /gnu/store/930nwsiysdvy2x5zv1sf6v7ym75z8ayk-gcc-11.3.0-lib/lib/libgcc_s.so.1 (0x00007f2396de6000)
    libc.so.6 => /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/libc.so.6 (0x00007f238e604000)
    /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f239ac6a000)
    libffi.so.8 => /gnu/store/w8b0l8hk6g0fahj4fvmc4qqm3cvaxnmv-libffi-3.4.4/lib/libffi.so.8 (0x00007f2396dd6000)

The problem is that there is no way to communicate desired choices of libraries to ./zig2 build using cmake.

Also, note there was attempts (in Guix) to patch std.build to properly handle library discovery, using mechanism known as "search paths" (meaning that there was attempt to make zig respect some C-related well-defined search paths).

I think, this again touches the same pain point. What do you think?

I opening this bug here, in Zig upstream because I believe this is a Zig problem - not eg. Guix. Also, from the packager point, there is no room to "fix" this using Guix build process: all one can do is to resort to patching of cmake's generated build files, which I think is no-option in Guix upstream.

Expected Behavior

Zig 0.11.0 get's built with provided Guix Package definition, with zig3's executable dynamically linked against Guix shared libraries (package inputs).

tribals commented 6 months ago

Guix exports LIBRARY_PATH especially for that purpose:

$ ./pre-inst-env guix shell -D zig@0.11 --search-paths | grep LIBRARY
export LIBRARY_PATH="/gnu/store/dy0hhdbz7z2gzy57m0jz9zdl6543dymm-profile/lib${LIBRARY_PATH:+:}$LIBRARY_PATH"

Tried to solve it this kind of "way" (only to be sure this action actually solves anything):

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 92be8fbfe..d3794f189 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -863,6 +863,15 @@ endif()
 # -Dno-autodocs is currently hardcoded because the C backend generates a miscompilation
 #   that prevents it from working.
 # To obtain these two forms of documentation, run zig build against stage3 rather than stage2.
+string(REPLACE ":" ";" LIBRARY_PATH "$ENV{LIBRARY_PATH}")
+set(SEARCH_PATHS "")
+
+foreach(PATH ${LIBRARY_PATH})
+  list(APPEND SEARCH_PATHS "--search-prefix ${PATH}")
+endforeach()
+
+list(JOIN SEARCH_PATHS " " SEARCH_PREFIXES)
+
 set(ZIG_BUILD_ARGS
   --zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"
   "-Dconfig_h=${ZIG_CONFIG_H_OUT}"
@@ -877,6 +886,7 @@ set(ZIG_BUILD_ARGS
   "-Dtarget=${ZIG_TARGET_TRIPLE}"
   "-Dcpu=${ZIG_TARGET_MCPU}"
   "-Dversion-string=${RESOLVED_ZIG_VERSION}"
+  ${SEARCH_PREFIXES}
 )

 add_custom_target(stage3 ALL

But stuck with the way cmake's set handles its "arguments" (I'm completely newbie to cmake, but its declarative nature makes it not so hard):

tribals commented 6 months ago

Finally managed to pass desired parameters through manual hacking:

$ rg 'zig2 build' build/CMakeFiles/
build/CMakeFiles/stage3.dir/build.make
73: build/zig2 build --prefix build/stage3 --zig-lib-dir lib -Dconfig_h=build/config.h -Denable-llvm -Dno-langref -Dno-autodocs -Dtarget=native -Dcpu=native -Dversion-string=0.11.0 --search-prefix /gnu/store/dy0hhdbz7z2gzy57m0jz9zdl6543dymm-profile/lib --search-prefix /gnu/store/hvckqjrpikqs1zgn5gw838mf3ad9q753-profile/lib

Resulting executable is as follows:

$ ldd build/stage3/bin/zig
    linux-vdso.so.1 (0x00007ffcd41cc000)
    libclang-cpp.so.16 => not found
    libLLVM-16.so => not found
    libstdc++.so.6 => not found
    libz.so.1 => not found
    libc.so.6 => /gnu/store/ln6hxqjvz6m9gdd9s97pivlqck7hzs99-glibc-2.35/lib/libc.so.6 (0x00007fbeda5b0000)
    /usr/lib64/ld-linux-x86-64.so.2 => /gnu/store/ln6hxqjvz6m9gdd9s97pivlqck7hzs99-glibc-2.35/lib/ld-linux-x86-64.so.2 (0x00007fbeda7ae000)
zilti commented 2 months ago

I, too, am trying to build it on Guix. This here seems to work for adding the arguments:

diff -crB zig.orig/CMakeLists.txt zig/CMakeLists.txt
*** zig.orig/CMakeLists.txt 2024-04-16 00:59:10.664981173 +0200
--- zig/CMakeLists.txt  2024-04-16 02:33:53.218625749 +0200
***************
*** 921,926 ****
--- 921,932 ----
    "-Dversion-string=${RESOLVED_ZIG_VERSION}"
  )

+ string(REPLACE ":" ";" LIBRARY_PATH "$ENV{LIBRARY_PATH}")
+ foreach(entry ${LIBRARY_PATH})
+   LIST(APPEND ZIG_BUILD_ARGS "--search-prefix")
+   LIST(APPEND ZIG_BUILD_ARGS "${entry}")
+ endforeach()
+ 
  add_custom_target(stage3 ALL
    DEPENDS "${CMAKE_BINARY_DIR}/stage3/bin/zig"
  )

And results in the following command:

[100%] Building stage3
/tmp/guix-build-zig-0.11.0.drv-0/source/zig2 build --prefix /tmp/guix-build-zig-0.11.0.drv-0/source/stage3 --zig-lib-dir /tmp/guix-build-zig-0.11.0.drv-0/source/lib -Dconfig_h=/tmp/guix-build-zig-0.11.0.drv-0/source/config.h -Denable-llvm -Doptimize=ReleaseFast -Dno-langref -Dno-autodocs -Dtarget=native -Dcpu=baseline -Dversion-string=0.11.0 --search-prefix /gnu/store/381rppgdk3b9psw1h1ix3hwy2x7iy5a5-clang-toolchain-16.0.6/lib --search-prefix /gnu/store/nz98paylp1jg2fkchdmrkac0fh7lnxkw-llvm-16.0.6/lib --search-prefix /gnu/store/slzq3zqwj75lbrg4ly51hfhbv2vhryv5-zlib-1.2.13/lib --search-prefix /gnu/store/hqxzgbbbnxl8l9q8bcsvzvmyw1mjws4r-zstd-1.5.2-lib/lib --search-prefix /gnu/store/g9f9nmgajrym0azkmjscv3xpns6k7293-clang-16.0.6/lib --search-prefix /gnu/store/9g9096xd7g1g4ah9kvh24gjgkxjs13mv-lld-16.0.6/lib --search-prefix /gnu/store/j8wlfmlmfvpbza6is9wv9xsd8psrxn00-bzip2-1.0.8/lib --search-prefix /gnu/store/gr0sy0m1mv36qv54idm6cn10l3mngshq-file-5.44/lib --search-prefix /gnu/store/hc05d76f1j3iz3v2bs5jz4fpljl1r4dj-gawk-5.2.1/lib --search-prefix /gnu/store/6k1yys9wqrfn4y41ic1win8gpnimncwj-xz-5.2.8/lib --search-prefix /gnu/store/zh4x65snfis7svs6906gj1z8i7dx2j3m-binutils-2.38/lib --search-prefix /gnu/store/gsjczqir1wbz8p770zndrpw4rnppmxi3-glibc-2.35/lib --search-prefix /gnu/store/l0yryi5jsa1grnvw01c9nkz9c81cv224-glibc-2.35-static/lib --search-prefix /gnu/store/visfdda934gvivwihwhlm63fdqhhcc8a-glibc-utf8-locales-2.35/lib --search-prefix /gnu/store/6r1jjb71w32dcqxpcddlyq2x0m86rdmn-clang-runtime-16.0.6/lib

The check phase, however, still fails:

/gnu/store/x6magg76w4pzcl6kl53j4nxl2c1a4jbd-zig-0.11.0/bin/zig: error while loading shared libraries: libclang-cpp.so.16: cannot open shared object file: No such file or directory
zilti commented 2 months ago

As of zig 0.12, I am getting a bunch of these warnings building stage3:

warning: Encountered error: FileNotFound, falling back to default ABI and dynamic linker.

The check phase still fails completely, but with a slightly different error this time:

In execvp of /gnu/store/y5g77v1l3slm485a21bzy9dmkch5hfm5-zig-0.12.0/bin/zig: No such file or directory

Unfortunately, I don't have even remotely enough knowledge to fix this, or to know where to look for more infos, but here's hoping someone who knows will drop by.

EDIT: for reference, my package definition is here: https://gitea.lyrion.ch/zilti/guixchannel/src/branch/master/zilti/packages/zig.scm