#define B_IMPLEMENTATION
#include "src/b.h"
#include <libgen.h>
#define BUILD_DIR "build/"
#define TEMPLATE_DIR BUILD_DIR"templates/"
int debug_level = 0;
void
debug_or_release(B_Cmd* cmd)
{
if (debug_level == 0)
b_cmd_append(cmd, "-O3", "-s", "-DNDEBUG");
else if (debug_level == 1)
b_cmd_append(cmd, "-O2", "-ggdb", "-DVKDEBUG");
else if (debug_level == 2)
b_cmd_append(cmd, "-O1", "-ggdb", "-DVKDEBUG");
else {
//b_cmd_append(cmd, "-O0", "-ggdb", "-DVKDEBUG", "-pg");
b_cmd_append(cmd, "-O0", "-ggdb", "-DVKDEBUG");
b_cmd_append(cmd, "-fsanitize=address");
}
}
void
inlcude_dirs(B_Cmd* cmd)
{
b_cmd_append(cmd, "-I./src/", "-I./"TEMPLATE_DIR);
}
void
cflags_common(B_Cmd* cmd)
{
b_cmd_append(cmd, "-Wall", "-Wextra");
debug_or_release(cmd);
b_cmd_append(cmd, "-march=native", "-lm");
b_cmd_append(cmd, "-fno-math-errno", "-funroll-loops", "-flto");
}
void
synth_libs(B_Cmd *cmd)
{
b_cmd_append(cmd, "-lportaudio", "-lrt", "-lasound", "-lraylib", "-lportmidi",
"-lfftw3f", "-lsndfile", "-lconfig", "-lpthread",
"-lwebsockets");
inlcude_dirs(cmd);
}
void cc(B_Cmd *cmd)
{
b_cmd_append(cmd, "clang");
cflags_common(cmd);
}
bool force = false;
bool
build_c(B_Cmd* cmd,
const char** input_paths,
size_t input_paths_len,
const char** dep_paths,
size_t dep_paths_len,
const char* output_path)
{
int rebuild_is_needed =
b_needs_rebuild(B_COMPILE, output_path, input_paths, input_paths_len);
int dep_rebuild = 0;
if (rebuild_is_needed == 0)
dep_rebuild =
b_needs_rebuild(B_COMPILE, output_path, dep_paths, dep_paths_len);
if (rebuild_is_needed < 0 || dep_rebuild < 0) return false;
if (force || rebuild_is_needed || dep_rebuild) {
cmd->count = 0;
cc(cmd);
b_cmd_append(cmd, "-o", output_path);
b_da_append_many(cmd, input_paths, input_paths_len);
if (0 == strcmp(output_path, BUILD_DIR"synth"))
synth_libs(cmd);
return b_cmd_run_sync(*cmd);
}
b_log(B_INFO, "%s is up-to-date", output_path);
return true;
}
bool build_templates(B_Cmd *cmd, const char **templates, size_t len) {
char dest[1024] = "";
for (size_t i = 0; i < len; i++) {
cmd->count = 0;
char *base = strdup(templates[i]);
strcpy(dest, TEMPLATE_DIR);
strcat(dest, basename(base));
strcat(dest, ".h");
if (b_needs_rebuild1(B_TEMPLATE, dest, templates[i]) == 0 &&
force == false) {
b_log(B_INFO, "%s is up-to-date", dest);
continue;
}
char tmp[1024] = "";
strcat(tmp, "build/tt ");
strcat(tmp, templates[i]);
strcat(tmp, " > ");
strcat(tmp, dest);
b_cmd_append(cmd, "bash", "-c", tmp);
b_cmd_run_sync(*cmd);
}
return true;
}
int
main(int argc, char *argv[])
{
B_GO_REBUILD_URSELF(argc, argv);
const char *program_name = b_shift_args(&argc, &argv);
(void)program_name;
while (argc > 0) {
const char *flag = b_shift_args(&argc, &argv);
if (strcmp(flag, "-f") == 0) {
force = true;
} else {
b_log(B_ERROR, "Unknown flag `%s`", flag);
return 1;
}
}
const char *synth_deps[] = {
"src/adsr.h",
"src/b.h",
"src/control.h",
"src/filter.h",
"src/generator.h",
"src/gen.h",
"src/lowpass.h",
"src/midi.h",
"src/notes.h",
"src/osc.h",
"src/pa_memorybarrier.h",
"src/pa_ringbuffer.h",
"src/raygui.h",
"src/sound.h",
"src/stats.h",
"src/synth_common.h",
"src/synth_engine.h",
"src/synth_gui.h",
"src/synth_math.h",
"src/types.h",
"src/web.h",
"src/gui.h",
BUILD_DIR"templates/index.html.h",
};
const char* synth_paths[] = {
"src/adsr.c",
"src/control.c",
"src/filter.c",
// "src/generator.c",
// "src/gtk.c",
"src/lowpass.c",
"src/midi.c",
"src/osc.c",
"src/osc_digisaw.c",
"src/osc_saw.c",
"src/osc_sin.c",
"src/osc_sound.c",
"src/osc_sqr.c",
"src/osc_tri.c",
"src/osc_weird.c",
"src/pa_ringbuffer.c",
"src/sound.c",
"src/synth.c",
"src/synth_engine_v2.c",
"src/synth_gui.c",
"src/web.c",
};
const char *templates[] = {
"tmpl/index.html"
};
B_Cmd cmd = {0};
b_mkdir_if_not_exists(BUILD_DIR);
b_mkdir_if_not_exists(TEMPLATE_DIR);
if (!build_c(&cmd, (const char *[]){"src/tt.c"}, 1, NULL, 0,
BUILD_DIR "tt"))
return 1;
if (!build_templates(&cmd, templates, B_ARRAY_LEN(templates)))
return 1;
if (!build_c(&cmd, synth_paths, B_ARRAY_LEN(synth_paths), synth_deps,
B_ARRAY_LEN(synth_deps), BUILD_DIR "synth"))
return 1;
return 0;
}