Hello,
I’m working on a project which wraps the C++ sdk of the DAW Reaper.
I’m having to compile the c++ dependencies using an external command instead of using addCSourceFiles
and zig’s internal C compiler.
The reason is: the C++ dependencies carry a lot of templates which break my compilation. I figure there must be a way to work around the problem, but I can’t figure it out.
In one case, linking libCpp and using addCSourceFiles
will compile fine on Macos but fail on Linux, due to the templates.
I’ve resorted to the following build. Here’s an abridged version:
const lib = b.addSharedLibrary(.{
.name = "reaper_c1",
.root_source_file = b.path("src/console1_extension.zig"),
.target = target,
.optimize = optimize,
});
const wdl_dep = b.dependency("WDL", .{ .target = target, .optimize = optimize });
const reaper_sdk_dep = b.dependency("reaper-sdk", .{ .target = target, .optimize = optimize });
var client_install: *std.Build.Step.InstallArtifact = undefined;
lib.linkLibC();
// I’m having to link against AppKit and libCpp on Macos
if (target.result.isDarwin()) {
lib.root_module.linkFramework("AppKit", .{});
lib.linkLibCpp();
client_install = b.addInstallArtifact(lib, .{
.dest_sub_path = "reaper_c1.dylib",
.dest_dir = .{ .override = .{
.custom = "",
} },
});
} else {
client_install = b.addInstallArtifact(lib, .{
.dest_sub_path = "reaper_c1.so",
.dest_dir = .{ .override = .{
.custom = "",
} },
});
}
// […]
// include path for c header files
lib.addIncludePath(b.path("./src/"));
lib.addIncludePath(wdl_dep.path(""));
lib.addIncludePath(reaper_sdk_dep.path(""));
// I need to add a system command to run a PHP script
// which generates some modstub and rc files
const php_cmd = b.addSystemCommand(&[_][]const u8{"php"});
php_cmd.addFileArg(php_script); // Convert LazyPath to string
php_cmd.addFileArg(resource_rc); // Convert LazyPath to string
lib.step.dependOn(&php_cmd.step);
// from here, get the CPP flags, list the cpp files
// and call the external compiler (clang or gcc) on each of the files.
// their output is then added as
const cpp_flags = [_][]const u8{
if (target.result.isDarwin()) "clang" else "gcc",
"-c",
"-fPIC",
"-O2",
"-std=c++14",
b.fmt("-I{s}", .{wdl_dep.path("").getPath(b)}),
"-DSWELL_PROVIDED_BY_APP",
"-o",
};
// Define cpp files using dependency paths
const cppfiles = [_]std.Build.LazyPath{
b.path("src/csurf/control_surface.cpp"),
b.path("src/csurf/control_surface_wrapper.cpp"),
b.path("src/csurf/midi_wrapper.cpp"),
modstub,
};
// Add the C++ source files to the library as object files
inline for (comptime cppfiles) |cppfile| {
const filearg = try std.fmt.allocPrint(
b.allocator,
"{s}.o",
.{std.fs.path.basename(cppfile.getPath(b))},
);
const cxx = b.addSystemCommand(&cpp_flags);
lib.addObjectFile(cxx.addOutputFileArg(filearg));
cxx.addFileArg(cppfile);
cxx.step.dependOn(&php_cmd.step);
}
My questions:
- is there a way to use the
linkCSourceFiles
for this - and have it handle the cpp templates on Linux, or am I stuck with this approach? - which compiler does zig wrap on Linux? GCC or Clang?