diff --git a/README.md b/README.md index 52a22e0..1dcadc7 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Steps: uninstall Remove build artifacts from prefix path c_app Run a C application built with Zig's build system. zig_app Run a Zig application linked to C source code. + c_app_with_static_lib Run a C app linked to a c static lib all built with zig build. + c_app_with_shared_lib Run a C app linked to a c dynamic lib all built with zig build. zmath_static Create a static library from C source code. zmath_shared Create a shared library from C source code. zig_app_shared Run a Zig application that is linked to a shared library. @@ -205,16 +207,16 @@ const std = @import("std"); const zmath = @cImport(@cInclude("zmath.h")); pub fn main() !void { - const stdio = std.io.getStdOut().writer(); + const stdio = std.fs.File.stdout.writerStreaming(.{}); const a = 10; const b = 5; const resultAdd = zmath.add(a, b); - try stdio.print("{} + {} = {}\n", .{ a, b, resultAdd }); + try stdio.interface.print("{} + {} = {}\n", .{ a, b, resultAdd }); const resultSub = zmath.sub(a, b); - try stdio.print("{} - {} = {}\n", .{ a, b, resultSub }); + try stdio.interface.print("{} - {} = {}\n", .{ a, b, resultSub }); } ``` @@ -281,10 +283,12 @@ pub fn build(b: *std.Build) *std.Build.Step.Compile { lib.addIncludePath(b.path("include")); lib.addCSourceFiles(.{ .files = &[_][]const u8{"src/zmath.c"} }); - + lib.linkLibC(); b.installArtifact(lib); + // return the lib to the caller so it can be passed in to the fn that builds apps + return lib; } ``` @@ -354,16 +358,16 @@ const std = @import("std"); const zmath = @import("zmath.zig"); pub fn main() !void { - const stdio = std.io.getStdOut().writer(); + const stdio = std.fs.File.stdout.writerStreaming(.{}); const a = 10; const b = 5; const resultAdd = try zmath.add(a, b); - try stdio.print("{d} + {d} = {d}\n", .{ a, b, resultAdd }); + try stdio.interface.print("{d} + {d} = {d}\n", .{ a, b, resultAdd }); const resultSub = try zmath.sub(a, b); - try stdio.print("{d} - {d} = {d}\n", .{ a, b, resultSub }); + try stdio.interface.print("{d} - {d} = {d}\n", .{ a, b, resultSub }); } ``` @@ -376,16 +380,18 @@ to link our application to our library. ```c const std = @import("std"); -pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { +pub fn build(b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + lib: *std.Build.Step.Compile) *std.Build.Step.Compile { const exe = b.addExecutable(.{ .name = "zig_app_shared", .root_source_file = b.path("src/zig_c_wrapper.zig"), .target = target, .optimize = optimize, }); - - exe.addObjectFile(b.path("zig-out/lib/zmath-shared.lib")); - + // this avoids having to name the library file. Libraries are named very differently on Linux, Osx and Windows + exe.linkLibrary(lib) return exe; } ``` @@ -452,7 +458,13 @@ pub fn build(b: *std.Build) void { b.installArtifact(tests_exe); } ``` +## Two more pure 'C' examples +Two additional 'C' examples have been provided to demonstrate how to use `zig build` to +compile and link a 'C' program to a 'C' static or shared library. They are: +- `build_c_app_with_shared_lib` which builds an executable `c_app_with_shared_lib`, and +- `build_c_app_with_static_lib` which builds an executable `c_app_with_static_lib` + ## Resources - https://mtlynch.io/notes/zig-call-c-simple/ What initially made me want to tackle this subject, this article is a great diff --git a/build.zig b/build.zig index c9a653d..a8b0854 100644 --- a/build.zig +++ b/build.zig @@ -1,7 +1,10 @@ const std = @import("std"); const module_c_app = @import("build_c_app.zig"); -const module_zig_app = @import("build_zig_app.zig"); +const module_c_app_with_static_lib = @import("build_c_app_with_static_lib.zig"); +const module_c_app_with_shared_lib = @import("build_c_app_with_shared_lib.zig"); + +const module_zig_call_c_app = @import("build_zig_call_c_app.zig"); const module_lib_static = @import("build_c_static_lib.zig"); const module_lib_shared = @import("build_c_shared_lib.zig"); const module_zig_app_static = @import("build_zig_app_static.zig"); @@ -12,68 +15,72 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - // c_app - const c_app = module_c_app.build(b, target, optimize); - const run_c_app = b.addRunArtifact(c_app); - - b.installArtifact(c_app); - - const run_c_app_step = b.step("c_app", "Run a C application built with Zig's build system."); - run_c_app_step.dependOn(&run_c_app.step); - - // zig_app - const zig_app = module_zig_app.build(b, target, optimize); - const run_zig_app = b.addRunArtifact(zig_app); - - b.installArtifact(zig_app); - - const run_zig_app_step = b.step("zig_app", "Run a Zig application linked to C source code."); - run_zig_app_step.dependOn(&run_zig_app.step); - - // zmath_static + // zmath lib static const lib_static = module_lib_static.build(b, target, optimize); const install_lib_static = b.addInstallArtifact(lib_static, .{}); - b.installArtifact(lib_static); - const install_lib_static_step = b.step("zmath_static", "Create a static library from C source code."); install_lib_static_step.dependOn(&install_lib_static.step); - // zmath_shared + // zmath lib shared const lib_shared = module_lib_shared.build(b, target, optimize); const install_lib_shared = b.addInstallArtifact(lib_shared, .{}); - b.installArtifact(lib_shared); - const install_lib_shared_step = b.step("zmath_shared", "Create a shared library from C source code."); install_lib_shared_step.dependOn(&install_lib_shared.step); - // zig_app_shared - const zig_app_shared = module_zig_app_shared.build(b, target, optimize); - const run_zig_app_shared = b.addInstallArtifact(zig_app_shared, .{}); + // c_app - a c program linked with c object by compiling c_app.c and zmath.c + const c_app = module_c_app.build(b, target, optimize); + const run_c_app = b.addRunArtifact(c_app); + b.installArtifact(c_app); + const run_c_app_step = b.step("c_app", "Run a C application likned to otehr c objects."); + run_c_app_step.dependOn(&run_c_app.step); - b.installArtifact(zig_app_shared); + // c_app_with_static_lib - a c program linked against zmath static lib + const c_app_with_static_lib = module_c_app_with_static_lib.build(b, target, optimize, lib_static); + const run_c_app_with_static_lib = b.addRunArtifact(c_app_with_static_lib); + b.installArtifact(c_app_with_static_lib); + const run_c_app_with_static_lib_step = b.step("c_app_with_static_lib", "Run a C application linked to a c static lib all built with zig build."); + run_c_app_with_static_lib_step.dependOn(&run_c_app_with_static_lib.step); + + // c_app_with_shared_lib - a c program compiled andlinked against zmath shared lib + const c_app_with_shared_lib = module_c_app_with_shared_lib.build(b, target, optimize, lib_shared); + const run_c_app_with_shared_lib = b.addRunArtifact(c_app_with_shared_lib); + b.installArtifact(c_app_with_shared_lib); + const run_c_app_with_shared_lib_step = b.step("c_app_with_shared_lib", "Run a C application linked to a c dynamic lib all built with zig build."); + run_c_app_with_shared_lib_step.dependOn(&run_c_app_with_shared_lib.step); + + // zig_call_c_app - zig_call_c_app.zig is compiled with zmath.c and the 2 objects linked together + // zig_call_c_app explicitly imports zmath.c as a c module + const zig_call_c_app = module_zig_call_c_app.build(b, target, optimize); + const run_zig_call_c_app = b.addRunArtifact(zig_call_c_app); + b.installArtifact(zig_call_c_app); + const run_zig_app_step = b.step("zig_app", "Run a Zig application linked to C source code."); + run_zig_app_step.dependOn(&run_zig_call_c_app.step); + // zig_app_shared - zig_c_wrapped.zig calls zmath.zig which calls zmath_ext.zig which transforms the calls to c and then all + // that is liked with the static c library + const zig_app_shared = module_zig_app_shared.build(b, target, optimize, lib_shared); + const run_zig_app_shared = b.addInstallArtifact(zig_app_shared, .{}); + b.installArtifact(zig_app_shared); const run_zig_app_shared_step = b.step("zig_app_shared", "Run a Zig application that is linked to a shared library."); run_zig_app_shared_step.dependOn(&install_lib_shared.step); // create and install shared library run_zig_app_shared_step.dependOn(&run_zig_app_shared.step); - // zig_app_static - const zig_app_static = module_zig_app_static.build(b, target, optimize); + // zig_app_static - zig_c_wrapped.zig calls zmath.zig which calls zmath_ext.zig which transforms the calls to c + // then all that is linked against the c shared library + const zig_app_static = module_zig_app_static.build(b, target, optimize, lib_static); const run_zig_app_static = b.addInstallArtifact(zig_app_static, .{}); - b.installArtifact(zig_app_static); - const run_zig_app_static_step = b.step("zig_app_static", "Run a Zig application that is linked to a static library."); run_zig_app_static_step.dependOn(&install_lib_static.step); // create and install static library run_zig_app_static_step.dependOn(&run_zig_app_static.step); - // tests + // // tests const tests = module_tests.build(b, target, optimize); const run_tests = b.addRunArtifact(tests); - b.installArtifact(tests); - const run_tests_step = b.step("tests", "Run a Zig tests of C source code."); run_tests_step.dependOn(&run_tests.step); } +// diff --git a/build_c_app.zig b/build_c_app.zig index f28b926..593439b 100644 --- a/build_c_app.zig +++ b/build_c_app.zig @@ -1,15 +1,13 @@ const std = @import("std"); pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const exe = b.addExecutable(.{ - .name = "c_app", + const exe = b.addExecutable(.{ .name = "c_app", .root_module = b.createModule(.{ .target = target, .optimize = optimize, - }); + }) }); exe.addIncludePath(b.path("include")); exe.addCSourceFiles(.{ .files = &[_][]const u8{ "src/c_app.c", "src/zmath.c" } }); - exe.linkLibC(); return exe; diff --git a/build_c_app_with_shared_lib.zig b/build_c_app_with_shared_lib.zig new file mode 100644 index 0000000..3bc88e2 --- /dev/null +++ b/build_c_app_with_shared_lib.zig @@ -0,0 +1,15 @@ +const std = @import("std"); + +pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, lib: *std.Build.Step.Compile) *std.Build.Step.Compile { + const exe = b.addExecutable(.{ .name = "c_app_with_shared_lib", .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }) }); + + exe.addIncludePath(b.path("include")); + exe.addCSourceFiles(.{ .files = &[_][]const u8{"src/c_app.c"} }); //, "src/zmath.c" } }); + exe.linkLibrary(lib); + exe.linkLibC(); + + return exe; +} diff --git a/build_c_app_with_static_lib.zig b/build_c_app_with_static_lib.zig new file mode 100644 index 0000000..4ee3608 --- /dev/null +++ b/build_c_app_with_static_lib.zig @@ -0,0 +1,15 @@ +const std = @import("std"); + +pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, lib: *std.Build.Step.Compile) *std.Build.Step.Compile { + const exe = b.addExecutable(.{ .name = "c_app_with_static_lib", .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }) }); + + exe.addIncludePath(b.path("include")); + exe.addCSourceFiles(.{ .files = &[_][]const u8{"src/c_app.c"} }); //, "src/zmath.c" } }); + exe.linkLibrary(lib); + exe.linkLibC(); + + return exe; +} diff --git a/build_c_shared_lib.zig b/build_c_shared_lib.zig index c2a64b0..366f2ef 100644 --- a/build_c_shared_lib.zig +++ b/build_c_shared_lib.zig @@ -1,11 +1,10 @@ const std = @import("std"); pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const lib = b.addSharedLibrary(.{ - .name = "zmath-shared", + const lib = b.addLibrary(.{ .linkage = .dynamic, .name = "zmath-shared", .root_module = b.createModule(.{ .target = target, .optimize = optimize, - }); + }) }); lib.addIncludePath(b.path("include")); lib.addCSourceFiles(.{ .files = &[_][]const u8{"src/zmath.c"} }); diff --git a/build_c_static_lib.zig b/build_c_static_lib.zig index 7610f3c..13afbb5 100644 --- a/build_c_static_lib.zig +++ b/build_c_static_lib.zig @@ -1,16 +1,17 @@ const std = @import("std"); pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const lib = b.addStaticLibrary(.{ - .name = "zmath-static", + const lib = b.addLibrary(.{ .linkage = .static, .name = "zmath-static", .root_module = b.createModule(.{ .target = target, .optimize = optimize, - }); + }) }); lib.addIncludePath(b.path("include")); lib.addCSourceFiles(.{ .files = &[_][]const u8{"src/zmath.c"} }); lib.linkLibC(); + var stdio = std.fs.File.stdout().writerStreaming(&.{}); + stdio.interface.print("\nXXBuild static library name {s}. \n", .{lib.out_lib_filename}) catch {}; return lib; } diff --git a/build_test_zmath.zig b/build_test_zmath.zig index dd39d62..19e8b86 100644 --- a/build_test_zmath.zig +++ b/build_test_zmath.zig @@ -1,12 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const exe = b.addTest(.{ - .name = "test_zmath", + const exe = b.addTest(.{ .name = "test_zmath", .root_module = b.createModule(.{ .root_source_file = b.path("tests/test_zmath.zig"), .target = target, .optimize = optimize, - }); + }) }); exe.addIncludePath(b.path("include")); exe.addCSourceFile(.{ diff --git a/build_zig_app_shared.zig b/build_zig_app_shared.zig index 93ecaa3..1a1fad5 100644 --- a/build_zig_app_shared.zig +++ b/build_zig_app_shared.zig @@ -1,14 +1,15 @@ const std = @import("std"); -pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const exe = b.addExecutable(.{ - .name = "zig_app_shared", +pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, lib: *std.Build.Step.Compile) *std.Build.Step.Compile { + const exe = b.addExecutable(.{ .name = "zig_app_shared", .root_module = b.createModule(.{ .root_source_file = b.path("src/zig_c_wrapper.zig"), .target = target, .optimize = optimize, - }); + }) }); - exe.addObjectFile(b.path("zig-out/lib/zmath-shared.lib")); + // exe.addObjectFile(b.path("zig-out/lib/libzmath-shared.dylib")); + exe.linkLibrary(lib); + // exe.addRPath(b.path("zig-out/lib")); return exe; } diff --git a/build_zig_app_static.zig b/build_zig_app_static.zig index 870fba4..00f673a 100644 --- a/build_zig_app_static.zig +++ b/build_zig_app_static.zig @@ -1,14 +1,13 @@ const std = @import("std"); -pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const exe = b.addExecutable(.{ - .name = "zig_app_static", +pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, lib: *std.Build.Step.Compile) *std.Build.Step.Compile { + const exe = b.addExecutable(.{ .name = "zig_app_static", .root_module = b.createModule(.{ .root_source_file = b.path("src/zig_c_wrapper.zig"), .target = target, .optimize = optimize, - }); - - exe.addObjectFile(b.path("zig-out/lib/zmath-static.lib")); + }) }); + // exe.addObjectFile(b.path("zig-out/lib/libzmath-static.a")); + exe.linkLibrary(lib); return exe; } diff --git a/build_zig_call_c_app.zig b/build_zig_call_c_app.zig new file mode 100644 index 0000000..c8b04fc --- /dev/null +++ b/build_zig_call_c_app.zig @@ -0,0 +1,18 @@ +const std = @import("std"); + +pub fn build(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { + const exe = b.addExecutable(.{ .name = "zig_call_c_app", .root_module = b.createModule(.{ + .root_source_file = b.path("src/zig_call_c_app.zig"), + .target = target, + .optimize = optimize, + }) }); + + exe.addIncludePath(b.path("include")); + exe.addCSourceFile(.{ + .file = b.path("src/zmath.c"), + }); + + exe.linkLibC(); + + return exe; +} diff --git a/src/zig_app.zig b/src/zig_app.zig deleted file mode 100644 index 08a3c65..0000000 --- a/src/zig_app.zig +++ /dev/null @@ -1,15 +0,0 @@ -const std = @import("std"); -const zmath = @cImport(@cInclude("zmath.h")); - -pub fn main() !void { - const stdio = std.io.getStdOut().writer(); - - const a = 10; - const b = 5; - - const resultAdd = zmath.add(a, b); - try stdio.print("{} + {} = {}\n", .{ a, b, resultAdd }); - - const resultSub = zmath.sub(a, b); - try stdio.print("{} - {} = {}\n", .{ a, b, resultSub }); -} diff --git a/src/zig_c_wrapper.zig b/src/zig_c_wrapper.zig index 2a627ec..2286251 100644 --- a/src/zig_c_wrapper.zig +++ b/src/zig_c_wrapper.zig @@ -2,14 +2,14 @@ const std = @import("std"); const zmath = @import("zmath.zig"); pub fn main() !void { - const stdio = std.io.getStdOut().writer(); - + var stdio = std.fs.File.stdout().writerStreaming(&.{}); + try stdio.interface.print("Hello this is zig_wrappper \n", .{}); const a = 10; const b = 5; const resultAdd = try zmath.add(a, b); - try stdio.print("{d} + {d} = {d}\n", .{ a, b, resultAdd }); + try stdio.interface.print("{d} + {d} = {d}\n", .{ a, b, resultAdd }); const resultSub = try zmath.sub(a, b); - try stdio.print("{d} - {d} = {d}\n", .{ a, b, resultSub }); + try stdio.interface.print("{d} - {d} = {d}\n", .{ a, b, resultSub }); } diff --git a/src/zig_call_c_app.zig b/src/zig_call_c_app.zig new file mode 100644 index 0000000..91048c4 --- /dev/null +++ b/src/zig_call_c_app.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const zmath = @cImport(@cInclude("zmath.h")); + +pub fn main() !void { + // const stdio = std.io.getStdOut().writer(); + var stdio = std.fs.File.stdout().writerStreaming(&.{}); + try stdio.interface.print("zig_call_c_app.zig .. calls zmath.c \n", .{}); + const a = 10; + const b = 5; + + const resultAdd = zmath.add(a, b); + try stdio.interface.print("{} + {} = {}\n", .{ a, b, resultAdd }); + + const resultSub = zmath.sub(a, b); + try stdio.interface.print("{} - {} = {}\n", .{ a, b, resultSub }); +} diff --git a/src/zmath.c b/src/zmath.c index e98ef0f..7df0487 100644 --- a/src/zmath.c +++ b/src/zmath.c @@ -1,9 +1,11 @@ #include "zmath.h" - +#include int add(int a, int b) { + printf("zmath.c add a: %d b: %d\n", a, b); return a + b; } int sub(int a, int b) { + printf("zmath.c sub a: %d b: %d\n", a, b); return a - b; } diff --git a/src/zmath_ext.zig b/src/zmath_ext.zig index 0704c83..5101c0d 100644 --- a/src/zmath_ext.zig +++ b/src/zmath_ext.zig @@ -1,4 +1,5 @@ +const builtin = @import("builtin"); const zmath_h = @cImport(@cInclude("zmath.h")); -pub extern fn add(a: c_int, b: c_int) callconv(.C) c_int; -pub extern fn sub(a: c_int, b: c_int) callconv(.C) c_int; +pub extern fn add(a: c_int, b: c_int) callconv(.c) c_int; +pub extern fn sub(a: c_int, b: c_int) callconv(.c) c_int;