From dc3865ba6dd079fe7557716dd05be5f6464a0a0c Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Mon, 3 Feb 2025 22:06:54 +0100 Subject: [PATCH] march, flags, and git dependencies --- .github/workflows/release.yaml | 19 ++++++++++++++ Crafter.Build-Configuration.cpp | 12 ++++++++- Crafter.Build-Configuration.cppm | 4 ++- Crafter.Build-ModuleFile.cpp | 10 +++++-- Crafter.Build-Project.cpp | 45 +++++++++++++++++++++++--------- README.md | 12 +++++++-- build.sh | 4 +-- main.cpp | 14 +++++++++- 8 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..8fe48ab --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,19 @@ +name: Main + +on: push + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Prepare + run: sudo apt install clang lld + - name: Build + run: ./build.sh + - name: Release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + files: build/crafter-build \ No newline at end of file diff --git a/Crafter.Build-Configuration.cpp b/Crafter.Build-Configuration.cpp index 2fd8e51..78a72db 100644 --- a/Crafter.Build-Configuration.cpp +++ b/Crafter.Build-Configuration.cpp @@ -24,7 +24,7 @@ module Crafter.Build; using namespace Crafter::Build; namespace fs = std::filesystem; -Configuration::Configuration(std::string name, std::string standard, std::vector sourceFiles, std::vector moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::vector dependencies, std::vector additionalFiles): name(name), standard(standard), sourceFiles(sourceFiles), moduleFiles(moduleFiles), optimizationLevel(optimizationLevel), buildDir(buildDir), outputDir(outputDir), type(type), target(target), dependencies(dependencies), additionalFiles(additionalFiles) { +Configuration::Configuration(std::string name, std::string standard, std::vector sourceFiles, std::vector moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::string march, std::vector dependencies, std::vector additionalFiles, std::vector flags): name(name), standard(standard), sourceFiles(sourceFiles), moduleFiles(moduleFiles), optimizationLevel(optimizationLevel), buildDir(buildDir), outputDir(outputDir), type(type), target(target), march(march), dependencies(dependencies), additionalFiles(additionalFiles), flags(flags) { } @@ -38,6 +38,8 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json target = val.get(); } else if(key == "type") { type = val.get(); + } else if(key == "march") { + march = val.get(); } else if(key == "source_files") { const std::vector tempSourceFiles = val.get>(); sourceFiles = std::vector(tempSourceFiles.size()); @@ -46,6 +48,8 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json const std::filesystem::path fullFilePath = workingDir / filePath; sourceFiles[i] = fullFilePath.generic_string(); } + } else if(key == "flags") { + flags = val.get>(); } else if(key == "module_files") { const std::vector tempModuleFiles = val.get>(); moduleFiles = std::vector(tempModuleFiles.size()); @@ -118,6 +122,12 @@ Configuration::Configuration(const nlohmann::json& configs, const nlohmann::json if(!extendData.type.empty() && type.empty()) { type = extendData.type; } + if(!extendData.march.empty() && march.empty()) { + march = extendData.march; + } + if(!extendData.flags.empty()){ + flags.insert(flags.end(), extendData.flags.begin(), extendData.flags.end()); + } break; } } diff --git a/Crafter.Build-Configuration.cppm b/Crafter.Build-Configuration.cppm index 9d22644..2900575 100644 --- a/Crafter.Build-Configuration.cppm +++ b/Crafter.Build-Configuration.cppm @@ -41,9 +41,11 @@ export namespace Crafter::Build { std::string outputDir; std::string type; std::string target; + std::string march; std::vector dependencies; std::unordered_map additionalProperties; - Configuration(std::string name, std::string standard, std::vector sourceFiles, std::vector moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::vector dependencies, std::vector additionalFiles); + std::vector flags; + Configuration(std::string name, std::string standard, std::vector sourceFiles, std::vector moduleFiles, std::string optimizationLevel, std::string buildDir, std::string outputDir, std::string type, std::string target, std::string march, std::vector dependencies, std::vector additionalFiles, std::vector flags); Configuration(const nlohmann::json& configs, const nlohmann::json& config, fs::path workingDir); }; } diff --git a/Crafter.Build-ModuleFile.cpp b/Crafter.Build-ModuleFile.cpp index 84d01e6..f4360b5 100644 --- a/Crafter.Build-ModuleFile.cpp +++ b/Crafter.Build-ModuleFile.cpp @@ -94,11 +94,17 @@ void ModuleFile::Compile(std::string clangDir, const Configuration& config, fs:: for(ModuleFile* dep : dependencies){ dep->Compile(clangDir, config, pcmDir, target); } - system(std::format("{} -std={} {}.cppm --precompile -fprebuilt-module-path={} -o {}.pcm {}", clangDir, config.standard, path.generic_string(), pcmDir.generic_string(), (pcmDir/path.filename()).generic_string(), target).c_str()); + + std::string flags; + for(const std::string& flag : config.flags) { + flags+=flag; + } + + system(std::format("{} -std={} {}.cppm --precompile -march={} {} -fprebuilt-module-path={} -o {}.pcm {}", clangDir, config.standard, path.generic_string(), config.march, flags, pcmDir.generic_string(), (pcmDir/path.filename()).generic_string(), target).c_str()); recompiled = true; fileMutex.unlock(); - system(std::format("{} -std={} {}.pcm -fprebuilt-module-path={} -c -O{} -o {}.o {}", clangDir, config.standard, (pcmDir/path.filename()).generic_string(), pcmDir.generic_string(), config.optimizationLevel, (config.buildDir/path.filename()).generic_string(), target).c_str()); + system(std::format("{} -std={} {}.pcm -fprebuilt-module-path={} -c -O{} -march={} {} -o {}.o {}", clangDir, config.standard, (pcmDir/path.filename()).generic_string(), pcmDir.generic_string(), config.optimizationLevel, config.march, flags, (config.buildDir/path.filename()).generic_string(), target).c_str()); } else { fileMutex.unlock(); } diff --git a/Crafter.Build-Project.cpp b/Crafter.Build-Project.cpp index d6e68ec..9f1bf1b 100644 --- a/Crafter.Build-Project.cpp +++ b/Crafter.Build-Project.cpp @@ -74,6 +74,16 @@ void Project::Build(Configuration config, fs::path outputDir) const { } void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) const { + if(config.standard.empty()) { + config.standard = "c++26"; + } + if(config.march.empty()) { + config.march = "native"; + } + if(config.type.empty()) { + config.type = "executable"; + } + if (!fs::exists(config.buildDir)) { fs::create_directory(config.buildDir); } @@ -101,7 +111,11 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c } for(std::int_fast32_t i = 0; i < depThreads.size(); i++) { - Project project = Project::LoadFromJSON(config.dependencies[i].path); + if(config.dependencies[i].path.ends_with(".git")) { + system(std::format("cd {} && git clone {}", config.buildDir, config.dependencies[i].path).c_str()); + } + config.dependencies[i].path = fs::path(config.dependencies[i].path).filename().replace_extension(); + Project project = Project::LoadFromJSON(fs::path(config.buildDir)/config.dependencies[i].path/"project.json"); libs+=std::format(" -l{}", project.name); depThreads[i] = std::thread([i, pcmDir, config, project, binDir]() { project.Build(config.dependencies[i].configuration, pcmDir, binDir); @@ -125,30 +139,35 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c clangDir = "clang++ -Wno-unused-command-line-argument"; } + std::string flags; + for(const std::string& flag : config.flags) { + flags+=flag; + } + for(std::thread& thread : depThreads){ thread.join(); } std::string files; - std::vector moduleThreads(config.moduleFiles.size()); + //std::vector moduleThreads(config.moduleFiles.size()); for(std::uint_fast32_t i = 0; i < config.moduleFiles.size(); i++) { - moduleThreads[i] = std::thread([i, &config, pcmDir, target, clangDir](){ + //moduleThreads[i] = std::thread([i, &config, pcmDir, target, clangDir](){ ModuleFile::CompileModuleFile(config.moduleFiles[i], clangDir, config, pcmDir, target); - }); + //}); files+=std::format("{}.o ",(config.buildDir/config.moduleFiles[i].filename()).generic_string()); } - for(std::thread& thread : moduleThreads){ - thread.join(); - } + // for(std::thread& thread : moduleThreads){ + // thread.join(); + // } std::vector threads; for(std::uint_fast32_t i = 0; i < config.sourceFiles.size(); i++) { files+=std::format("{}_source.o ",(config.buildDir/config.sourceFiles[i].filename()).generic_string()); - if(!fs::exists((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.sourceFiles[i].generic_string()+".cpp") > fs::last_write_time((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o")) { - threads.emplace_back([i, &config, pcmDir, target, clangDir](){ - system(std::format("{} -std={} {}.cpp -fprebuilt-module-path={} -c -O{} -o {}_source.o {}", clangDir, config.standard, config.sourceFiles[i].generic_string(), pcmDir.generic_string(), config.optimizationLevel, (config.buildDir/config.sourceFiles[i].filename()).generic_string(), target).c_str()); + //if(!fs::exists((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o") || fs::last_write_time(config.sourceFiles[i].generic_string()+".cpp") > fs::last_write_time((config.buildDir/config.sourceFiles[i].filename()).generic_string()+"_source.o")) { + threads.emplace_back([i, &config, pcmDir, target, clangDir, flags](){ + system(std::format("{} -std={} {}.cpp -fprebuilt-module-path={} -c -O{} -march={} {} -o {}_source.o {}", clangDir, config.standard, config.sourceFiles[i].generic_string(), pcmDir.generic_string(), config.optimizationLevel, config.march, flags, (config.buildDir/config.sourceFiles[i].filename()).generic_string(), target).c_str()); }); - } + //} } for(std::thread& thread : threads){ @@ -156,11 +175,11 @@ void Project::Build(Configuration config, fs::path outputDir, fs::path binDir) c } if(config.type == "executable"){ - system(std::format("{} {}-O{} -o {} {} {}", clangDir, files, config.optimizationLevel, (outputDir/name).generic_string(), target, libs).c_str()); + system(std::format("{} {}-O{} -o {} {} {} -fuse-ld=lld", clangDir, files, config.optimizationLevel, (outputDir/name).generic_string(), target, libs).c_str()); } else if(config.type == "library"){ system(std::format("ar r {}.a {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str()); } else if(config.type == "shared-library"){ - system(std::format("ar r {}.so {} -shared", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str()); + system(std::format("ar r {}.so {}", (outputDir/fs::path("lib"+name)).generic_string(), files).c_str()); } for(const fs::path& additionalFile : config.additionalFiles){ diff --git a/README.md b/README.md index dcfabb8..7e7a840 100644 --- a/README.md +++ b/README.md @@ -67,10 +67,12 @@ Save and close, then run ``crafter-build -c debug``. Now you can run the ``hello ``-o`` Overrides the output folder. +``-r`` Runs the executable after building. + ## configuration properties ``name`` Name of the configuration. -``standard`` C++ standard that this configuration uses, please refer to the [relevant clang documentation](https://clang.llvm.org/cxx_status.html) +``standard`` C++ standard that this configuration uses, please refer to the [relevant clang documentation](https://clang.llvm.org/cxx_status.html), defaults to ``c++26``. ``source_files`` All source files of the project ``.cpp`` extension is assumed. @@ -82,9 +84,11 @@ Save and close, then run ``crafter-build -c debug``. Now you can run the ``hello ``output_dir`` The directory where the output files will be placed. +``type`` The type of the project: ``executable``, ``library``, ``shared-library``. + ``extends`` An array of configuration names that this configuration extends, later elements in the array take priority over previous ones. -``optimization_level`` Please refer to the [relevant clang documentation](https://clang.llvm.org/docs/CommandGuide/clang.html#code-generation-options). +``optimization_level`` Please refer to the [relevant clang documentation](https://clang.llvm.org/docs/CommandGuide/clang.html#code-generation-options), defaults to ``0``. ``dependencies`` An object array of the dependencies of this project, example: ```json @@ -93,6 +97,10 @@ Save and close, then run ``crafter-build -c debug``. Now you can run the ``hello "path":"/home/Crafter.Build/project.json", "configuration":"debug-lib" } + { + "path":"https://github.com/Catcrafts/Crafter.Build.git", + "configuration":"debug-lib" + } ] ``` This will now link the library of Crafter.Build in the configuration you use this in. diff --git a/build.sh b/build.sh index d9e5943..7c950ac 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,3 @@ -clear mkdir build mkdir bin @@ -21,5 +20,4 @@ clang++ -std=c++26 ./build/Crafter.Build-Dependency.pcm -fprebuilt-module-path=. clang++ -std=c++26 ./build/Crafter.Build.pcm -fprebuilt-module-path=./build -c -O3 -o ./build/Crafter.Build.o clang++ ./build/main.o ./build/Crafter.Build-ModuleFile_source.o ./build/Crafter.Build-ModuleFile.o ./build/Crafter.Build.o ./build/Crafter.Build-Configuration.o ./build/Crafter.Build-Configuration_source.o ./build/Crafter.Build-Project.o ./build/Crafter.Build-Project_source.o ./build/Crafter.Build-Dependency.o ./build/Crafter.Build-Dependency_source.o -O3 -o ./bin/crafter-build -rm -rf build; -# crafter-build -c debug +rm -rf build diff --git a/main.cpp b/main.cpp index 54f1916..b42b34c 100644 --- a/main.cpp +++ b/main.cpp @@ -31,13 +31,16 @@ int main(int argc, char* argv[]) { fs::path filepath = "project.json"; std::string configuration; std::string outputDir; + bool run = false; for (std::uint_fast32_t i = 1; i < argc; i++) { std::string arg = std::string(argv[i]); if(arg == "--help"){ - std::println("--help\tDisplays this help message.\n-c The name of the configuration to build.\n-p The path to the project file. defualts to project.json\n-o Overrides the output folder.\n"); + std::println("--help\tDisplays this help message.\n-c The name of the configuration to build.\n-p The path to the project file. defualts to project.json\n-o Overrides the output folder.\n-r Runs the executable after building."); return 0; } else if(arg == "-c"){ configuration = argv[++i]; + } else if(arg == "-r"){ + run = true; } else if(arg == "-o"){ outputDir = argv[++i]; } else if(arg == "-p"){ @@ -61,4 +64,13 @@ int main(int argc, char* argv[]) { } else{ project.Build(configuration, fs::path(outputDir)); } + + if(run){ + for(const Configuration& config : project.configurations) { + if(config.name == configuration){ + system(std::format("{}", (projectPath/fs::path(config.outputDir)/project.name).generic_string()).c_str()); + return 0; + } + } + } }