Skip to content

Commit

Permalink
Merge pull request #369 from ttytm/build/update-zig-11-build
Browse files Browse the repository at this point in the history
Refine and fix building with zig
  • Loading branch information
hassandraga authored May 29, 2024
2 parents a54d906 + 58f7648 commit cd06462
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 108 deletions.
19 changes: 16 additions & 3 deletions .github/workflows/zig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,25 @@ jobs:
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: maxim-lobanov/setup-xcode@v1
if: runner.os == 'macOS'
with:
xcode-version: latest-stable
- uses: actions/checkout@v4
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: 0.11.0
- name: Build libarary
run: zig build
- name: Build static library
run: zig build -Dverbose
- name: Build dynamic library
if: ${{ !cancelled() }}
run: zig build -Ddynamic -Dverbose
- name: Build static library with TLS support
if: runner.os == 'Linux'
run: zig build -Denable-tls -Dverbose
- name: Build dynamic library with TLS support
if: runner.os == 'Linux'
run: zig build -Ddynamic -Denable-tls -Dverbose
- name: Build examples
run: zig build build_all
run: zig build examples
182 changes: 82 additions & 100 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,95 @@ const OptimizeMode = std.builtin.OptimizeMode;
const CrossTarget = std.zig.CrossTarget;
const Compile = Build.Step.Compile;
const Module = Build.Module;
const current_version = builtin.zig_version.minor;

const log = std.log.scoped(.WebUI);

const default_isStatic = true;
const default_enableTLS = false;
const lib_name = "webui";

pub fn build(b: *Build) void {
if (current_version > 11) {
if (builtin.zig_version.minor > 11) {
log.err("unsupported Zig version. For building with 0.12 and later, plaese see `github.com/webui-dev/zig-webui`", .{});
std.process.exit(1);
return;
}
const isStatic = b.option(bool, "is_static", "whether lib is static") orelse default_isStatic;
const enableTLS = b.option(bool, "enable_tls", "whether lib enable tls") orelse default_enableTLS;

const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const is_dynamic = b.option(bool, "dynamic", "build the dynamic library") orelse false;
const enable_tls = b.option(bool, "enable-tls", "enable TLS support") orelse false;
const verbose = b.option(bool, "verbose", "enable verbose output") orelse false;

if (enableTLS) {
std.log.info("enable TLS support", .{});
if (!target.isNative()) {
std.log.info("when enable tls, not support cross compile", .{});
std.os.exit(1);
}
if (enable_tls and !target.isNative()) {
log.err("cross compilation is not supported with TLS enabled", .{});
std.os.exit(1);
}

const webui = build_webui_11(b, optimize, target, isStatic, enableTLS);

webui.installHeader("include/webui.h", "webui.h");
if (verbose) {
std.debug.print("Building {s} WebUI library{s}...\n", .{
if (is_dynamic) "dynamic" else "static",
if (enable_tls) " with TLS support" else "",
});
}

build_examples_11(b, optimize, target, webui);
const lib = build_lib(b, target, optimize, is_dynamic, enable_tls) catch |err| {
log.err("failed to build webui library: {}", .{err});
std.os.exit(1);
};
build_examples(b, target, optimize, lib) catch |err| {
log.err("failed to build examples: {}", .{err});
std.os.exit(1);
};

b.installArtifact(webui);
if (verbose) {
std.debug.print("Done.\n", .{});
}
}

fn build_webui_11(b: *Build, optimize: OptimizeMode, target: CrossTarget, is_static: bool, enable_tls: bool) *Compile {
const name = "webui";
const webui = if (is_static) b.addStaticLibrary(.{ .name = name, .target = target, .optimize = optimize }) else b.addSharedLibrary(.{ .name = name, .target = target, .optimize = optimize });

const extra_flags = if (target.os_tag == .windows or (target.os_tag == null and builtin.os.tag == .windows))
"-DMUST_IMPLEMENT_CLOCK_GETTIME"
else
"";

const cflags = if (enable_tls)
[_][]const u8{ "-DNDEBUG", "-DNO_CACHING", "-DNO_CGI", "-DUSE_WEBSOCKET", "-DWEBUI_TLS", "-DNO_SSL_DL", "-DOPENSSL_API_1_1", extra_flags }
else
[_][]const u8{ "-DNDEBUG", "-DNO_CACHING", "-DNO_CGI", "-DUSE_WEBSOCKET", "-DNO_SSL", extra_flags, "", "" };
fn build_lib(b: *Build, target: CrossTarget, optimize: OptimizeMode, is_dynamic: bool, enable_tls: bool) !*Compile {
// Prepare compiler flags.
const tls_flags = &[_][]const u8{ "-DWEBUI_TLS", "-DNO_SSL_DL", "-DOPENSSL_API_1_1" };

var civetweb_flags = std.ArrayList([]const u8).init(std.heap.page_allocator);
defer civetweb_flags.deinit();
try civetweb_flags.appendSlice(&[_][]const u8{ "-DNDEBUG", "-DNO_CACHING", "-DNO_CGI", "-DUSE_WEBSOCKET" });
try civetweb_flags.appendSlice(if (enable_tls) tls_flags else &.{ "-DUSE_WEBSOCKET", "-DNO_SSL" });
if (target.isWindows()) try civetweb_flags.append("-DMUST_IMPLEMENT_CLOCK_GETTIME");

const webui = if (is_dynamic) b.addSharedLibrary(.{
.name = lib_name,
.target = target,
.optimize = optimize,
}) else b.addStaticLibrary(.{
.name = lib_name,
.target = target,
.optimize = optimize,
});

webui.addCSourceFile(.{
.file = .{ .path = "src/webui.c" },
.flags = if (enable_tls)
&[_][]const u8{ "-DNO_SSL", "-DWEBUI_TLS", "-DNO_SSL_DL", "-DOPENSSL_API_1_1" }
else
&[_][]const u8{"-DNO_SSL"},
.flags = if (enable_tls) tls_flags else &[_][]const u8{"-DNO_SSL"},
});

webui.addCSourceFile(.{
.file = .{ .path = "src/civetweb/civetweb.c" },
.flags = &cflags,
.flags = civetweb_flags.items,
});

webui.linkLibC();

webui.addIncludePath(.{ .path = "include" });
webui.installHeader("include/webui.h", "webui.h");

if (target.os_tag == .windows or (target.os_tag == null and builtin.os.tag == .windows)) {
if (target.isDarwin()) {
webui.addCSourceFile(.{
.file = .{ .path = "src/webview/wkwebview.m" },
.flags = &.{},
});
webui.linkFramework("Cocoa");
webui.linkFramework("WebKit");
} else if (target.isWindows()) {
webui.linkSystemLibrary("ws2_32");
webui.linkSystemLibrary("Ole32");
if (target.abi == .msvc) {
webui.linkSystemLibrary("Advapi32");
webui.linkSystemLibrary("Shell32");
webui.linkSystemLibrary("user32");
}
if (enable_tls) {
webui.linkSystemLibrary("bcrypt");
}
Expand All @@ -84,79 +105,40 @@ fn build_webui_11(b: *Build, optimize: OptimizeMode, target: CrossTarget, is_sta
webui.linkSystemLibrary("ssl");
webui.linkSystemLibrary("crypto");
}
if (target.abi == .msvc) {
webui.linkSystemLibrary("shell32");
webui.linkSystemLibrary("Advapi32");
webui.linkSystemLibrary("user32");
}

b.installArtifact(webui);
return webui;
}

fn build_examples_11(b: *Build, optimize: OptimizeMode, target: CrossTarget, webui_lib: *Compile) void {
var lazy_path = Build.LazyPath{
.path = "examples/C",
};

const build_all_step = b.step("build_all", "build all examples");

const examples_path = lazy_path.getPath(b);

var iter_dir =
std.fs.openIterableDirAbsolute(examples_path, .{}) catch |err| {
log.err("open examples_path failed, err is {}", .{err});
std.os.exit(1);
};
defer iter_dir.close();
fn build_examples(b: *Build, target: CrossTarget, optimize: OptimizeMode, webui_lib: *Compile) !void {
const build_all_step = b.step("examples", "builds the library and its examples");

var itera = iter_dir.iterate();
const examples_path = (Build.LazyPath{ .path = "examples/C" }).getPath(b);
var examples_dir = try std.fs.openIterableDirAbsolute(examples_path, .{});
defer examples_dir.close();

while (itera.next()) |val| {
const entry = val orelse break;
if (entry.kind != .directory) {
var paths = examples_dir.iterate();
while (try paths.next()) |val| {
if (val.kind != .directory) {
continue;
}

const example_name = entry.name;
const path = std.fmt.allocPrint(b.allocator, "examples/C/{s}/main.c", .{example_name}) catch |err| {
log.err("fmt path for examples failed, err is {}", .{err});
std.os.exit(1);
};
const example_name = val.name;
const exe = b.addExecutable(.{ .name = example_name, .target = target, .optimize = optimize });
const path = try std.fmt.allocPrint(b.allocator, "examples/C/{s}/main.c", .{example_name});

const exe = b.addExecutable(.{
.name = example_name,
.target = target,
.optimize = optimize,
});
exe.addCSourceFile(.{ .file = .{ .path = path }, .flags = &.{} });
exe.linkLibrary(webui_lib);
exe.addCSourceFile(.{
.file = .{ .path = path },
.flags = &.{},
});

const exe_install = b.addInstallArtifact(exe, .{});
const exe_run = b.addRunArtifact(exe);
build_all_step.dependOn(&exe_install.step);
exe_run.step.dependOn(&exe_install.step);
const step_name = try std.fmt.allocPrint(b.allocator, "run_{s}", .{example_name});
const step_desc = try std.fmt.allocPrint(b.allocator, "run example {s}", .{example_name});

const cwd = std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ examples_path, example_name }) catch |err| {
log.err("fmt path for examples failed, err is {}", .{err});
std.os.exit(1);
};
exe_run.cwd = cwd;

const step_name = std.fmt.allocPrint(b.allocator, "run_{s}", .{example_name}) catch |err| {
log.err("fmt step_name for examples failed, err is {}", .{err});
std.os.exit(1);
};
const step_desc = std.fmt.allocPrint(b.allocator, "run example {s}", .{example_name}) catch |err| {
log.err("fmt step_desc for examples failed, err is {}", .{err});
std.os.exit(1);
};
const exe_run_step = b.step(step_name, step_desc);
exe_run_step.dependOn(&exe_run.step);
} else |err| {
log.err("iterate examples_path failed, err is {}", .{err});
std.os.exit(1);
exe_run.cwd = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ examples_path, example_name });

exe_run.step.dependOn(&exe_install.step);
build_all_step.dependOn(&exe_install.step);
b.step(step_name, step_desc).dependOn(&exe_run.step);
}
}
6 changes: 2 additions & 4 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
.{
.name = "webui",
.version = "2.5.0",
.version = "2.5.0-beta1",
.dependencies = .{},
.paths = .{
"",
},
.paths = .{""},
}
2 changes: 1 addition & 1 deletion src/webui.c
Original file line number Diff line number Diff line change
Expand Up @@ -8770,7 +8770,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
ULONG STDMETHODCALLTYPE ReleaseController(ICoreWebView2CreateCoreWebView2ControllerCompletedHandler* This);

HRESULT STDMETHODCALLTYPE TitleChanged_Invoke(
ICoreWebView2DocumentTitleChangedEventHandler* This, ICoreWebView2* sender, void* args) {
ICoreWebView2DocumentTitleChangedEventHandler* This, ICoreWebView2* sender, IUnknown* args) {
TitleChangedHandler* handler = (TitleChangedHandler*)This;
_webui_wv_win32_t* webView = handler->webView;
LPWSTR newTitle = NULL;
Expand Down

0 comments on commit cd06462

Please sign in to comment.