// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #pragma once #include #include #include #include #include #include #include namespace ctor { enum class target_type { automatic, // Default - deduce from target name and sources extensions executable, static_library, dynamic_library, object, unit_test, unit_test_library, function, }; enum class language { automatic, // Default - deduce language from source extensions c, cpp, assembler, }; enum class output_system { host, // Output for the target system build, // Internal tool during cross-compilation }; struct source { source(const char* file) : file(file) {} source(const std::string& file) : file(file) {} source(const char* file, ctor::language lang) : file(file), language(lang) {} source(const std::string& file, ctor::language lang) : file(file), language(lang) {} source(const char* file, const char* output) : file(file), output(output) {} source(const std::string& file, const std::string& output) : file(file), output(output) {} source(const char* file, ctor::language lang, const char* output) : file(file), language(lang), output(output) {} source(const std::string& file, ctor::language lang, const std::string& output) : file(file), language(lang), output(output) {} std::string file; ctor::language language{ctor::language::automatic}; std::string output{}; }; enum class toolchain { any, none, gcc, clang, }; enum class cxx_opt { // gcc/clang output, // -o debug, // -g warn_all, // -Wall warnings_as_errors, // -Werror generate_dep_tree, // -MMD no_link, // -c include_path, // -I cpp_std, // -std= optimization, // -O position_independent_code, // -fPIC position_independent_executable, // -fPIE custom, // entire option taken verbatim from }; enum class c_opt { // gcc/clang output, // -o debug, // -g warn_all, // -Wall warnings_as_errors, // -Werror generate_dep_tree, // -MMD no_link, // -c include_path, // -I c_std, // -std= optimization, // -O position_independent_code, // -fPIC position_independent_executable, // -fPIE custom, // entire option taken verbatim from }; enum class ld_opt { // gcc/clang output, // -o strip, // -s warn_all, // -Wall warnings_as_errors, // -Werror library_path, // -L link, // -l cpp_std, // -std= build_shared, // -shared threads, // -pthread position_independent_code, // -fPIC position_independent_executable, // -fPIE custom, // entire option taken verbatim from }; enum class ar_opt { // gcc/clang replace, // -r add_index, // -s create, // -c output, // custom, // entire option taken verbatim from }; enum class asm_opt { // gcc/clang custom, // entire option taken verbatim from }; template class flag { public: flag(const std::string& str); flag(const char* str); flag(T opt) : opt(opt) {} flag(T opt, const std::string& arg) : opt(opt), arg(arg) {} flag(T opt, const char* arg) : opt(opt), arg(arg) {} flag(ctor::toolchain toolchain, T opt) : toolchain(toolchain), opt(opt) {} flag(ctor::toolchain toolchain, T opt, const char* arg) : toolchain(toolchain), opt(opt), arg(arg) {} flag(ctor::toolchain toolchain, T opt, const std::string& arg) : toolchain(toolchain), opt(opt), arg(arg) {} ctor::toolchain toolchain{ctor::toolchain::any}; T opt; std::string arg; }; using c_flag = ctor::flag; using cxx_flag = ctor::flag; using ld_flag = ctor::flag; using ar_flag = ctor::flag; using asm_flag = ctor::flag; using c_flags = std::vector; using cxx_flags = std::vector; using ld_flags= std::vector; using ar_flags = std::vector; using asm_flags = std::vector; struct flags { ctor::c_flags cflags; // flags for c compiler ctor::cxx_flags cxxflags; // flags for c++ compiler ctor::ld_flags ldflags; // flags for linker ctor::ar_flags arflags; // flags for archiver ctor::asm_flags asmflags; // flags for asm translator }; struct settings { std::string builddir{"build"}; std::size_t parallel_processes{1}; int verbose{0}; // -1: completely silent, 0: normal, 1: verbose, ... }; struct build_configuration; using GeneratorCb = std::function; struct build_configuration { std::string name; // Name - used for referring in other configurations. ctor::target_type type{ctor::target_type::automatic}; ctor::output_system system{ctor::output_system::host}; std::string target; // Output target file for this configuration std::vector sources; // source list std::vector depends; // internal target dependencies ctor::flags flags; std::vector externals; // externals used by this configuration GeneratorCb function; }; using build_configurations = std::vector; int reg(ctor::build_configurations (*cb)(const ctor::settings&), const std::source_location location = std::source_location::current()); // This type will use flags verbatim struct external_manual { ctor::flags flags; }; struct external_configuration { std::string name; // Name for configuration ctor::output_system system{ctor::output_system::host}; std::variant external; }; using external_configurations = std::vector; int reg(ctor::external_configurations (*cb)(const ctor::settings&), const std::source_location location = std::source_location::current()); // Convenience macro - ugly but keeps things simple(r) #define CONCAT(a, b) CONCAT_INNER(a, b) #define CONCAT_INNER(a, b) a ## b #define UNIQUE_NAME(base) CONCAT(base, __LINE__) #define REG(cb) namespace { int UNIQUE_NAME(unique) = reg(cb); } // Predefined configuration keys namespace cfg { constexpr auto builddir = "builddir"; constexpr auto host_cc = "host-cc"; constexpr auto host_cxx = "host-cpp"; constexpr auto host_ar = "host-ar"; constexpr auto host_ld = "host-ld"; constexpr auto build_cc = "build-cc"; constexpr auto build_cxx = "build-cpp"; constexpr auto build_ar = "build-ar"; constexpr auto build_ld = "build-ld"; constexpr auto ctor_includedir = "ctor-includedir"; constexpr auto ctor_libdir = "ctor-libdir"; } struct configuration { bool has(const std::string& key) const; const std::string& get(const std::string& key, const std::string& default_value = {}) const; ctor::toolchain host_toolchain{ctor::toolchain::none}; ctor::toolchain build_toolchain{ctor::toolchain::none}; std::vector args; // vector of arguments used when last calling configure std::map env; // env used when last calling configure std::map tools; // tools std::map externals; }; const ctor::configuration& get_configuration(); } // ctor::