From cdfbcf4f61a61c628865c5c64d7b267e34d967e6 Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Sat, 20 Dec 2025 06:37:29 +0100 Subject: [PATCH] Initial project sketch --- .gitignore | 2 ++ CMake/cpr.cmake | 13 +++++++ CMake/libprocess.cmake | 11 ++++++ CMakeLists.txt | 7 ++++ Toolchain/CMakeLists.txt | 29 +++++++++++++++ Toolchain/Include/Command.hpp | 0 Toolchain/Include/Common.hpp | 12 +++++++ Toolchain/Include/Download.hpp | 11 ++++++ Toolchain/Include/Package.hpp | 34 ++++++++++++++++++ Toolchain/Include/Unpack.hpp | 11 ++++++ Toolchain/Main.cpp | 12 +++++++ Toolchain/Source/Command.cpp | 0 Toolchain/Source/Download.cpp | 65 ++++++++++++++++++++++++++++++++++ Toolchain/Source/Package.cpp | 6 ++++ Toolchain/Source/Unpack.cpp | 33 +++++++++++++++++ 15 files changed, 246 insertions(+) create mode 100644 .gitignore create mode 100644 CMake/cpr.cmake create mode 100644 CMake/libprocess.cmake create mode 100644 CMakeLists.txt create mode 100644 Toolchain/CMakeLists.txt create mode 100644 Toolchain/Include/Command.hpp create mode 100644 Toolchain/Include/Common.hpp create mode 100644 Toolchain/Include/Download.hpp create mode 100644 Toolchain/Include/Package.hpp create mode 100644 Toolchain/Include/Unpack.hpp create mode 100644 Toolchain/Main.cpp create mode 100644 Toolchain/Source/Command.cpp create mode 100644 Toolchain/Source/Download.cpp create mode 100644 Toolchain/Source/Package.cpp create mode 100644 Toolchain/Source/Unpack.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc95448 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.cache/ +build/ diff --git a/CMake/cpr.cmake b/CMake/cpr.cmake new file mode 100644 index 0000000..8079948 --- /dev/null +++ b/CMake/cpr.cmake @@ -0,0 +1,13 @@ +include(FetchContent) + +FetchContent_Declare( + cpr + GIT_REPOSITORY ssh://git@code.3011.io/Mirrors/cpr.git + GIT_TAG 1.14.1 +) + +set(BUILD_SHARED_LIBS OFF) + +FetchContent_MakeAvailable( + cpr +) diff --git a/CMake/libprocess.cmake b/CMake/libprocess.cmake new file mode 100644 index 0000000..b4ec39f --- /dev/null +++ b/CMake/libprocess.cmake @@ -0,0 +1,11 @@ +include(FetchContent) + +FetchContent_Declare( + libcbor + GIT_REPOSITORY ssh://git@code.3011.io/TennesseeTrash/LibProcess.git + GIT_TAG v0.0.1 +) + +FetchContent_MakeAvailable( + libcbor +) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a471205 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.25) + +project(Toolchain + LANGUAGES CXX +) + +add_subdirectory(Toolchain) diff --git a/Toolchain/CMakeLists.txt b/Toolchain/CMakeLists.txt new file mode 100644 index 0000000..5c38308 --- /dev/null +++ b/Toolchain/CMakeLists.txt @@ -0,0 +1,29 @@ +include(${PROJECT_SOURCE_DIR}/CMake/cpr.cmake) +include(${PROJECT_SOURCE_DIR}/CMake/libprocess.cmake) + +add_executable(Toolchain) + +target_compile_features(Toolchain + PRIVATE + cxx_std_23 +) + +target_include_directories(Toolchain + PRIVATE + "Include" +) + +target_link_libraries(Toolchain + PRIVATE + "cpr::cpr" + "LibProcess" +) + +target_sources(Toolchain + PRIVATE + "Main.cpp" + "Source/Command.cpp" + "Source/Download.cpp" + "Source/Package.cpp" + "Source/Unpack.cpp" +) diff --git a/Toolchain/Include/Command.hpp b/Toolchain/Include/Command.hpp new file mode 100644 index 0000000..e69de29 diff --git a/Toolchain/Include/Common.hpp b/Toolchain/Include/Common.hpp new file mode 100644 index 0000000..d30ec00 --- /dev/null +++ b/Toolchain/Include/Common.hpp @@ -0,0 +1,12 @@ +#ifndef TOOLCHAIN_COMMON_HPP +#define TOOLCHAIN_COMMON_HPP + +#include // IWYU pragma: export + +namespace Toolchain +{ + // NOLINTNEXTLINE: We're defining this to make life easier. + namespace fs = std::filesystem; +} + +#endif // TOOLCHAIN_COMMON_HPP diff --git a/Toolchain/Include/Download.hpp b/Toolchain/Include/Download.hpp new file mode 100644 index 0000000..e6b1fe3 --- /dev/null +++ b/Toolchain/Include/Download.hpp @@ -0,0 +1,11 @@ +#ifndef TOOLCHAIN_DOWNLOAD_HPP +#define TOOLCHAIN_DOWNLOAD_HPP + +#include "Common.hpp" + +namespace Toolchain +{ + bool DownloadFile(const fs::path &path, std::string_view url); +} + +#endif // TOOLCHAIN_DOWNLOAD_HPP diff --git a/Toolchain/Include/Package.hpp b/Toolchain/Include/Package.hpp new file mode 100644 index 0000000..374c3f9 --- /dev/null +++ b/Toolchain/Include/Package.hpp @@ -0,0 +1,34 @@ +#ifndef TOOLCHAIN_PACKAGE_HPP +#define TOOLCHAIN_PACKAGE_HPP + +namespace Toolchain +{ + // The package should have a name, version, source url, and it should describe + // the series of steps necessary to take to properly build and install the package + // into the final destination. + + // There are some things that are still to be decided. Should there be a set of abstractions + // to deal with common build systems, and package installation steps? How should a potential + // escape hatch work for this? + + // The package download and extraction should be identical for every single package. + // Afterwards, the process should be split up into three separate stages, the configuration, + // the build, and the installation. Every single step should be as isolated from the host system + // as possible, to prevent dirtying the result with dependencies on system libraries or binaries. + + // All the package sets should be split into three stages. Stage0 should be used to bootstrap + // a suitable compiler for maximum compatibility and cross compilation. + // Stage1 should be a full toolchain independent from the host system, including most packages. + // Finally, stage2 should produce three full toolchains, cross compiled for all target systems. + + // Initially, the scope should be to stop at stage1, it should be good enough to get started + // with all the other projects. It will still require system dependencies for certain bits, but + // that doesn't matter too much, as long as the host has a reasonably complete package registry. + + class Package + { + + }; +} + +#endif // TOOLCHAIN_PACKAGE_HPP diff --git a/Toolchain/Include/Unpack.hpp b/Toolchain/Include/Unpack.hpp new file mode 100644 index 0000000..841db16 --- /dev/null +++ b/Toolchain/Include/Unpack.hpp @@ -0,0 +1,11 @@ +#ifndef TOOLCHAIN_UNPACK_HPP +#define TOOLCHAIN_UNPACK_HPP + +#include "Common.hpp" + +namespace Toolchain +{ + bool UnpackArchive(const fs::path &sourceArchive, const fs::path &destinationDirectory); +} + +#endif // TOOLCHAIN_UNPACK_HPP diff --git a/Toolchain/Main.cpp b/Toolchain/Main.cpp new file mode 100644 index 0000000..9e1e462 --- /dev/null +++ b/Toolchain/Main.cpp @@ -0,0 +1,12 @@ +#include "Download.hpp" + +#include + +int main() +{ + std::println("Hello World!"); + + if (!Toolchain::DownloadFile("index.html", "https://3011.io/")) { + std::println("Unlucky"); + } +} diff --git a/Toolchain/Source/Command.cpp b/Toolchain/Source/Command.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Toolchain/Source/Download.cpp b/Toolchain/Source/Download.cpp new file mode 100644 index 0000000..0107790 --- /dev/null +++ b/Toolchain/Source/Download.cpp @@ -0,0 +1,65 @@ +#include "Download.hpp" + +#include + +#include + +namespace +{ + struct CursorGuard + { + public: + CursorGuard() + { + std::print("\033[?25l"); + } + + ~CursorGuard() + { + std::print("\033[?25h"); + } + }; +} + +namespace Toolchain +{ + bool DownloadFile(const fs::path &path, std::string_view url) + { + using offset_t = cpr::cpr_off_t; + + std::ofstream file(path, std::ios::binary); + if (!file) { + return false; + } + + CursorGuard guard; + + cpr::Response response = cpr::Get( + cpr::Url(url), + cpr::WriteCallback( + [&file] (std::string_view data, std::intptr_t) { + file.write(data.data(), data.size()); + return true; + } + ), + cpr::ProgressCallback( + [path] (offset_t dt, offset_t dp, offset_t ut, offset_t up, std::intptr_t) { + double progress = double(dp) / double(dt); + std::print("\rDownloading {}: {:.2f}% ({}/{})", + path.c_str(), progress * 100, dp, dt); + return true; + } + ) + ); + std::println(); + + if (response.status_code != 200) { + std::println("Download failed with status: {}, {}", + response.status_code, response.status_line); + return false; + } + + file.close(); + return true; + } +} diff --git a/Toolchain/Source/Package.cpp b/Toolchain/Source/Package.cpp new file mode 100644 index 0000000..2f156db --- /dev/null +++ b/Toolchain/Source/Package.cpp @@ -0,0 +1,6 @@ +#include "Package.hpp" + +namespace Toolchain +{ + +} diff --git a/Toolchain/Source/Unpack.cpp b/Toolchain/Source/Unpack.cpp new file mode 100644 index 0000000..3c10270 --- /dev/null +++ b/Toolchain/Source/Unpack.cpp @@ -0,0 +1,33 @@ +#include "Unpack.hpp" + +#include + +namespace Toolchain +{ + bool UnpackArchive(const fs::path &sourceArchive, const fs::path &destinationDirectory) + { + // Select the command based on the file extension + + // Extract the archive into a temporary directory + + // Check how many items were extracted (non-recursively, we only care about the top level) + + // If there was only one item, and it's a directory, it should be moved (and renamed) + // to the destination. In case it's a file, the destination should be created, and the + // file moved there. + + // If there are multiple items, the destination will be created, and all items moved into + // the destination. + + // Error handling and cleanup should be done so the temporary directory is always + // kept clean in case the program tries to use it for other stuff. + + // The reasoning behind this sort of behaviour is that the whole thing should always be as + // consistent as possible, we want everything to be as consistent as possible, and easy to + // work with afterwards. The point is that for the most part, the structure is know, so + // it is easy to proceed, and otherwise it should be easy to analyze the contents + // programatically. + + return false; + } +}