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

481 lines
11 KiB
Plaintext

/**
* ***** 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 *******
*
* Package build script file.
*
* ******** END FILE DESCRIPTION ********
*/
fn exe_name(exe: str) -> str
{
return if platform.os == "Windows" { exe +~ ".exe"; } else { exe; };
}
fn add_exe(exe: str, dep_list: []str) -> str
{
ret: str = exe_name(exe);
target ret: dep_list
{
$ @(config["exe_cmd_line"]) @tgt %deps;
}
return ret;
}
fn add_exe_by_name(exe: str, dep_list: []str) -> str
{
ret: str = exe_name(exe);
file: str = exe +~ ".c";
target ret: file, dep_list
{
$ @(config["exe_cmd_line"]) @tgt %deps;
}
return ret;
}
fn add_link_exe(exe: str, dep: str) -> str
{
ret: str = exe_name(exe);
target ret: dep
{
if platform.os != "Windows"
{
$ ln -sf @("./" +~ deps[0]) @tgt;
}
else
{
// I don't want to deal with symlinks on Windows.
$ copy @("./" +~ deps[0]) @tgt;
}
}
return ret;
}
fn add_lib(lib: str, dep_list: []str) -> str
{
libtgt: str =
if platform.os == "Windows"
{
"lib" +~ lib +~ ".lib";
}
else
{
"lib" +~ lib +~ ".a";
};
target libtgt: dep_list
{
if platform.os == "Windows"
{
$ @(config["cmd_line"]) @tgt %deps;
}
else
{
$ ar -r -cu @tgt %deps;
}
}
return libtgt;
}
fn add_config_file(out: str, file: str) -> str
{
return configure_file out, file;
}
fn option(defopt: str, name: str, opt: str) -> []str
{
opt: str = defopt +~ name +~ (if config[opt] { "=1"; } else { "=0"; });
return #[ opt ];
}
fn add_c_file(f: str) -> str
{
ext: str = if platform.os == "Windows" { "obj" } else { "o" };
obj: str = replace_ext f, "c", ext;
// TODO: Check for includes and add them as dynamic dependencies.
target obj: f
{
$ @(config["cmd_line"]) @tgt %deps;
}
return obj;
}
fn walk_src_dir() -> []str
{
files: ![]str = #[ ];
src_files: []str = find "*.c", "src";
foreach f: src_files
{
// Skip these two files for now.
if f contains "main.c" || f contains "stdio.c"
{
continue;
}
files! +~= f;
}
dirs: []str = find_dirs "src";
foreach d: dirs
{
d_files: []str = find "*.c", d;
foreach f: d_files
{
files! +~= f;
}
dos: str = d +~ "/os";
if exists dos
{
if platform.os == "Windows"
{
win_files: []str = find "*.c", dos +~ "/windows";
foreach f: win_files
{
files! +~= f;
}
}
else if platform.os == "Mac OSX" && exists (dos +~ "/darwin")
{
darwin_files: []str = find "*.c", dos +~ "/darwin";
foreach f: darwin_files
{
files! +~= f;
}
}
else
{
posix_files: []str = find "*.c", dos +~ "/posix";
foreach f: posix_files
{
if f contains "semaphore"
{
if (platform.os == "Mac OSX" &&
!(f contains "semaphore_darwin")) ||
(platform.os != "Mac OSX" &&
f contains "semaphore_darwin")
{
continue;
}
}
files! +~= f;
}
}
}
}
obj_files: []str =
foreach f: files
{
add_c_file(f);
};
return obj_files;
}
fn add_standalone_c_test(name: str, dep_list: []str) -> void
{
tst: str = add_exe(name, #[ name +~ ".c" ] +~ dep_list);
test tst, #[ tst ];
}
fn add_test_lib(name: str, dep_list: []str) -> str
{
obj: str = add_c_file(name +~ ".c");
return add_lib(name, dep_list +~ obj);
}
fn walk_test_dir(lib: str) -> []str
{
exes: ![]str = #[ ];
// TODO: Make this more efficient by creating lists that are common, like
// lib by itself or lib and libcommon together.
if config["extra_long_tests"]
{
add_standalone_c_test("tests/yc_memcpy", #[ lib ]);
}
// This keyword creates a target with the given name that copies a file from
// the source directory to the build directory. It returns the name of the
// target to use later.
//
// I did it this way so that targets that have the same name as both a
// source and a target won't clash.
//
// `configure_file` does something similar, but it configures a file as
// well. There will also be a `copy_dir` keyword.
words: str = copy_file "tests/words.txt";
strgen: str = add_exe("tests/strgen.c", #[ lib ]);
libiterator: str = add_test_lib("tests/iterator_tests", #[ lib ]);
libcommon: str = add_test_lib("tests/common", #[ lib ]);
dirs: []str = find_dirs "tests";
foreach d: dirs
{
if d contains "container"
{
if config["long_tests"]
{
kjvbiblec: str = "kjvbible.c";
target kjvbiblec: strgen, "kjvbible.txt"
{
$ @(deps[0]) @(deps[1]) @tgt "kjvbible_array" 1;
}
kjvbible: str = add_lib(d +~ "/" +~ "kjvbible", #[ ]);
add_standalone_c_test(d +~ "/map_countwords",
#[ kjvbible, lib, libcommon ]);
add_standalone_c_test(d +~ "/map_stress", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/nvec_stress", #[ lib, libcommon ]);
}
plain_tests: []str = #[
"map_all",
"array_all",
"vec_push",
"vec_npush",
"vec_pop",
"vec_npop",
"vec_add",
"vec_nadd",
"vec_remove",
"vec_nremove",
"vec_setcap",
"vec_setlen",
"vec_stress",
"vec_copy",
"svec_push",
"svec_npush",
"svec_pop",
"svec_npop",
"stack_all",
"treevec_all",
];
foreach t: plain_tests
{
if t == "vec_stress" || t == "map_all"
{
add_standalone_c_test(d +~ "/" +~ t,
#[ lib, libcommon, words ]);
}
else
{
add_standalone_c_test(d +~ "/" +~ t, #[ lib, libcommon ]);
}
}
nvec_tests: []str = #[
"nvec_push",
"nvec_npush",
"nvec_pop",
"nvec_npop",
"nvec_add",
"nvec_nadd",
"nvec_remove",
"nvec_nremove",
"nvec_setcap",
"nvec_setlen",
"nvec_copy",
];
libnvec: str = add_test_lib(d +~ "/nvec_tests",
#[ lib, libcommon ]);
foreach t: nvec_tests
{
add_standalone_c_test(d +~ "/" +~ t,
#[ lib, libcommon, libnvec ]);
}
tree_tests: []str = #[
"tree_add",
"tree_remove",
"tree_removeAll",
"tree_copy",
"tree_empty",
"tree_iterator",
];
libtree: str = add_test_lib(d +~ "/tree_tests", #[ lib ]);
foreach t: tree_tests
{
if t == "tree_iterator"
{
add_standalone_c_test(d +~ "/" +~ t, #[ lib, libcommon,
libtree,
libiterator ]);
}
else
{
add_standalone_c_test(d +~ "/" +~ t,
#[ lib, libcommon, libtree ]);
}
}
ntree_tests: [] str = #[
"ntree_add",
"ntree_remove",
"ntree_copy",
"ntree_empty",
"ntree_iterator",
];
libntree: str = add_test_lib(d +~ "/ntree_tests", #[ lib ]);
foreach t: ntree_tests
{
if t == "ntree_iterator"
{
add_standalone_c_test(d +~ "/" +~ t, #[ lib, libcommon,
libntree,
libiterator ]);
}
else
{
add_standalone_c_test(d +~ "/" +~ t,
#[ lib, libcommon, libntree ]);
}
}
}
else if d contains "arith"
{
if config["long_tests"]
{
add_standalone_c_test(d +~ "/arith_sn", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/arith_slt", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/arith_sle", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/arith_sgt", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/arith_sge", #[ lib, libcommon ]);
}
add_standalone_c_test(d +~ "/arith_sshr", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/arith_ushr", #[ lib, libcommon ]);
}
else if d contains "str"
{
add_standalone_c_test(d +~ "/string_all", #[ lib, libcommon ]);
}
else if d contains "io"
{
add_standalone_c_test(d +~ "/fs_open", #[ lib, libcommon ]);
add_standalone_c_test(d +~ "/fs_read", #[ lib, libcommon, words ]);
add_standalone_c_test(d +~ "/fs_unicode", #[ lib, libcommon ]);
}
else if d contains "gaml"
{
exes! +~= add_exe_by_name(d +~ "/gaml_fuzz_parse",
#[ lib, libcommon ]);
exes! +~= add_exe_by_name(d +~ "/gaml_fuzz_edit",
#[ lib, libcommon ]);
}
else if d contains "alloc"
{
add_standalone_c_test(d +~ "/mappool_all", #[ lib, libcommon ]);
}
else if d contains "util"
{
libhashobj: str = add_c_file(d +~ "/hash_tests.c");
libhash: str = add_lib(d +~ "/hash_tests", #[ libhashobj, lib]);
add_standalone_c_test(d +~ "/hash_results",
#[ lib, libcommon, libhash ]);
add_standalone_c_test(d +~ "/hash_alignment",
#[ lib, libcommon, libhash ]);
add_standalone_c_test(d +~ "/hash_pieces",
#[ lib, libcommon, libhash ]);
if config["extra_long_tests"]
{
add_standalone_c_test(d +~ "/hash_deltas",
#[ lib, libcommon, libhash ]);
}
}
else
{
error "Unhandled test directory: " +~ d;
}
}
return exes;
}