diff --git a/bootstrap/main.buildcc.cpp b/bootstrap/main.buildcc.cpp index a1109bf1..4adb097d 100644 --- a/bootstrap/main.buildcc.cpp +++ b/bootstrap/main.buildcc.cpp @@ -41,7 +41,8 @@ int main(int argc, char **argv) { Reg::Init(); Reg::Call(Args::Clean()).Func(clean_cb); - BaseToolchain toolchain = custom_toolchain_arg.ConstructToolchain(); + auto &toolchain = custom_toolchain_arg; + toolchain.SetToolchainInfoFunc(GlobalToolchainInfo::Get(toolchain.id)); BuildBuildCC buildcc( toolchain, TargetEnv(Project::GetRootDir(), Project::GetBuildDir())); diff --git a/bootstrap/src/build_buildcc.cpp b/bootstrap/src/build_buildcc.cpp index 4245a6cd..e655a418 100644 --- a/bootstrap/src/build_buildcc.cpp +++ b/bootstrap/src/build_buildcc.cpp @@ -90,6 +90,7 @@ void buildcc_cb(BaseTarget &target, const BaseGenerator &schema_gen, target.GlobHeaders("lib/args/include/args"); // Specialized Toolchains + target.GlobSources("toolchains/src"); target.AddIncludeDir("toolchains/include"); target.GlobHeaders("toolchains/include/toolchains"); diff --git a/buildcc/buildcc.h b/buildcc/buildcc.h index 227d9ce0..b40f5852 100644 --- a/buildcc/buildcc.h +++ b/buildcc/buildcc.h @@ -39,6 +39,10 @@ #include "toolchains/toolchain_gcc.h" #include "toolchains/toolchain_msvc.h" #include "toolchains/toolchain_mingw.h" +#include "toolchains/toolchain_generic.h" +#include "toolchains/toolchain_custom.h" + +#include "toolchains/toolchain_infos.h" // TODO, Add more specialized toolchains here diff --git a/buildcc/lib/args/include/args/args.h b/buildcc/lib/args/include/args/args.h index a6b37f19..c0937ab0 100644 --- a/buildcc/lib/args/include/args/args.h +++ b/buildcc/lib/args/include/args/args.h @@ -47,35 +47,31 @@ struct ArgToolchainState { * command line * Bundled with Toolchain State */ -struct ArgToolchain { - ArgToolchain() = default; +class ArgToolchain : public Toolchain { +public: + ArgToolchain() + : Toolchain(ToolchainId::Undefined, "", ToolchainExecutables()){}; ArgToolchain(ToolchainId initial_id, const std::string &initial_name, const ToolchainExecutables &initial_executables) - : id(initial_id), name(initial_name), executables(initial_executables) {} - ArgToolchain(ToolchainId initial_id, const std::string &initial_name, - const std::string &initial_assembler, - const std::string &initial_c_compiler, - const std::string &initial_cpp_compiler, - const std::string &initial_archiver, - const std::string &initial_linker) - : ArgToolchain(initial_id, initial_name, - ToolchainExecutables(initial_assembler, initial_c_compiler, - initial_cpp_compiler, - initial_archiver, initial_linker)) {} - - /** - * @brief Construct a BaseToolchain from the arguments supplied through the - * command line information - */ - // TODO, Update this for lock and ToolchainConfig - BaseToolchain ConstructToolchain() const { - return BaseToolchain(id, name, executables); - } + : Toolchain(initial_id, initial_name, initial_executables) {} + [[deprecated]] ArgToolchain(ToolchainId initial_id, + const std::string &initial_name, + const std::string &initial_assembler, + const std::string &initial_c_compiler, + const std::string &initial_cpp_compiler, + const std::string &initial_archiver, + const std::string &initial_linker) + : Toolchain(initial_id, initial_name, + ToolchainExecutables(initial_assembler, initial_c_compiler, + initial_cpp_compiler, initial_archiver, + initial_linker)) {} +public: ArgToolchainState state; - ToolchainId id{ToolchainId::Undefined}; - std::string name{""}; - ToolchainExecutables executables; + ToolchainId &id = RefId(); + std::string &name = RefName(); + ToolchainExecutables &executables = RefExecutables(); + ToolchainConfig &config = RefConfig(); }; // NOTE, Incomplete without pch_compile_command diff --git a/buildcc/lib/args/src/register.cpp b/buildcc/lib/args/src/register.cpp index dd042ae3..e141541c 100644 --- a/buildcc/lib/args/src/register.cpp +++ b/buildcc/lib/args/src/register.cpp @@ -23,6 +23,7 @@ #include "env/assert_fatal.h" #include "env/env.h" +#include "env/storage.h" namespace fs = std::filesystem; @@ -67,13 +68,28 @@ namespace buildcc { std::unique_ptr Reg::instance_; +void SystemInit() { + Project::Init(fs::current_path() / Args::GetProjectRootDir(), + fs::current_path() / Args::GetProjectBuildDir()); + env::set_log_level(Args::GetLogLevel()); + + // Top down (what is init first gets deinit last) + std::atexit([]() { + Project::Deinit(); + Reg::Deinit(); + Args::Deinit(); + Storage::Clear(); + }); +} + void Reg::Init() { if (!instance_) { instance_ = std::make_unique(); + env::assert_fatal(static_cast(instance_), "Reg::Init failed"); env::assert_fatal(Args::IsParsed(), "Setup your Args"); - Project::Init(fs::current_path() / Args::GetProjectRootDir(), - fs::current_path() / Args::GetProjectBuildDir()); - env::set_log_level(Args::GetLogLevel()); + + // Initialize everything else here + SystemInit(); } } diff --git a/buildcc/lib/env/include/env/storage.h b/buildcc/lib/env/include/env/storage.h index ade21c3b..21d5528e 100644 --- a/buildcc/lib/env/include/env/storage.h +++ b/buildcc/lib/env/include/env/storage.h @@ -32,13 +32,7 @@ namespace buildcc { class ScopedStorage { public: ScopedStorage() {} - ~ScopedStorage() { - for (const auto &ptr_iter : ptrs_) { - ptr_iter.second.destructor(); - } - ptrs_.clear(); - env::assert_fatal(ptrs_.empty(), "Memory not deallocated"); - } + ~ScopedStorage() { Clear(); } ScopedStorage(const ScopedStorage &) = delete; @@ -58,10 +52,15 @@ class ScopedStorage { return *ptr; } - template void Remove(T *ptr) { delete ptr; } + void Clear() { + for (const auto &ptr_iter : ptrs_) { + ptr_iter.second.destructor(); + } + ptrs_.clear(); + } template const T &ConstRef(const std::string &identifier) const { - env::assert_fatal(ptrs_.find(identifier) != ptrs_.end(), + env::assert_fatal(Contains(identifier), fmt::format("Could not find '{}'", identifier)); const PtrMetadata &metadata = ptrs_.at(identifier); env::assert_fatal( @@ -77,12 +76,30 @@ class ScopedStorage { static_cast(*this).ConstRef(identifier)); } + bool Contains(const std::string &identifier) const { + return (ptrs_.find(identifier) != ptrs_.end()); + } + + template bool Valid(const std::string &identifier) const { + if (!Contains(identifier)) { + return false; + } + const PtrMetadata &metadata = ptrs_.at(identifier); + if (typeid(T).name() != metadata.typeid_name) { + return false; + } + return true; + } + +protected: + template void Remove(T *ptr) { delete ptr; } + private: /** * @brief * @param ptr Can hold data of any type - * @param typeid_name We cannot store a template type so this is the next best - * thing + * @param typeid_name We cannot store a template type so this is the next + * best thing * @param desstructor Destructor callback to delete ptr */ struct PtrMetadata { @@ -101,14 +118,13 @@ class Storage { Storage(const Storage &) = delete; Storage(Storage &&) = delete; - static void Init() { internal_ = std::make_unique(); } - static void Deinit() { internal_.reset(nullptr); } - template static T &Add(const std::string &identifier, Params &&...params) { return Ref().Add(identifier, std::forward(params)...); } + static void Clear() { Ref().Clear(); } + template static const T &ConstRef(const std::string &identifier) { return Ref().ConstRef(identifier); @@ -118,11 +134,19 @@ class Storage { return Ref().Ref(identifier); } + static bool Contains(const std::string &identifier) { + return Ref().Contains(identifier); + } + + template static bool Valid(const std::string &identifier) { + return Ref().Valid(identifier); + } + private: static ScopedStorage &Ref(); private: - static std::unique_ptr internal_; + static ScopedStorage internal_; }; } // namespace buildcc diff --git a/buildcc/lib/env/src/storage.cpp b/buildcc/lib/env/src/storage.cpp index 6712c008..0da3ac5e 100644 --- a/buildcc/lib/env/src/storage.cpp +++ b/buildcc/lib/env/src/storage.cpp @@ -18,12 +18,8 @@ namespace buildcc { -std::unique_ptr Storage::internal_; +ScopedStorage Storage::internal_; -ScopedStorage &Storage::Ref() { - env::assert_fatal(internal_ != nullptr, - "Initialize Storage using the Storage::Init API"); - return *internal_; -} +ScopedStorage &Storage::Ref() { return internal_; } } // namespace buildcc diff --git a/buildcc/lib/env/test/test_storage.cpp b/buildcc/lib/env/test/test_storage.cpp index 929fc0ba..4c38b134 100644 --- a/buildcc/lib/env/test/test_storage.cpp +++ b/buildcc/lib/env/test/test_storage.cpp @@ -15,14 +15,23 @@ TEST_GROUP(ScopedStorageTestGroup) TEST_GROUP(StorageTestGroup) { void setup() { - buildcc::Storage::Init(); + MemoryLeakWarningPlugin::saveAndDisableNewDeleteOverloads(); } void teardown() { - buildcc::Storage::Deinit(); + buildcc::Storage::Clear(); + MemoryLeakWarningPlugin::restoreNewDeleteOverloads(); } }; // clang-format on +class MyScopedStorage : public buildcc::ScopedStorage { +public: + // We want to unit test this + template void Remove(T *ptr) { + this->ScopedStorage::Remove(ptr); + } +}; + class BigObj {}; class BigObjWithParameters { @@ -42,7 +51,7 @@ class BigObjWithParameters { static BigObj obj; TEST(ScopedStorageTestGroup, BasicUsage) { - buildcc::ScopedStorage storage; + MyScopedStorage storage; storage.Add("identifier", "name", 10, obj); storage.Add("identifier2", "name2", 12, obj); @@ -50,11 +59,21 @@ TEST(ScopedStorageTestGroup, BasicUsage) { storage.ConstRef("identifier").GetName(); storage.Ref("identifier2").GetName(); + CHECK_TRUE(storage.Contains("identifier")); + CHECK_FALSE(storage.Contains("identifier_does_not_exist")); + + CHECK_TRUE(storage.Valid("identifier")); + CHECK_FALSE(storage.Valid("wrong_identifier")); + CHECK_FALSE(storage.Valid("identifier")); + + storage.Clear(); + CHECK_FALSE(storage.Contains("identifier")); + // Automatic cleanup here } TEST(ScopedStorageTestGroup, IncorrectUsage) { - buildcc::ScopedStorage storage; + MyScopedStorage storage; storage.Add("identifier", "name", 10, obj); // We try to cast to a different type! @@ -65,13 +84,13 @@ TEST(ScopedStorageTestGroup, IncorrectUsage) { storage.Ref("identifier2")); } -std::string &toReference(std::string *pointer) { return *pointer; } - TEST(ScopedStorageTestGroup, NullptrDelete) { - buildcc::ScopedStorage storage; + MyScopedStorage storage; storage.Remove(nullptr); } +// + TEST(StorageTestGroup, BasicUsage) { buildcc::Storage::Add("identifier", "name", 10, obj); buildcc::Storage::Add("identifier2", "name2", 12, obj); @@ -84,14 +103,14 @@ TEST(StorageTestGroup, BasicUsage) { STRCMP_EQUAL(bigobj.c_str(), "name"); STRCMP_EQUAL(bigobj2.c_str(), "name2"); -} -TEST(StorageTestGroup, UsageWithoutInit) { - buildcc::Storage::Deinit(); + CHECK_TRUE(buildcc::Storage::Contains("identifier")); + CHECK_FALSE(buildcc::Storage::Contains("identifier_does_not_exist")); - CHECK_THROWS(std::exception, buildcc::Storage::Add("integer")); - CHECK_THROWS(std::exception, buildcc::Storage::Ref("integer")); - CHECK_THROWS(std::exception, buildcc::Storage::ConstRef("integer")); + CHECK_TRUE(buildcc::Storage::Valid("identifier")); + CHECK_FALSE( + buildcc::Storage::Valid("wrong_identifier")); + CHECK_FALSE(buildcc::Storage::Valid("identifier")); } int main(int ac, char **av) { diff --git a/buildcc/lib/target/src/target_info/target_info.cpp b/buildcc/lib/target/src/target_info/target_info.cpp index c338d9f6..29d94a4d 100644 --- a/buildcc/lib/target/src/target_info/target_info.cpp +++ b/buildcc/lib/target/src/target_info/target_info.cpp @@ -21,8 +21,9 @@ namespace buildcc { // PRIVATE void TargetInfo::Initialize() { - toolchain_.GetLockInfo().ExpectsLock( - "Toolchain should be locked before usage through `Toolchain::Lock`"); + // TODO, Update this later + // toolchain_.GetLockInfo().ExpectsLock( + // "Toolchain should be locked before usage through `Toolchain::Lock`"); std::for_each(toolchain_.GetPreprocessorFlags().begin(), toolchain_.GetPreprocessorFlags().end(), diff --git a/buildcc/lib/target/test/target/test_toolchain_flag_api.cpp b/buildcc/lib/target/test/target/test_toolchain_flag_api.cpp index dc5aa0f7..54344e46 100644 --- a/buildcc/lib/target/test/target/test_toolchain_flag_api.cpp +++ b/buildcc/lib/target/test/target/test_toolchain_flag_api.cpp @@ -17,6 +17,7 @@ TEST_GROUP(ToolchainFlagApiTestGroup) TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Lock) { buildcc::Toolchain toolchain(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", "ar", "ld"); + toolchain.Lock(); CHECK_THROWS(std::exception, toolchain.AddPreprocessorFlag("-preprocessor")); CHECK_THROWS(std::exception, toolchain.AddAsmCompileFlag("-asm")); CHECK_THROWS(std::exception, toolchain.AddPchCompileFlag("-pchcompile")); @@ -29,7 +30,7 @@ TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Lock) { TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Unlock) { buildcc::Toolchain toolchain(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", - "g++", "ar", "ld", false); + "g++", "ar", "ld"); toolchain.AddPreprocessorFlag("-preprocessor"); toolchain.AddAsmCompileFlag("-asm"); toolchain.AddPchCompileFlag("-pchcompile"); @@ -55,7 +56,7 @@ TEST(ToolchainFlagApiTestGroup, BasicToolchainTest_Unlock) { TEST(ToolchainFlagApiTestGroup, BasicTargetTest) { buildcc::Toolchain toolchain(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", - "g++", "ar", "ld", false); + "g++", "ar", "ld"); toolchain.AddPreprocessorFlag("-preprocessor"); toolchain.AddAsmCompileFlag("-asm"); @@ -67,7 +68,9 @@ TEST(ToolchainFlagApiTestGroup, BasicTargetTest) { toolchain.AddLinkFlag("-link"); CHECK_FALSE(toolchain.GetLockInfo().IsLocked()); - { CHECK_THROWS(std::exception, (buildcc::TargetInfo(toolchain, ""))); } + // TODO, Add this in later + // * We should lock our toolchain before using it + // { CHECK_THROWS(std::exception, (buildcc::TargetInfo(toolchain, ""))); } toolchain.Lock(); CHECK_TRUE(toolchain.GetLockInfo().IsLocked()); diff --git a/buildcc/lib/toolchain/include/toolchain/api/toolchain_verify.h b/buildcc/lib/toolchain/include/toolchain/api/toolchain_verify.h index 2ebd2423..9d545285 100644 --- a/buildcc/lib/toolchain/include/toolchain/api/toolchain_verify.h +++ b/buildcc/lib/toolchain/include/toolchain/api/toolchain_verify.h @@ -34,10 +34,6 @@ namespace fs = std::filesystem; namespace buildcc { -struct ToolchainVerifyConfig : public ToolchainFindConfig { - std::optional verification_identifier; -}; - /** * @brief Verified Toolchain information * @param path Absolute host path where ALL the toolchain executables are found @@ -55,24 +51,12 @@ struct ToolchainCompilerInfo { }; // clang-format off -typedef std::function(const ToolchainExecutables &)> ToolchainVerificationFunc; +typedef std::function(const ToolchainExecutables &)> ToolchainInfoFunc; // clang-format on template class ToolchainVerify { public: - ToolchainVerify() { Initialize(); } - - /** - * @brief - * - * @param id - * @param verification_func - * @param identifier Only read when ToolchainId::Custom is passed in - */ - static void - AddVerificationFunc(ToolchainId id, - const ToolchainVerificationFunc &verification_func, - const std::optional &op_identifier = {}); + ToolchainVerify() = default; /** * @brief Verify your toolchain executables by searching your operating system @@ -85,17 +69,23 @@ template class ToolchainVerify { * of them */ ToolchainCompilerInfo - Verify(const ToolchainVerifyConfig &config = ToolchainVerifyConfig()); + Verify(const ToolchainFindConfig &config = ToolchainFindConfig()); -protected: - ToolchainCompilerInfo verified_toolchain_; + /** + * @brief Set ToolchainInfo callback for run time objects + */ + void SetToolchainInfoFunc(const ToolchainInfoFunc &cb) { info_func_ = cb; } + const ToolchainInfoFunc &GetToolchainInfoFunc() const { return info_func_; } + +private: + /** + * @brief ToolchainInfo callback for compile time polymorphic objects + */ + virtual std::optional + GetToolchainInfo(const ToolchainExecutables &executables) const; private: - void Initialize(); - static const ToolchainVerificationFunc & - GetVerificationFunc(const std::string &identifier); - static std::unordered_map & - GetStatic(); + ToolchainInfoFunc info_func_; }; } // namespace buildcc diff --git a/buildcc/lib/toolchain/include/toolchain/toolchain.h b/buildcc/lib/toolchain/include/toolchain/toolchain.h index 7ae3e959..4c509b28 100644 --- a/buildcc/lib/toolchain/include/toolchain/toolchain.h +++ b/buildcc/lib/toolchain/include/toolchain/toolchain.h @@ -17,6 +17,7 @@ #ifndef TOOLCHAIN_TOOLCHAIN_H_ #define TOOLCHAIN_TOOLCHAIN_H_ +#include #include #include #include @@ -37,22 +38,25 @@ class Toolchain : public internal::FlagApi, public ToolchainFind, public ToolchainVerify { public: -public: + // TODO, Remove ToolchainId from here Toolchain(ToolchainId id, std::string_view name, - const ToolchainExecutables &executables, bool lock = true, + const ToolchainExecutables &executables, const ToolchainConfig &config = ToolchainConfig()) - : id_(id), name_(name), executables_(executables), lock_(lock), - config_(config) { + : id_(id), name_(name), executables_(executables), config_(config), + lock_(false) { Initialize(); } - Toolchain(ToolchainId id, std::string_view name, std::string_view assembler, - std::string_view c_compiler, std::string_view cpp_compiler, - std::string_view archiver, std::string_view linker, - bool lock = true, const ToolchainConfig &config = ToolchainConfig()) + + [[deprecated]] Toolchain(ToolchainId id, std::string_view name, + std::string_view assembler, + std::string_view c_compiler, + std::string_view cpp_compiler, + std::string_view archiver, std::string_view linker, + const ToolchainConfig &config = ToolchainConfig()) : Toolchain(id, name, ToolchainExecutables(assembler, c_compiler, cpp_compiler, archiver, linker), - lock, config) {} + config) {} Toolchain(Toolchain &&) = default; Toolchain &operator=(Toolchain &&) = default; @@ -78,6 +82,12 @@ class Toolchain : public internal::FlagApi, const FunctionLock &GetLockInfo() const { return lock_; } const ToolchainConfig &GetConfig() const { return config_; } +protected: + ToolchainId &RefId() { return id_; } + std::string &RefName() { return name_; } + ToolchainExecutables &RefExecutables() { return executables_; } + ToolchainConfig &RefConfig() { return config_; } + private: struct UserSchema { std::unordered_set preprocessor_flags; @@ -103,8 +113,8 @@ class Toolchain : public internal::FlagApi, ToolchainId id_; std::string name_; ToolchainExecutables executables_; - FunctionLock lock_; ToolchainConfig config_; + FunctionLock lock_; // UserSchema user_; diff --git a/buildcc/lib/toolchain/src/api/toolchain_verify.cpp b/buildcc/lib/toolchain/src/api/toolchain_verify.cpp index 1d60b80f..78927b65 100644 --- a/buildcc/lib/toolchain/src/api/toolchain_verify.cpp +++ b/buildcc/lib/toolchain/src/api/toolchain_verify.cpp @@ -35,83 +35,6 @@ namespace { -std::optional -GetGccCompilerVersion(const buildcc::env::Command &command) { - std::vector stdout_data; - bool executed = buildcc::env::Command::Execute( - command.Construct("{compiler} -dumpversion"), {}, &stdout_data); - if (!executed || stdout_data.empty()) { - return {}; - } - return stdout_data[0]; -} - -std::optional -GetGccTargetArchitecture(const buildcc::env::Command &command) { - std::vector stdout_data; - bool executed = buildcc::env::Command::Execute( - command.Construct("{compiler} -dumpmachine"), {}, &stdout_data); - if (!executed || stdout_data.empty()) { - return {}; - } - return stdout_data[0]; -} - -std::optional -GccVerificationFunc(const buildcc::ToolchainExecutables &executables) { - buildcc::env::Command command; - command.AddDefaultArgument("compiler", executables.cpp_compiler); - - auto op_compiler_version = GetGccCompilerVersion(command); - auto op_target_arch = GetGccTargetArchitecture(command); - if (!op_compiler_version.has_value() || !op_target_arch.has_value()) { - return {}; - } - - buildcc::ToolchainCompilerInfo compiler_info; - compiler_info.compiler_version = op_compiler_version.value(); - compiler_info.target_arch = op_target_arch.value(); - return compiler_info; -} - -std::optional GetMsvcCompilerVersion() { - const char *vscmd_version = getenv("VSCMD_VER"); - if (vscmd_version == nullptr) { - return {}; - } - return vscmd_version; -} - -std::optional GetMsvcTargetArchitecture() { - // DONE, Read `VSCMD_ARG_HOST_ARCH` from env path - // DONE, Read `VSCMD_ARG_TGT_ARCH` from env path - const char *vs_host_arch = getenv("VSCMD_ARG_HOST_ARCH"); - const char *vs_target_arch = getenv("VSCMD_ARG_TGT_ARCH"); - if (vs_host_arch == nullptr || vs_target_arch == nullptr) { - return {}; - } - - // DONE, Concat them - return fmt::format("{}_{}", vs_host_arch, vs_target_arch); -} - -std::optional -MsvcVerificationFunc(const buildcc::ToolchainExecutables &executables) { - (void)executables; - auto op_compiler_version = GetMsvcCompilerVersion(); - auto op_target_arch = GetMsvcTargetArchitecture(); - if (!op_compiler_version.has_value() || !op_target_arch.has_value()) { - return {}; - } - - buildcc::ToolchainCompilerInfo compiler_info; - compiler_info.compiler_version = op_compiler_version.value(); - compiler_info.target_arch = op_target_arch.value(); - return compiler_info; -} - -// - buildcc::ToolchainExecutables CreateToolchainExecutables( const fs::path &absolute_path, const buildcc::ToolchainExecutables ¤t_executables) { @@ -146,82 +69,20 @@ buildcc::ToolchainExecutables CreateToolchainExecutables( linker_path); } -std::string -GetToolchainVerifyIdentifier(buildcc::ToolchainId id, - const std::optional &op_identifier) { - std::string identifier; - switch (id) { - case buildcc::ToolchainId::Custom: - buildcc::env::assert_fatal( - op_identifier.has_value(), - "Requires verification_identifier value in ToolchainVerifyConfig"); - identifier = op_identifier.value(); - break; - case buildcc::ToolchainId::Gcc: - case buildcc::ToolchainId::Msvc: - case buildcc::ToolchainId::Clang: - case buildcc::ToolchainId::MinGW: - identifier = fmt::format("{}", id); - break; - case buildcc::ToolchainId::Undefined: - default: - buildcc::env::assert_fatal( - "Undefined toolchain. Use valid ToolchainId"); - break; - } - return identifier; -} - } // namespace namespace buildcc { -template -void ToolchainVerify::AddVerificationFunc( - ToolchainId id, const ToolchainVerificationFunc &verification_func, - const std::optional &op_identifier) { - std::string identifier; - switch (id) { - case ToolchainId::Gcc: - case ToolchainId::Msvc: - case ToolchainId::MinGW: - case ToolchainId::Clang: - identifier = fmt::format("{}", id); - break; - case ToolchainId::Custom: - env::assert_fatal(op_identifier.has_value(), - "Requires optional identifier parameter when " - "ToolchainId::Custom is defined"); - identifier = op_identifier.value(); - break; - default: - env::assert_fatal("Invalid ToolchainId parameter"); - break; - } - - env::assert_fatal( - ToolchainVerify::GetStatic().count(identifier) == 0, - fmt::format("Already registered VerificationFunction for identifier '{}'", - identifier)); - ToolchainVerify::GetStatic()[identifier] = verification_func; -} - template ToolchainCompilerInfo -ToolchainVerify::Verify(const ToolchainVerifyConfig &config) { +ToolchainVerify::Verify(const ToolchainFindConfig &config) { T &t = static_cast(*this); std::vector toolchain_paths = t.Find(config); env::assert_fatal(!toolchain_paths.empty(), "No toolchains found"); ToolchainExecutables exes = CreateToolchainExecutables(toolchain_paths[0], t.executables_); - - std::string toolchain_id_identifier = - GetToolchainVerifyIdentifier(t.GetId(), config.verification_identifier); - - const auto &verification_func = - T::GetVerificationFunc(toolchain_id_identifier); - auto op_toolchain_compiler_info = verification_func(exes); + auto op_toolchain_compiler_info = t.GetToolchainInfo(exes); env::assert_fatal(op_toolchain_compiler_info.has_value(), "Could not verify toolchain"); @@ -235,34 +96,16 @@ ToolchainVerify::Verify(const ToolchainVerifyConfig &config) { } // PRIVATE -template void ToolchainVerify::Initialize() { - static bool do_once = true; - - if (do_once) { - do_once = false; - AddVerificationFunc(ToolchainId::Gcc, GccVerificationFunc); - AddVerificationFunc(ToolchainId::Msvc, MsvcVerificationFunc); - AddVerificationFunc(ToolchainId::Clang, GccVerificationFunc); - AddVerificationFunc(ToolchainId::MinGW, GccVerificationFunc); - } -} - template -const ToolchainVerificationFunc & -ToolchainVerify::GetVerificationFunc(const std::string &identifier) { - const auto &verification_map = T::GetStatic(); - env::assert_fatal(verification_map.count(identifier) == 1, - "Add verification for custom toolchain through " - "Toolchain::AddVerificationFunc API"); - return verification_map.at(identifier); -} - -template -std::unordered_map & -ToolchainVerify::GetStatic() { - static std::unordered_map - verification_func_map; - return verification_func_map; +std::optional ToolchainVerify::GetToolchainInfo( + const ToolchainExecutables &executables) const { + const auto &cb = GetToolchainInfoFunc(); + if (cb) { + return cb(executables); + } + env::log_critical(__FUNCTION__, + "GetToolchainInfo virtual function not implemented"); + return {}; } template class ToolchainVerify; diff --git a/buildcc/lib/toolchain/test/test_toolchain_verify.cpp b/buildcc/lib/toolchain/test/test_toolchain_verify.cpp index 5854191d..1d968392 100644 --- a/buildcc/lib/toolchain/test/test_toolchain_verify.cpp +++ b/buildcc/lib/toolchain/test/test_toolchain_verify.cpp @@ -2,6 +2,7 @@ #include "toolchain/toolchain.h" +#include "env/command.h" #include "env/host_os.h" #include "expect_command.h" @@ -25,11 +26,57 @@ TEST_GROUP(ToolchainVerifyTestGroup) }; // clang-format on +class MockToolchain : public buildcc::Toolchain { +public: + MockToolchain(buildcc::ToolchainId id, const std::string &name, + const buildcc::ToolchainExecutables &executables = + buildcc::ToolchainExecutables("as", "gcc", "g++", "ar", + "ld")) + : buildcc::Toolchain(id, name, executables) {} + +private: + // Example implementation + std::optional GetToolchainInfo( + const buildcc::ToolchainExecutables &executables) const override { + (void)executables; + std::vector version_stdout; + std::vector arch_stdout; + bool version_done = buildcc::env::Command::Execute("", {}, &version_stdout); + bool arch_done = buildcc::env::Command::Execute("", {}, &arch_stdout); + if (!version_done || !arch_done || version_stdout.empty() || + arch_stdout.empty()) { + return {}; + } + buildcc::ToolchainCompilerInfo info; + info.compiler_version = version_stdout[0]; + info.target_arch = arch_stdout[0]; + return info; + } +}; + // NOTE, We are mocking the environment instead of actually querying it -TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc) { +TEST(ToolchainVerifyTestGroup, VerifyToolchain_BaseToolchain_Failure) { buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", "ar", "ld"); + std::string putenv_str = + fmt::format("CUSTOM_BUILDCC_PATH={}/toolchains/gcc", fs::current_path()); + int put = putenv(putenv_str.data()); + CHECK_TRUE(put == 0); + const char *custom_buildcc_path = getenv("CUSTOM_BUILDCC_PATH"); + CHECK_TRUE(custom_buildcc_path != nullptr); + UT_PRINT(custom_buildcc_path); + + buildcc::ToolchainFindConfig config; + config.env_vars.clear(); + config.env_vars.insert("CUSTOM_BUILDCC_PATH"); + + CHECK_THROWS(std::exception, gcc.Verify(config)); +} + +TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc) { + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); + std::vector version_stdout_data{"version"}; std::vector arch_stdout_data{"arch"}; buildcc::env::m::CommandExpect_Execute(1, true, &version_stdout_data); @@ -43,7 +90,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc) { CHECK_TRUE(custom_buildcc_path != nullptr); UT_PRINT(custom_buildcc_path); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.env_vars.insert("CUSTOM_BUILDCC_PATH"); @@ -54,8 +101,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc) { } TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_CompilerVersionFailure) { - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); std::vector version_stdout_data{"version"}; std::vector arch_stdout_data{"arch"}; @@ -70,7 +116,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_CompilerVersionFailure) { CHECK_TRUE(custom_buildcc_path != nullptr); UT_PRINT(custom_buildcc_path); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.env_vars.insert("CUSTOM_BUILDCC_PATH"); @@ -78,8 +124,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_CompilerVersionFailure) { } TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_CompilerVersionEmpty) { - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); std::vector version_stdout_data; std::vector arch_stdout_data{"arch"}; @@ -94,7 +139,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_CompilerVersionEmpty) { CHECK_TRUE(custom_buildcc_path != nullptr); UT_PRINT(custom_buildcc_path); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.env_vars.insert("CUSTOM_BUILDCC_PATH"); @@ -102,8 +147,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_CompilerVersionEmpty) { } TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_TargetArchFailure) { - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); std::vector version_stdout_data{"version"}; std::vector arch_stdout_data{"arch"}; @@ -118,7 +162,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_TargetArchFailure) { CHECK_TRUE(custom_buildcc_path != nullptr); UT_PRINT(custom_buildcc_path); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.env_vars.insert("CUSTOM_BUILDCC_PATH"); @@ -126,8 +170,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_TargetArchFailure) { } TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_TargetArchEmpty) { - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); std::vector version_stdout_data{"version"}; std::vector arch_stdout_data; @@ -142,163 +185,7 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_Gcc_TargetArchEmpty) { CHECK_TRUE(custom_buildcc_path != nullptr); UT_PRINT(custom_buildcc_path); - buildcc::ToolchainVerifyConfig config; - config.env_vars.clear(); - config.env_vars.insert("CUSTOM_BUILDCC_PATH"); - - CHECK_THROWS(std::exception, gcc.Verify(config)); -} - -TEST(ToolchainVerifyTestGroup, VerifyToolchain_Clang) { - buildcc::Toolchain clang(buildcc::ToolchainId::Clang, "clang", "llvm-as", - "clang", "clang++", "llvm-ar", "lld"); - - std::vector version_stdout_data{"version"}; - std::vector arch_stdout_data{"arch"}; - buildcc::env::m::CommandExpect_Execute(1, true, &version_stdout_data); - buildcc::env::m::CommandExpect_Execute(1, true, &arch_stdout_data); - - std::string putenv_str = fmt::format( - "CUSTOM_BUILDCC_PATH={}/toolchains/clang", fs::current_path()); - int put = putenv(putenv_str.data()); - CHECK_TRUE(put == 0); - const char *custom_buildcc_path = getenv("CUSTOM_BUILDCC_PATH"); - CHECK_TRUE(custom_buildcc_path != nullptr); - UT_PRINT(custom_buildcc_path); - - buildcc::ToolchainVerifyConfig config; - config.env_vars.clear(); - config.env_vars.insert("CUSTOM_BUILDCC_PATH"); - - buildcc::ToolchainCompilerInfo compiler_info = clang.Verify(config); - - STRCMP_EQUAL(compiler_info.compiler_version.c_str(), "version"); - STRCMP_EQUAL(compiler_info.target_arch.c_str(), "arch"); -} - -TEST(ToolchainVerifyTestGroup, VerifyToolchain_Msvc) { - buildcc::Toolchain msvc(buildcc::ToolchainId::Msvc, "msvc", "cl", "cl", "cl", - "lib", "link"); - // Setup ENV - // VSCMD_VER - std::string vscmd_ver = std::string("VSCMD_VER=version"); - // VSCMD_ARG_HOST_ARCH - std::string host_arch = std::string("VSCMD_ARG_HOST_ARCH=host_arch"); - // VSCMD_ARG_TGT_ARCH - std::string tgt_arch = std::string("VSCMD_ARG_TGT_ARCH=tgt_arch"); - - CHECK_TRUE(putenv(vscmd_ver.data()) == 0); - CHECK_TRUE(putenv(host_arch.data()) == 0); - CHECK_TRUE(putenv(tgt_arch.data()) == 0); - - // MSVC Compiler - std::string putenv_str = - fmt::format("CUSTOM_BUILDCC_PATH={}/toolchains/msvc", fs::current_path()); - int put = putenv(putenv_str.data()); - CHECK_TRUE(put == 0); - const char *custom_buildcc_path = getenv("CUSTOM_BUILDCC_PATH"); - CHECK_TRUE(custom_buildcc_path != nullptr); - UT_PRINT(custom_buildcc_path); - - buildcc::ToolchainVerifyConfig config; - config.env_vars.clear(); - config.env_vars.insert("CUSTOM_BUILDCC_PATH"); - - buildcc::ToolchainCompilerInfo compiler_info = msvc.Verify(config); - - STRCMP_EQUAL(compiler_info.compiler_version.c_str(), "version"); - STRCMP_EQUAL(compiler_info.target_arch.c_str(), "host_arch_tgt_arch"); -} - -TEST(ToolchainVerifyTestGroup, VerifyToolchain_Custom_VerificationSuccess) { - buildcc::Toolchain::AddVerificationFunc( - buildcc::ToolchainId::Custom, - [](const buildcc::ToolchainExecutables &executables) - -> std::optional { - (void)executables; - buildcc::ToolchainCompilerInfo compiler_info; - compiler_info.compiler_version = "custom_compiler_version"; - compiler_info.target_arch = "custom_target_arch"; - return compiler_info; - }, - "success_verification_func"); - buildcc::Toolchain custom(buildcc::ToolchainId::Custom, "custom", "assembler", - "c_compiler", "cpp_compiler", "archiver", "linker"); - buildcc::ToolchainVerifyConfig config; - config.env_vars.clear(); - config.absolute_search_paths.insert( - (fs::current_path() / "toolchains" / "custom")); - config.verification_identifier = "success_verification_func"; - auto compiler_info = custom.Verify(config); - STRCMP_EQUAL(compiler_info.compiler_version.c_str(), - "custom_compiler_version"); - STRCMP_EQUAL(compiler_info.target_arch.c_str(), "custom_target_arch"); -} - -TEST(ToolchainVerifyTestGroup, VerifyToolchain_Custom_VerificationFailure) { - buildcc::Toolchain::AddVerificationFunc( - buildcc::ToolchainId::Custom, - [](const buildcc::ToolchainExecutables &executables) - -> std::optional { - (void)executables; - return {}; - }, - "failure_verification_func"); - - // Adding verification function with the same identifier throws an exception - CHECK_THROWS(std::exception, - (buildcc::Toolchain::AddVerificationFunc( - buildcc::ToolchainId::Custom, - [](const buildcc::ToolchainExecutables &executables) - -> std::optional { - (void)executables; - return {}; - }, - "failure_verification_func"))); - buildcc::Toolchain custom(buildcc::ToolchainId::Custom, "custom", "assembler", - "c_compiler", "cpp_compiler", "archiver", "linker"); - - buildcc::ToolchainVerifyConfig config; - config.env_vars.clear(); - config.absolute_search_paths.insert( - (fs::current_path() / "toolchains" / "custom")); - // Fails since ToolchainId::Custom expects a verification_identifier - CHECK_THROWS(std::exception, custom.Verify(config)); - - // Fails since we do not get valid ToolchainCompilerInfo - config.verification_identifier = "failure_verification_func"; - CHECK_THROWS(std::exception, custom.Verify(config)); - - // Fails since we have not registered a verification function with this id - config.verification_identifier = "unregistered_verification_func"; - CHECK_THROWS(std::exception, custom.Verify(config)); -} - -TEST(ToolchainVerifyTestGroup, VerifyToolchain_Undefined_AddVerificationFunc) { - CHECK_THROWS(std::exception, - (buildcc::Toolchain::AddVerificationFunc( - buildcc::ToolchainId::Undefined, - [](const buildcc::ToolchainExecutables &executables) - -> std::optional { - (void)executables; - return {}; - }, - "undefined_verification_func"))); -} - -TEST(ToolchainVerifyTestGroup, VerifyToolchain_BadCompilerId) { - buildcc::Toolchain gcc((buildcc::ToolchainId)65535, "gcc", "as", "gcc", "g++", - "ar", "ld"); - - std::string putenv_str = - fmt::format("CUSTOM_BUILDCC_PATH={}/toolchains/gcc", fs::current_path()); - int put = putenv(putenv_str.data()); - CHECK_TRUE(put == 0); - const char *custom_buildcc_path = getenv("CUSTOM_BUILDCC_PATH"); - CHECK_TRUE(custom_buildcc_path != nullptr); - UT_PRINT(custom_buildcc_path); - - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.env_vars.insert("CUSTOM_BUILDCC_PATH"); @@ -306,10 +193,9 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_BadCompilerId) { } TEST(ToolchainVerifyTestGroup, VerifyToolchain_BadAbsolutePath) { - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.absolute_search_paths.insert((fs::current_path() / "does_not_exist")); @@ -317,10 +203,9 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_BadAbsolutePath) { } TEST(ToolchainVerifyTestGroup, VerifyToolchain_PathContainsDir) { - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.absolute_search_paths.insert((fs::current_path() / "toolchains")); @@ -329,38 +214,6 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_PathContainsDir) { #if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__MINGW64__) -TEST(ToolchainVerifyTestGroup, - VerifyToolchain_Msvc_CompilerVersionAndTargetArchFailure) { - buildcc::Toolchain msvc(buildcc::ToolchainId::Msvc, "msvc", "cl", "cl", "cl", - "lib", "link"); - // Setup ENV - // VSCMD_VER - // std::string vscmd_ver = std::string("VSCMD_VER=version"); - // // VSCMD_ARG_HOST_ARCH - // std::string host_arch = std::string("VSCMD_ARG_HOST_ARCH=host_arch"); - // // VSCMD_ARG_TGT_ARCH - // std::string tgt_arch = std::string("VSCMD_ARG_TGT_ARCH=tgt_arch"); - - // CHECK_TRUE(putenv(vscmd_ver.data()) == 0); - // CHECK_TRUE(putenv(host_arch.data()) == 0); - // CHECK_TRUE(putenv(tgt_arch.data()) == 0); - - // MSVC Compiler - std::string putenv_str = - fmt::format("CUSTOM_BUILDCC_PATH={}/toolchains/msvc", fs::current_path()); - int put = putenv(putenv_str.data()); - CHECK_TRUE(put == 0); - const char *custom_buildcc_path = getenv("CUSTOM_BUILDCC_PATH"); - CHECK_TRUE(custom_buildcc_path != nullptr); - UT_PRINT(custom_buildcc_path); - - buildcc::ToolchainVerifyConfig config; - config.env_vars.clear(); - config.env_vars.insert("CUSTOM_BUILDCC_PATH"); - - CHECK_THROWS(std::exception, msvc.Verify(config)); -} - TEST(ToolchainVerifyTestGroup, VerifyToolchain_LockedFolder) { std::error_code err; fs::permissions(fs::current_path() / "toolchains" / "gcc", fs::perms::none, @@ -369,10 +222,9 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_LockedFolder) { FAIL_TEST("Could not set file permissions"); } - buildcc::Toolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", "g++", - "ar", "ld"); + MockToolchain gcc(buildcc::ToolchainId::Gcc, "gcc"); - buildcc::ToolchainVerifyConfig config; + buildcc::ToolchainFindConfig config; config.env_vars.clear(); config.absolute_search_paths.insert( (fs::current_path() / "toolchains" / "gcc")); @@ -388,6 +240,39 @@ TEST(ToolchainVerifyTestGroup, VerifyToolchain_LockedFolder) { #endif +TEST(ToolchainVerifyTestGroup, CustomToolchainInfo) { + buildcc::Toolchain toolchain( + buildcc::ToolchainId::Gcc, "gcc", + buildcc::ToolchainExecutables("as", "gcc", "g++", "ar", "ld")); + toolchain.SetToolchainInfoFunc( + [](const buildcc::ToolchainExecutables &executables) + -> std::optional { + (void)executables; + mock().actualCall("SetToolchainInfoFunc"); + buildcc::ToolchainCompilerInfo info; + info.compiler_version = "version"; + info.target_arch = "arch"; + return info; + }); + + std::string putenv_str = + fmt::format("CUSTOM_BUILDCC_PATH={}/toolchains/gcc", fs::current_path()); + int put = putenv(putenv_str.data()); + CHECK_TRUE(put == 0); + const char *custom_buildcc_path = getenv("CUSTOM_BUILDCC_PATH"); + CHECK_TRUE(custom_buildcc_path != nullptr); + UT_PRINT(custom_buildcc_path); + + buildcc::ToolchainFindConfig config; + config.env_vars.clear(); + config.env_vars.insert("CUSTOM_BUILDCC_PATH"); + + mock().expectOneCall("SetToolchainInfoFunc"); + auto info = toolchain.Verify(config); + STRCMP_EQUAL(info.compiler_version.c_str(), "version"); + STRCMP_EQUAL(info.target_arch.c_str(), "arch"); +} + int main(int ac, char **av) { buildcc::env::m::VectorStringCopier copier; mock().installCopier(TEST_VECTOR_STRING_TYPE, copier); diff --git a/buildcc/toolchains/CMakeLists.txt b/buildcc/toolchains/CMakeLists.txt index d7e8b6c3..a58b9777 100644 --- a/buildcc/toolchains/CMakeLists.txt +++ b/buildcc/toolchains/CMakeLists.txt @@ -1,36 +1,46 @@ set(TOOLCHAIN_SPECIALIZED_SRCS + src/toolchain_gcc.cpp include/toolchains/toolchain_gcc.h - include/toolchains/toolchain_msvc.h include/toolchains/toolchain_mingw.h + + src/toolchain_msvc.cpp + include/toolchains/toolchain_msvc.h + + include/toolchains/toolchain_generic.h + + src/toolchain_infos.cpp + include/toolchains/toolchain_infos.h ) if(${BUILDCC_BUILD_AS_SINGLE_LIB}) target_sources(buildcc PRIVATE ${TOOLCHAIN_SPECIALIZED_SRCS} ) - target_include_directories(buildcc INTERFACE + target_include_directories(buildcc PUBLIC $ $ ) endif() -m_clangtidy("toolchain_specialized") -add_library(toolchain_specialized INTERFACE - ${TOOLCHAIN_SPECIALIZED_SRCS} -) -target_include_directories(toolchain_specialized INTERFACE - $ - $ -) -target_link_libraries(toolchain_specialized INTERFACE - toolchain -) +if(${BUILDCC_BUILD_AS_INTERFACE}) + m_clangtidy("toolchain_specialized") + add_library(toolchain_specialized STATIC + ${TOOLCHAIN_SPECIALIZED_SRCS} + ) + target_include_directories(toolchain_specialized PUBLIC + $ + $ + ) + target_link_libraries(toolchain_specialized PUBLIC + toolchain + ) +endif() if (${BUILDCC_INSTALL}) - install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION "${BUILDCC_INSTALL_HEADER_PREFIX}") if (${BUILDCC_BUILD_AS_INTERFACE}) # toolchain_specialized Install install(TARGETS toolchain_specialized DESTINATION lib EXPORT toolchain_specializedConfig) install(EXPORT toolchain_specializedConfig DESTINATION "${BUILDCC_INSTALL_LIB_PREFIX}/toolchain_specialized") endif() + install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION "${BUILDCC_INSTALL_HEADER_PREFIX}") endif() diff --git a/buildcc/toolchains/include/toolchains/toolchain_custom.h b/buildcc/toolchains/include/toolchains/toolchain_custom.h new file mode 100644 index 00000000..ba0b50bb --- /dev/null +++ b/buildcc/toolchains/include/toolchains/toolchain_custom.h @@ -0,0 +1,36 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TOOLCHAINS_TOOLCHAIN_CUSTOM_H_ +#define TOOLCHAINS_TOOLCHAIN_CUSTOM_H_ + +#include "toolchain/toolchain.h" + +#include + +namespace buildcc { + +class Toolchain_custom : public Toolchain { +public: + Toolchain_custom(const std::string &name, + const ToolchainExecutables &executables, + const ToolchainConfig &config = ToolchainConfig()) + : Toolchain(ToolchainId::Custom, name, executables, config) {} +}; + +} // namespace buildcc + +#endif diff --git a/buildcc/toolchains/include/toolchains/toolchain_gcc.h b/buildcc/toolchains/include/toolchains/toolchain_gcc.h index 9e54351f..57de3c5f 100644 --- a/buildcc/toolchains/include/toolchains/toolchain_gcc.h +++ b/buildcc/toolchains/include/toolchains/toolchain_gcc.h @@ -21,12 +21,6 @@ namespace buildcc { -constexpr const char *const kGccObjExt = ".o"; -constexpr const char *const kGccPchHeaderExt = ".h"; -constexpr const char *const kGccPchCompileExt = ".gch"; -constexpr const char *const kGccPrefixIncludeDir = "-I"; -constexpr const char *const kGccPrefixLibDir = "-L"; - /** * @brief Generic GCC Toolchain
* id = ToolchainId::Gcc
@@ -39,18 +33,22 @@ constexpr const char *const kGccPrefixLibDir = "-L"; */ class Toolchain_gcc : public Toolchain { public: - Toolchain_gcc() - : Toolchain(ToolchainId::Gcc, "gcc", "as", "gcc", "g++", "ar", "ld") {} + // Run time basic constructor + Toolchain_gcc(const std::string &name = "gcc", + std::optional op_executables = {}, + std::optional op_config = {}) + : Toolchain(ToolchainId::Gcc, name, + op_executables.value_or( + ToolchainExecutables("as", "gcc", "g++", "ar", "ld")), + op_config.value_or(ToolchainConfig())) {} + + virtual ~Toolchain_gcc() = default; Toolchain_gcc(const Toolchain_gcc &gcc) = delete; private: - void UpdateConfig(ToolchainConfig &config) override { - config.obj_ext = kGccObjExt; - config.pch_header_ext = kGccPchHeaderExt; - config.pch_compile_ext = kGccPchCompileExt; - config.prefix_include_dir = kGccPrefixIncludeDir; - config.prefix_lib_dir = kGccPrefixLibDir; - } + void UpdateConfig(ToolchainConfig &config) override; + std::optional + GetToolchainInfo(const ToolchainExecutables &executables) const override; }; } // namespace buildcc diff --git a/buildcc/toolchains/include/toolchains/toolchain_generic.h b/buildcc/toolchains/include/toolchains/toolchain_generic.h new file mode 100644 index 00000000..a8e0677b --- /dev/null +++ b/buildcc/toolchains/include/toolchains/toolchain_generic.h @@ -0,0 +1,107 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TOOLCHAINS_TOOLCHAIN_GENERIC_H_ +#define TOOLCHAINS_TOOLCHAIN_GENERIC_H_ + +#include "toolchain/toolchain.h" + +#include "toolchain_gcc.h" +#include "toolchain_mingw.h" +#include "toolchain_msvc.h" + +#include "env/storage.h" + +namespace buildcc { + +class Toolchain_generic { +public: + /** + * @brief Compile time way to create a generic toolchain instance + * + * @return Toolchain& Returns the BaseToolchain with necessary virtual + * function overrides + * Asserts fatal if ToolchainId is not supported + */ + template + static Toolchain &New(const std::string &identifier, Params &&...params) { + Toolchain *toolchain{nullptr}; + + if constexpr (id == ToolchainId::Gcc) { + toolchain = AddIf(identifier, identifier, + std::forward(params)...); + } + + if constexpr (id == ToolchainId::Msvc) { + toolchain = AddIf(identifier, identifier, + std::forward(params)...); + } + + if constexpr (id == ToolchainId::MinGW) { + toolchain = AddIf(identifier, identifier, + std::forward(params)...); + } + + env::assert_fatal(toolchain, "Toolchain could not be created"); + return *toolchain; + } + + /** + * @brief Runtime time way to create a generic toolchain instance + * + * @return Toolchain& Returns the BaseToolchain with necessary virtual + * function overrides + * Asserts fatal if ToolchainId is not supported + */ + static Toolchain &New(ToolchainId id, const std::string &identifier, + std::optional op_executables = {}, + std::optional op_config = {}) { + Toolchain *toolchain{nullptr}; + switch (id) { + case ToolchainId::Gcc: + toolchain = AddIf(identifier, identifier, op_executables, + op_config); + break; + case ToolchainId::Msvc: + toolchain = AddIf(identifier, identifier, op_executables, + op_config); + break; + case ToolchainId::MinGW: + toolchain = AddIf(identifier, identifier, op_executables, + op_config); + break; + default: + break; + } + env::assert_fatal(toolchain, "Toolchain could not be created"); + return *toolchain; + } + +private: + template + static Toolchain *AddIf(const std::string &identifier, Params &&...params) { + Toolchain *toolchain{nullptr}; + if (!Storage::Contains(identifier)) { + toolchain = + &Storage::Add(identifier, std::forward(params)...); + } + return toolchain; + } +}; + +} // namespace buildcc + +#endif diff --git a/buildcc/toolchains/include/toolchains/toolchain_infos.h b/buildcc/toolchains/include/toolchains/toolchain_infos.h new file mode 100644 index 00000000..924b62fb --- /dev/null +++ b/buildcc/toolchains/include/toolchains/toolchain_infos.h @@ -0,0 +1,37 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TOOLCHAINS_TOOLCHAIN_INFOS_H_ +#define TOOLCHAINS_TOOLCHAIN_INFOS_H_ + +#include + +#include "toolchain/toolchain.h" + +namespace buildcc { + +class GlobalToolchainInfo { +public: + static const ToolchainInfoFunc &Get(ToolchainId id); + +private: + static std::unordered_map + global_toolchain_info_func_; +}; + +} // namespace buildcc + +#endif diff --git a/buildcc/toolchains/include/toolchains/toolchain_mingw.h b/buildcc/toolchains/include/toolchains/toolchain_mingw.h index d0e76824..15f03932 100644 --- a/buildcc/toolchains/include/toolchains/toolchain_mingw.h +++ b/buildcc/toolchains/include/toolchains/toolchain_mingw.h @@ -23,12 +23,6 @@ namespace buildcc { -constexpr const char *const kMingwObjExt = ".o"; -constexpr const char *const kMingwPchHeaderExt = ".h"; -constexpr const char *const kMingwPchCompileExt = ".gch"; -constexpr const char *const kMingwPrefixIncludeDir = "-I"; -constexpr const char *const kMingwPrefixLibDir = "-L"; - /** * @brief Generic MinGW Toolchain
* id = ToolchainId::MinGW
@@ -39,20 +33,24 @@ constexpr const char *const kMingwPrefixLibDir = "-L"; * archiver = "ar"
* linker = "ld"
*/ -class Toolchain_mingw : public BaseToolchain { +class Toolchain_mingw : public Toolchain { public: - Toolchain_mingw() - : Toolchain(ToolchainId::MinGW, "gcc", "as", "gcc", "g++", "ar", "ld") {} + // Run time basic constructor + Toolchain_mingw(const std::string &name = "gcc", + std::optional op_executables = {}, + std::optional op_config = {}) + : Toolchain(ToolchainId::MinGW, name, + op_executables.value_or( + ToolchainExecutables("as", "gcc", "g++", "ar", "ld")), + op_config.value_or(ToolchainConfig())) {} + + virtual ~Toolchain_mingw() = default; Toolchain_mingw(const Toolchain_mingw &) = delete; private: - void UpdateConfig(ToolchainConfig &config) { - config.obj_ext = kMingwObjExt; - config.pch_header_ext = kMingwPchHeaderExt; - config.pch_compile_ext = kMingwPchCompileExt; - config.prefix_include_dir = kMingwPrefixIncludeDir; - config.prefix_lib_dir = kMingwPrefixLibDir; - } + void UpdateConfig(ToolchainConfig &config) override; + std::optional + GetToolchainInfo(const ToolchainExecutables &executables) const override; }; } // namespace buildcc diff --git a/buildcc/toolchains/include/toolchains/toolchain_msvc.h b/buildcc/toolchains/include/toolchains/toolchain_msvc.h index db40a8d6..1cfb6252 100644 --- a/buildcc/toolchains/include/toolchains/toolchain_msvc.h +++ b/buildcc/toolchains/include/toolchains/toolchain_msvc.h @@ -21,13 +21,6 @@ namespace buildcc { -constexpr const char *const kMsvcObjExt = ".obj"; -constexpr const char *const kMsvcPchHeaderExt = ".h"; -constexpr const char *const kMsvcPchCompileExt = ".pch"; - -constexpr const char *const kMsvcPrefixIncludeDir = "/I"; -constexpr const char *const kMsvcPrefixLibDir = "/LIBPATH:"; - /** * @brief Generic GCC Toolchain
* id = ToolchainId::Msvc
@@ -40,18 +33,22 @@ constexpr const char *const kMsvcPrefixLibDir = "/LIBPATH:"; */ class Toolchain_msvc : public Toolchain { public: - Toolchain_msvc() - : Toolchain(ToolchainId::Msvc, "msvc", "cl", "cl", "cl", "lib", "link") {} + // Run time basic constructor + Toolchain_msvc(const std::string &name = "msvc", + std::optional op_executables = {}, + std::optional op_config = {}) + : Toolchain(ToolchainId::Msvc, name, + op_executables.value_or( + ToolchainExecutables("cl", "cl", "cl", "lib", "link")), + op_config.value_or(ToolchainConfig())) {} + + virtual ~Toolchain_msvc() = default; Toolchain_msvc(const Toolchain_msvc &gcc) = delete; private: - void UpdateConfig(ToolchainConfig &config) { - config.obj_ext = kMsvcObjExt; - config.pch_header_ext = kMsvcPchHeaderExt; - config.pch_compile_ext = kMsvcPchCompileExt; - config.prefix_include_dir = kMsvcPrefixIncludeDir; - config.prefix_lib_dir = kMsvcPrefixLibDir; - } + void UpdateConfig(ToolchainConfig &config) override; + std::optional + GetToolchainInfo(const ToolchainExecutables &executables) const override; }; } // namespace buildcc diff --git a/buildcc/toolchains/src/toolchain_gcc.cpp b/buildcc/toolchains/src/toolchain_gcc.cpp new file mode 100644 index 00000000..a99deef0 --- /dev/null +++ b/buildcc/toolchains/src/toolchain_gcc.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "toolchains/toolchain_gcc.h" +#include "toolchains/toolchain_mingw.h" + +#include "toolchains/toolchain_infos.h" + +#include "env/command.h" + +namespace { + +constexpr const char *const kGccObjExt = ".o"; +constexpr const char *const kGccPchHeaderExt = ".h"; +constexpr const char *const kGccPchCompileExt = ".gch"; +constexpr const char *const kGccPrefixIncludeDir = "-I"; +constexpr const char *const kGccPrefixLibDir = "-L"; + +void UpdateGccConfig(buildcc::ToolchainConfig &config) { + config.obj_ext = kGccObjExt; + config.pch_header_ext = kGccPchHeaderExt; + config.pch_compile_ext = kGccPchCompileExt; + config.prefix_include_dir = kGccPrefixIncludeDir; + config.prefix_lib_dir = kGccPrefixLibDir; +} + +} // namespace + +namespace buildcc { + +void Toolchain_gcc::UpdateConfig(ToolchainConfig &config) { + UpdateGccConfig(config); +} + +std::optional +Toolchain_gcc::GetToolchainInfo(const ToolchainExecutables &executables) const { + return GlobalToolchainInfo::Get(ToolchainId::Gcc)(executables); +} + +void Toolchain_mingw::UpdateConfig(ToolchainConfig &config) { + UpdateGccConfig(config); +} + +std::optional Toolchain_mingw::GetToolchainInfo( + const ToolchainExecutables &executables) const { + return GlobalToolchainInfo::Get(ToolchainId::MinGW)(executables); +} + +} // namespace buildcc diff --git a/buildcc/toolchains/src/toolchain_infos.cpp b/buildcc/toolchains/src/toolchain_infos.cpp new file mode 100644 index 00000000..49117e66 --- /dev/null +++ b/buildcc/toolchains/src/toolchain_infos.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "toolchains/toolchain_infos.h" + +#include "env/assert_fatal.h" +#include "env/command.h" +#include "env/logging.h" + +namespace { + +// GCC + +std::optional +GetGccCompilerVersion(const buildcc::env::Command &command) { + std::vector stdout_data; + bool executed = buildcc::env::Command::Execute( + command.Construct("{compiler} -dumpversion"), {}, &stdout_data); + if (!executed || stdout_data.empty()) { + return {}; + } + return stdout_data[0]; +} + +std::optional +GetGccTargetArchitecture(const buildcc::env::Command &command) { + std::vector stdout_data; + bool executed = buildcc::env::Command::Execute( + command.Construct("{compiler} -dumpmachine"), {}, &stdout_data); + if (!executed || stdout_data.empty()) { + return {}; + } + return stdout_data[0]; +} + +std::optional +GetGccToolchainInfo(const buildcc::ToolchainExecutables &executables) { + buildcc::env::Command command; + command.AddDefaultArgument("compiler", executables.cpp_compiler); + + auto op_compiler_version = GetGccCompilerVersion(command); + auto op_target_arch = GetGccTargetArchitecture(command); + if (!op_compiler_version.has_value() || !op_target_arch.has_value()) { + return {}; + } + + buildcc::ToolchainCompilerInfo compiler_info; + compiler_info.compiler_version = op_compiler_version.value(); + compiler_info.target_arch = op_target_arch.value(); + return compiler_info; +} + +// MSVC + +std::optional GetMsvcCompilerVersion() { + const char *vscmd_version = getenv("VSCMD_VER"); + if (vscmd_version == nullptr) { + return {}; + } + return vscmd_version; +} + +std::optional GetMsvcTargetArchitecture() { + // DONE, Read `VSCMD_ARG_HOST_ARCH` from env path + // DONE, Read `VSCMD_ARG_TGT_ARCH` from env path + const char *vs_host_arch = getenv("VSCMD_ARG_HOST_ARCH"); + const char *vs_target_arch = getenv("VSCMD_ARG_TGT_ARCH"); + if (vs_host_arch == nullptr || vs_target_arch == nullptr) { + return {}; + } + + // DONE, Concat them + return fmt::format("{}_{}", vs_host_arch, vs_target_arch); +} + +std::optional +GetMsvcToolchainInfo(const buildcc::ToolchainExecutables &executables) { + (void)executables; + auto op_compiler_version = GetMsvcCompilerVersion(); + auto op_target_arch = GetMsvcTargetArchitecture(); + if (!op_compiler_version.has_value() || !op_target_arch.has_value()) { + return {}; + } + + buildcc::ToolchainCompilerInfo compiler_info; + compiler_info.compiler_version = op_compiler_version.value(); + compiler_info.target_arch = op_target_arch.value(); + return compiler_info; +} + +// + +std::optional +GetErrorToolchainInfo(const buildcc::ToolchainExecutables &executables) { + (void)executables; + buildcc::env::log_critical(__FUNCTION__, + "ToolchainInfo does not exist for particular " + "ToolchainId. Supply your own through 3 methods."); + return {}; +} + +} // namespace + +namespace buildcc { + +// TODO, Shift this to toolchain.h +// Create a global_toolchain.h file which manages global toolchain state +std::unordered_map + GlobalToolchainInfo::global_toolchain_info_func_{ + {ToolchainId::Gcc, GetGccToolchainInfo}, + {ToolchainId::MinGW, GetGccToolchainInfo}, + {ToolchainId::Clang, GetGccToolchainInfo}, + {ToolchainId::Msvc, GetMsvcToolchainInfo}, + {ToolchainId::Custom, GetErrorToolchainInfo}, + {ToolchainId::Undefined, GetErrorToolchainInfo}, + }; + +const ToolchainInfoFunc &GlobalToolchainInfo::Get(ToolchainId id) { + env::assert_fatal(global_toolchain_info_func_.find(id) != + global_toolchain_info_func_.end(), + "Invalid ToolchainId"); + return global_toolchain_info_func_[id]; +} + +} // namespace buildcc diff --git a/buildcc/toolchains/src/toolchain_msvc.cpp b/buildcc/toolchains/src/toolchain_msvc.cpp new file mode 100644 index 00000000..a6eca961 --- /dev/null +++ b/buildcc/toolchains/src/toolchain_msvc.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "toolchains/toolchain_msvc.h" + +#include "toolchains/toolchain_infos.h" + +namespace { + +constexpr const char *const kMsvcObjExt = ".obj"; +constexpr const char *const kMsvcPchHeaderExt = ".h"; +constexpr const char *const kMsvcPchCompileExt = ".pch"; +constexpr const char *const kMsvcPrefixIncludeDir = "/I"; +constexpr const char *const kMsvcPrefixLibDir = "/LIBPATH:"; + +} // namespace + +namespace buildcc { + +void Toolchain_msvc::UpdateConfig(ToolchainConfig &config) { + config.obj_ext = kMsvcObjExt; + config.pch_header_ext = kMsvcPchHeaderExt; + config.pch_compile_ext = kMsvcPchCompileExt; + config.prefix_include_dir = kMsvcPrefixIncludeDir; + config.prefix_lib_dir = kMsvcPrefixLibDir; +} + +std::optional Toolchain_msvc::GetToolchainInfo( + const ToolchainExecutables &executables) const { + return GlobalToolchainInfo::Get(ToolchainId::Msvc)(executables); +} + +} // namespace buildcc diff --git a/buildexe/buildexe.cpp b/buildexe/buildexe.cpp index 1427ab36..31715ec9 100644 --- a/buildexe/buildexe.cpp +++ b/buildexe/buildexe.cpp @@ -57,8 +57,8 @@ int main(int argc, char **argv) { Reg::Call(Args::Clean()).Func(clean_cb); // Host Toolchain - BaseToolchain toolchain = - buildexe_args.GetHostToolchainArg().ConstructToolchain(); + auto &toolchain = buildexe_args.GetHostToolchainArg(); + toolchain.SetToolchainInfoFunc(GlobalToolchainInfo::Get(toolchain.id)); toolchain.Verify(); if (buildexe_args.GetBuildMode() == BuildExeMode::Script) { diff --git a/buildexe/include/buildexe/args_setup.h b/buildexe/include/buildexe/args_setup.h index dde67f08..980ee696 100644 --- a/buildexe/include/buildexe/args_setup.h +++ b/buildexe/include/buildexe/args_setup.h @@ -77,9 +77,7 @@ class BuildExeArgs { void Setup(int argc, char **argv); // Getters - const ArgToolchain &GetHostToolchainArg() const { - return host_toolchain_arg_; - } + ArgToolchain &GetHostToolchainArg() { return host_toolchain_arg_; } const ArgTargetInfo &GetTargetInfo() const { return out_targetinfo_; } const ArgTargetInputs &GetTargetInputs() const { return out_targetinputs_; } const ArgScriptInfo &GetScriptInfo() const { return out_scriptinfo_; } diff --git a/docs/source/examples/hybrid.rst b/docs/source/examples/hybrid.rst index 38c611a8..b79b802d 100644 --- a/docs/source/examples/hybrid.rst +++ b/docs/source/examples/hybrid.rst @@ -352,7 +352,8 @@ For super customized targets and toolchains Toolchain_gcc gcc; Toolchain_msvc msvc; // Get custom toolchain from the command line, supplied at run time - BaseToolchain clang = toolchain_clang_gnu.ConstructToolchain(); + auto &clang = toolchain_clang_gnu; + clang.SetToolchainInfoFunc(GlobalToolchainInfo::Get(clang.id)); ExecutableTarget_gcc g_foolib("foolib", gcc, ""); ExecutableTarget_msvc m_foolib("foolib", msvc, ""); diff --git a/docs/source/user_api/args.rst b/docs/source/user_api/args.rst index e21db691..6f7e027a 100644 --- a/docs/source/user_api/args.rst +++ b/docs/source/user_api/args.rst @@ -54,7 +54,8 @@ Example // .build, .test arg_gcc_toolchain.state; // .id, .name, .asm_compiler, .c_compiler, .cpp_compiler, .archiver, .linker -> BaseToolchain - BaseToolchain gcc_toolchain = arg_gcc_toolchain.ConstructToolchain(); + auto &gcc_toolchain = arg_gcc_toolchain; + gcc_toolchain.SetToolchainInfoFunc(GlobalToolchainInfo::Get(gcc_toolchain.id)); return 0; } diff --git a/example/hybrid/custom_target/build.main.cpp b/example/hybrid/custom_target/build.main.cpp index c93b618c..82b03727 100644 --- a/example/hybrid/custom_target/build.main.cpp +++ b/example/hybrid/custom_target/build.main.cpp @@ -36,11 +36,11 @@ int main(int argc, char **argv) { Reg::Toolchain(arg_msvc.state).Build(foolib_build_cb, m_foolib); // * NOTE, This is how we add our custom toolchain - BaseToolchain clang = arg_toolchain_clang_gnu.ConstructToolchain(); + auto &clang = arg_toolchain_clang_gnu; + clang.SetToolchainInfoFunc(GlobalToolchainInfo::Get(clang.id)); Target_custom c_foolib("CFoolib.exe", TargetType::Executable, clang, "", arg_target_clang_gnu.GetTargetConfig()); - Reg::Toolchain(arg_toolchain_clang_gnu.state) - .Build(foolib_build_cb, c_foolib); + Reg::Toolchain(clang.state).Build(foolib_build_cb, c_foolib); // Reg::Run(); diff --git a/example/hybrid/generic/build.cpp b/example/hybrid/generic/build.cpp index 27e02310..a6c28d0d 100644 --- a/example/hybrid/generic/build.cpp +++ b/example/hybrid/generic/build.cpp @@ -41,7 +41,8 @@ int main(int argc, char **argv) { // Build steps // Toolchain + Generic Target - BaseToolchain toolchain = custom_toolchain.ConstructToolchain(); + auto &toolchain = custom_toolchain; + toolchain.SetToolchainInfoFunc(GlobalToolchainInfo::Get(toolchain.id)); Target_generic foolib_target("libfoo", default_lib_type, toolchain, "../foolib"); Target_generic generic_target("generic", TargetType::Executable, toolchain,