szkkng/juzi
Zig build utilities for JUCE
masterBuild JUCE projects using the Zig build system.
Currently WIP.
Initialize a Zig build project if you haven't already:
zig init
Download and add juzi as a dependency by running the following command in your project root:
zig fetch --save git+https://github.com/szkkng/juzi
Then, configure your build.zig to use juzi.
Here is an example configuration for an audio plugin project:
const std = @import("std");
const zon = @import("build.zig.zon");
// Import juzi build utilities.
const juzi = @import("juzi");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Create project configuration.
const config = juzi.ProjectConfig.create(b, .{
.product_name = "JuziPlugin",
.version = zon.version,
.bundle_id = "com.example.juzi",
.plugin_manufacturer_code = "Juzi",
.plugin_code = "Juzi",
.formats = &.{ .vst3, .au, .standalone },
});
// Create the module for the plugin's C++ source files.
const module = b.createModule(.{ .target = target, .optimize = optimize });
module.addCSourceFiles(.{
.root = b.path("src"),
.files = &.{
"PluginEditor.cpp",
"PluginProcessor.cpp",
},
.flags = &.{
"--std=c++20",
"-Wall",
"-Wextra",
"-Werror",
},
});
// Initialize juzi setup using this module and the juzi dependency.
const juzi_dep = b.dependency("juzi", .{ .target = target, .optimize = optimize });
var juzi_setup = juzi.Setup.init(juzi_dep, module);
// Configure JUCE-related preprocessor macros.
juzi_setup.addJuceMacro("JUCE_VST3_CAN_REPLACE_VST2", "0");
juzi_setup.addJuceMacro("JUCE_WEB_BROWSER", "0");
juzi_setup.addJuceMacro("JUCE_USE_CURL", "0");
// Configure embedded binary data here, similar to JUCE's add_binary_data.
// juzi_setup.addBinaryData(.{
// .namespace = "JuziBinary",
// .header_name = "JuziBinary",
// .files = &.{ "res/juzi.wav", "res/juzi.icon" },
// });
// After configuring juzi, add plugin targets for the selected formats.
const plugin = juzi_setup.addPlugin(.{
.juce_modules = &.{.juce_audio_utils},
.config = config,
});
// Add the collected install steps as dependencies of the top-level install step.
var steps_it = plugin.install_steps.valueIterator();
while (steps_it.next()) |step| {
b.getInstallStep().dependOn(step.*);
}
}
To build:
zig build -Doptimize=ReleaseFast
For audio plugin projects, you can build a specific format and install it:
zig build vst3 -Doptimize=ReleaseFast -p ~/Library/Audio/Plug-Ins/VST3
The vst3 step becomes available when you specify the format in your ProjectConfig, for example:
const config = juzi.ProjectConfig.create(b, .{
// ...
.formats = &.{ .vst3 },
});
You can list all available steps by running:
zig build -l
These fields correspond to the arguments used in JUCE’s juce_add_<target> functions.
Refer to the JUCE CMake API documentation for detailed behaviour of each option.
If you're using ZLS, your editor can show available values and jump to definitions, making it easy to inspect each field.
Note that some fields are not yet implemented.
juce_add_<target> argument |
ProjectConfig field |
|---|---|
PRODUCT_NAME |
product_name |
VERSION |
version |
BUILD_VERSION |
build_version |
BUNDLE_ID |
bundle_id |
MICROPHONE_PERMISSION_ENABLED |
microphone_permission_enabled |
MICROPHONE_PERMISSION_TEXT |
microphone_permission_text |
CAMERA_PERMISSION_ENABLED |
camera_permission_enabled |
CAMERA_PERMISSION_TEXT |
camera_permission_text |
BLUETOOTH_PERMISSION_ENABLED |
bluetooth_permission_enabled |
BLUETOOTH_PERMISSION_TEXT |
bluetooth_permission_text |
LOCAL_NETWORK_PERMISSION_ENABLED |
local_network_permission_enabled |
LOCAL_NETWORK_PERMISSION_TEXT |
local_network_permission_text |
SEND_APPLE_EVENTS_PERMISSION_ENABLED |
send_apple_events_permission_enabled |
SEND_APPLE_EVENTS_PERMISSION_TEXT |
send_apple_events_permission_text |
FILE_SHARING_ENABLED |
(not implemented) |
DOCUMENT_BROWSER_ENABLED |
(not implemented) |
STATUS_BAR_HIDDEN |
(not implemented) |
REQUIRES_FULL_SCREEN |
(not implemented) |
BACKGROUND_AUDIO_ENABLED |
(not implemented) |
BACKGROUND_BLE_ENABLED |
(not implemented) |
APP_GROUPS_ENABLED |
(not implemented) |
APP_GROUP_IDS |
(not implemented) |
ICLOUD_PERMISSIONS_ENABLED |
(not implemented) |
IPHONE_SCREEN_ORIENTATIONS |
(not implemented) |
IPAD_SCREEN_ORIENTATIONS |
(not implemented) |
LAUNCH_STORYBOARD_FILE |
(not implemented) |
CUSTOM_XCASSETS_FOLDER |
(not implemented) |
TARGETED_DEVICE_FAMILY |
(not implemented) |
ICON_BIG |
(not implemented) |
ICON_SMALL |
(not implemented) |
COMPANY_COPYRIGHT |
company_copyright |
COMPANY_NAME |
company_name |
COMPANY_WEBSITE |
company_website |
COMPANY_EMAIL |
company_email |
DOCUMENT_EXTENSIONS |
document_extensions |
NEEDS_CURL |
needs_curl |
NEEDS_WEB_BROWSER |
needs_web_browser |
NEEDS_WEBVIEW2 |
needs_webview2 |
NEEDS_STORE_KIT |
needs_store_kit |
PUSH_NOTIFICATIONS_ENABLED |
(not implemented) |
NETWORK_MULTICAST_ENABLED |
(not implemented) |
HARDENED_RUNTIME_ENABLED |
(not implemented) |
HARDENED_RUNTIME_OPTIONS |
(not implemented) |
APP_SANDBOX_ENABLED |
(not implemented) |
APP_SANDBOX_INHERIT |
(not implemented) |
APP_SANDBOX_OPTIONS |
(not implemented) |
APP_SANDBOX_FILE_ACCESS_HOME_RO |
(not implemented) |
APP_SANDBOX_FILE_ACCESS_HOME_RW |
(not implemented) |
APP_SANDBOX_FILE_ACCESS_ABS_RO |
(not implemented) |
APP_SANDBOX_FILE_ACCESS_ABS_RW |
(not implemented) |
APP_SANDBOX_EXCEPTION_IOKIT |
(not implemented) |
PLIST_TO_MERGE |
plist_to_merge |
FORMATS |
formats |
PLUGIN_NAME |
plugin_name |
PLUGIN_MANUFACTURER_CODE |
plugin_manufacturer_code |
PLUGIN_CODE |
plugin_code |
DESCRIPTION |
description |
IS_SYNTH |
is_synth |
NEEDS_MIDI_INPUT |
needs_midi_input |
NEEDS_MIDI_OUTPUT |
needs_midi_output |
IS_MIDI_EFFECT |
is_midi_effect |
EDITOR_WANTS_KEYBOARD_FOCUS |
editor_wants_keyboard_focus |
DISABLE_AAX_BYPASS |
(not implemented) |
DISABLE_AAX_MULTI_MONO |
(not implemented) |
AAX_IDENTIFIER |
(not implemented) |
LV2URI |
(not implemented) |
VST_NUM_MIDI_INS |
vst_num_midi_ins |
VST_NUM_MIDI_OUTS |
vst_num_midi_outs |
VST2_CATEGORY |
vst2_category |
VST3_CATEGORIES |
vst3_categories |
AU_MAIN_TYPE |
au_main_type |
AU_EXPORT_PREFIX |
au_export_prefix |
AU_SANDBOX_SAFE |
au_sandbox_safe |
SUPPRESS_AU_PLIST_RESOURCE_USAGE |
suppress_au_plist_resource_usage |
AAX_CATEGORY |
(not implemented) |
PLUGINHOST_AU |
(not implemented) |
USE_LEGACY_COMPATIBILITY_PLUGIN_CODE |
use_legacy_compatibility_plugin_code |
COPY_PLUGIN_AFTER_BUILD |
(not implemented) |
VST_COPY_DIR |
(not implemented) |
VST3_COPY_DIR |
(not implemented) |
AAX_COPY_DIR |
(not implemented) |
AU_COPY_DIR |
(not implemented) |
UNITY_COPY_DIR |
(not implemented) |
IS_ARA_EFFECT |
(not implemented) |
ARA_FACTORY_ID |
(not implemented) |
ARA_DOCUMENT_ARCHIVE_ID |
(not implemented) |
ARA_ANALYSIS_TYPES |
(not implemented) |
ARA_TRANSFORMATION_FLAGS |
(not implemented) |
VST3_AUTO_MANIFEST |
vst3_auto_manifest |
Zig doesn't currently support generating compile_commands.json.
A common solution is to use the-argus/zig-compile-commands.
See the example projects in this repo for how to use it with juzi.
MIT.
JUCE is licensed separately: https://github.com/juce-framework/JUCE