You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
9.8 KiB

/**
* ***** BEGIN LICENSE BLOCK *****
*
* Copyright 2017-2023 Yzena, LLC
*
* Licensed under the Yzena Viral User License, Version 0.1 (the "Yzena Viral
* User License" or "YVUL"), the GNU Affero General Public License (the "GNU
* AGPL"), Version 3.0, and the Server Side Public License (the "SSPL"),
* Version 1. You may not use this file except in compliance with all of those
* licenses.
*
* You may obtain a copy of the Yzena Viral User License at
*
* https://yzena.com/yzena-viral-user-license/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Yzena Viral User License is distributed under the
* following disclaimer:
*
* As far as the law allows, this software comes as is, without any
* warranty or condition, and no contributor will be liable to anyone for
* any damages related to this software or this license, under any kind of
* legal claim.
*
* You may obtain a copy of the GNU Affero General Public License at
*
* https://www.gnu.org/licenses/agpl-3.0.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the GNU Affero General Public License is distributed under
* the following disclaimer:
*
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You may obtain a copy of the Server Side Public License at
*
* https://www.mongodb.com/licensing/server-side-public-license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Server Side Public License is distributed under the
* following disclaimer:
*
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Server
* Side Public License for more details.
*
* ****** END LICENSE BLOCK ******
*
* *****************************************************************
*
* ******* BEGIN FILE DESCRIPTION *******
*
* Main build script file.
*
* ******** END FILE DESCRIPTION ********
*/
if config["afl"] && !config["debug"]
{
error "Cannot enable AFL for non-debug builds";
}
if config["ftrace"] && !config["alloc_accounting"]
{
error "Must enable allocator accounting with ftrace";
}
if config["cflags.opt"] == ""
{
config["cflags.opt"]! = "0";
}
dbg: str = if config["debug"] { sysdb["debug"]; } else { ""; };
opt: str = sysdb["cflags.opt"] +~ config["optimization"];
cc: str = if config["cc"] != "" { config["cc"]; } else { sysdb["cc"]; };
if !(rigdb["execs"] contains cc)
{
error "C compiler " +~ cc +~ " does not exist";
}
outopt: str = sysdb[cc]["outopt"];
objopt: str = sysdb[cc]["objopt"];
incopt: str = sysdb[cc]["incopt"] +~ "include";
defopt: str = sysdb[cc]["defopt"];
defs: ![]str =
if platform.os == "Windows"
{
#[ ];
}
else
{
if platform.os != "FreeBSD"
{
#[ "-D_BSD_SOURCE", "-D_GNU_SOURCE", "-D_DEFAULT_SOURCE",
"-D_DARWIN_C_SOURCE", "-D_POSIX_C_SOURCE=200809L",
"-D_XOPEN_SOURCE=700" ];
}
else
{
#[ "-D_BSD_SOURCE", "-D_GNU_SOURCE", "-D_DEFAULT_SOURCE",
"-D_DARWIN_C_SOURCE" ];
}
};
defs! +~= option(defopt, "YC_SAFE", "safe");
defs! +~= option(defopt, "YC_ENABLE_STACKTRACES", "stacktraces");
defs! +~= option(defopt, "YC_ENABLE_FTRACE", "ftrace");
defs! +~= option(defopt, "YC_ENABLE_AFL", "afl");
defs! +~= option(defopt, "YC_ENABLE_ALLOC_ACCOUNTING", "alloc_accounting");
defs! +~= option(defopt, "YC_ENABLE_BUILTIN_128", "builtin_128");
cflags: ![]str = config["cflags"];
ldflags: ![]str = config["ldflags"];
// We need pthread for POSIX systems.
if platform.os != "Windows"
{
ldflags! +~= "-lpthread";
}
if platform.os != "Windows"
{
defs! +~= option(defopt, "YC_USE_VALGRIND", "use_valgrind");
if cc contains "clang" || cc contains "gcc"
{
cflags! +~= "-std=c11";
if config["strict"]
{
cflags! +~= #[ "-Wall", "-Wextra", "-Werror", "-pedantic" ];
if cc contains "clang"
{
// I also want to see all of the errors at once.
cflags! +~= #[ "-Weverything", "-Wno-c++98-compat",
"-ferror-limit=100000" ];
}
}
if !config["debug"]
{
cflags! +~= #[ "-flto", "-fsanitize=cfi", "-fvisibility=hidden" ];
}
}
defs! +~= option(defopt, "YC_USE_POSIX_SPAWN", "use_posix_spawn");
}
else
{
if config["strict"]
{
cflags! +~= #[ "/W4", "/WX", "/wd\"4996\"", "/permissive-" ];
}
}
if cc contains "clang"
{
if config["debug"]
{
sanitizer: sym = config["sanitizer"];
if sanitizer != #none
{
if config["use_valgrind"]
{
error "Cannot use a sanitizer with Valgrind";
}
}
else
{
flags: []str = #[ "-fno-omit-frame-pointer",
"-fno-optimize-sibling-calls", "-fno-common" ];
cflags! +~= flags;
ldflags! +~= flags;
cflags! +~= #[ "-fno-sanitize-recover=all" ];
}
if sanitizer == #address
{
cflags! +~= #[ "-fsanitize=address" ];
}
else if sanitizer == #memory
{
cflags! +~= #[ "-fsanitize=memory" ];
}
else if sanitizer == #undefined
{
cflags! +~= #[ "-fsanitize=undefined" ];
}
else if sanitizer == #thread
{
cflags! +~= #[ "-fsanitize=thread" ];
}
}
}
if config["debug"]
{
defs! = defs +~ option(defopt, "YC_DEBUG_CODE", "debug_code");
defs! = defs +~ option(defopt, "YC_DEBUG_PRINT", "debug_print");
}
else
{
defs! = defs +~ #[ defopt +~ "YC_DEBUG_CODE=0" ];
defs! = defs +~ #[ defopt +~ "YC_DEBUG_PRINT=0" ];
}
cmd_line: []str = #[ cc ] +~ cflags +~ defs +~ ldflags +~ #[ dbg, opt, objout,
incopt, outopt ];
config["cmd_line"]! = cmd_line;
exe_cmd_line: []str = #[ cc ] +~ cflags +~ defs +~ ldflags +~ #[ dbg, opt,
incopt,
outopt ];
config["exe_cmd_line"]! = exe_cmd_line;
src_files: []str = walk_src_dir();
libyc: str = add_lib("yc", src_files);
yc: str = add_exe(yc, #[ "src/main.c", libyc ]);
extras: ![]str = #[ ];
exes: ![]str = #[ ];
exes! +~= yc;
exes! +~= walk_test_dir(libyc);
if config["benchmarks"]
{
if config["benchmark.arith"]
{
exes! +~= add_exe("benchmarks/yc_benchmark_arith",
#[ "benchmarks/arith.c", libyc ]);
}
if config["benchmark.memcpy"]
{
exes! +~= add_exe("benchmarks/yc_benchmark_memcpy",
#[ "benchmarks/memcpy.c", libyc ]);
}
if config["benchmark.xxh3_v_spooky"]
{
exes! +~= add_exe("benchmarks/yc_benchmark_xxh3_v_spooky",
#[ "benchmarks/xxh3_v_spooky.c", libyc ]);
}
if config["benchmark.listdir"]
{
exes! +~= add_exe("benchmarks/yc_benchmark_listdir",
#[ "benchmarks/listdir.c", libyc ]);
}
}
if config["samples"] && config["samples.io"]
{
exes! +~= add_exe("samples/io/file_open",
#[ "samples/io/file_open.c", libyc ]);
exes! +~= add_exe("samples/io/random_access",
#[ "samples/io/random_access.c", libyc ]);
exes! +~= add_exe("samples/io/interactive",
#[ "samples/io/interactive.c", libyc ]);
exes! +~= add_exe("samples/io/list_to_file",
#[ "samples/io/list_to_file.c", libyc ]);
}
pub_headers: []str = find "*.h", "include/yc";
if config["docs.install"]
{
install #include: pub_headers;
}
if platform.os != "Windows" && config["docs"]
{
if !(rigdb["execs"] contains "doxygen")
{
error "Cannot find doxygen, required for docs";
}
if !(rigdb["execs"] contains "sphinx-build")
{
error "Cannot find sphinx-build, required for docs";
}
if config["docs.versioned"] &&
!(rigdb["execs"] contains "sphinx-multiversion")
{
error "Cannot find sphinx-multiversion, required for versioned docs";
}
priv_headers: []str =
if config["docs.internal"]
{
find_recursive "*.h", "src/";
}
else
{
#[ ];
};
config["YC_DOCS_INTERNAL"]! =
if config["docs.internal"]
{
"INTERNAL";
}
else
{
"";
};
doxy_out_dir: str = config["binary"] +~ "/doxygen";
doxy_idx: str = doxy_out_dir +~ "xml/index.xml";
config["doxy_out_dir"]! = doxy_out_dir;
doxyfile: str = add_config_file("docs/doxyfile", "docs/doxyfile.in");
target #doxygen: doxy_idx;
target doxy_idx: doxyfile, pub_headers, priv_headers
{
$ doxygen @(deps[0]);
}
sphinx_bin_dir: str = rigdb["binary_dir"] +~ "/sphinx";
config["sphinx_bin_dir"]! = sphinx_bin_dir;
sphinx_idx: str = sphinx_bin_dir +~ "/index.html";
sphinx_conf: str = rigdb["source_dir"] +~ "/docs/conf.py";
rst_files: str = find_recursive "*.rst", "docs/";
if config["docs.versioned"]
{
target sphinx_idx: sphinx_conf, rst_files, doxy_idx
{
$ sphinx-multiversion
@("-Dbreathe_projects.yc=" +~ config["doxy_out_dir"] +~ "/xml")
@(rigdb["source_dir"] +~ "/docs")
@(config["sphinx_bin_dir"]);
}
}
else
{
target sphinx_idx: sphinx_conf, rst_files, doxy_idx
{
$ sphinx-build -b html
@("-Dbreathe_projects.yc=" +~ config["doxy_out_dir"] +~ "/xml")
@(config["source_dir"] +~ "/docs")
@(config["sphinx_bin_dir"] +~ "/docs");
}
}
target #docs: sphinx_idx
{
$ @(config["source_dir"] +~ "/docs/_res/compress.sh")
@(config["sphinx_bin_dir"])
@(rigdb["binary_dir"] +~ "/docs");
$ @(config["source_dir"] +~ "/docs/_res/copy_static.sh")
@(config["source_dir"] +~ "/docs")
@(config["sphinx_bin_dir"]);
}
// TODO: Handle installing docs. This has to be done *after* I make my own
// docs system to replace sphinx and breathe because the only docs that
// should be installed are manpages, and I need to make my system able to
// handle generating manpages.
// Make sure to generate docs when running the #all target.
extras! +~= #docs;
}
exes! +~= add_link_exe("rig", yc);
exes! +~= add_link_exe("rigc", yc);
install #bin: execs;
install #lib: libyc;
target #all: exes, extras;