I’m trying to use devkitPro to create homebrew for the Nintendo Switch with Zig, but after upgrading from Zig 0.15.1 to Zig 0.16 I get a lot of type‑redefinition and function‑redefinition errors in libnx headers
this is the code I want to compile:
const c = @cImport({
@cInclude("switch.h");
@cInclude("stdio.h");
});
export fn main(_: c_int, _: [*]const [*:0]const u8) void {
_ = c.consoleInit(null);
defer c.consoleExit(null);
_ = c.printf("Hello, Zig");
while (c.appletMainLoop()) {
c.consoleUpdate(null);
}
}
using:
zig build-obj --name zig-switch src/main.zig \
-target aarch64-freestanding -mcpu=cortex_a57 \
-I $DEVKITPRO/libnx/include/ \
--libc libc.txt -lc
works fine on zig 0.15.1 but on zig 0.16 I get this errors (I cant upload the full logs):
src/main.zig:1:11: error: C import failed
const c = @cImport({
^~~~~~~~
referenced by:
main: src/main.zig:7:9
main: src/main.zig:6:1
4 reference(s) hidden; use '-freference-trace=6' to see all references
error: translation failure
/opt/zig-bin-0.16.0/lib/include/arm_acle.h:21:2: error: \"ACLE intrinsics support not enabled.\"
#error "ACLE intrinsics support not enabled."
^
/opt/devkitpro/libnx/include/switch/arm/../types.h:48:35: error: typedef redefinition with different types ('struct (anonymous struct at /opt/devkitpro/libnx/include/switch/arm/../types.h:48:9)' vs 'struct (anonymous struct at /opt/devkitpro/libnx/include/switch/types.h:48:9)')
typedef struct { u8 uuid[0x10]; } Uuid; ///< Unique identifier.
..................................
........................................
........................................
/opt/devkitpro/libnx/include/switch/crypto/../types.h:48:35: error: typedef redefinition with different types ('struct (anonymous struct at /opt/devkitpro/libnx/include/switch/crypto/../types.h:48:9)' vs 'struct (anonymous struct at /opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/../types.h:48:9)')
typedef struct { u8 uuid[0x10]; } Uuid; ///< Unique identifier.
^
/opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/../types.h:48:35: note: previous definition is here
typedef struct { u8 uuid[0x10]; } Uuid; ///< Unique identifier.
^
/opt/devkitpro/libnx/include/switch/crypto/../types.h:50:36: error: typedef redefinition with different types ('struct (anonymous struct at /opt/devkitpro/libnx/include/switch/crypto/../types.h:50:9)' vs 'struct (anonymous struct at /opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/../types.h:50:9)')
typedef struct { float value[3]; } UtilFloat3; ///< 3 floats.
^
/opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/../types.h:50:36: note: previous definition is here
typedef struct { float value[3]; } UtilFloat3; ///< 3 floats.
^
/opt/devkitpro/libnx/include/switch/crypto/sha256.h:25:3: error: typedef redefinition with different types ('struct (anonymous struct at /opt/devkitpro/libnx/include/switch/crypto/sha256.h:19:9)' vs 'struct (anonymous struct at /opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/sha256.h:19:9)')
} Sha256Context;
^
/opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/sha256.h:25:3: note: previous definition is here
} Sha256Context;
^
/opt/devkitpro/libnx/include/switch/crypto/sha256.h:28:6: error: redefinition of 'sha256ContextCreate' with a different type
void sha256ContextCreate(Sha256Context *out);
^
/opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/sha256.h:28:6: note: previous definition is here
void sha256ContextCreate(Sha256Context *out);
^
/opt/devkitpro/libnx/include/switch/crypto/sha256.h:30:6: error: redefinition of 'sha256ContextUpdate' with a different type
void sha256ContextUpdate(Sha256Context *ctx, const void *src, size_t size);
^
/opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/sha256.h:30:6: note: previous definition is here
void sha256ContextUpdate(Sha256Context *ctx, const void *src, size_t size);
^
/opt/devkitpro/libnx/include/switch/crypto/sha256.h:32:6: error: redefinition of 'sha256ContextGetHash' with a different type
void sha256ContextGetHash(Sha256Context *ctx, void *dst);
^
/opt/devkitpro/libnx/include/switch/runtime/devices/../../services/../crypto/sha256.h:32:6: note: previous definition is here
void sha256ContextGetHash(Sha256Context *ctx, void *dst);
^
/opt/zig-bin-0.16.0/lib/include/arm_acle.h:60:7: error: assignment to 'uint32_t' (aka 'unsigned int') from incompatible type 'void'
v = __builtin_arm_ldrex(__p);
contents of the libc.txt used:
# The directory that contains `stdlib.h`.
# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
include_dir=/opt/devkitpro/devkitA64/aarch64-none-elf/include
# The system-specific include directory. May be the same as `include_dir`.
# On Windows it's the directory that includes `vcruntime.h`.
# On POSIX it's the directory that includes `sys/errno.h`.
sys_include_dir=/opt/devkitpro/devkitA64/aarch64-none-elf/include
# The directory that contains `crt1.o` or `crt2.o`.
# On POSIX, can be found with `cc -print-file-name=crt1.o`.
# Not needed when targeting MacOS.
crt_dir=/opt/devkitpro/devkitA64/lib
# The directory that contains `vcruntime.lib`.
# Only needed when targeting MSVC on Windows.
msvc_lib_dir=
# The directory that contains `kernel32.lib`.
# Only needed when targeting MSVC on Windows.
kernel32_lib_dir=
# The directory that contains `crtbeginS.o` and `crtendS.o`
# Only needed when targeting Haiku.
gcc_dir=
I also tried to use zig translate-c with:
zig translate-c -target aarch64-freestanding \
-I /opt/devkitpro/libnx/include \
--libc libc.txt -lc /opt/devkitpro/libnx/include/switch.h > libnx.zig
but I get the exact same results as before.
The only thing that currently builds is manually declaring the needed libnx functions as extern symbols:
pub extern fn consoleInit(console: ?*void) void;
pub extern fn consoleExit(console: ?*void) void;
pub extern fn consoleUpdate(console: ?*void) void;
pub extern fn appletMainLoop() bool;
pub extern fn printf(fmt: [*:0]const u8, ...) c_int;
export fn main(_: c_int, _: [*]const [*:0]const u8) void {
_ = consoleInit(null);
defer consoleExit(null);
_ = printf("Hello, Zig");
while (appletMainLoop()) {
consoleUpdate(null);
}
}
this works but is a pain in the ass.
If anyone has a proper fix or a set of flags that lets Zig compile against devkitPro/libnx without resorting to manual extern declarations, please share. This seems to be a fairly niche setup, so any insight would be greatly appreciated. Thanks!
