diff mbox series

[bug#47006,WIP,v2,2/2] gnu: Add zig.

Message ID 865yv6mmk2.fsf@mgsn.dev
State Accepted
Headers show
Series None | expand

Commit Message

Sarah Morgensen Sept. 12, 2021, 4:42 a.m. UTC
Hi,

I finally got a chance to run some tests.  I've attached a patch below
that works.  As András pointed out,

András Vöröskői <voroskoi@gmail.com> writes:

> Hi,
>
> So zig testing result is the following:
> -Dskip-libc does not work, my best result is with -Dskip-non-native.
>
> -Dskip-non-native fails with "libc headers note" test from
> `compile_errors.zig` (I had to comment it around line 2750) and std
> library tests also fails instantaneously.
>
> So I suggest the following test command for now: `zig build
> -Dskip-non-native test-toolchain` with a patch to disable that failing
> test. This will test everything except the std library and docs.

'test-toolchain' is probably a good choice because it skips standard
library tests, which I found out can take a lot of memory (>7.5GB)!  I
also disabled stage 2 tests since stage 2 is experimental and isn't
actually installed.

Now that I have an output:

--8<---------------cut here---------------start------------->8---
$ ./pre-inst-env guix size zig 
store item                                                       total    self
/gnu/store/kwjw55f4syys5gg8a9lr6bk6a3jdqw0i-zig-0.8.1              576.6   177.4  30.8%
/gnu/store/rmc131fpy2hv408a1awd2wm7kiwyf7d7-llvm-12.0.0            234.1   162.7  28.2%
/gnu/store/rn75fm7adgx3pw5j8pg3bczfqq1y17lk-gcc-7.5.0              178.5   107.3  18.6%
/gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-2.31              38.4    36.7   6.4%
/gnu/store/f0ca0lf64bw08srv1bj7gkg6ag0sbdb2-gcc-7.5.0-lib           71.0    32.6   5.7%
/gnu/store/01b4w3m6mp55y531kyi1g8shh722kwqm-gcc-7.5.0-lib           71.0    32.6   5.7%
/gnu/store/nzfhh1rm85lx2p5plbx45qqj82pcv5hp-clang-runtime-12.0.0    95.9    24.9   4.3%
/gnu/store/mmhimfwmmidf09jw1plw3aw1g1zn2nkh-bash-static-5.0.16       1.6     1.6   0.3%
/gnu/store/g2s5jfkfd4k973wb58476b1bbv9zpm6m-zlib-1.2.11             38.6     0.2   0.0%
/gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-1.2.11             71.2     0.2   0.0%
/gnu/store/bw15z9kh9c65ycc2vbhl2izwfwfva7p1-libffi-3.3              71.2     0.2   0.0%
total: 576.6 MiB
--8<---------------cut here---------------end--------------->8---

It looks like we're retaining references to the main gcc-7.5.0 output,
but only to its "include/c++" directory, as a single reference in the
zig binary.  I expect this would cause issues if another GCC version
were later used with Zig.

We're retaining double direct references to gcc-7.5.0-lib, and double
indirect references to zlib-1.2.11.  This seems to come from clang.
(Wow, clang is big. Maybe it should have a separate "lib" output?  Zig,
for example, only needs libclang to build, not the binaries.)

Other than those items, it looks good!

I've asked on their ML about exactly which dependencies are needed for
the host and target architectures, so hopefully that will solve that.

--
Sarah

Comments

Liliana Marie Prikler Sept. 12, 2021, 7:32 a.m. UTC | #1
Hi,

Am Samstag, den 11.09.2021, 21:42 -0700 schrieb Sarah Morgensen:
> Hi,
> 
> I finally got a chance to run some tests.  I've attached a patch
> below
> that works.  As András pointed out,
> 
> András Vöröskői <voroskoi@gmail.com> writes:
> 
> > Hi,
> > 
> > So zig testing result is the following:
> > -Dskip-libc does not work, my best result is with -Dskip-non-
> > native.
> > 
> > -Dskip-non-native fails with "libc headers note" test from
> > `compile_errors.zig` (I had to comment it around line 2750) and std
> > library tests also fails instantaneously.
> > 
> > So I suggest the following test command for now: `zig build
> > -Dskip-non-native test-toolchain` with a patch to disable that
> > failing
> > test. This will test everything except the std library and docs.
> 
> 'test-toolchain' is probably a good choice because it skips standard
> library tests, which I found out can take a lot of memory
> (>7.5GB)!  I also disabled stage 2 tests since stage 2 is
> experimental and isn't actually installed.
So far, so good.

> Now that I have an output:
> 
> --8<---------------cut here---------------start------------->8---
> $ ./pre-inst-env guix size zig 
> store
> item                                                       total    s
> elf
> /gnu/store/kwjw55f4syys5gg8a9lr6bk6a3jdqw0i-zig-
> 0.8.1              576.6   177.4  30.8%
> /gnu/store/rmc131fpy2hv408a1awd2wm7kiwyf7d7-llvm-
> 12.0.0            234.1   162.7  28.2%
> /gnu/store/rn75fm7adgx3pw5j8pg3bczfqq1y17lk-gcc-
> 7.5.0              178.5   107.3  18.6%
> /gnu/store/fa6wj5bxkj5ll1d7292a70knmyl7a0cr-glibc-
> 2.31              38.4    36.7   6.4%
> /gnu/store/f0ca0lf64bw08srv1bj7gkg6ag0sbdb2-gcc-7.5.0-
> lib           71.0    32.6   5.7%
> /gnu/store/01b4w3m6mp55y531kyi1g8shh722kwqm-gcc-7.5.0-
> lib           71.0    32.6   5.7%
> /gnu/store/nzfhh1rm85lx2p5plbx45qqj82pcv5hp-clang-runtime-
> 12.0.0    95.9    24.9   4.3%
> /gnu/store/mmhimfwmmidf09jw1plw3aw1g1zn2nkh-bash-static-
> 5.0.16       1.6     1.6   0.3%
> /gnu/store/g2s5jfkfd4k973wb58476b1bbv9zpm6m-zlib-
> 1.2.11             38.6     0.2   0.0%
> /gnu/store/rykm237xkmq7rl1p0nwass01p090p88x-zlib-
> 1.2.11             71.2     0.2   0.0%
> /gnu/store/bw15z9kh9c65ycc2vbhl2izwfwfva7p1-libffi-
> 3.3              71.2     0.2   0.0%
> total: 576.6 MiB
> --8<---------------cut here---------------end--------------->8---
> 
> It looks like we're retaining references to the main gcc-7.5.0
> output, but only to its "include/c++" directory, as a single
> reference in the zig binary.  I expect this would cause issues if
> another GCC version were later used with Zig.
Where does that include/c++ come from?  Could it be related to the libc
header thing we talked about in IRC?  I don't see any substitution for
that going on either.

> We're retaining double direct references to gcc-7.5.0-lib, and double
> indirect references to zlib-1.2.11.  This seems to come from clang.
> (Wow, clang is big. Maybe it should have a separate "lib"
> output?  Zig, for example, only needs libclang to build, not the
> binaries.)
> 
> Other than those items, it looks good!
According to `guix refresh', there's only two dependents of Clang 12,
but since we'd have to rebuild all clangs, that might go into core-
updates territory.  We might also want to check with an expert on
X/Mesa, since that seems to be one of our biggest clang dependents.

> +       (patches
> +        (search-patches
> +         "zig-disable-libc-note-test.patch"
Is this test really necessary to skip that test?  If not, let's try to
use the command line for that.
> +         ;; XXX: Remove the following patch when updating LLVM to
> 12.0.1.
> +         "zig-disable-MIPS-tests.patch"
There's a patch for LLVM 12.0.1 waiting in the ML and we could
potentially bump lld to 12.0.1 regardless.  (Can LLVM components be
mix-matched like that?)
> +         "zig-fix-cross-native-execution.patch"
IIUC this is weaker than "-Dskip-non-native".  Is there a reason to
include specifically these non-native tests?
> +         "zig-use-explicit-paths.patch"))))

> +    (native-search-paths
> +     (list
> +      (search-path-specification
> +       (variable "ZIG_INCLUDE_DIRS")
> +       ;; XXX: It doesn't seem as though Zig can distinguish between
> C and C++
> +       ;;      include paths, so provide both.
> +       (files '("include/c++" "include")))
> +      (search-path-specification
> +       ;; TODO: Might be confused with "ZIG_LIB_DIR"... Maybe use
> +       ;;       "ZIG_INCLUDE_PATH" and "ZIG_LIBRARY_PATH"?
> +       (variable "ZIG_LIB_DIRS")
> +       (files '("lib" "lib64")))))
You can rewrite "zig-use-explicit-paths.patch" in-place with Emacs'
query-replace and/or sed (or even just manually, there are no lines to
add or remove) if you disagree with my environment variable naming
choice.  Just make sure you don't accidentally break diff by deleting
trailing space.

Regards
Liliana Marie Prikler Sept. 12, 2021, 7:39 a.m. UTC | #2
Hi,

Am Sonntag, den 12.09.2021, 09:32 +0200 schrieb Liliana Marie Prikler:
> > +    (native-search-paths
> > +     (list
> > +      (search-path-specification
> > +       (variable "ZIG_INCLUDE_DIRS")
> > +       ;; XXX: It doesn't seem as though Zig can distinguish
> > between
> > C and C++
> > +       ;;      include paths, so provide both.
> > +       (files '("include/c++" "include")))
> > +      (search-path-specification
> > +       ;; TODO: Might be confused with "ZIG_LIB_DIR"... Maybe use
> > +       ;;       "ZIG_INCLUDE_PATH" and "ZIG_LIBRARY_PATH"?
> > +       (variable "ZIG_LIB_DIRS")
> > +       (files '("lib" "lib64")))))
> You can rewrite "zig-use-explicit-paths.patch" in-place with Emacs'
> query-replace and/or sed (or even just manually, there are no lines
> to add or remove) if you disagree with my environment variable naming
> choice.  Just make sure you don't accidentally break diff by deleting
> trailing space.
Another potential naming choice would be to prefix everything with
ZIG_LIBC_ rather than simply ZIG_.  Of course I thought about that only
after sending my previous mail ^^"
Sarah Morgensen Sept. 12, 2021, 10:40 p.m. UTC | #3
Liliana Marie Prikler <liliana.prikler@gmail.com> writes:

>> It looks like we're retaining references to the main gcc-7.5.0
>> output, but only to its "include/c++" directory, as a single
>> reference in the zig binary.  I expect this would cause issues if
>> another GCC version were later used with Zig.
> Where does that include/c++ come from?  Could it be related to the libc
> header thing we talked about in IRC?  I don't see any substitution for
> that going on either.

I think the build process for Zig might save it after auto-detecting it
as a default include path or something? In the binary, here's where it
appears:

--8<---------------cut here---------------start------------->8---
-gpsize=
GNU::Linker
/lib/i386-gnu
/../lib/
/usr/lib/
/usr/lib/../
static-lib-linker
GNU::StaticLibTool
/../../../../
/libc
/gnu/store/rn75fm7adgx3pw5j8pg3bczfqq1y17lk-gcc-7.5.0/include/c++
/../include/g++
ld-uClibc-mipsn8.so.0
ld-uClibc.so.0
ld-musl-mipsel.so.1
ld-musl-mips.so.1
/system/bin/linker
/system/bin/linker64
/lib/ld-musl-
ld-linux-riscv32-
ld-linux-riscv64-
--8<---------------cut here---------------end--------------->8---

Searching the Clang source yields a const reference in
'lib/Driver/ToolChains/Linux.cpp' at line 406:

--8<---------------cut here---------------start------------->8---
  const StringRef InstallDir = GCCInstallation.getInstallPath();
  const StringRef TripleStr = GCCInstallation.getTriple().str();
  const Multilib &Multilib = GCCInstallation.getMultilib();

  std::string Path =
      (InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix())
          .str();
--8<---------------cut here---------------end--------------->8---

And I just searched the Clang input for this reference--that exact path
with the exact same context as above is present in libclang,
libclangDriver, and everything that gets linked to them.  So it looks
like this one we can blame on Clang as well.

>> We're retaining double direct references to gcc-7.5.0-lib, and double
>> indirect references to zlib-1.2.11.  This seems to come from clang.
>> (Wow, clang is big. Maybe it should have a separate "lib"
>> output?  Zig, for example, only needs libclang to build, not the
>> binaries.)
>> 
>> Other than those items, it looks good!
> According to `guix refresh', there's only two dependents of Clang 12,
> but since we'd have to rebuild all clangs, that might go into core-
> updates territory.  We might also want to check with an expert on
> X/Mesa, since that seems to be one of our biggest clang dependents.

Yeah, Clang is an absolute beast to mess with, so I don't think we
should let this be a blocker for Zig.  I'll submit a bug report to see
if I can summon the experts, though.

>> +       (patches
>> +        (search-patches
>> +         "zig-disable-libc-note-test.patch"
> Is this test really necessary to skip that test?  If not, let's try to
> use the command line for that.

We could use "-Dskip-compile-errors", but that also skips ~600 other
test cases.

>> +         ;; XXX: Remove the following patch when updating LLVM to
>> 12.0.1.
>> +         "zig-disable-MIPS-tests.patch"
> There's a patch for LLVM 12.0.1 waiting in the ML and we could
> potentially bump lld to 12.0.1 regardless.  (Can LLVM components be
> mix-matched like that?)

I have no idea if they *can*, but I'm pretty sure they're not intended
to be, as LLVM wants you to build everything together in one big blob.

>> +         "zig-fix-cross-native-execution.patch"
> IIUC this is weaker than "-Dskip-non-native".  Is there a reason to
> include specifically these non-native tests?

Yes, as I wrote in the patch header, it fixes the behavior of 'zig run'
and 'zig test' when the target is cross-native.  Would we want to stick
to upstream, even if it's buggy?

We might want to add "-Dskip-non-native" anyway as it speeds up tests by
an order of magnitude, in which case tests will succeed without the
patch.  It looks their CI uses it "-Dskip-non-native" as well, and I
suppose there's not a whole lot Guix can do to mess up Zig's
cross-compiling anyway, since it's pretty self-contained...

>> +    (native-search-paths
>> +     (list
>> +      (search-path-specification
>> +       (variable "ZIG_INCLUDE_DIRS")
>> +       ;; XXX: It doesn't seem as though Zig can distinguish between
>> C and C++
>> +       ;;      include paths, so provide both.
>> +       (files '("include/c++" "include")))
>> +      (search-path-specification
>> +       ;; TODO: Might be confused with "ZIG_LIB_DIR"... Maybe use
>> +       ;;       "ZIG_INCLUDE_PATH" and "ZIG_LIBRARY_PATH"?
>> +       (variable "ZIG_LIB_DIRS")
>> +       (files '("lib" "lib64")))))
> You can rewrite "zig-use-explicit-paths.patch" in-place with Emacs'
> query-replace and/or sed (or even just manually, there are no lines to
> add or remove) if you disagree with my environment variable naming
> choice.  Just make sure you don't accidentally break diff by deleting
> trailing space.

> Another potential naming choice would be to prefix everything with
> ZIG_LIBC_ rather than simply ZIG_.  Of course I thought about that only
> after sending my previous mail ^^"

Ah, I meant to mention it in my last e-mail but I forgot.  I didn't want
to just go changing it on you without discussing it.

As far as I can tell, there's no such thing as a "Zig library" or a "Zig
header"; these are for including system C headers and libraries.  So, I
would just go with LIBRARY_PATH and CPLUS_INCLUDE_PATH unless we
anticipate needing to tell Zig something different than what we tell
GCC/Clang.  Furthermore, the in-development 'zig cc' command is intended
to be a drop-in replacement for GCC/Clang, so it should probably honor
the same environment variables.

--
Sarah
diff mbox series

Patch

From 06ed65a6f49c290bbf1b773da8874353344a5b55 Mon Sep 17 00:00:00 2001
Message-Id: <06ed65a6f49c290bbf1b773da8874353344a5b55.1631421568.git.iskarian@mgsn.dev>
In-Reply-To: <de7531db2e27b002cc4ba4d6347baa35cece0264.1631421568.git.iskarian@mgsn.dev>
References: <de7531db2e27b002cc4ba4d6347baa35cece0264.1631421568.git.iskarian@mgsn.dev>
From: Liliana Prikler <liliana.prikler@gmail.com>
Date: Thu, 9 Sep 2021 15:32:22 +0200
Subject: [WIP PATCH v3 2/2] gnu: Add zig.

* gnu/packages/patches/zig-disable-libc-note-test.patch,
gnu/packages/patches/zig-disable-MIPS-tests.patch,
gnu/packages/patches/zig-fix-cross-native-execution.patch,
gnu/packages/patches/zig-use-explicit-paths.patch: New files.
* gnu/packages/zig.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES, dist_patch_DATA): Adjust accordingly.
---
 gnu/local.mk                                  |   5 +
 .../patches/zig-disable-MIPS-tests.patch      |  87 ++++++++++++
 .../patches/zig-disable-libc-note-test.patch  |  31 ++++
 .../zig-fix-cross-native-execution.patch      |  64 +++++++++
 .../patches/zig-use-explicit-paths.patch      | 132 ++++++++++++++++++
 gnu/packages/zig.scm                          | 109 +++++++++++++++
 6 files changed, 428 insertions(+)
 create mode 100644 gnu/packages/patches/zig-disable-MIPS-tests.patch
 create mode 100644 gnu/packages/patches/zig-disable-libc-note-test.patch
 create mode 100644 gnu/packages/patches/zig-fix-cross-native-execution.patch
 create mode 100644 gnu/packages/patches/zig-use-explicit-paths.patch
 create mode 100644 gnu/packages/zig.scm

diff --git a/gnu/local.mk b/gnu/local.mk
index 2a56c4a9e2..dab959845c 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -598,6 +598,7 @@  GNU_SYSTEM_MODULES =				\
   %D%/packages/xdisorg.scm			\
   %D%/packages/xorg.scm				\
   %D%/packages/xfce.scm				\
+  %D%/packages/zig.scm				\
   %D%/packages/zile.scm				\
   %D%/packages/zwave.scm			\
 						\
@@ -1903,6 +1904,10 @@  dist_patch_DATA =						\
   %D%/packages/patches/ytfzf-updates.patch        \
   %D%/packages/patches/ytnef-CVE-2021-3403.patch	\
   %D%/packages/patches/ytnef-CVE-2021-3404.patch	\
+  %D%/packages/patches/zig-disable-libc-note-test.patch         \
+  %D%/packages/patches/zig-disable-MIPS-tests.patch             \
+  %D%/packages/patches/zig-fix-cross-native-execution.patch     \
+  %D%/packages/patches/zig-use-explicit-paths.patch	        \
   %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch	\
   %D%/packages/patches/zziplib-CVE-2018-16548.patch
 
diff --git a/gnu/packages/patches/zig-disable-MIPS-tests.patch b/gnu/packages/patches/zig-disable-MIPS-tests.patch
new file mode 100644
index 0000000000..80d72f1b9c
--- /dev/null
+++ b/gnu/packages/patches/zig-disable-MIPS-tests.patch
@@ -0,0 +1,87 @@ 
+Upstream issue: https://github.com/ziglang/zig/issues/8155
+
+Zig fails to cross-compile to MIPS architectures with LLVM 12.0.0.  The issue
+is fixed in LLVM 12.0.1.
+
+diff --git a/test/tests.zig b/test/tests.zig
+index b80c082fb..cd0c24fc9 100644
+--- a/test/tests.zig
++++ b/test/tests.zig
+@@ -153,22 +153,22 @@ const test_targets = blk: {
+         //    .link_libc = true,
+         //},
+ 
+-        TestTarget{
+-            .target = .{
+-                .cpu_arch = .mips,
+-                .os_tag = .linux,
+-                .abi = .none,
+-            },
+-        },
+-
+-        TestTarget{
+-            .target = .{
+-                .cpu_arch = .mips,
+-                .os_tag = .linux,
+-                .abi = .musl,
+-            },
+-            .link_libc = true,
+-        },
++        // TestTarget{
++        //     .target = .{
++        //         .cpu_arch = .mips,
++        //         .os_tag = .linux,
++        //         .abi = .none,
++        //     },
++        // },
++
++        // TestTarget{
++        //     .target = .{
++        //         .cpu_arch = .mips,
++        //         .os_tag = .linux,
++        //         .abi = .musl,
++        //     },
++        //     .link_libc = true,
++        // },
+ 
+         // https://github.com/ziglang/zig/issues/4927
+         //TestTarget{
+@@ -180,22 +180,22 @@ const test_targets = blk: {
+         //    .link_libc = true,
+         //},
+ 
+-        TestTarget{
+-            .target = .{
+-                .cpu_arch = .mipsel,
+-                .os_tag = .linux,
+-                .abi = .none,
+-            },
+-        },
+-
+-        TestTarget{
+-            .target = .{
+-                .cpu_arch = .mipsel,
+-                .os_tag = .linux,
+-                .abi = .musl,
+-            },
+-            .link_libc = true,
+-        },
++        // TestTarget{
++        //     .target = .{
++        //         .cpu_arch = .mipsel,
++        //         .os_tag = .linux,
++        //         .abi = .none,
++        //     },
++        // },
++
++        // TestTarget{
++        //     .target = .{
++        //         .cpu_arch = .mipsel,
++        //         .os_tag = .linux,
++        //         .abi = .musl,
++        //     },
++        //     .link_libc = true,
++        // },
+ 
+         // https://github.com/ziglang/zig/issues/4927
+         //TestTarget{
diff --git a/gnu/packages/patches/zig-disable-libc-note-test.patch b/gnu/packages/patches/zig-disable-libc-note-test.patch
new file mode 100644
index 0000000000..971ae53912
--- /dev/null
+++ b/gnu/packages/patches/zig-disable-libc-note-test.patch
@@ -0,0 +1,31 @@ 
+This test fails with "error.CompilationIncorrectlySucceeded".
+
+diff --git a/test/compile_errors.zig b/test/compile_errors.zig
+index fd1255c..20d5548 100644
+--- a/test/compile_errors.zig
++++ b/test/compile_errors.zig
+@@ -2751,15 +2751,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
+             "tmp.zig:3:5: error: dependency on libc must be explicitly specified in the build command",
+         });
+ 
+-        cases.addTest("libc headers note",
+-            \\const c = @cImport(@cInclude("stdio.h"));
+-            \\export fn entry() void {
+-            \\    _ = c.printf("hello, world!\n");
+-            \\}
+-        , &[_][]const u8{
+-            "tmp.zig:1:11: error: C import failed",
+-            "tmp.zig:1:11: note: libc headers not available; compilation does not link against libc",
+-        });
++//        cases.addTest("libc headers note",
++//            \\const c = @cImport(@cInclude("stdio.h"));
++//            \\export fn entry() void {
++//            \\    _ = c.printf("hello, world!\n");
++//            \\}
++//        , &[_][]const u8{
++//            "tmp.zig:1:11: error: C import failed",
++//            "tmp.zig:1:11: note: libc headers not available; compilation does not link against libc",
++//        });
+     }
+ 
+     cases.addTest("comptime vector overflow shows the index",
diff --git a/gnu/packages/patches/zig-fix-cross-native-execution.patch b/gnu/packages/patches/zig-fix-cross-native-execution.patch
new file mode 100644
index 0000000000..1952c6b867
--- /dev/null
+++ b/gnu/packages/patches/zig-fix-cross-native-execution.patch
@@ -0,0 +1,64 @@ 
+Upstream issue: https://github.com/ziglang/zig/issues/9738
+
+Without this patch, 'zig run' or 'zig test' attempts to run cross-native
+binaries even if their dynamic loader isn't present, which causes a crash
+with "error: FileNotFound".
+
+---
+diff --git a/src/main.zig b/src/main.zig
+index c1d12fcba..9b1bee0d6 100644
+--- a/src/main.zig
++++ b/src/main.zig
+@@ -2040,7 +2040,7 @@ fn buildOutputType(
+             test_exec_args.items,
+             self_exe_path,
+             arg_mode,
+-            target_info.target,
++            target_info,
+             watch,
+             &comp_destroyed,
+             all_args,
+@@ -2110,7 +2110,7 @@ fn buildOutputType(
+                         test_exec_args.items,
+                         self_exe_path,
+                         arg_mode,
+-                        target_info.target,
++                        target_info,
+                         watch,
+                         &comp_destroyed,
+                         all_args,
+@@ -2134,7 +2134,7 @@ fn buildOutputType(
+                         test_exec_args.items,
+                         self_exe_path,
+                         arg_mode,
+-                        target_info.target,
++                        target_info,
+                         watch,
+                         &comp_destroyed,
+                         all_args,
+@@ -2158,7 +2158,7 @@ fn runOrTest(
+     test_exec_args: []const ?[]const u8,
+     self_exe_path: []const u8,
+     arg_mode: ArgMode,
+-    target: std.Target,
++    target: std.zig.system.NativeTargetInfo,
+     watch: bool,
+     comp_destroyed: *bool,
+     all_args: []const []const u8,
+@@ -2174,7 +2174,15 @@ fn runOrTest(
+     defer argv.deinit();
+ 
+     if (test_exec_args.len == 0) {
+-        if (!std.Target.current.canExecBinariesOf(target)) {
++        const can_run = blk: {
++              if (!std.Target.current.canExecBinariesOf(target.target)) break :blk false;
++              if (target.dynamic_linker.get()) |dl| {
++                  std.fs.cwd().access(dl, .{}) catch break :blk false;
++                  break :blk true;
++              }
++              break :blk false;
++        };
++        if (!can_run) {
+             switch (arg_mode) {
+                 .zig_test => {
+                     warn("created {s} but skipping execution because it is non-native", .{exe_path});
diff --git a/gnu/packages/patches/zig-use-explicit-paths.patch b/gnu/packages/patches/zig-use-explicit-paths.patch
new file mode 100644
index 0000000000..ab0d2c7f8b
--- /dev/null
+++ b/gnu/packages/patches/zig-use-explicit-paths.patch
@@ -0,0 +1,132 @@ 
+This patch replaces the OS-specific detection mechanism by one that solely
+relies on environment variables.  This has the benefit that said environment
+variables can be used as search paths in Guix.
+
+Index: zig-0.8.1/lib/std/zig/system.zig
+===================================================================
+--- zig-0.8.1.orig/lib/std/zig/system.zig
++++ zig-0.8.1/lib/std/zig/system.zig
+@@ -39,101 +39,44 @@ pub const NativePaths = struct {
+         };
+         errdefer self.deinit();
+ 
+-        var is_nix = false;
+-        if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
+-            defer allocator.free(nix_cflags_compile);
+-
+-            is_nix = true;
+-            var it = mem.tokenize(nix_cflags_compile, " ");
++        // TODO: Support cross-compile paths?
++        if (process.getEnvVarOwned(allocator, "ZIG_INCLUDE_DIRS")) |zig_include_dirs| {
++            defer allocator.free(zig_include_dirs);
++            var it = mem.tokenize(zig_include_dirs, ":");
+             while (true) {
+-                const word = it.next() orelse break;
+-                if (mem.eql(u8, word, "-isystem")) {
+-                    const include_path = it.next() orelse {
+-                        try self.addWarning("Expected argument after -isystem in NIX_CFLAGS_COMPILE");
+-                        break;
+-                    };
+-                    try self.addIncludeDir(include_path);
+-                } else {
+-                    if (mem.startsWith(u8, word, "-frandom-seed=")) {
+-                        continue;
+-                    }
+-                    try self.addWarningFmt("Unrecognized C flag from NIX_CFLAGS_COMPILE: {s}", .{word});
+-                }
++                const dir = it.next() orelse break;
++                try self.addIncludeDir(dir);
+             }
+         } else |err| switch (err) {
+             error.InvalidUtf8 => {},
+             error.EnvironmentVariableNotFound => {},
+             error.OutOfMemory => |e| return e,
+         }
+-        if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| {
+-            defer allocator.free(nix_ldflags);
+ 
+-            is_nix = true;
+-            var it = mem.tokenize(nix_ldflags, " ");
++        if (process.getEnvVarOwned(allocator, "ZIG_LIB_DIRS")) |zig_lib_dirs| {
++            defer allocator.free(zig_lib_dirs);
++            var it = mem.tokenize(zig_lib_dirs, ":");
+             while (true) {
+-                const word = it.next() orelse break;
+-                if (mem.eql(u8, word, "-rpath")) {
+-                    const rpath = it.next() orelse {
+-                        try self.addWarning("Expected argument after -rpath in NIX_LDFLAGS");
+-                        break;
+-                    };
+-                    try self.addRPath(rpath);
+-                } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') {
+-                    const lib_path = word[2..];
+-                    try self.addLibDir(lib_path);
+-                } else {
+-                    try self.addWarningFmt("Unrecognized C flag from NIX_LDFLAGS: {s}", .{word});
+-                    break;
+-                }
++                const dir = it.next() orelse break;
++                try self.addLibDir(dir);
+             }
+         } else |err| switch (err) {
+             error.InvalidUtf8 => {},
+             error.EnvironmentVariableNotFound => {},
+             error.OutOfMemory => |e| return e,
+         }
+-        if (is_nix) {
+-            return self;
+-        }
+-
+-        if (comptime Target.current.isDarwin()) {
+-            try self.addIncludeDir("/usr/include");
+-            try self.addIncludeDir("/usr/local/include");
+-
+-            try self.addLibDir("/usr/lib");
+-            try self.addLibDir("/usr/local/lib");
+-
+-            try self.addFrameworkDir("/Library/Frameworks");
+-            try self.addFrameworkDir("/System/Library/Frameworks");
+-
+-            return self;
+-        }
+-
+-        if (native_target.os.tag != .windows) {
+-            const triple = try native_target.linuxTriple(allocator);
+-            const qual = native_target.cpu.arch.ptrBitWidth();
+-
+-            // TODO: $ ld --verbose | grep SEARCH_DIR
+-            // the output contains some paths that end with lib64, maybe include them too?
+-            // TODO: what is the best possible order of things?
+-            // TODO: some of these are suspect and should only be added on some systems. audit needed.
+ 
+-            try self.addIncludeDir("/usr/local/include");
+-            try self.addLibDirFmt("/usr/local/lib{d}", .{qual});
+-            try self.addLibDir("/usr/local/lib");
+-
+-            try self.addIncludeDirFmt("/usr/include/{s}", .{triple});
+-            try self.addLibDirFmt("/usr/lib/{s}", .{triple});
+-
+-            try self.addIncludeDir("/usr/include");
+-            try self.addLibDirFmt("/lib{d}", .{qual});
+-            try self.addLibDir("/lib");
+-            try self.addLibDirFmt("/usr/lib{d}", .{qual});
+-            try self.addLibDir("/usr/lib");
+-
+-            // example: on a 64-bit debian-based linux distro, with zlib installed from apt:
+-            // zlib.h is in /usr/include (added above)
+-            // libz.so.1 is in /lib/x86_64-linux-gnu (added here)
+-            try self.addLibDirFmt("/lib/{s}", .{triple});
++        if (process.getEnvVarOwned(allocator, "ZIG_FRAMEWORK_DIRS")) |zig_framework_dirs| {
++            defer allocator.free(zig_framework_dirs);
++            var it = mem.tokenize(zig_framework_dirs, ":");
++            while (true) {
++                const dir = it.next() orelse break;
++                try self.addFrameworkDir(dir);
++            }
++        } else |err| switch (err) {
++            error.InvalidUtf8 => {},
++            error.EnvironmentVariableNotFound => {},
++            error.OutOfMemory => |e| return e,
+         }
+ 
+         return self;
diff --git a/gnu/packages/zig.scm b/gnu/packages/zig.scm
new file mode 100644
index 0000000000..639cc937e6
--- /dev/null
+++ b/gnu/packages/zig.scm
@@ -0,0 +1,109 @@ 
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2021 Liliana Prikler <liliana.prikler@gmail.com>
+;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages zig)
+  #:use-module (guix packages)
+  #:use-module (guix git-download)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix build-system cmake)
+  #:use-module (gnu packages)
+  #:use-module (gnu packages llvm))
+
+(define-public zig
+  (package
+    (name "zig")
+    (version "0.8.1")
+    (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 "147qx7xgj0r353wh5ragzn6kmm1vrf31i8038z3zqwjnqqgqxi6c"))
+       (patches
+        (search-patches
+         "zig-disable-libc-note-test.patch"
+         ;; XXX: Remove the following patch when updating LLVM to 12.0.1.
+         "zig-disable-MIPS-tests.patch"
+         "zig-fix-cross-native-execution.patch"
+         "zig-use-explicit-paths.patch"))))
+    (build-system cmake-build-system)
+    (inputs
+     `(("clang" ,clang-12) ; Clang propagates llvm.
+       ("lld" ,lld-12)))
+    ;; Zig compiles fine with GCC, but also needs native LLVM libraries.
+    (native-inputs
+     `(("llvm" ,llvm-12)))
+    (arguments
+     `(#:configure-flags
+       (list ,@(if (%current-target-system)
+                   (string-append "-DZIG_TARGET_TRIPLE="
+                                  (%current-target-system))
+                   '()))
+       #:out-of-source? #f ; for tests
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'configure 'set-cache-dir
+           (lambda _
+             ;; Set cache dir, otherwise Zig looks for `$HOME/.cache'.
+             (setenv "ZIG_GLOBAL_CACHE_DIR"
+                     (string-append (getcwd) "/zig-cache"))))
+         (delete 'check)
+         (add-after 'install 'check
+           (lambda* (#:key outputs tests? #:allow-other-keys)
+             (when tests?
+               (invoke (string-append (assoc-ref outputs "out") "/bin/zig")
+                       ;; Testing the standard library takes >7.5GB RAM, and
+                       ;; will fail if it is OOM-killed.  The 'test-toolchain'
+                       ;; target skips standard library and doc tests.
+                       "build" "test-toolchain"
+                       ;; Stage 2 is experimental, not what we run with `zig',
+                       ;; and stage 2 tests require a lot of RAM.
+                       "-Dskip-stage2-tests"
+                       ;; Options to drop some test configurations.
+                       ;;"-Dskip-non-native" "-Dskip-release-small"
+                       ;;"-Dskip-release-fast" "-Dskip-release-safe"
+                       )))))))
+    (native-search-paths
+     (list
+      (search-path-specification
+       (variable "ZIG_INCLUDE_DIRS")
+       ;; XXX: It doesn't seem as though Zig can distinguish between C and C++
+       ;;      include paths, so provide both.
+       (files '("include/c++" "include")))
+      (search-path-specification
+       ;; TODO: Might be confused with "ZIG_LIB_DIR"... Maybe use
+       ;;       "ZIG_INCLUDE_PATH" and "ZIG_LIBRARY_PATH"?
+       (variable "ZIG_LIB_DIRS")
+       (files '("lib" "lib64")))))
+    (synopsis "General purpose programming language and toolchain")
+    (description "Zig is a general-purpose programming language and
+toolchain.  Among other features it provides
+@itemize
+@item an Optional type instead of null pointers,
+@item manual memory management,
+@item generic data structures and functions,
+@item compile-time reflection and compile-time code execution,
+@item integration with C using zig as a C compiler, and
+@item concurrency via async functions.
+@end itemize")
+    (home-page "https://github.com/ziglang/zig")
+    (license license:expat)))
-- 
2.33.0