diff options
Diffstat (limited to 'src/ctor.h')
-rw-r--r-- | src/ctor.h | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/src/ctor.h b/src/ctor.h new file mode 100644 index 0000000..3b64cb5 --- /dev/null +++ b/src/ctor.h @@ -0,0 +1,282 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#pragma once + +#include <source_location> +#include <string> +#include <vector> +#include <map> +#include <variant> +#include <cstddef> +#include <functional> + +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, + + unknown, +}; + +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 +}; + +enum class arch +{ + unix, //!< Target platform architecture is unix-based (ie. linux, bsd, etc) + apple, //!< Target platform architecture is macos + windows, //!< Target platform architecture is windows + + unknown, //!< Target platform architecture has not yet detected or was not possible to detect +}; + +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<arg> + cpp_std, // -std=<arg> + optimization, // -O<arg> + position_independent_code, // -fPIC + position_independent_executable, // -fPIE + custom, // entire option taken verbatim from <arg> +}; + +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<arg> + c_std, // -std=<arg> + optimization, // -O<arg> + position_independent_code, // -fPIC + position_independent_executable, // -fPIE + custom, // entire option taken verbatim from <arg> +}; + +enum class ld_opt +{ + // gcc/clang + output, // -o + strip, // -s + warn_all, // -Wall + warnings_as_errors, // -Werror + library_path, // -L<arg> + link, // -l<arg> + cpp_std, // -std=<arg> + build_shared, // -shared + threads, // -pthread + position_independent_code, // -fPIC + position_independent_executable, // -fPIE + custom, // entire option taken verbatim from <arg> +}; + +enum class ar_opt +{ + // gcc/clang + replace, // -r + add_index, // -s + create, // -c + output, // <arg> + + custom, // entire option taken verbatim from <arg> +}; + +enum class asm_opt +{ + // gcc/clang + custom, // entire option taken verbatim from <arg> +}; + +template<typename T> +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<ctor::c_opt>; +using cxx_flag = ctor::flag<ctor::cxx_opt>; +using ld_flag = ctor::flag<ctor::ld_opt>; +using ar_flag = ctor::flag<ctor::ar_opt>; +using asm_flag = ctor::flag<ctor::asm_opt>; + +using c_flags = std::vector<ctor::c_flag>; +using cxx_flags = std::vector<ctor::cxx_flag>; +using ld_flags= std::vector<ctor::ld_flag>; +using ar_flags = std::vector<ctor::ar_flag>; +using asm_flags = std::vector<ctor::asm_flag>; + +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<int(const std::string& input, + const std::string& output, + const build_configuration& config, + const ctor::settings& settings)>; + +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::build}; + std::string target; // Output target file for this configuration + std::vector<ctor::source> sources; // source list + std::vector<std::string> depends; // internal target dependencies + ctor::flags flags; + std::vector<std::string> externals; // externals used by this configuration + GeneratorCb function; +}; + +using build_configurations = std::vector<build_configuration>; + +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::build}; + std::variant<ctor::external_manual> external; +}; + +using external_configurations = std::vector<ctor::external_configuration>; + +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 CTOR_CONCAT(a, b) CTOR_CONCAT_INNER(a, b) +#define CTOR_CONCAT_INNER(a, b) a ## b +#define CTOR_UNIQUE_NAME(base) CTOR_CONCAT(base, __LINE__) +#define REG(cb) namespace { int CTOR_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::arch host_arch{ctor::arch::unknown}; + + ctor::toolchain build_toolchain{ctor::toolchain::none}; + ctor::arch build_arch{ctor::arch::unknown}; + + std::vector<std::string> args; // vector of arguments used when last calling configure + std::map<std::string, std::string> env; // env used when last calling configure + + std::map<std::string, std::string> tools; // tools + std::map<std::string, ctor::flags> externals; +}; + +const ctor::configuration& get_configuration(); + +} // ctor:: |