2017-04-30 17:37:22 +00:00
|
|
|
/* A build system for libostd. */
|
|
|
|
|
2017-05-09 19:20:37 +00:00
|
|
|
/* for Windows so that we avoid dllimport/dllexport */
|
|
|
|
#define OSTD_BUILD_LIB
|
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
#include <string>
|
2017-05-01 15:28:54 +00:00
|
|
|
#include <vector>
|
2017-04-30 17:37:22 +00:00
|
|
|
#include <stdexcept>
|
2017-05-01 22:56:45 +00:00
|
|
|
#include <utility>
|
2017-05-01 15:28:54 +00:00
|
|
|
|
2017-05-01 22:56:45 +00:00
|
|
|
#include "ostd/io.hh"
|
|
|
|
#include "ostd/range.hh"
|
|
|
|
#include "ostd/format.hh"
|
|
|
|
#include "ostd/string.hh"
|
|
|
|
#include "ostd/filesystem.hh"
|
2017-04-30 18:16:24 +00:00
|
|
|
#include "ostd/thread_pool.hh"
|
2017-05-03 19:09:25 +00:00
|
|
|
#include "ostd/channel.hh"
|
2017-05-15 22:40:09 +00:00
|
|
|
#include "ostd/argparse.hh"
|
2017-04-30 18:16:24 +00:00
|
|
|
|
2017-05-01 22:56:45 +00:00
|
|
|
namespace fs = ostd::filesystem;
|
|
|
|
|
|
|
|
/* ugly, but do not explicitly compile */
|
|
|
|
#include "src/io.cc"
|
2017-05-07 19:16:42 +00:00
|
|
|
#include "src/process.cc"
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
using strvec = std::vector<std::string>;
|
2017-05-05 20:24:08 +00:00
|
|
|
using pathvec = std::vector<fs::path>;
|
2017-05-05 00:00:02 +00:00
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
/* THESE VARIABLES CAN BE ALTERED */
|
|
|
|
|
2017-05-11 17:21:02 +00:00
|
|
|
static pathvec EXAMPLES = {
|
2017-04-30 17:37:22 +00:00
|
|
|
"format", "listdir", "range", "range_pipe", "signal",
|
|
|
|
"stream1", "stream2", "coroutine1", "coroutine2", "concurrency"
|
|
|
|
};
|
|
|
|
|
2017-05-09 20:37:00 +00:00
|
|
|
static fs::path ASM_SOURCE_DIR = fs::path{"src"} / "asm";
|
2017-05-11 17:21:02 +00:00
|
|
|
static pathvec ASM_SOURCES = {
|
2017-04-30 17:37:22 +00:00
|
|
|
"jump_all_gas", "make_all_gas", "ontop_all_gas"
|
|
|
|
};
|
|
|
|
|
2017-05-01 17:03:47 +00:00
|
|
|
static fs::path CXX_SOURCE_DIR = "src";
|
2017-05-11 17:21:02 +00:00
|
|
|
static pathvec CXX_SOURCES = {
|
2017-05-07 20:48:02 +00:00
|
|
|
"context_stack", "environ", "io", "concurrency", "process"
|
2017-04-30 17:37:22 +00:00
|
|
|
};
|
|
|
|
|
2017-05-01 17:03:47 +00:00
|
|
|
static fs::path TEST_DIR = "tests";
|
2017-05-11 17:21:02 +00:00
|
|
|
static pathvec TEST_CASES = {
|
2017-04-30 17:37:22 +00:00
|
|
|
"algorithm", "range"
|
|
|
|
};
|
|
|
|
|
2017-05-05 20:24:08 +00:00
|
|
|
static fs::path OSTD_SHARED_LIB = "libostd.so";
|
|
|
|
static fs::path OSTD_STATIC_LIB = "libostd.a";
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-01 17:12:17 +00:00
|
|
|
static std::string DEFAULT_CXXFLAGS = "-std=c++1z -I. -O2 -Wall -Wextra "
|
|
|
|
"-Wshadow -Wold-style-cast";
|
|
|
|
static std::string DEFAULT_LDFLAGS = "-pthread";
|
|
|
|
static std::string DEFAULT_ASFLAGS = "";
|
|
|
|
|
|
|
|
static std::string DEBUG_CXXFLAGS = "-g";
|
|
|
|
|
|
|
|
static std::string SHARED_CXXFLAGS = "-fPIC";
|
|
|
|
static std::string SHARED_LDFLAGS = "-shared";
|
|
|
|
static std::string SHARED_ASFLAGS = "-fPIC";
|
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
/* DO NOT CHANGE PAST THIS POINT */
|
|
|
|
|
|
|
|
static std::string from_env_or(char const *evar, char const *defval) {
|
|
|
|
char const *varv = std::getenv(evar);
|
|
|
|
if (!varv || !varv[0]) {
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
return varv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_cross(std::string &arg) {
|
|
|
|
char const *cross = std::getenv("CROSS");
|
|
|
|
if (!cross || !cross[0]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
arg.insert(0, cross);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_env(std::string &val, char const *evar) {
|
|
|
|
char const *varv = std::getenv(evar);
|
|
|
|
if (!varv || !varv[0]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
val += ' ';
|
|
|
|
val += varv;
|
|
|
|
}
|
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
static void exec_command(strvec const &args) {
|
2017-05-13 16:35:58 +00:00
|
|
|
if (int ret = ostd::subprocess{nullptr, ostd::iter(args)}.close(); ret) {
|
2017-05-11 17:36:17 +00:00
|
|
|
throw std::runtime_error{ostd::format(
|
|
|
|
ostd::appender<std::string>(), "command failed with code %d", ret
|
|
|
|
).get()};
|
2017-05-01 15:28:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
static std::string get_command(strvec const &args) {
|
|
|
|
std::string ret;
|
2017-05-01 15:28:54 +00:00
|
|
|
for (auto &s: args) {
|
2017-05-08 01:44:58 +00:00
|
|
|
if (!ret.empty()) {
|
|
|
|
ret += ' ';
|
|
|
|
}
|
2017-05-03 19:09:25 +00:00
|
|
|
ret += s;
|
2017-05-01 15:28:54 +00:00
|
|
|
}
|
2017-05-03 19:09:25 +00:00
|
|
|
return ret;
|
2017-05-01 15:28:54 +00:00
|
|
|
}
|
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
static void add_args(strvec &args, std::string const &cmdl) {
|
2017-05-11 21:49:51 +00:00
|
|
|
ostd::split_args([&args](ostd::string_range arg) {
|
|
|
|
args.emplace_back(arg);
|
|
|
|
}, cmdl);
|
2017-05-01 15:28:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static fs::path path_with_ext(fs::path const &p, fs::path const &ext) {
|
|
|
|
fs::path rp = p;
|
|
|
|
rp.replace_extension(ext);
|
|
|
|
return rp;
|
|
|
|
}
|
|
|
|
|
2017-05-01 15:49:27 +00:00
|
|
|
static void try_remove(fs::path const &path, bool all = false) {
|
2017-05-01 15:28:54 +00:00
|
|
|
try {
|
2017-05-01 15:49:27 +00:00
|
|
|
if (all) {
|
|
|
|
fs::remove_all(path);
|
|
|
|
} else {
|
|
|
|
fs::remove(path);
|
|
|
|
}
|
2017-05-01 15:28:54 +00:00
|
|
|
} catch (fs::filesystem_error const &) {}
|
|
|
|
}
|
|
|
|
|
2017-05-01 15:49:27 +00:00
|
|
|
static bool verbose = false;
|
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
bool build_examples = true;
|
|
|
|
bool build_testsuite = true;
|
|
|
|
bool build_static = true;
|
|
|
|
bool build_shared = false;
|
2017-05-01 17:03:47 +00:00
|
|
|
std::string build_cfg = "debug";
|
2017-04-30 17:37:22 +00:00
|
|
|
bool clean = false;
|
|
|
|
|
2017-05-01 17:12:17 +00:00
|
|
|
std::string cxxflags = DEFAULT_CXXFLAGS;
|
|
|
|
std::string ldflags = DEFAULT_LDFLAGS;
|
|
|
|
std::string asflags = DEFAULT_ASFLAGS;
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-15 22:40:09 +00:00
|
|
|
ostd::arg_parser ap;
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-15 22:40:09 +00:00
|
|
|
auto &help = ap.add_help("print this message and exit");
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("--no-examples", ostd::arg_value::NONE)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("do not build examples")
|
|
|
|
.action(ostd::arg_store_false(build_examples));
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("--no-test-suite", ostd::arg_value::NONE)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("do not build test suite")
|
|
|
|
.action(ostd::arg_store_false(build_testsuite));
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("--no-static", ostd::arg_value::NONE)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("do not build static libostd")
|
|
|
|
.action(ostd::arg_store_false(build_static));
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("--shared", ostd::arg_value::NONE)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("build shared libostd")
|
|
|
|
.action(ostd::arg_store_true(build_shared));
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("--config", ostd::arg_value::REQUIRED)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("build configuration (debug/release)")
|
|
|
|
.action(ostd::arg_store_str(build_cfg));
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("-v", "--verbose", ostd::arg_value::NONE)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("print entire commands")
|
|
|
|
.action(ostd::arg_store_true(verbose));
|
|
|
|
|
2017-05-16 17:25:20 +00:00
|
|
|
ap.add_optional("--clean", ostd::arg_value::NONE)
|
2017-05-15 22:40:09 +00:00
|
|
|
.help("remove generated files and exit")
|
|
|
|
.action(ostd::arg_store_true(clean));
|
|
|
|
|
|
|
|
try {
|
|
|
|
ap.parse(argc, argv);
|
|
|
|
} catch (ostd::arg_error const &e) {
|
|
|
|
ostd::cerr.writefln("argument parsing failed: %s", e.what());
|
|
|
|
ap.print_help(ostd::cerr.iter());
|
2017-04-30 17:37:22 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-15 22:40:09 +00:00
|
|
|
if (help.used()) {
|
|
|
|
return 0;
|
|
|
|
}
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-09 19:20:37 +00:00
|
|
|
std::string default_lib = OSTD_SHARED_LIB.string();
|
2017-04-30 17:37:22 +00:00
|
|
|
if (build_static) {
|
2017-05-09 19:20:37 +00:00
|
|
|
default_lib = OSTD_STATIC_LIB.string();
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto strip = from_env_or("STRIP", "strip");
|
|
|
|
auto cxx = from_env_or("CXX", "c++");
|
2017-05-01 15:28:54 +00:00
|
|
|
auto as = from_env_or("AS", "c++");
|
2017-04-30 17:37:22 +00:00
|
|
|
auto ar = from_env_or("AR", "ar");
|
|
|
|
|
|
|
|
add_cross(strip);
|
|
|
|
add_cross(cxx);
|
|
|
|
add_cross(as);
|
|
|
|
add_cross(ar);
|
|
|
|
|
2017-05-01 17:03:47 +00:00
|
|
|
if (build_cfg == "debug") {
|
2017-05-01 17:12:17 +00:00
|
|
|
cxxflags += ' ';
|
|
|
|
cxxflags += DEBUG_CXXFLAGS;
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
add_env(cxxflags, "CXXFLAGS");
|
|
|
|
add_env(ldflags, "LDFLAGS");
|
|
|
|
add_env(asflags, "ASFLAGS");
|
|
|
|
|
|
|
|
if (clean) {
|
2017-05-01 22:56:45 +00:00
|
|
|
ostd::writeln("Cleaning...");
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-11 17:21:02 +00:00
|
|
|
for (auto &ex: EXAMPLES) {
|
|
|
|
auto rp = "examples" / ex;
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(rp);
|
2017-04-30 17:37:22 +00:00
|
|
|
rp.replace_extension(".o");
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(rp);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
2017-05-11 17:21:02 +00:00
|
|
|
for (auto &aso: ASM_SOURCES) {
|
2017-05-01 17:03:47 +00:00
|
|
|
auto rp = path_with_ext(ASM_SOURCE_DIR / aso, ".o");
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(rp);
|
2017-05-11 17:21:02 +00:00
|
|
|
rp.replace_filename(aso.string() + "_dyn.o");
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(rp);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
2017-05-11 17:21:02 +00:00
|
|
|
for (auto &cso: CXX_SOURCES) {
|
2017-05-01 17:03:47 +00:00
|
|
|
auto rp = path_with_ext(CXX_SOURCE_DIR / cso, ".o");
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(rp);
|
2017-05-11 17:21:02 +00:00
|
|
|
rp.replace_filename(cso.string() + "_dyn.o");
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(rp);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(OSTD_STATIC_LIB);
|
|
|
|
try_remove(OSTD_SHARED_LIB);
|
|
|
|
try_remove("test_runner.o");
|
|
|
|
try_remove("test_runner");
|
2017-05-01 15:49:27 +00:00
|
|
|
try_remove("tests", true);
|
2017-04-30 17:37:22 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-03 19:09:25 +00:00
|
|
|
/* a queue of stuff to print to stdout */
|
|
|
|
ostd::channel<std::string> io_msgs;
|
|
|
|
|
|
|
|
/* a thread which reads from the queue */
|
|
|
|
std::thread io_thread{[&io_msgs]() {
|
|
|
|
try {
|
|
|
|
for (;;) {
|
|
|
|
/* wait for a msg; if closed, throw channel_error */
|
|
|
|
ostd::writeln(io_msgs.get());
|
|
|
|
}
|
|
|
|
} catch (ostd::channel_error const &) {
|
|
|
|
/* the queue is empty and closed, thread is done */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}};
|
|
|
|
|
|
|
|
auto echo_q = [&io_msgs](ostd::string_range fmt, auto const &...args) {
|
|
|
|
if (!verbose) {
|
|
|
|
auto app = ostd::appender<std::string>();
|
|
|
|
ostd::format(app, fmt, args...);
|
|
|
|
io_msgs.put(std::move(app.get()));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
auto exec_v = [&io_msgs](strvec const &args) {
|
2017-05-03 19:09:25 +00:00
|
|
|
if (verbose) {
|
2017-05-08 01:44:58 +00:00
|
|
|
io_msgs.put(get_command(args));
|
2017-05-03 19:09:25 +00:00
|
|
|
}
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_command(args);
|
2017-05-03 19:09:25 +00:00
|
|
|
};
|
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
auto call_cxx = [&](
|
2017-05-10 21:40:03 +00:00
|
|
|
fs::path const &input, fs::path const &output, bool lib, bool shared
|
2017-05-01 15:28:54 +00:00
|
|
|
) {
|
2017-05-08 01:44:58 +00:00
|
|
|
strvec args = { cxx };
|
2017-05-01 15:28:54 +00:00
|
|
|
add_args(args, cxxflags);
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
auto ifs = input.string();
|
|
|
|
auto outp = output;
|
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
if (shared) {
|
2017-05-05 00:00:02 +00:00
|
|
|
outp.replace_extension();
|
|
|
|
outp += "_dyn.o";
|
|
|
|
echo_q("CXX (shared): %s", ifs);
|
2017-05-01 17:12:17 +00:00
|
|
|
add_args(args, SHARED_CXXFLAGS);
|
2017-04-30 17:37:22 +00:00
|
|
|
} else {
|
2017-05-05 00:00:02 +00:00
|
|
|
echo_q("CXX: %s", ifs);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-10 21:40:03 +00:00
|
|
|
if (lib) {
|
|
|
|
args.push_back("-DOSTD_BUILD_LIB");
|
|
|
|
if (shared) {
|
|
|
|
args.push_back("-DOSTD_BUILD_DLL");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
args.push_back("-c");
|
|
|
|
args.push_back("-o");
|
2017-05-05 00:00:02 +00:00
|
|
|
args.push_back(outp.string());
|
|
|
|
args.push_back(ifs);
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_v(args);
|
2017-05-05 00:00:02 +00:00
|
|
|
|
|
|
|
return outp;
|
2017-04-30 17:37:22 +00:00
|
|
|
};
|
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
/* mostly unnecessary to separately compile shared, but
|
|
|
|
* the files may check for __PIC__ (at least mips32 does)
|
|
|
|
*/
|
|
|
|
auto call_as = [&](
|
2017-05-10 21:40:03 +00:00
|
|
|
fs::path const &input, fs::path const &output, bool, bool shared
|
2017-05-01 15:28:54 +00:00
|
|
|
) {
|
2017-05-08 01:44:58 +00:00
|
|
|
strvec args = { as };
|
2017-05-01 15:28:54 +00:00
|
|
|
add_args(args, asflags);
|
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
auto ifs = input.string();
|
|
|
|
auto outp = output;
|
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
if (shared) {
|
2017-05-05 00:00:02 +00:00
|
|
|
outp.replace_extension();
|
|
|
|
outp += "_dyn.o";
|
|
|
|
echo_q("AS (shared): %s", ifs);
|
2017-05-01 17:12:17 +00:00
|
|
|
add_args(args, SHARED_ASFLAGS);
|
2017-05-01 15:28:54 +00:00
|
|
|
} else {
|
2017-05-05 00:00:02 +00:00
|
|
|
echo_q("AS: %s", ifs);
|
2017-05-01 15:28:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
args.push_back("-c");
|
|
|
|
args.push_back("-o");
|
2017-05-05 00:00:02 +00:00
|
|
|
args.push_back(outp.string());
|
|
|
|
args.push_back(ifs);
|
2017-05-01 15:28:54 +00:00
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_v(args);
|
2017-05-05 00:00:02 +00:00
|
|
|
|
|
|
|
return outp;
|
2017-04-30 17:37:22 +00:00
|
|
|
};
|
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
auto call_ld = [&](
|
2017-05-05 20:24:08 +00:00
|
|
|
fs::path const &output, pathvec const &files, strvec const &flags
|
2017-05-01 15:28:54 +00:00
|
|
|
) {
|
2017-05-01 22:56:45 +00:00
|
|
|
echo_q("LD: %s", output);
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
strvec args = { cxx };
|
2017-05-01 15:28:54 +00:00
|
|
|
add_args(args, cxxflags);
|
|
|
|
|
|
|
|
args.push_back("-o");
|
2017-05-05 20:24:08 +00:00
|
|
|
args.push_back(output.string());
|
|
|
|
for (auto &p: files) {
|
|
|
|
args.push_back(p.string());
|
|
|
|
}
|
2017-05-01 15:28:54 +00:00
|
|
|
args.insert(args.cend(), flags.begin(), flags.end());
|
|
|
|
|
|
|
|
add_args(args, ldflags);
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_v(args);
|
2017-05-01 15:28:54 +00:00
|
|
|
|
2017-05-01 17:03:47 +00:00
|
|
|
if (build_cfg == "release") {
|
2017-05-01 15:28:54 +00:00
|
|
|
args.clear();
|
2017-05-08 01:44:58 +00:00
|
|
|
args.push_back(strip);
|
2017-05-05 20:24:08 +00:00
|
|
|
args.push_back(output.string());
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_v(args);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
auto call_ldlib = [&](
|
2017-05-05 20:24:08 +00:00
|
|
|
fs::path const &output, pathvec const &files, bool shared
|
2017-05-01 15:28:54 +00:00
|
|
|
) {
|
2017-04-30 17:37:22 +00:00
|
|
|
if (shared) {
|
2017-05-08 01:44:58 +00:00
|
|
|
strvec flags;
|
|
|
|
add_args(flags, SHARED_CXXFLAGS);
|
|
|
|
add_args(flags, SHARED_LDFLAGS);
|
|
|
|
call_ld(output, files, flags);
|
2017-04-30 17:37:22 +00:00
|
|
|
} else {
|
2017-05-08 01:44:58 +00:00
|
|
|
strvec args = { ar };
|
2017-05-01 22:56:45 +00:00
|
|
|
echo_q("AR: %s", output);
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
args.push_back("rcs");
|
2017-05-05 20:24:08 +00:00
|
|
|
args.push_back(output.string());
|
|
|
|
for (auto &p: files) {
|
|
|
|
args.push_back(p.string());
|
|
|
|
}
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_v(args);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-11 17:21:02 +00:00
|
|
|
auto build_example = [&](fs::path const &name) {
|
|
|
|
auto base = "examples" / name;
|
2017-05-01 15:28:54 +00:00
|
|
|
auto ccf = path_with_ext(base, ".cc");
|
|
|
|
auto obf = path_with_ext(base, ".o");
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-10 21:40:03 +00:00
|
|
|
call_cxx(ccf, obf, false, false);
|
2017-05-05 20:24:08 +00:00
|
|
|
call_ld(base, { obf }, { default_lib });
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(obf);
|
2017-04-30 17:37:22 +00:00
|
|
|
};
|
|
|
|
|
2017-05-11 17:21:02 +00:00
|
|
|
auto build_test = [&](fs::path const &name) {
|
2017-05-01 17:03:47 +00:00
|
|
|
auto base = TEST_DIR / name;
|
2017-05-01 15:28:54 +00:00
|
|
|
auto ccf = path_with_ext(base, ".cc");
|
|
|
|
auto obf = path_with_ext(base, ".o");
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(ccf);
|
2017-05-01 22:56:45 +00:00
|
|
|
ostd::file_stream f{ccf.string(), ostd::stream_mode::WRITE};
|
|
|
|
if (!f.is_open()) {
|
|
|
|
auto app = ostd::appender<std::string>();
|
|
|
|
ostd::format(app, "cannot open '%s' for writing", ccf);
|
|
|
|
throw std::runtime_error{app.get()};
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
2017-05-01 22:56:45 +00:00
|
|
|
f.writef(
|
2017-04-30 17:37:22 +00:00
|
|
|
"#define OSTD_BUILD_TESTS libostd_%s\n"
|
|
|
|
"\n"
|
|
|
|
"#include <ostd/unit_test.hh>\n"
|
|
|
|
"#include <ostd/%s.hh>\n"
|
|
|
|
"#include <ostd/io.hh>\n"
|
|
|
|
"\n"
|
|
|
|
"int main() {\n"
|
|
|
|
" auto [ succ, fail ] = ostd::test::run();\n"
|
|
|
|
" ostd::writeln(succ, \" \", fail);\n"
|
|
|
|
" return 0;\n"
|
|
|
|
"}\n",
|
2017-05-01 22:56:45 +00:00
|
|
|
name, name
|
2017-04-30 17:37:22 +00:00
|
|
|
);
|
2017-05-01 22:56:45 +00:00
|
|
|
f.close();
|
2017-04-30 17:37:22 +00:00
|
|
|
|
2017-05-10 21:40:03 +00:00
|
|
|
call_cxx(ccf, obf, false, false);
|
2017-05-05 20:24:08 +00:00
|
|
|
call_ld(base, { obf }, { default_lib });
|
2017-05-01 15:28:54 +00:00
|
|
|
try_remove(obf);
|
2017-04-30 17:37:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
auto build_test_runner = [&]() {
|
2017-05-10 21:40:03 +00:00
|
|
|
call_cxx("test_runner.cc", "test_runner.o", false, false);
|
2017-05-01 15:28:54 +00:00
|
|
|
call_ld("test_runner", { "test_runner.o" }, { default_lib });
|
|
|
|
try_remove("test_runner.o");
|
2017-04-30 17:37:22 +00:00
|
|
|
};
|
|
|
|
|
2017-04-30 18:16:24 +00:00
|
|
|
ostd::thread_pool tp;
|
|
|
|
tp.start();
|
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
std::queue<std::future<fs::path>> future_obj, future_dynobj;
|
2017-05-01 22:56:45 +00:00
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
/* build object files in static and shared (PIC) variants */
|
|
|
|
auto build_all = [&](
|
2017-05-11 17:21:02 +00:00
|
|
|
pathvec const &list, fs::path const &spath,
|
|
|
|
fs::path const &sext, auto &buildf
|
2017-05-01 15:28:54 +00:00
|
|
|
) {
|
2017-05-05 00:00:02 +00:00
|
|
|
auto build_obj = [&](fs::path const &fpath, bool shared) {
|
|
|
|
auto srcf = path_with_ext(fpath, sext);
|
2017-05-01 15:28:54 +00:00
|
|
|
auto srco = path_with_ext(srcf, ".o");
|
2017-05-05 00:00:02 +00:00
|
|
|
auto &fq = (shared ? future_dynobj : future_obj);
|
|
|
|
fq.push(tp.push([&buildf, srcf, srco, shared]() {
|
2017-05-10 21:40:03 +00:00
|
|
|
return buildf(srcf, srco, true, shared);
|
2017-05-01 22:56:45 +00:00
|
|
|
}));
|
2017-05-05 00:00:02 +00:00
|
|
|
};
|
2017-05-11 17:21:02 +00:00
|
|
|
for (auto &sf: list) {
|
2017-05-05 00:00:02 +00:00
|
|
|
auto sp = spath / sf;
|
|
|
|
if (build_static) {
|
|
|
|
build_obj(sp, false);
|
|
|
|
}
|
|
|
|
if (build_shared) {
|
|
|
|
build_obj(sp, true);
|
|
|
|
}
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
2017-05-01 15:28:54 +00:00
|
|
|
};
|
|
|
|
|
2017-05-03 19:09:25 +00:00
|
|
|
echo_q("Building the library...");
|
2017-05-05 00:00:02 +00:00
|
|
|
build_all(ASM_SOURCES, ASM_SOURCE_DIR, ".S", call_as);
|
|
|
|
build_all(CXX_SOURCES, CXX_SOURCE_DIR, ".cc", call_cxx);
|
2017-04-30 18:16:24 +00:00
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
if (build_static) {
|
2017-05-05 20:24:08 +00:00
|
|
|
pathvec objs;
|
2017-05-05 00:00:02 +00:00
|
|
|
while (!future_obj.empty()) {
|
|
|
|
objs.push_back(future_obj.front().get());
|
|
|
|
future_obj.pop();
|
|
|
|
}
|
|
|
|
call_ldlib(OSTD_STATIC_LIB, objs, false);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
if (build_shared) {
|
2017-05-05 20:24:08 +00:00
|
|
|
pathvec objs;
|
2017-05-05 00:00:02 +00:00
|
|
|
while (!future_dynobj.empty()) {
|
|
|
|
objs.push_back(future_dynobj.front().get());
|
|
|
|
future_dynobj.pop();
|
|
|
|
}
|
|
|
|
call_ldlib(OSTD_SHARED_LIB, objs, true);
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
std::queue<std::future<void>> future_bin;
|
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
if (build_examples) {
|
2017-05-03 19:09:25 +00:00
|
|
|
echo_q("Building examples...");
|
2017-05-11 17:21:02 +00:00
|
|
|
for (auto &ex: EXAMPLES) {
|
2017-05-05 00:00:02 +00:00
|
|
|
future_bin.push(tp.push([&build_example, ex]() {
|
2017-04-30 18:16:24 +00:00
|
|
|
build_example(ex);
|
2017-05-01 22:56:45 +00:00
|
|
|
}));
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (build_testsuite) {
|
2017-05-03 19:09:25 +00:00
|
|
|
echo_q("Building tests...");
|
2017-04-30 17:37:22 +00:00
|
|
|
build_test_runner();
|
|
|
|
if (!fs::is_directory(TEST_DIR)) {
|
|
|
|
if (!fs::create_directory(TEST_DIR)) {
|
2017-05-03 19:09:25 +00:00
|
|
|
echo_q("Failed creating test directory");
|
2017-04-30 17:37:22 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2017-05-11 17:21:02 +00:00
|
|
|
for (auto &test: TEST_CASES) {
|
2017-05-05 00:00:02 +00:00
|
|
|
future_bin.push(tp.push([&build_test, test]() {
|
2017-04-30 17:37:22 +00:00
|
|
|
build_test(test);
|
2017-05-01 22:56:45 +00:00
|
|
|
}));
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
2017-04-30 18:16:24 +00:00
|
|
|
}
|
|
|
|
|
2017-05-05 00:00:02 +00:00
|
|
|
while (!future_bin.empty()) {
|
2017-05-01 22:56:45 +00:00
|
|
|
/* wait and propagate possible exception */
|
2017-05-05 00:00:02 +00:00
|
|
|
future_bin.front().get();
|
|
|
|
future_bin.pop();
|
2017-05-01 22:56:45 +00:00
|
|
|
}
|
2017-04-30 18:16:24 +00:00
|
|
|
|
|
|
|
if (build_testsuite) {
|
2017-05-08 01:44:58 +00:00
|
|
|
exec_v({ "./test_runner", TEST_DIR.string() });
|
2017-04-30 17:37:22 +00:00
|
|
|
}
|
|
|
|
|
2017-05-03 19:09:25 +00:00
|
|
|
io_msgs.close();
|
|
|
|
io_thread.join();
|
|
|
|
|
2017-04-30 17:37:22 +00:00
|
|
|
return 0;
|
|
|
|
}
|