diff --git a/bootstrap/config/toolchain_linux_gcc.toml b/bootstrap/config/toolchain_linux_gcc.toml index 6ac3dd34..89ce7d40 100644 --- a/bootstrap/config/toolchain_linux_gcc.toml +++ b/bootstrap/config/toolchain_linux_gcc.toml @@ -1,4 +1,4 @@ -[toolchain.custom] +[toolchain.host] build = true test = true diff --git a/bootstrap/config/toolchain_win_gcc.toml b/bootstrap/config/toolchain_win_gcc.toml index dfd67809..d078e06f 100644 --- a/bootstrap/config/toolchain_win_gcc.toml +++ b/bootstrap/config/toolchain_win_gcc.toml @@ -1,8 +1,8 @@ -[toolchain.custom] +[toolchain.host] build = true test = true -id = "gcc" +id = "mingw" name = "x86_64-w64-mingw32" asm_compiler = "as" c_compiler = "gcc" diff --git a/bootstrap/config/toolchain_win_msvc.toml b/bootstrap/config/toolchain_win_msvc.toml index f14f51e5..2fb80da5 100644 --- a/bootstrap/config/toolchain_win_msvc.toml +++ b/bootstrap/config/toolchain_win_msvc.toml @@ -1,4 +1,4 @@ -[toolchain.custom] +[toolchain.host] build = true test = true diff --git a/bootstrap/include/bootstrap/build_tpl.h b/bootstrap/include/bootstrap/build_tpl.h index 5ac24653..296892a2 100644 --- a/bootstrap/include/bootstrap/build_tpl.h +++ b/bootstrap/include/bootstrap/build_tpl.h @@ -21,7 +21,13 @@ namespace buildcc { -void tpl_cb(BaseTarget &target); +struct TplConfig { + TplConfig() = default; + + OsId os_id{OsId::Linux}; +}; + +void tpl_cb(BaseTarget &target, const TplConfig &config = TplConfig()); } // namespace buildcc diff --git a/bootstrap/main.buildcc.cpp b/bootstrap/main.buildcc.cpp index ee26e955..6104c73a 100644 --- a/bootstrap/main.buildcc.cpp +++ b/bootstrap/main.buildcc.cpp @@ -35,7 +35,7 @@ static void hybrid_simple_example_cb(BaseTarget &target, int main(int argc, char **argv) { Args args; ArgToolchain custom_toolchain_arg; - args.AddToolchain("custom", "Host Toolchain", custom_toolchain_arg); + args.AddToolchain("host", "Host Toolchain", custom_toolchain_arg); args.Parse(argc, argv); Register reg(args); @@ -43,7 +43,6 @@ int main(int argc, char **argv) { BaseToolchain toolchain = custom_toolchain_arg.ConstructToolchain(); - PersistentStorage storage; BuildBuildCC buildcc( reg, toolchain, TargetEnv(env::get_project_root_dir(), env::get_project_build_dir())); diff --git a/bootstrap/src/build_buildcc.cpp b/bootstrap/src/build_buildcc.cpp index ec40da1b..76bf48a9 100644 --- a/bootstrap/src/build_buildcc.cpp +++ b/bootstrap/src/build_buildcc.cpp @@ -54,8 +54,10 @@ void buildcc_cb(BaseTarget &target, const BaseGenerator &schema_gen, target.GlobHeaders("lib/env/include/env"); // TOOLCHAIN + target.GlobSources("lib/toolchain/src/api"); target.AddIncludeDir("lib/toolchain/include"); target.GlobHeaders("lib/toolchain/include/toolchain"); + target.GlobHeaders("lib/toolchain/include/toolchain/api"); // TARGET target.GlobSources("lib/target/src/common"); @@ -238,7 +240,9 @@ void BuildBuildCC::Setup(const ArgToolchainState &state) { "tiny-process-library", env_.GetTargetBuildDir())); reg_.CallbackIf(state, global_flags_cb, tpl_lib, toolchain_); - reg_.Build(state, tpl_cb, tpl_lib); + TplConfig tpl_config; + tpl_config.os_id = get_host_os(); + reg_.Build(state, tpl_cb, tpl_lib, tpl_config); // TODO, Make this a generic selection between StaticTarget and // DynamicTarget diff --git a/bootstrap/src/build_cli11.cpp b/bootstrap/src/build_cli11.cpp index fa900aa7..d464c7c4 100644 --- a/bootstrap/src/build_cli11.cpp +++ b/bootstrap/src/build_cli11.cpp @@ -21,7 +21,6 @@ namespace buildcc { void cli11_ho_cb(TargetInfo &info) { info.AddIncludeDir("include"); info.GlobHeaders("include/CLI"); - // TODO, Add PCH } } // namespace buildcc diff --git a/bootstrap/src/build_flatbuffers.cpp b/bootstrap/src/build_flatbuffers.cpp index 01039ae0..68c706d6 100644 --- a/bootstrap/src/build_flatbuffers.cpp +++ b/bootstrap/src/build_flatbuffers.cpp @@ -82,45 +82,30 @@ void build_flatc_exe_cb(BaseTarget &target) { kFlatcPreprocessorFlags.cend(), [&](const auto &f) { target.AddPreprocessorFlag(f); }); - if constexpr (env::is_win()) { - switch (target.GetToolchain().GetId()) { - case ToolchainId::Gcc: - case ToolchainId::MinGW: - std::for_each(kFlatcGccCppCompileFlags.cbegin(), - kFlatcGccCppCompileFlags.cend(), - [&](const auto &f) { target.AddCppCompileFlag(f); }); - break; - case ToolchainId::Msvc: - std::for_each(kFlatcMsvcCppCompileFlags.cbegin(), - kFlatcMsvcCppCompileFlags.cend(), - [&](const auto &f) { target.AddCppCompileFlag(f); }); - break; - default: - break; - } + switch (target.GetToolchain().GetId()) { + case ToolchainId::Gcc: + case ToolchainId::MinGW: + std::for_each(kFlatcGccCppCompileFlags.cbegin(), + kFlatcGccCppCompileFlags.cend(), + [&](const auto &f) { target.AddCppCompileFlag(f); }); + break; + case ToolchainId::Msvc: + std::for_each(kFlatcMsvcCppCompileFlags.cbegin(), + kFlatcMsvcCppCompileFlags.cend(), + [&](const auto &f) { target.AddCppCompileFlag(f); }); + break; + case ToolchainId::Clang: + break; + default: + break; } - if constexpr (env::is_linux()) { - switch (target.GetToolchain().GetId()) { - case ToolchainId::Gcc: - std::for_each(kFlatcGccCppCompileFlags.cbegin(), - kFlatcGccCppCompileFlags.cend(), - [&](const auto &f) { target.AddCppCompileFlag(f); }); - break; - default: - break; - } - } - - // TODO, Add PCH - target.Build(); } void flatbuffers_ho_cb(TargetInfo &info) { info.AddIncludeDir("include"); info.GlobHeaders("include/flatbuffers"); - // TODO, Add PCH } } // namespace buildcc diff --git a/bootstrap/src/build_taskflow.cpp b/bootstrap/src/build_taskflow.cpp index 9d945194..22049ad3 100644 --- a/bootstrap/src/build_taskflow.cpp +++ b/bootstrap/src/build_taskflow.cpp @@ -23,7 +23,12 @@ void taskflow_ho_cb(TargetInfo &info) { info.GlobHeaders("taskflow"); info.GlobHeaders("taskflow/core"); info.GlobHeaders("taskflow/core/algorithm"); - // TODO, Track more header files + info.GlobHeaders("taskflow/cuda"); + info.GlobHeaders("taskflow/cuda/cuda_algorithm"); + info.GlobHeaders("taskflow/dsl"); + info.GlobHeaders("taskflow/sycl"); + info.GlobHeaders("taskflow/sycl/sycl_algorithm"); + info.GlobHeaders("taskflow/utility"); } } // namespace buildcc diff --git a/bootstrap/src/build_tpl.cpp b/bootstrap/src/build_tpl.cpp index 5fbdf513..b212f2c7 100644 --- a/bootstrap/src/build_tpl.cpp +++ b/bootstrap/src/build_tpl.cpp @@ -18,15 +18,22 @@ namespace buildcc { -void tpl_cb(BaseTarget &target) { +void tpl_cb(BaseTarget &target, const TplConfig &config) { target.AddSource("process.cpp"); target.AddIncludeDir(""); target.AddHeader("process.hpp"); - if constexpr (env::is_win()) { + switch (config.os_id) { + case OsId::Win: target.AddSource("process_win.cpp"); - } else { + break; + case OsId::Linux: + case OsId::Unix: + case OsId::Mac: target.AddSource("process_unix.cpp"); + break; + default: + break; } target.Build(); diff --git a/buildcc/lib/args/include/args/persistent_storage.h b/buildcc/lib/args/include/args/persistent_storage.h index 4c3c5b73..9e4c86e7 100644 --- a/buildcc/lib/args/include/args/persistent_storage.h +++ b/buildcc/lib/args/include/args/persistent_storage.h @@ -48,7 +48,7 @@ class PersistentStorage { metadata.ptr = (void *)ptr; metadata.typeid_name = typeid(T).name(); metadata.destructor = [this, identifier, ptr]() { - env::log_info("Cleaning", identifier); + env::log_trace("Cleaning", identifier); Remove(ptr); }; ptrs_.emplace(identifier, metadata); diff --git a/buildcc/lib/args/src/args.cpp b/buildcc/lib/args/src/args.cpp index 67a09998..c9ab18cb 100644 --- a/buildcc/lib/args/src/args.cpp +++ b/buildcc/lib/args/src/args.cpp @@ -77,11 +77,12 @@ const std::unordered_map kLogLevelMap{ const std::unordered_map kToolchainIdMap{ - {"gcc", buildcc::base::Toolchain::Id::Gcc}, - {"msvc", buildcc::base::Toolchain::Id::Msvc}, - {"clang", buildcc::base::Toolchain::Id::Clang}, - {"custom", buildcc::base::Toolchain::Id::Custom}, - {"undefined", buildcc::base::Toolchain::Id::Undefined}, + {"gcc", buildcc::ToolchainId::Gcc}, + {"msvc", buildcc::ToolchainId::Msvc}, + {"mingw", buildcc::ToolchainId::MinGW}, + {"clang", buildcc::ToolchainId::Clang}, + {"custom", buildcc::ToolchainId::Custom}, + {"undefined", buildcc::ToolchainId::Undefined}, }; } // namespace @@ -136,19 +137,17 @@ void Args::RootArgs() { ->expected(kMinFiles, kMaxFiles); // Root flags + auto *root_group = app_.add_option_group(kRootGroup); - app_.add_flag(kCleanParam, clean_, kCleanDesc)->group(kRootGroup); - app_.add_option(kLoglevelParam, loglevel_, kLoglevelDesc) - ->transform(CLI::CheckedTransformer(kLogLevelMap, CLI::ignore_case)) - ->group(kRootGroup); + root_group->add_flag(kCleanParam, clean_, kCleanDesc); + root_group->add_option(kLoglevelParam, loglevel_, kLoglevelDesc) + ->transform(CLI::CheckedTransformer(kLogLevelMap, CLI::ignore_case)); // Dir flags - app_.add_option(kRootDirParam, project_root_dir_, kRootDirDesc) - ->required() - ->group(kRootGroup); - app_.add_option(kBuildDirParam, project_build_dir_, kBuildDirDesc) - ->required() - ->group(kRootGroup); + root_group->add_option(kRootDirParam, project_root_dir_, kRootDirDesc) + ->required(); + root_group->add_option(kBuildDirParam, project_build_dir_, kBuildDirDesc) + ->required(); } } // namespace buildcc diff --git a/buildcc/lib/env/include/env/host_os.h b/buildcc/lib/env/include/env/host_os.h index 36a6c2fd..18740211 100644 --- a/buildcc/lib/env/include/env/host_os.h +++ b/buildcc/lib/env/include/env/host_os.h @@ -56,4 +56,37 @@ inline constexpr bool is_unix() { } // namespace buildcc::env +namespace buildcc { + +enum class OsId { + Linux, + Win, + Mac, + Unix, + Undefined, +}; + +inline constexpr OsId get_host_os() { + OsId os_id = OsId::Undefined; + if constexpr (env::is_linux()) { + os_id = OsId::Linux; + } + + if constexpr (env::is_unix()) { + os_id = OsId::Unix; + } + + if constexpr (env::is_win()) { + os_id = OsId::Win; + } + + if constexpr (env::is_mac()) { + os_id = OsId::Mac; + } + + return os_id; +} + +} // namespace buildcc + #endif diff --git a/buildcc/lib/target/src/api/include_api.cpp b/buildcc/lib/target/src/api/include_api.cpp index 2b66eb19..3b5de205 100644 --- a/buildcc/lib/target/src/api/include_api.cpp +++ b/buildcc/lib/target/src/api/include_api.cpp @@ -54,7 +54,6 @@ void IncludeApi::GlobHeadersAbsolute(const fs::path &absolute_path) { for (const auto &p : fs::directory_iterator(absolute_path)) { if (t.config_.IsValidHeader(p.path())) { - env::log_trace(__FUNCTION__, fmt::format("Added header {}", p.path())); AddHeaderAbsolute(p.path()); } } diff --git a/buildcc/lib/target/src/target/build.cpp b/buildcc/lib/target/src/target/build.cpp index 6fea12c9..ef9654a5 100644 --- a/buildcc/lib/target/src/target/build.cpp +++ b/buildcc/lib/target/src/target/build.cpp @@ -86,11 +86,11 @@ void Target::Build() { {kLinkFlags, internal::aggregate(GetLinkFlags())}, // Toolchain executables here - {kAsmCompiler, toolchain_.GetAsmCompiler()}, - {kCCompiler, toolchain_.GetCCompiler()}, - {kCppCompiler, toolchain_.GetCppCompiler()}, - {kArchiver, toolchain_.GetArchiver()}, - {kLinker, toolchain_.GetLinker()}, + {kAsmCompiler, fmt::format("{}", fs::path(toolchain_.GetAsmCompiler()))}, + {kCCompiler, fmt::format("{}", fs::path(toolchain_.GetCCompiler()))}, + {kCppCompiler, fmt::format("{}", fs::path(toolchain_.GetCppCompiler()))}, + {kArchiver, fmt::format("{}", fs::path(toolchain_.GetArchiver()))}, + {kLinker, fmt::format("{}", fs::path(toolchain_.GetLinker()))}, }); // Load the serialized file diff --git a/buildcc/lib/target/src/target/friend/compile_object.cpp b/buildcc/lib/target/src/target/friend/compile_object.cpp index 2f001993..fe6b74ae 100644 --- a/buildcc/lib/target/src/target/friend/compile_object.cpp +++ b/buildcc/lib/target/src/target/friend/compile_object.cpp @@ -50,7 +50,7 @@ void CompileObject::CacheCompileCommands() { const std::string selected_aggregated_compile_flags = target_.SelectCompileFlags(type).value_or(""); const std::string selected_compiler = - target_.SelectCompiler(type).value_or(""); + fmt::format("{}", fs::path(target_.SelectCompiler(type).value_or(""))); object_iter.second.command = target_.command_.Construct( target_.GetConfig().compile_command, { diff --git a/buildcc/lib/target/src/target/friend/compile_pch.cpp b/buildcc/lib/target/src/target/friend/compile_pch.cpp index 4914e856..23767692 100644 --- a/buildcc/lib/target/src/target/friend/compile_pch.cpp +++ b/buildcc/lib/target/src/target/friend/compile_pch.cpp @@ -136,9 +136,10 @@ fs::path CompilePch::ConstructObjectPath() const { } std::string CompilePch::ConstructCompileCommand() const { - const std::string compiler = target_.GetState().contains_cpp - ? target_.GetToolchain().GetCppCompiler() - : target_.GetToolchain().GetCCompiler(); + std::string compiler = target_.GetState().contains_cpp + ? target_.GetToolchain().GetCppCompiler() + : target_.GetToolchain().GetCCompiler(); + compiler = fmt::format("{}", fs::path(compiler)); const TargetFileExt file_ext_type = target_.GetState().contains_cpp ? TargetFileExt::Cpp : TargetFileExt::C; const std::string compile_flags = diff --git a/buildcc/targets/include/targets/target_generic.h b/buildcc/targets/include/targets/target_generic.h index efefb7a7..0d5d5ed0 100644 --- a/buildcc/targets/include/targets/target_generic.h +++ b/buildcc/targets/include/targets/target_generic.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 Niket Naidu. All rights reserved. + * 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. @@ -21,9 +21,11 @@ #include #include "target/target.h" +#include "toolchain/toolchain.h" + #include "target_gcc.h" +#include "target_mingw.h" #include "target_msvc.h" -#include "toolchain/toolchain.h" namespace buildcc { @@ -76,8 +78,10 @@ class GenericConfig : ConfigInterface { case ToolchainId::Msvc: config = MsvcConfig::Executable(); break; - case ToolchainId::Clang: case ToolchainId::MinGW: + config = MingwConfig::Executable(); + break; + case ToolchainId::Clang: default: env::assert_fatal("Compiler ID not supported"); break; @@ -95,8 +99,10 @@ class GenericConfig : ConfigInterface { case ToolchainId::Msvc: config = MsvcConfig::StaticLib(); break; - case ToolchainId::Clang: case ToolchainId::MinGW: + config = MingwConfig::StaticLib(); + break; + case ToolchainId::Clang: default: env::assert_fatal("Compiler ID not supported"); break; @@ -114,8 +120,10 @@ class GenericConfig : ConfigInterface { case ToolchainId::Msvc: config = MsvcConfig::DynamicLib(); break; - case ToolchainId::Clang: case ToolchainId::MinGW: + config = MingwConfig::DynamicLib(); + break; + case ToolchainId::Clang: default: env::assert_fatal("Compiler ID not supported"); break; @@ -139,8 +147,10 @@ class ExecutableTarget_generic : public BaseTarget { case ToolchainId::Msvc: Copy(ExecutableTarget_msvc(name, toolchain, env), kGenericCopyOptions); break; - case ToolchainId::Clang: case ToolchainId::MinGW: + Copy(ExecutableTarget_mingw(name, toolchain, env), kGenericCopyOptions); + break; + case ToolchainId::Clang: default: env::assert_fatal("Compiler ID not supported"); break; @@ -163,8 +173,10 @@ class StaticTarget_generic : public BaseTarget { case ToolchainId::Msvc: Copy(StaticTarget_msvc(name, toolchain, env), kGenericCopyOptions); break; - case ToolchainId::Clang: case ToolchainId::MinGW: + Copy(StaticTarget_mingw(name, toolchain, env), kGenericCopyOptions); + break; + case ToolchainId::Clang: default: env::assert_fatal("Compiler ID not supported"); break; @@ -186,8 +198,10 @@ class DynamicTarget_generic : public BaseTarget { case ToolchainId::Msvc: Copy(DynamicTarget_msvc(name, toolchain, env), kGenericCopyOptions); break; - case ToolchainId::Clang: case ToolchainId::MinGW: + Copy(DynamicTarget_mingw(name, toolchain, env), kGenericCopyOptions); + break; + case ToolchainId::Clang: default: env::assert_fatal("Compiler ID not supported"); break; @@ -208,7 +222,6 @@ class Target_generic : public BaseTarget { Copy(ExecutableTarget_generic(name, toolchain, env), kGenericCopyOptions); break; case TargetType::StaticLibrary: - Copy(StaticTarget_generic(name, toolchain, env), kGenericCopyOptions); break; case TargetType::DynamicLibrary: diff --git a/buildcc/targets/include/targets/target_mingw.h b/buildcc/targets/include/targets/target_mingw.h index f2326229..44f93720 100644 --- a/buildcc/targets/include/targets/target_mingw.h +++ b/buildcc/targets/include/targets/target_mingw.h @@ -41,6 +41,8 @@ class MingwConfig : ConfigInterface { kGccExecutableLinkCommand); } + static TargetConfig StaticLib() { return GccConfig::StaticLib(); } + static TargetConfig DynamicLib() { return DefaultMingwConfig(kMingwDynamicLibExt, kGccGenericCompileCommand, kMingwDynamicLibLinkCommand); diff --git a/buildexe/CMakeLists.txt b/buildexe/CMakeLists.txt index 9e1f9ea2..51ba908c 100644 --- a/buildexe/CMakeLists.txt +++ b/buildexe/CMakeLists.txt @@ -1,5 +1,14 @@ add_executable(buildexe buildexe.cpp + + src/args_setup.cpp + include/buildexe/args_setup.h + + src/toolchain_setup.cpp + include/buildexe/toolchain_setup.h + + src/build_env_setup.cpp + include/buildexe/build_env_setup.h ) target_sources(buildexe PRIVATE ../bootstrap/src/build_buildcc.cpp @@ -11,6 +20,7 @@ target_sources(buildexe PRIVATE ../bootstrap/src/build_tpl.cpp ) target_include_directories(buildexe PRIVATE + include ../bootstrap/include ) target_link_libraries(buildexe PRIVATE buildcc) diff --git a/buildexe/buildexe.cpp b/buildexe/buildexe.cpp index 36738ead..1c4aff44 100644 --- a/buildexe/buildexe.cpp +++ b/buildexe/buildexe.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2021 Niket Naidu. All rights reserved. + * 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. @@ -16,6 +16,10 @@ #include "buildcc.h" +#include "buildexe/args_setup.h" +#include "buildexe/build_env_setup.h" +#include "buildexe/toolchain_setup.h" + #include "bootstrap/build_buildcc.h" #include "bootstrap/build_cli11.h" #include "bootstrap/build_flatbuffers.h" @@ -28,81 +32,16 @@ using namespace buildcc; constexpr const char *const kTag = "BuildExe"; -enum class BuildExeMode { - Immediate, - Script, -}; - -struct ArgTargetInfo { - std::string name; - TargetType type; - fs::path relative_to_root; -}; - -struct ArgTargetInputs { - // Sources - std::vector source_files; - std::vector include_dirs; - - // External libs - std::vector lib_dirs; - std::vector external_lib_deps; - - // Flags - std::vector preprocessor_flags; - std::vector common_compile_flags; - std::vector asm_compile_flags; - std::vector c_compile_flags; - std::vector cpp_compile_flags; - std::vector link_flags; -}; - -struct ArgScriptInfo { - std::vector configs; -}; - -static const std::unordered_map kTargetTypeMap{ - {"executable", TargetType::Executable}, - {"staticLibrary", TargetType::StaticLibrary}, - {"dynamicLibrary", TargetType::DynamicLibrary}, -}; - -static const std::unordered_map kBuildExeModeMap{ - {"immediate", BuildExeMode::Immediate}, - {"script", BuildExeMode::Script}, -}; - static void clean_cb(); -static void setup_arg_target_info(Args &args, ArgTargetInfo &out); -static void setup_arg_target_inputs(Args &args, ArgTargetInputs &out); -static void setup_arg_script_mode(Args &args, ArgScriptInfo &out); - -static void host_toolchain_verify(const BaseToolchain &toolchain); - -static fs::path get_env_buildcc_home(); - -static void user_output_target_cb(BaseTarget &target, - const ArgTargetInputs &inputs); - -// TODO, Add BuildExeMode::Script usage -// TODO, Refactor magic strings int main(int argc, char **argv) { Args args; - ArgToolchain custom_toolchain_arg; - args.AddToolchain("custom", "Host Toolchain", custom_toolchain_arg); - - // TODO, Add Verification subcommand here for OS, Compiler etc! - // os win, linux considerations - // compiler gcc, msvc considerations - // arch considerations + ArgToolchain host_toolchain_arg; + args.AddToolchain("host", "Host Toolchain", host_toolchain_arg); - BuildExeMode mode; - args.Ref() - .add_option("--mode", mode, "Provide BuildExe run mode") - ->transform(CLI::CheckedTransformer(kBuildExeModeMap, CLI::ignore_case)) - ->required(); + BuildExeMode out_mode; + setup_arg_buildexe_mode(args, out_mode); ArgTargetInfo out_targetinfo; setup_arg_target_info(args, out_targetinfo); @@ -113,120 +52,48 @@ int main(int argc, char **argv) { ArgScriptInfo out_scriptinfo; setup_arg_script_mode(args, out_scriptinfo); - // script mode specific arguments + args.Parse(argc, argv); + + // TODO, Add Verification subcommand here for OS, Compiler etc! + // os win, linux considerations + // compiler gcc, msvc considerations + // arch considerations // TODO, Add buildcc (git cloned) // TODO, Add libraries (git cloned) // TODO, Add extension (git cloned) - args.Parse(argc, argv); - Register reg(args); reg.Clean(clean_cb); // Build - BaseToolchain toolchain = custom_toolchain_arg.ConstructToolchain(); - - // BaseToolchain toolchain = custom_toolchain_arg.ConstructToolchain(); - auto verified_toolchains = toolchain.Verify(); - env::assert_fatal(!verified_toolchains.empty(), - "Toolchain could not be verified. Please input correct " - "Gcc, Msvc, Clang or MinGW toolchain executable names"); - if (verified_toolchains.size() > 1) { - env::log_info( - kTag, - fmt::format( - "Found {} toolchains. By default using the first added" - "toolchain. Modify your environment `PATH` information if you " - "would like compiler precedence when similar compilers are " - "detected in different folders", - verified_toolchains.size())); - } - - // Print - int counter = 1; - for (const auto &vt : verified_toolchains) { - std::string info = fmt::format("{}. : {}", counter, vt.ToString()); - env::log_info("Host Toolchain", info); - counter++; - } - - // TODO, Update Toolchain with VerifiedToolchain - // toolchain.UpdateFrom(verified_toolchain); - - if (mode == BuildExeMode::Script) { + BaseToolchain toolchain = host_toolchain_arg.ConstructToolchain(); + find_toolchain_verify(toolchain); + if (out_mode == BuildExeMode::Script) { host_toolchain_verify(toolchain); } - PersistentStorage storage; - Target_generic user_output_target(out_targetinfo.name, out_targetinfo.type, - toolchain, - TargetEnv(out_targetinfo.relative_to_root)); - if (mode == BuildExeMode::Script) { - // Compile buildcc using the constructed toolchain - fs::path buildcc_home = get_env_buildcc_home(); - auto &buildcc_package = storage.Add( - "BuildccPackage", reg, toolchain, - TargetEnv(buildcc_home / "buildcc", - buildcc_home / "buildcc" / "_build_exe")); - buildcc_package.Setup(custom_toolchain_arg.state); - - // Add buildcc as a dependency to user_output_target - user_output_target.AddLibDep(buildcc_package.GetBuildcc()); - user_output_target.Insert(buildcc_package.GetBuildcc(), - { - SyncOption::PreprocessorFlags, - SyncOption::CppCompileFlags, - SyncOption::IncludeDirs, - SyncOption::LinkFlags, - SyncOption::HeaderFiles, - SyncOption::IncludeDirs, - SyncOption::LibDeps, - SyncOption::ExternalLibDeps, - }); - switch (toolchain.GetId()) { - case ToolchainId::Gcc: - case ToolchainId::MinGW: - user_output_target.AddLinkFlag("-Wl,--allow-multiple-definition"); - break; - default: - break; - } - } - - reg.Build(custom_toolchain_arg.state, user_output_target_cb, - user_output_target, out_targetinputs); - - if (mode == BuildExeMode::Script) { - auto &buildcc_package = storage.Ref("BuildccPackage"); - reg.Dep(user_output_target, buildcc_package.GetBuildcc()); + // Build environment + BuildEnvSetup build_setup(reg, toolchain, out_targetinfo, out_targetinputs); + if (out_mode == BuildExeMode::Script) { + // buildcc and user target + build_setup.ConstructUserTargetWithBuildcc(); + } else { + // user target + build_setup.ConstructUserTarget(); } - - // Runners reg.RunBuild(); // Run - if (mode == BuildExeMode::Script) { - std::vector configs; - for (const auto &c : out_scriptinfo.configs) { - std::string config = fmt::format("--config {}", c); - configs.push_back(config); - } - std::string aggregated_configs = fmt::format("{}", fmt::join(configs, " ")); - - env::Command command; - std::string command_str = command.Construct( - "{executable} {configs}", - { - {"executable", - fmt::format("{}", user_output_target.GetTargetPath())}, - {"configs", aggregated_configs}, - }); - env::Command::Execute(command_str); + if (out_mode == BuildExeMode::Script) { + env::log_info(kTag, + fmt::format("************** Running '{}' **************", + out_targetinfo.name)); + build_setup.RunUserTarget(out_scriptinfo); } // - Clang Compile Commands - plugin::ClangCompileCommands({&user_output_target}).Generate(); + plugin::ClangCompileCommands({&build_setup.GetUserTarget()}).Generate(); return 0; } @@ -235,158 +102,3 @@ static void clean_cb() { env::log_info(kTag, fmt::format("Cleaning {}", env::get_project_build_dir())); fs::remove_all(env::get_project_build_dir()); } - -// TODO, Add subcommand [build.info] -static void setup_arg_target_info(Args &args, ArgTargetInfo &out) { - auto &app = args.Ref(); - - app.add_option("--name", out.name, "Provide Target name")->required(); - - app.add_option("--type", out.type, "Provide Target Type") - ->transform(CLI::CheckedTransformer(kTargetTypeMap, CLI::ignore_case)) - ->required(); - - app.add_option("--relative_to_root", out.relative_to_root, - "Provide Target relative to root") - ->required(); -} - -// TODO, Add subcommand [build.inputs] -// TODO, Add group, group by sources, headers, inncludes on CLI -static void setup_arg_target_inputs(Args &args, ArgTargetInputs &out) { - auto &app = args.Ref(); - - app.add_option("--srcs", out.source_files, "Provide source files"); - app.add_option("--includes", out.include_dirs, "Provide include dirs"); - - app.add_option("--lib_dirs", out.lib_dirs, "Provide lib dirs"); - app.add_option("--external_libs", out.external_lib_deps, - "Provide external libs"); - - app.add_option("--preprocessor_flags", out.preprocessor_flags, - "Provide Preprocessor flags"); - app.add_option("--common_compile_flags", out.common_compile_flags, - "Provide CommonCompile Flags"); - app.add_option("--asm_compile_flags", out.asm_compile_flags, - "Provide AsmCompile Flags"); - app.add_option("--c_compile_flags", out.c_compile_flags, - "Provide CCompile Flags"); - app.add_option("--cpp_compile_flags", out.cpp_compile_flags, - "Provide CppCompile Flags"); - app.add_option("--link_flags", out.link_flags, "Provide Link Flags"); -} - -static void setup_arg_script_mode(Args &args, ArgScriptInfo &out) { - auto *script_args = args.Ref().add_subcommand("script"); - script_args->add_option("--configs", out.configs, - "Config files for script mode"); -} - -static void host_toolchain_verify(const BaseToolchain &toolchain) { - env::log_info(kTag, "*** Starting Toolchain verification ***"); - - fs::path file = env::get_project_build_dir() / "verify_host_toolchain" / - "verify_host_toolchain.cpp"; - fs::create_directories(file.parent_path()); - std::string file_data = R"(// Generated by BuildExe -#include -#include - -namespace fs = std::filesystem; - -int main() { - std::cout << "Verifying host toolchain" << std::endl; - std::cout << "Current Path: " << fs::current_path() << std::endl; - return 0; -})"; - env::save_file(path_as_string(file).c_str(), file_data, false); - - ExecutableTarget_generic target( - "verify", toolchain, TargetEnv(file.parent_path(), file.parent_path())); - - target.AddSource(file); - switch (toolchain.GetId()) { - case ToolchainId::Gcc: - case ToolchainId::MinGW: - target.AddCppCompileFlag("-std=c++17"); - break; - case ToolchainId::Msvc: - target.AddCppCompileFlag("/std:c++17"); - break; - default: - env::assert_fatal("Invalid Compiler Id"); - } - target.Build(); - - // Build - tf::Executor executor; - executor.run(target.GetTaskflow()); - executor.wait_for_all(); - env::assert_fatal(env::get_task_state() == env::TaskState::SUCCESS, - "Input toolchain could not compile host program. " - "Requires HOST toolchain"); - - // Run - bool execute = env::Command::Execute(fmt::format( - "{executable}", fmt::arg("executable", target.GetTargetPath().string()))); - env::assert_fatal(execute, "Could not execute verification target"); - env::log_info(kTag, "*** Toolchain verification done ***"); -} - -static fs::path get_env_buildcc_home() { - const char *buildcc_home = getenv("BUILDCC_HOME"); - env::assert_fatal(buildcc_home != nullptr, - "BUILDCC_HOME environment variable not defined"); - - // NOTE, Verify BUILDCC_HOME - // auto &buildcc_path = storage.Add("buildcc_path", buildcc_home); - fs::path buildcc_home_path{buildcc_home}; - env::assert_fatal(fs::exists(buildcc_home_path), - "{BUILDCC_HOME} path not found path not found"); - env::assert_fatal(fs::exists(buildcc_home_path / "buildcc"), - "{BUILDCC_HOME}/buildcc path not found"); - env::assert_fatal(fs::exists(buildcc_home_path / "libs"), - "{BUILDCC_HOME}/libs path not found"); - env::assert_fatal(fs::exists(buildcc_home_path / "extensions"), - "{BUILDCC_HOME}/extensions path not found"); - - return buildcc_home_path; -} - -static void user_output_target_cb(BaseTarget &target, - const ArgTargetInputs &inputs) { - for (const auto &s : inputs.source_files) { - target.AddSource(s); - } - for (const auto &i : inputs.include_dirs) { - target.AddIncludeDir(i); - } - - for (const auto &l : inputs.lib_dirs) { - target.AddLibDir(l); - } - for (const auto &el : inputs.external_lib_deps) { - target.AddLibDep(el); - } - - for (const auto &flag : inputs.preprocessor_flags) { - target.AddPreprocessorFlag(flag); - } - for (const auto &flag : inputs.common_compile_flags) { - target.AddCommonCompileFlag(flag); - } - for (const auto &flag : inputs.asm_compile_flags) { - target.AddAsmCompileFlag(flag); - } - for (const auto &flag : inputs.c_compile_flags) { - target.AddCCompileFlag(flag); - } - for (const auto &flag : inputs.cpp_compile_flags) { - target.AddCppCompileFlag(flag); - } - for (const auto &flag : inputs.link_flags) { - target.AddLinkFlag(flag); - } - - target.Build(); -} diff --git a/buildexe/include/buildexe/args_setup.h b/buildexe/include/buildexe/args_setup.h new file mode 100644 index 00000000..d511a116 --- /dev/null +++ b/buildexe/include/buildexe/args_setup.h @@ -0,0 +1,64 @@ +/* + * 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 BUILDEXE_ARGS_SETUP_H_ +#define BUILDEXE_ARGS_SETUP_H_ + +#include "buildcc.h" + +namespace buildcc { + +enum class BuildExeMode { + Immediate, + Script, +}; + +struct ArgTargetInfo { + std::string name; + TargetType type; + fs::path relative_to_root; +}; + +struct ArgTargetInputs { + // Sources + std::vector source_files; + std::vector include_dirs; + + // External libs + std::vector lib_dirs; + std::vector external_lib_deps; + + // Flags + std::vector preprocessor_flags; + std::vector common_compile_flags; + std::vector asm_compile_flags; + std::vector c_compile_flags; + std::vector cpp_compile_flags; + std::vector link_flags; +}; + +struct ArgScriptInfo { + std::vector configs; +}; + +void setup_arg_buildexe_mode(Args &args, BuildExeMode &out); +void setup_arg_target_info(Args &args, ArgTargetInfo &out); +void setup_arg_target_inputs(Args &args, ArgTargetInputs &out); +void setup_arg_script_mode(Args &args, ArgScriptInfo &out); + +} // namespace buildcc + +#endif diff --git a/buildexe/include/buildexe/build_env_setup.h b/buildexe/include/buildexe/build_env_setup.h new file mode 100644 index 00000000..4cc219d5 --- /dev/null +++ b/buildexe/include/buildexe/build_env_setup.h @@ -0,0 +1,75 @@ +/* + * 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 BUILDEXE_BUILD_ENV_SETUP_H_ +#define BUILDEXE_BUILD_ENV_SETUP_H_ + +#include "buildcc.h" + +#include "bootstrap/build_buildcc.h" +#include "buildexe/args_setup.h" + +namespace buildcc { + +class BuildEnvSetup { +public: + static constexpr const char *const kBuildccPackageName = "BuildccPackage"; + static constexpr const char *const kUserTargetName = "UserTarget"; + +public: + BuildEnvSetup(Register ®, const BaseToolchain &toolchain, + const ArgTargetInfo &arg_target_info, + const ArgTargetInputs &arg_target_inputs) + : reg_(reg), toolchain_(toolchain), arg_target_info_(arg_target_info), + arg_target_inputs_(arg_target_inputs) { + state_.build = true; + } + + void ConstructUserTarget(); + void ConstructUserTargetWithBuildcc(); + + void RunUserTarget(const ArgScriptInfo &arg_script_info); + + // Getters + StaticTarget_generic &GetBuildcc() { + return storage_.Ref(kBuildccPackageName).GetBuildcc(); + } + Target_generic &GetUserTarget() { + return storage_.Ref(kUserTargetName); + } + +private: + void BuildccTargetSetup(); + void UserTargetSetup(); + void UserTargetCb(); + void UserTargetBuild(); + + void UserTargetWithBuildccSetup(); + void DepUserTargetOnBuildcc(); + +private: + Register ®_; + const BaseToolchain &toolchain_; + const ArgTargetInfo &arg_target_info_; + const ArgTargetInputs &arg_target_inputs_; + + ArgToolchainState state_; + PersistentStorage storage_; +}; + +} // namespace buildcc + +#endif diff --git a/buildexe/include/buildexe/toolchain_setup.h b/buildexe/include/buildexe/toolchain_setup.h new file mode 100644 index 00000000..423bbbf4 --- /dev/null +++ b/buildexe/include/buildexe/toolchain_setup.h @@ -0,0 +1,29 @@ +/* + * 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 BUILDEXE_TOOLCHAIN_SETUP_H_ +#define BUILDEXE_TOOLCHAIN_SETUP_H_ + +#include "buildcc.h" + +namespace buildcc { + +void find_toolchain_verify(BaseToolchain &toolchain); +void host_toolchain_verify(const BaseToolchain &toolchain); + +} // namespace buildcc + +#endif diff --git a/buildexe/src/args_setup.cpp b/buildexe/src/args_setup.cpp new file mode 100644 index 00000000..c69c9be6 --- /dev/null +++ b/buildexe/src/args_setup.cpp @@ -0,0 +1,97 @@ +/* + * 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 "buildexe/args_setup.h" + +namespace buildcc { + +static const std::unordered_map kBuildExeModeMap{ + {"immediate", BuildExeMode::Immediate}, + {"script", BuildExeMode::Script}, +}; + +static const std::unordered_map kTargetTypeMap{ + {"executable", TargetType::Executable}, + {"staticLibrary", TargetType::StaticLibrary}, + {"dynamicLibrary", TargetType::DynamicLibrary}, +}; + +void setup_arg_buildexe_mode(Args &args, BuildExeMode &out) { + args.Ref() + .add_option("--mode", out, "Provide BuildExe run mode") + ->transform(CLI::CheckedTransformer(kBuildExeModeMap, CLI::ignore_case)) + ->required(); +} + +// TODO, Add subcommand [build.info] +void setup_arg_target_info(Args &args, ArgTargetInfo &out) { + constexpr const char *const kProjectInfo = "Project Info"; + auto &app = args.Ref(); + + auto *project_info_app = app.add_option_group(kProjectInfo); + + project_info_app->add_option("--name", out.name, "Provide Target name") + ->required(); + + project_info_app->add_option("--type", out.type, "Provide Target Type") + ->transform(CLI::CheckedTransformer(kTargetTypeMap, CLI::ignore_case)) + ->required(); + + project_info_app + ->add_option("--relative_to_root", out.relative_to_root, + "Provide Target relative to root") + ->required(); +} + +// TODO, Add subcommand [build.inputs] +// TODO, Add group, group by sources, headers, inncludes on CLI +void setup_arg_target_inputs(Args &args, ArgTargetInputs &out) { + constexpr const char *const kTargetInputs = "Target Inputs"; + auto &app = args.Ref(); + + auto *target_inputs_app = app.add_option_group(kTargetInputs); + + target_inputs_app->add_option("--srcs", out.source_files, + "Provide source files"); + target_inputs_app->add_option("--includes", out.include_dirs, + "Provide include dirs"); + + target_inputs_app->add_option("--lib_dirs", out.lib_dirs, "Provide lib dirs"); + target_inputs_app->add_option("--external_libs", out.external_lib_deps, + "Provide external libs"); + + target_inputs_app->add_option("--preprocessor_flags", out.preprocessor_flags, + "Provide Preprocessor flags"); + target_inputs_app->add_option("--common_compile_flags", + out.common_compile_flags, + "Provide CommonCompile Flags"); + target_inputs_app->add_option("--asm_compile_flags", out.asm_compile_flags, + "Provide AsmCompile Flags"); + target_inputs_app->add_option("--c_compile_flags", out.c_compile_flags, + "Provide CCompile Flags"); + target_inputs_app->add_option("--cpp_compile_flags", out.cpp_compile_flags, + "Provide CppCompile Flags"); + target_inputs_app->add_option("--link_flags", out.link_flags, + "Provide Link Flags"); +} + +void setup_arg_script_mode(Args &args, ArgScriptInfo &out) { + auto *script_args = args.Ref().add_subcommand("script"); + script_args->add_option("--configs", out.configs, + "Config files for script mode"); +} + +} // namespace buildcc diff --git a/buildexe/src/build_env_setup.cpp b/buildexe/src/build_env_setup.cpp new file mode 100644 index 00000000..1c65d8c1 --- /dev/null +++ b/buildexe/src/build_env_setup.cpp @@ -0,0 +1,171 @@ +/* + * 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 "buildexe/build_env_setup.h" + +namespace buildcc { + +static fs::path get_env_buildcc_home() { + const char *buildcc_home = getenv("BUILDCC_HOME"); + env::assert_fatal(buildcc_home != nullptr, + "BUILDCC_HOME environment variable not defined"); + + // NOTE, Verify BUILDCC_HOME + // auto &buildcc_path = storage.Add("buildcc_path", buildcc_home); + fs::path buildcc_home_path{buildcc_home}; + env::assert_fatal(fs::exists(buildcc_home_path), + "{BUILDCC_HOME} path not found"); + env::assert_fatal(fs::exists(buildcc_home_path / "buildcc"), + "{BUILDCC_HOME}/buildcc path not found"); + env::assert_fatal(fs::exists(buildcc_home_path / "libs"), + "{BUILDCC_HOME}/libs path not found"); + env::assert_fatal(fs::exists(buildcc_home_path / "extensions"), + "{BUILDCC_HOME}/extensions path not found"); + + return buildcc_home_path; +} + +void BuildEnvSetup::ConstructUserTarget() { + UserTargetSetup(); + UserTargetCb(); + UserTargetBuild(); +} + +void BuildEnvSetup::ConstructUserTargetWithBuildcc() { + BuildccTargetSetup(); + UserTargetSetup(); + UserTargetCb(); + UserTargetWithBuildccSetup(); + UserTargetBuild(); + DepUserTargetOnBuildcc(); +} + +void BuildEnvSetup::RunUserTarget(const ArgScriptInfo &arg_script_info) { + // Aggregate the different input build .toml files to + // `--config .toml` files + std::vector configs; + std::transform(arg_script_info.configs.begin(), arg_script_info.configs.end(), + std::back_inserter(configs), + [](const std::string &c) -> std::string { + return fmt::format("--config {}", c); + }); + std::string aggregated_configs = fmt::format("{}", fmt::join(configs, " ")); + + // Construct and execute with user target on subprocess + std::string command_str = + fmt::format("{executable} {configs}", + fmt::arg("executable", + fmt::format("{}", GetUserTarget().GetTargetPath())), + fmt::arg("configs", aggregated_configs)); + env::Command::Execute(command_str); +} + +// Private + +void BuildEnvSetup::DepUserTargetOnBuildcc() { + reg_.Dep(GetUserTarget(), GetBuildcc()); +} + +void BuildEnvSetup::BuildccTargetSetup() { + fs::path buildcc_home = get_env_buildcc_home(); + auto &buildcc_package = storage_.Add( + kBuildccPackageName, reg_, toolchain_, + TargetEnv(buildcc_home / "buildcc", + buildcc_home / "buildcc" / "_build_exe")); + buildcc_package.Setup(state_); +} + +void BuildEnvSetup::UserTargetSetup() { + storage_.Add(kUserTargetName, arg_target_info_.name, + arg_target_info_.type, toolchain_, + TargetEnv(arg_target_info_.relative_to_root)); +} + +/** + * @brief Adds from Arg Target Inputs + * + * Source files + * Include Dirs + * Lib Dirs + * External Lib Deps + * Preprocessor flags + * Common Compile flags + * Asm Compile flags + * C Compile flags + * Cpp Compile flags + * Link flags + */ +void BuildEnvSetup::UserTargetCb() { + Target_generic &user_target = GetUserTarget(); + for (const auto &s : arg_target_inputs_.source_files) { + user_target.AddSource(s); + } + for (const auto &i : arg_target_inputs_.include_dirs) { + user_target.AddIncludeDir(i); + } + for (const auto &l : arg_target_inputs_.lib_dirs) { + user_target.AddLibDir(l); + } + for (const auto &el : arg_target_inputs_.external_lib_deps) { + user_target.AddLibDep(el); + } + for (const auto &flag : arg_target_inputs_.preprocessor_flags) { + user_target.AddPreprocessorFlag(flag); + } + for (const auto &flag : arg_target_inputs_.common_compile_flags) { + user_target.AddCommonCompileFlag(flag); + } + for (const auto &flag : arg_target_inputs_.asm_compile_flags) { + user_target.AddAsmCompileFlag(flag); + } + for (const auto &flag : arg_target_inputs_.c_compile_flags) { + user_target.AddCCompileFlag(flag); + } + for (const auto &flag : arg_target_inputs_.cpp_compile_flags) { + user_target.AddCppCompileFlag(flag); + } + for (const auto &flag : arg_target_inputs_.link_flags) { + user_target.AddLinkFlag(flag); + } +} + +void BuildEnvSetup::UserTargetBuild() { + reg_.Build( + state_, [](BaseTarget &target) { target.Build(); }, GetUserTarget()); +} + +void BuildEnvSetup::UserTargetWithBuildccSetup() { + GetUserTarget().AddLibDep(GetBuildcc()); + GetUserTarget().Insert(GetBuildcc(), { + SyncOption::PreprocessorFlags, + SyncOption::CppCompileFlags, + SyncOption::IncludeDirs, + SyncOption::LinkFlags, + SyncOption::HeaderFiles, + SyncOption::IncludeDirs, + SyncOption::LibDeps, + SyncOption::ExternalLibDeps, + }); + switch (GetUserTarget().GetToolchain().GetId()) { + case ToolchainId::MinGW: + GetUserTarget().AddLinkFlag("-Wl,--allow-multiple-definition"); + break; + default: + break; + } +} + +} // namespace buildcc diff --git a/buildexe/src/toolchain_setup.cpp b/buildexe/src/toolchain_setup.cpp new file mode 100644 index 00000000..e9bfe0e1 --- /dev/null +++ b/buildexe/src/toolchain_setup.cpp @@ -0,0 +1,104 @@ +/* + * 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. + */ + +namespace { + +constexpr const char *const kTag = "BuildExe"; + +} + +namespace buildcc { + +void find_toolchain_verify(BaseToolchain &toolchain) { + auto verified_toolchains = toolchain.Verify(); + env::assert_fatal(!verified_toolchains.empty(), + "Toolchain could not be verified. Please input correct " + "Gcc, Msvc, Clang or MinGW toolchain executable names"); + if (verified_toolchains.size() > 1) { + env::log_info( + kTag, + fmt::format( + "Found {} toolchains. By default using the first added" + "toolchain. Modify your environment `PATH` information if you " + "would like compiler precedence when similar compilers are " + "detected in different folders", + verified_toolchains.size())); + } + + // Print + int counter = 1; + for (const auto &vt : verified_toolchains) { + std::string info = fmt::format("{}. : {}", counter, vt.ToString()); + env::log_info("Host Toolchain", info); + counter++; + } +} + +void host_toolchain_verify(const BaseToolchain &toolchain) { + env::log_info(kTag, "*** Starting Toolchain verification ***"); + + fs::path file = env::get_project_build_dir() / "verify_host_toolchain" / + "verify_host_toolchain.cpp"; + fs::create_directories(file.parent_path()); + std::string file_data = R"(// Generated by BuildExe +#include +#include + +namespace fs = std::filesystem; + +int main() { + std::cout << "********************" << std::endl; + std::cout << "Verifying host toolchain" << std::endl; + std::cout << "Current Path: " << fs::current_path() << std::endl; + std::cout << "********************" << std::endl; + return 0; +})"; + env::save_file(path_as_string(file).c_str(), file_data, false); + + ExecutableTarget_generic target( + "verify", toolchain, TargetEnv(file.parent_path(), file.parent_path())); + + target.AddSource(file); + switch (toolchain.GetId()) { + case ToolchainId::Gcc: + case ToolchainId::MinGW: + target.AddCppCompileFlag("-std=c++17"); + break; + case ToolchainId::Msvc: + target.AddCppCompileFlag("/std:c++17"); + break; + default: + env::assert_fatal("Invalid Compiler Id"); + } + target.Build(); + + // Build + tf::Executor executor; + executor.run(target.GetTaskflow()); + executor.wait_for_all(); + env::assert_fatal(env::get_task_state() == env::TaskState::SUCCESS, + "Input toolchain could not compile host program. " + "Requires HOST toolchain"); + + // Run + bool execute = env::Command::Execute(fmt::format( + "{executable}", fmt::arg("executable", target.GetTargetPath().string()))); + env::assert_fatal(execute, "Could not execute verification target"); + + env::log_info(kTag, "*** Toolchain verification done ***"); +} + +} // namespace buildcc diff --git a/docs/source/getting_started/all_compile_options.rst b/docs/source/getting_started/all_compile_options.rst new file mode 100644 index 00000000..cfcad3d7 --- /dev/null +++ b/docs/source/getting_started/all_compile_options.rst @@ -0,0 +1,115 @@ +Compile Options for BuildExe +============================ + +We can pass in configuration parameters through the Command Line but writing them inside a ``.toml`` file and passing it through the ``--config`` flag is much easier. + +Command Line options +--------------------- + +.. code-block:: shell + + Options: + -h,--help Print this help message and exit + --help-all Expand individual options. + --config Read .toml files. + --mode ENUM:value in {script->1,immediate->0} OR {1,0} REQUIRED + Provide BuildExe run mode + [Option Group: Root] + Options: + --clean Clean artifacts + --loglevel ENUM:value in {warning->3,info->2,debug->1,critical->5,trace->0} OR {3,2,1,5,0} + LogLevel settings + --root_dir TEXT REQUIRED Project root directory (relative to current directory) + --build_dir TEXT REQUIRED Project build dir (relative to current directory) + [Option Group: Project Info] + Options: + --name TEXT REQUIRED Provide Target name + --type ENUM:value in {dynamicLibrary->2,staticLibrary->1,executable->0} OR {2,1,0} REQUIRED + Provide Target Type + --relative_to_root TEXT REQUIRED + Provide Target relative to root + [Option Group: Target Inputs] + Options: + --srcs TEXT ... Provide source files + --includes TEXT ... Provide include dirs + --lib_dirs TEXT ... Provide lib dirs + --external_libs TEXT ... Provide external libs + --preprocessor_flags TEXT ... + Provide Preprocessor flags + --common_compile_flags TEXT ... + Provide CommonCompile Flags + --asm_compile_flags TEXT ... + Provide AsmCompile Flags + --c_compile_flags TEXT ... Provide CCompile Flags + --cpp_compile_flags TEXT ... + Provide CppCompile Flags + --link_flags TEXT ... Provide Link Flags + + Subcommands: + toolchain + Select Toolchain + Supported Toolchains: + host Host Toolchain + + target + Select Target + + script + Options: + --configs TEXT ... Config files for script mode + +TOML file options +------------------- + +Relate the options below with the **Command Line options** above. + +You can also read the `CLI11 README `_ + +.. code-block:: toml + + # Default (ungrouped) Options + mode = "script" # REQUIRED script, immediate + + # Root Options + clean = true # true, false + loglevel = "trace" # "trace", "debug", "info", "warning", "critical" + root_dir = "" # REQUIRED + build_dir = "" # REQUIRED + + # Target Info Options + name = "" # REQUIRED + type = "executable" # REQUIRED, executable, staticLibrary, dynamicLibrary + relative_to_root = "" # REQUIRED + + # Target Inputs Options + srcs = [""] + includes = [""] + lib_dirs = [""] + external_libs = [""] + preprocessor_flags = [""] + common_compile_flags = [""] + asm_compile_flags = [""] + c_compile_flags = [""] + cpp_compile_flags = [""] + link_flags = [""] + + # Subcommand + + # Host Toolchain Options + [toolchain.host] # ALWAYS + build = true # ALWAYS + test = false # ALWAYS + + id = "gcc" + name = "x86_64-linux-gnu" + asm_compiler = "as" + c_compiler = "gcc" + cpp_compiler = "g++" + archiver = "ar" + linker = "ld" + + # TODO, Add more options to narrow down search when multiple toolchains are installed + + # Script Options + [script] + configs = ["build.toml", "custom_toolchain.toml"] # Converted to --config build.toml --config custom_toolchain.toml diff --git a/docs/source/getting_started/all_default_build_options.rst b/docs/source/getting_started/all_default_build_options.rst new file mode 100644 index 00000000..4d17c8e0 --- /dev/null +++ b/docs/source/getting_started/all_default_build_options.rst @@ -0,0 +1,78 @@ +Build Options for "scripts" +============================ + +We can pass in configuration parameters through the Command Line but writing them inside a ``.toml`` file and passing it through the ``--config`` flag is much easier. + +Command Line options +--------------------- + +.. code-block:: shell + + Options: + -h,--help Print this help message and exit + --help-all Expand individual options. + --config Read .toml files. + [Option Group: Root] + Options: + --clean Clean artifacts + --loglevel ENUM:value in {warning->3,info->2,debug->1,critical->5,trace->0} OR {3,2,1,5,0} + LogLevel settings + --root_dir TEXT REQUIRED Project root directory (relative to current directory) + --build_dir TEXT REQUIRED Project build dir (relative to current directory) + + Subcommands: + toolchain + Select Toolchain + Supported Toolchains: + gcc Generic gcc toolchain + + target + Select Target + +TOML file options +------------------- + +Relate the options below with the **Command Line options** above. + +You can also read the `CLI11 README `_ + +.. code-block:: toml + + # Root Options + clean = true # true, false + loglevel = "trace" # "trace", "debug", "info", "warning", "critical" + root_dir = "" # REQUIRED + build_dir = "" # REQUIRED + + # Subcommand + + # Host Toolchain Options + [toolchain.gcc] # DEPENDS on user + + # Run time way to select your build and test options during registration + # Valid options + # build = false, test = false, target not built or tested + # build = true, test = false, target built but not tested + # build = true, test = true, target built and tested (users responsiblity for a testable target) + build = true # REQUIRED + test = true # REQUIRED + + # Run time way to change the compiler on the fly + # Not recommended + # Prefer to use the specialized Toolchains during Compile time (See build.cpp in examples) + # id = "gcc" + # name = "x86_64-linux-gnu" + # asm_compiler = "as" + # c_compiler = "gcc" + # cpp_compiler = "g++" + # archiver = "ar" + # linker = "ld" + + # TODO, Add more options to narrow down search when multiple toolchains are installed + + +.. note:: These are the default build options during "script" mode. + + Users can also add custom arguments using CLI11 using the ``.Ref()`` API and using them in the ``.toml`` file. + + Please make sure to read the `CLI11 README `_ for those APIs. diff --git a/docs/source/getting_started/buildexe_immediate_example.rst b/docs/source/getting_started/buildexe_immediate_example.rst new file mode 100644 index 00000000..9b0e882b --- /dev/null +++ b/docs/source/getting_started/buildexe_immediate_example.rst @@ -0,0 +1,94 @@ +BuildExe "Immediate" example +============================= + +Basic Procedure +---------------- + +BuildExe has an "immediate" mode where it can directly provide us the Target (singular) without going through the intermediate steps that we followed in the "script" mode. + +.. uml:: + + usecase "main.cpp" as main_cpp + usecase "compile.toml" as compile_toml + usecase "host_or_cross_toolchain.toml" as host_or_cross_toolchain + + rectangle "./buildexe" as buildexe_exe + artifact "./hello_world" as hello_world_exe + + main_cpp -right-> buildexe_exe + compile_toml -up-> buildexe_exe + host_or_cross_toolchain -up-> buildexe_exe + buildexe_exe -right-> hello_world_exe + + +What is the point of the "script" mode then? +++++++++++++++++++++++++++++++++++++++++++++ + +The "immediate" mode has a lot of limitations but it is also useful in certain scenarios + +**Limitations** + +* Cannot build more than one target at a time +* No customizability allowed. + * Which means that apart from just building the target you cannot do anything else. + * For example: Setting dependencies between targets, running custom generators, running static analysis tools and so on. + +**Usecase** + +* Simple way to build one target. +* Completely run time dependent. Change your ``build.toml`` file and you can build a new target. +* Very easy to know how a particular target is built. + * For example. In a large project it might be very hard to visualize how a single target is built due to various code generation and library / target dependencies. + * Since .toml is easily readable, we can understand the sources, search directories and flags that the target requires at a glance. +* Can be shipped to customers for a pain free build process i.e removes technical debt. + * Building your artifact is as simple as ``buildexe --config build.toml --config %BUILDCC_HOME/host/host_or_cross_toolchain.toml`` + * build.toml contains the target information. + * host_or_cross_toolchain.toml contains the host/cross toolchain information + * We can combine the two into one .toml file. + + +Helloworld "immediate" example +------------------------------ + +* Write your ``build.toml`` file +* Invoke ``buildexe`` from the command line from the **[workspace]** folder + * Pay attention to the ``root_dir`` and ``build_dir`` parameters set in your ``build.toml`` file. + * These directories are relative to the directory from which you **invoke** buildexe + +.. code-block:: bash + + ./buildexe --config build.toml --config $BUILDCC_HOME/host/host_toolchain.toml + +* Your target will now be present in ``[build_dir]/[toolchain_name]/[target_name]`` (taken from ``build.toml``) + +Directory structure +++++++++++++++++++++ + +.. uml:: + + @startmindmap + * [workspace] + ** [src] + *** main.cpp + ** build.toml + @endmindmap + +Write your ``build.toml`` file ++++++++++++++++++++++++++++++++ + +.. code-block:: toml + + # Settings + root_dir = "" + build_dir = "_build" + loglevel = "info" + clean = false + + # BuildExe run mode + mode = "immediate" + + # Target information + name = "hello_world" + type = "executable" + relative_to_root = "src" + srcs = ["main.cpp"] diff --git a/docs/source/getting_started/buildexe_script_example.rst b/docs/source/getting_started/buildexe_script_example.rst new file mode 100644 index 00000000..23a3f211 --- /dev/null +++ b/docs/source/getting_started/buildexe_script_example.rst @@ -0,0 +1,213 @@ +BuildExe "Script" example +============================= + +Basic Procedure +---------------- + +Since we are writing our scripts in C++ we first need to **compile** our "script" to an executable, and then **execute** it to build targets. + +.. uml:: + + usecase "build.helloworld.cpp" as build_cpp + usecase "compile.toml" as compile_toml + usecase "host_toolchain.toml" as host_toolchain_toml + usecase "./build.helloworld" as build_project_exe + usecase "build.toml" as build_toml + + rectangle "./buildexe" as buildexe_exe + artifact "./hello_world" as hello_world_exe + + build_cpp -right-> buildexe_exe + compile_toml -up-> buildexe_exe + host_toolchain_toml -up-> buildexe_exe + buildexe_exe -right-> build_project_exe + build_toml -up-> build_project_exe + build_project_exe -right-> hello_world_exe + + +.. attention:: Limitation of **script** mode + + We need to compile our build "script" using a **HOST** toolchain. + We cannot use a cross compiler here. + +Helloworld "script" example +--------------------------- + +* Write your C++ "script" +* Write your ``compile.toml`` file +* Write your ``build.toml`` file +* Invoke ``buildexe`` from the command line from the **[workspace]** folder + * Pay attention to the ``root_dir`` and ``build_dir`` parameters set in your ``compile.toml`` and ``build.toml`` file. + * These directories are relative to the directory from which you **invoke** buildexe + +.. code-block:: bash + + ./buildexe --config compile.toml --config $BUILDCC_HOME/host/host_toolchain.toml + +* Your target will now be present in ``[build_dir]/[toolchain_name]/[target_name]`` (taken from ``build.toml`` and ``build.helloworld.cpp``) + +Directory structure +++++++++++++++++++++ + +.. uml:: + + @startmindmap + * [workspace] + ** [src] + *** main.cpp + ** build.helloworld.cpp + ** compile.toml + ** build.toml + @endmindmap + +Write your C++ "script" +++++++++++++++++++++++++ + +From the "script" below we can see that we have a few lines of **boilerplate** + +* Setup args +* Setup register (pre and post callback requirements) + +We then setup our main **toolchain**-**target** pairs. Highlighted below + +* Specify your toolchain + * Verify the toolchain existance on your machine by using the ``.Verify`` API + * If multiple similar toolchains are detected (due to multiple installations), the first found toolchain is picked + * You can pass in the ``VerifyToolchainConfig`` to narrow down your search and verification. +* Specify your compatible target + * Every specific target is meant to use a specific target. + * For example: ``ExecutableTarget_gcc`` specialized target can use the ``Toolchain_gcc`` specialized toolchain but not ``Toolchain_msvc``. +* Use the Register ``.Build`` API. We use callbacks here to avoid cluttering our ``int main`` function. + * ``arg_gcc.state`` contains our ``build`` and ``test`` values passed in from ``build.toml`` (see below). The ``.Build`` API conditionally selects the target at run time. + * **IMPORTANT** Please do not forget to invoke the Target ``.Build`` API. This API registers the various ``CompileCommandTasks`` and ``LinkCommandTasks``. + * **IMPORTANT** In line with the above statement, Once the Target ``.Build`` API has been executed (tasks have been registered), do not attempt to add more information to the Targets. Internally the ``.Build`` API locks the target from accepting further input and any attempt to do so will ``std::terminate`` your program (this is by design). + +.. code-block:: cpp + :linenos: + :emphasize-lines: 25,26,27,29,30 + :caption: build.helloworld.cpp + + #include "buildcc.h" + + using namespace buildcc; + + void clean_cb(); + // All specialized targets derive from BaseTarget + void hello_world_build_cb(BaseTarget & target); + + int main(int argc, char ** argv) { + // Step 1. Setup your args + Args args; + ArgToolchain arg_gcc; + args.AddToolchain("gcc", "GCC toolchain", arg_gcc); + args.Parse(argc, argv); + + // Step 2. Register + Register reg(args); + + // Step 3. Pre build steps + // for example. clean your environment + reg.Clean(clean_cb); + + // Step 4. Build steps + // Main setup + Toolchain_gcc gcc; + auto verified_gcc_toolchains = gcc.Verify(); + env::assert_fatal(!verified_gcc_toolchains.empty(), "GCC toolchain not found"); + + ExecutableTarget_gcc hello_world("hello_world", gcc, ""); + reg.Build(arg_gcc.state, hello_world_build_cb, hello_world); + + // Step 5. Build your targets + reg.RunBuild(); + + // Step 6. Post build steps + // for example. clang compile commands database + plugin::ClangCompileCommands({&hello_world}).Generate(); + + return 0; + } + + void clean_cb() { + fs::remove_all(env::get_project_build_dir()); + } + + void hello_world_build_cb(BaseTarget & target) { + // Add your source + target.AddSource("src/main.cpp"); + + // Initializes the target build tasks + target.Build(); + } + +Write your ``compile.toml`` file +++++++++++++++++++++++++++++++++ + +.. code-block:: toml + :linenos: + :caption: compile.toml + + # Settings + root_dir = "" + build_dir = "_build_internal" + loglevel = "info" + clean = false + + # BuildExe run mode + mode = "script" + + # Target information + name = "build.helloworld" + type = "executable" + relative_to_root = "" + srcs = ["build.helloworld.cpp"] + + [script] + configs = ["build.toml"] + +* ``root_dir`` tells BuildExe your project root directory relative from where it is invoked and ``build_dir`` tells BuildExe that the built artifacts should be inserted in this directory relative from where it is invoked. +* ``clean`` deletes your ``build_dir`` completely for a fresh setup. +* ``mode`` consists of **script** and **immediate** mode. See the **Basic Procedure** uml diagrams for a better understanding of the differences and purpose. + * Script Mode: :doc:`buildexe_script_example` + * Immediate Mode: :doc:`buildexe_immediate_example` +* Setup your target information + * ``name`` of your compiled "script" executable + * ``type`` MUST always be **executable** in script mode + * ``relative_to_root`` is a QOL feature to point to a path inside your root where the build "scripts" reside. + * ``srcs`` and equivalent are files that you want to compile. Please see :doc:`all_compile_options` for a full list of target options and inputs for script mode +* [script] submodule + * ``configs`` are .toml files passed to our compiled "script" executable. Please see :doc:`all_default_build_options` for a full list of default build options. + * The values inside ``configs`` are converted to ``--config [file].toml --config [file2].toml`` and so on and passed with the generated executable. + * In this example: ``./build.helloworld --config build.toml`` is run which generates your targets. + +Write your ``build.toml`` file ++++++++++++++++++++++++++++++++ + +.. code-block:: toml + :linenos: + :caption: build.toml + + # Root + root_dir = "" + build_dir = "_build" + loglevel = "debug" + + # Project + clean = false + + # Toolchain + [toolchain.gcc] + build = true + test = false + +* Please see the ``.cpp`` example above and correlate with these options. +* ``root_dir`` tells BuildExe your project root directory relative from where it is invoked and ``build_dir`` tells BuildExe that the built artifacts should be inserted in this directory relative from where it is invoked. +* ``clean`` invokes your ``clean_cb`` which determines how your build must be cleaned. In this example we delete the ``build_dir`` for a fresh setup. + +* [toolchain.gcc] submodule + * This is a nested submodule of ``toolchain`` -> ``gcc`` -> ``--build``, ``--test`` options and so on. + * The naming convention follows ``toolchain.[name]`` provided when using the ``.AddToolchain`` API. + * In our example: ``args.AddToolchain("gcc", "GCC toolchain", arg_gcc);`` + * The ``build`` and ``test`` values are used by the ``Register`` module. + * In our example ``arg_gcc.state.build`` and ``arg_gcc.state.test`` + * **REASONING** The reason why this has been done is because Buildcc allows your to mix multiple toolchains in a single script. We can now conditionally (at run time) choose the toolchains with which we would want to compile our targets. diff --git a/docs/source/getting_started/buildexe_setup.rst b/docs/source/getting_started/buildexe_setup.rst new file mode 100644 index 00000000..dd06ac93 --- /dev/null +++ b/docs/source/getting_started/buildexe_setup.rst @@ -0,0 +1,110 @@ +BuildExe Setup +============== + +ENV[BUILDCC_HOME] +----------------- + +* Add the environment variable ``BUILDCC_HOME`` with the absolute path on the operating system. For example: ``BUILDCC_HOME=C:\buildcc`` or ``BUILDCC_HOME=/local/mnt/buildcc`` +* Create directories **bin**, **extensions**, **libs** and **host** inside your ENV[BUILDCC_HOME] directory + * Download **BuildExe_Win.zip** or **BuildExe_Linux.zip** and unzip the bin file contents into the **bin** folder + * **extensions** and **libs** folder will be empty for the time being +* Update your ``PATH`` variable with the **bin** folder. + * For example: ``PATH += ENV[BUILDCC_HOME]/bin;ENV[PATH]`` + * Linux : ``export PATH="$BUILDCC_HOME/bin:$PATH"`` + * Windows : My Computer -> Properties -> Advanced System Settings -> Environment Variables -> [Update your system variables] + +* Git clone the buildcc project in the ENV[BUILDCC_HOME] directory. + +.. code-block:: bash + + git clone https://github.com/coder137/build_in_cpp.git buildcc + git submodule init + git submodule update + +* To update just do the following + +.. code-block:: bash + + git pull + git submodule init + git submodule update + +* Your ENV[BUILDCC_HOME] directory should look like the following + +.. uml:: + + @startmindmap + * ENV[BUILDCC_HOME] + ** bin + *** flatc + *** buildexe + ** buildcc + *** [git cloned] + ** extensions + *** [empty] + ** libs + *** [empty] + ** host + *** [empty] + @endmindmap + +Host Toolchains +------------------ + +From the above map we can see that the **host** folder is empty + +This folder will contain the .toml files of all the HOST toolchains present on your system. + +.. code-block:: toml + :linenos: + + [toolchain.host] + # Toolchain family id + # valid options are: gcc, msvc, mingw + # clang is not yet supported + id = "gcc" + + # NOTE: Each name MUST be unique + # Preferrably use the [id]_[target_arch]_[compiler_version] for uniqueness, + # but make sure the name is unique if you have multiple similar host toolchains installed on your system + name = "gcc_x86_64-linux-gnu_9.3.0" + + # Make sure all of these executables are present when you install your toolchain + asm_compiler = "as" + c_compiler = "gcc" + cpp_compiler = "g++" + archiver = "ar" + linker = "ld" + + # Additional information + # Necessary if multiple similar toolchains are installed + # For example. Installed gcc version 9.3.0 and 10.2.0 + path = "/usr/bin" + compiler_version = "9.3.0" + target_arch = "x86_64-linux-gnu" + +.. important:: For **Windows**, make sure to use ``vcvarsall.bat [flavour]`` to activate your toolchain + +* Your ENV[BUILDCC_HOME] directory should look like the following + +.. uml:: + + @startmindmap + * ENV[BUILDCC_HOME] + ** bin + *** flatc + *** buildexe + ** buildcc + *** [git cloned] + ** extensions + *** [empty] + ** libs + *** [empty] + ** host + *** gcc_x86_64-linux-gnu_9.3.0.toml + *** mingw_x86_64-w64-mingw32_10.2.0.toml + *** msvc_am64_19.29.30137.toml + @endmindmap + + +.. note:: **Extensions** and **Libs** will come later in the tutorial diff --git a/docs/source/getting_started/toc.rst b/docs/source/getting_started/toc.rst index 1d5daef4..3657d28f 100644 --- a/docs/source/getting_started/toc.rst +++ b/docs/source/getting_started/toc.rst @@ -1,14 +1,11 @@ Getting Started ================= -Pre-requisites ----------------- - -Installation and Setup ------------------------ - -Walkthroughs -------------- - -.. note:: Add walkthroughs and example snippets of increasing complexity - +.. toctree:: + + buildexe_setup + buildexe_script_example + buildexe_immediate_example + walkthroughs + all_compile_options + all_default_build_options diff --git a/docs/source/getting_started/walkthroughs.rst b/docs/source/getting_started/walkthroughs.rst new file mode 100644 index 00000000..7046f895 --- /dev/null +++ b/docs/source/getting_started/walkthroughs.rst @@ -0,0 +1,13 @@ +Walkthrough Examples +===================== + +.. note:: Provide a gist of the various APIs and features present in BuildCC + +* Simple +* IncludeDirs +* LibDeps +* Flags (Preprocessor, Compile and Link flags) +* Generators +* Target Info +* Custom Targets +* Custom Arguments diff --git a/docs/source/intro/toc.rst b/docs/source/intro/toc.rst index 91dc0d21..3e2b01f5 100644 --- a/docs/source/intro/toc.rst +++ b/docs/source/intro/toc.rst @@ -1,17 +1,73 @@ Introduction ============= -Aim/Purpose/Usecase --------------------- +Aim +---- -Definitions ------------- +BuildCC aims to be an alternative to Makefiles while using the feature rich C++ language instead of a custom DSL. Features ---------- -Community Help ---------------- +* Complete flexibility for custom workflows and toolchains +* C++ language feature benefits and debuggable build binaries +* Optimized rebuilds through serialization. + * Can optimize for rebuilds by comparing the previous stored build with current build. + * Further details given in **Architecture** +* Customizable for community plugins. + +Pre-requisites +-------------- + +* Technical Knowledge + * C++03 classes and template usage +* C++17 Compiler with + * C++17 filesystem library support + * C++11 thread library support +* Third Party Libraries (See License below) + * Flatbuffers v2.0.0 + * Taskflow v3.1.0 + * CLI11 v2.1.0 + * Tiny Process Library v2.0.4 + * fmt v8.0.1 + * spdlog v1.9.2 + * CppUTest v4.0 + +General Information +------------------- + +* A one stage **input / output** procedure is called a **Generator** with a wide variety of use cases + * Single input creates single output + * Single input creates multiple outputs + * Multiple inputs create single output + * Multiple inputs creates multiple outputs +* A two stage **compile** and **link** procedure is called a **Target** + * This means that Executables, StaticLibraries and DynamicLibraries are all categorized as Targets + * In the future C++20 modules can also be its own target depending on compiler implementations +* Every Target requires a complementary (and compatible) **Toolchain** + * This ensures that cross compiling is very easy and explicit in nature. + * Multiple toolchains can be `mixed` in a single build file i.e we can generate targets using the GCC, Clang, MSVC and many other compilers **simultaneously**. +* The **compile_command** (pch and object commands) and **link_command** (target command) is fed to the **process** call to invoke the **Toolchain**. +* Each **Target** can depend on other targets efficiently through Parallel Programming using **Taskflow**. + * Dependency between targets is explicitly mentioned through the Taskflow APIs + * This has been made easier for the user through the ``buildcc::Register`` module. +* Build files can be customized through command line arguments + * Command line arguments can be stored in configurable ``.toml`` files and passed using the ``--config`` flag. + * Users can define their own custom arguments. + * Argument passing has been made easy using the ``buildcc::Args`` module. Licenses --------- + +`BuildCC` is licensed under the Apache License, Version 2.0. See **LICENSE** for the full license text. `BuildCC` aims to use open-source libraries containing permissive licenses. + +.. note:: Developers who would like to suggest an alternative library, raise an issue with the **license** and **advantages** clearly outlined. + +* `Fmtlib `_ (Formatting) [MIT License] [Header Only] +* `Spdlog `_ (Logging) [MIT License] [Header Only] +* `Tiny Process Library `_ (Process handling) [MIT License] +* `Taskflow `_ (Parallel Programming) [MIT License] [Header Only] + * See also `3rd-Party `_ used by Taskflow +* `Flatbuffers `_ (Serialization) [Apache-2.0 License] [Header Only] +* `CLI11 `_ (Argument Parsing) [BSD-3-Clause License] [Header Only] +* `CppUTest `_ (Unit Testing/Mocking) [BSD-3-Clause License] diff --git a/example/hybrid/single/build.cpp b/example/hybrid/single/build.cpp index a94fb512..3abace55 100644 --- a/example/hybrid/single/build.cpp +++ b/example/hybrid/single/build.cpp @@ -24,11 +24,11 @@ int main(int argc, char **argv) { // 4. Build steps // Explicit toolchain - target pairs Toolchain_gcc gcc; - - ExecutableTarget_gcc hello_world("hello_world", gcc, ""); auto verified_toolchains = gcc.Verify(); env::assert_fatal(!verified_toolchains.empty(), "GCC Toolchain not found"); + ExecutableTarget_gcc hello_world("hello_world", gcc, ""); + // Select your builds and tests using the .toml files reg.Build(arg_gcc.state, hello_world_build_cb, hello_world);