Skip to content

Commit dcf5a5f

Browse files
committed
Zig build support added (>= 0.13.0)
1 parent a2d0be9 commit dcf5a5f

File tree

4 files changed

+261
-1
lines changed

4 files changed

+261
-1
lines changed

.github/workflows/zig-ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Zig-CI
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
strategy:
8+
fail-fast: false
9+
matrix:
10+
runs-on: [ubuntu-latest, macos-latest, windows-latest]
11+
runs-on: ${{ matrix.runs-on }}
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: mlugg/setup-zig@v1
15+
with:
16+
version: master
17+
- name: (Zig) Build
18+
run: zig build --summary all -Dexamples -freference-trace
19+
20+
cross:
21+
runs-on: ubuntu-latest
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
targets:
26+
- aarch64-linux-gnu
27+
- mipsel-linux-musl
28+
- aarch64-linux-musl
29+
- riscv64-linux-musl
30+
- x86_64-linux-musl
31+
- x86-linux-musl
32+
steps:
33+
- uses: actions/checkout@v4
34+
- uses: mlugg/setup-zig@v1
35+
with:
36+
version: master
37+
- name: Build Summary ${{ matrix.targets }}
38+
run: zig build --summary all -Dexamples -freference-trace -Dtarget=${{ matrix.targets }}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
.libs
77
/aclocal.m4
88
/autom4te.cache
9-
/bin*
9+
/bin
1010
/build
1111
/compile
1212
/config.guess
@@ -75,3 +75,4 @@ tools/doc/man-date.ent
7575
.cache/
7676
compile_commands.json
7777
codegen/
78+
*zig-*/

bindings/rmq.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub const rmq = @cImport({
2+
@cInclude("amqp.h");
3+
@cInclude("amqp_tcp_socket.h");
4+
@cInclude("amqp_ssl_socket.h");
5+
@cInclude("amqp_framing.h");
6+
});
7+
8+
test {
9+
_ = rmq;
10+
}

build.zig

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
const std = @import("std");
2+
3+
const rmq_version: std.SemanticVersion = .{
4+
.major = 0,
5+
.minor = 15,
6+
.patch = 0,
7+
};
8+
9+
pub fn build(b: *std.Build) void {
10+
const target = b.standardTargetOptions(.{});
11+
const optimize = b.standardOptimizeOption(.{});
12+
13+
const bindings = b.option(bool, "bindings", "Use zig module") orelse false;
14+
const examples = b.option(bool, "examples", "Build examples") orelse false;
15+
const shared = b.option(bool, "shared", "Build shared library") orelse false;
16+
const ssl = b.option(bool, "ssl", "Build with SSL support") orelse false;
17+
18+
const generated_export_header = b.addWriteFile("rabbitmq-c/export.h", export_h);
19+
20+
const lib = if (shared) b.addSharedLibrary(.{
21+
.name = "rabbitmq-c",
22+
.target = target,
23+
.optimize = optimize,
24+
.version = rmq_version,
25+
}) else b.addStaticLibrary(.{
26+
.name = "rabbitmq-c-static",
27+
.target = target,
28+
.optimize = optimize,
29+
.version = rmq_version,
30+
});
31+
if (!shared) {
32+
lib.pie = true;
33+
lib.defineCMacro("AMQP_STATIC", "");
34+
}
35+
const configH = b.addConfigHeader(.{
36+
.style = .blank,
37+
.include_path = "config.h",
38+
}, .{
39+
.HAVE_SELECT = if (lib.rootModuleTarget().os.tag == .windows) {} else null,
40+
.HAVE_POLL = if (lib.rootModuleTarget().os.tag != .windows) {} else null,
41+
.AMQ_PLATFORM = switch (lib.rootModuleTarget().os.tag) {
42+
.linux => "Linux",
43+
.macos => "Darwin",
44+
.windows => "Win32",
45+
else => @panic("Unsupported platform"),
46+
},
47+
.ENABLE_SSL_ENGINE_API = if (ssl) {} else null,
48+
});
49+
lib.defineCMacro("HAVE_CONFIG_H", null);
50+
lib.addConfigHeader(configH);
51+
lib.addIncludePath(generated_export_header.getDirectory());
52+
lib.addIncludePath(b.path("include"));
53+
lib.addIncludePath(b.path("librabbitmq"));
54+
if (lib.rootModuleTarget().os.tag == .windows) {
55+
lib.addIncludePath(b.path("librabbitmq/win32"));
56+
lib.addCSourceFile(.{
57+
.file = b.path("librabbitmq/win32/threads.c"),
58+
});
59+
lib.linkSystemLibrary("ws2_32");
60+
} else lib.addIncludePath(b.path("librabbitmq/unix"));
61+
lib.addCSourceFiles(.{
62+
.root = b.path("librabbitmq"),
63+
.files = &.{
64+
"amqp_api.c", "amqp_connection.c", "amqp_consumer.c", "amqp_framing.c",
65+
"amqp_mem.c", "amqp_socket.c", "amqp_table.c", "amqp_tcp_socket.c",
66+
"amqp_time.c", "amqp_url.c",
67+
},
68+
});
69+
if (ssl) {
70+
lib.addCSourceFiles(.{
71+
.root = b.path("librabbitmq"),
72+
.files = &.{
73+
"amqp_openssl.c",
74+
"amqp_openssl_bio.c",
75+
},
76+
});
77+
lib.linkSystemLibrary("ssl");
78+
lib.linkSystemLibrary("crypto");
79+
}
80+
lib.linkLibC();
81+
lib.installHeadersDirectory(b.path("include"), "", .{});
82+
83+
if (bindings) {
84+
const module_rmq = b.addModule("rabbitmq", .{
85+
.root_source_file = b.path("bindings/rmq.zig"),
86+
.link_libc = true,
87+
});
88+
for (lib.root_module.include_dirs.items) |include_dir| {
89+
module_rmq.include_dirs.append(b.allocator, include_dir) catch unreachable;
90+
}
91+
module_rmq.linkLibrary(lib);
92+
} else b.installArtifact(lib);
93+
94+
if (examples) {
95+
inline for (&.{
96+
"amqp_bind.c",
97+
if (ssl)
98+
"amqp_ssl_connect.c"
99+
else
100+
"amqp_connect_timeout.c",
101+
"amqp_consumer.c",
102+
"amqp_exchange_declare.c",
103+
"amqp_listen.c",
104+
"amqp_listenq.c",
105+
"amqp_producer.c",
106+
"amqp_rpc_sendstring_client.c",
107+
"amqp_sendstring.c",
108+
"amqp_unbind.c",
109+
}) |file| {
110+
buildExamples(b, .{
111+
.name = file[0 .. file.len - 2],
112+
.filepaths = &.{file},
113+
.target = target,
114+
.optimize = optimize,
115+
.lib = lib,
116+
});
117+
}
118+
}
119+
}
120+
121+
const buildOptions = struct {
122+
name: []const u8,
123+
target: std.Build.ResolvedTarget,
124+
optimize: std.builtin.OptimizeMode,
125+
filepaths: []const []const u8,
126+
lib: *std.Build.Step.Compile,
127+
};
128+
129+
fn buildExamples(b: *std.Build, options: buildOptions) void {
130+
const example = b.addExecutable(.{
131+
.name = options.name,
132+
.target = options.target,
133+
.optimize = options.optimize,
134+
});
135+
for (options.lib.root_module.include_dirs.items) |include_dir| {
136+
example.root_module.include_dirs.append(b.allocator, include_dir) catch unreachable;
137+
}
138+
example.addIncludePath(b.path("examples"));
139+
example.addCSourceFile(.{
140+
.file = b.path("examples/utils.c"),
141+
});
142+
if (example.rootModuleTarget().os.tag == .windows)
143+
example.addCSourceFile(.{
144+
.file = b.path("examples/win32/platform_utils.c"),
145+
})
146+
else
147+
example.addCSourceFile(.{
148+
.file = b.path("examples/unix/platform_utils.c"),
149+
});
150+
example.addCSourceFiles(.{
151+
.root = b.path("examples"),
152+
.files = options.filepaths,
153+
});
154+
example.linkLibrary(options.lib);
155+
example.linkLibC();
156+
b.installArtifact(example);
157+
158+
const run_cmd = b.addRunArtifact(example);
159+
run_cmd.step.dependOn(b.getInstallStep());
160+
if (b.args) |args| {
161+
run_cmd.addArgs(args);
162+
}
163+
const run_step = b.step(options.name, b.fmt("Run the {s} example", .{options.name}));
164+
run_step.dependOn(&run_cmd.step);
165+
}
166+
167+
const export_h =
168+
\\ #ifndef RABBITMQ_C_EXPORT_H
169+
\\ #define RABBITMQ_C_EXPORT_H
170+
\\
171+
\\ #ifdef AMQP_STATIC
172+
\\ # define AMQP_EXPORT
173+
\\ # define AMQP_NO_EXPORT
174+
\\ #else
175+
\\ # ifndef AMQP_EXPORT
176+
\\ # ifdef rabbitmq_EXPORTS
177+
\\ /* We are building this library */
178+
\\ # define AMQP_EXPORT __attribute__((visibility("default")))
179+
\\ # else
180+
\\ /* We are using this library */
181+
\\ # define AMQP_EXPORT __attribute__((visibility("default")))
182+
\\ # endif
183+
\\ # endif
184+
\\
185+
\\ # ifndef AMQP_NO_EXPORT
186+
\\ # define AMQP_NO_EXPORT __attribute__((visibility("hidden")))
187+
\\ # endif
188+
\\ #endif
189+
\\
190+
\\ #ifndef AMQP_DEPRECATED
191+
\\ # define AMQP_DEPRECATED __attribute__ ((__deprecated__))
192+
\\ #endif
193+
\\
194+
\\ #ifndef AMQP_DEPRECATED_EXPORT
195+
\\ # define AMQP_DEPRECATED_EXPORT AMQP_EXPORT AMQP_DEPRECATED
196+
\\ #endif
197+
\\
198+
\\ #ifndef AMQP_DEPRECATED_NO_EXPORT
199+
\\ # define AMQP_DEPRECATED_NO_EXPORT AMQP_NO_EXPORT AMQP_DEPRECATED
200+
\\ #endif
201+
\\
202+
\\/* NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if) */
203+
\\ #if 0 /* DEFINE_NO_DEPRECATED */
204+
\\ # ifndef AMQP_NO_DEPRECATED
205+
\\ # define AMQP_NO_DEPRECATED
206+
\\ # endif
207+
\\ #endif
208+
\\
209+
\\ #endif /* RABBITMQ_C_EXPORT_H */
210+
\\
211+
;

0 commit comments

Comments
 (0)