// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #pragma once #include #include #include #include #include #include #include enum class TargetType { Auto, // Default - deduce from target name and sources extensions Executable, StaticLibrary, DynamicLibrary, Object, UnitTest, UnitTestLib, Function, }; enum class Language { Auto, // Default - deduce language from source extensions C, Cpp, Asm, }; enum class OutputSystem { 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, Language lang) : file(file), language(lang) {} Source(const std::string& file, 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, Language lang, const char* output) : file(file), language(lang), output(output) {} Source(const std::string& file, Language lang, const std::string& output) : file(file), language(lang), output(output) {} std::string file; Language language{Language::Auto}; std::string output{}; }; struct Flags { std::vector cxxflags; // flags for c++ compiler std::vector cflags; // flags for c compiler std::vector ldflags; // flags for linker std::vector 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, ... std::string name; }; struct BuildConfiguration; using GeneratorCb = std::function; struct BuildConfiguration { std::string name; // Name - used for referring in other configurations. TargetType type{TargetType::Auto}; OutputSystem system{OutputSystem::Host}; std::string target; // Output target file for this configuration std::vector sources; // source list std::vector depends; // internal target dependencies Flags flags; std::vector externals; // externals used by this configuration GeneratorCb function; }; using BuildConfigurations = std::vector; int reg(BuildConfigurations (*cb)(const Settings&), const std::source_location location = std::source_location::current()); // This type will use flags verbatim struct ExternalManual { Flags flags; }; struct ExternalConfiguration { std::string name; // Name for configuration OutputSystem system{OutputSystem::Host}; std::variant external; }; using ExternalConfigurations = std::vector; int reg(ExternalConfigurations (*cb)(const 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 { 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 Configuration& configuration(); bool hasConfiguration(const std::string& key); const std::string& getConfiguration(const std::string& key, const std::string& defaultValue = {});