Smart parellalization

This commit is contained in:
2026-06-28 09:37:09 -04:00
parent 1813b3f5cf
commit ac98871cfc
9 changed files with 275 additions and 73 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
build/
.idea
*.dot

View File

@@ -4,6 +4,9 @@ project(build_script)
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
# Taskflow has a deprecated declaration issue in its small_vector.hpp file
add_compile_options(-Wno-deprecated-declarations)
file(GLOB REQUIRED_CMAKE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/*.required.cmake")
foreach (cmake_file ${REQUIRED_CMAKE_FILES})
include(${cmake_file})
@@ -23,13 +26,16 @@ add_executable(${PROJECT_NAME} ${SRC_FILES} ${HEADER_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC
"${structops_SOURCE_DIR}/include"
"${spdlog_SOURCE_DIR}/include"
"${taskflow_SOURCE_DIR}"
)
target_link_libraries(${PROJECT_NAME} PUBLIC
structopt
spdlog
Taskflow
)
# Structopt includes an outdated version of magic_enum that breaks some default defines
# This is needed to bypass it. Im not happy about it, but it is what it is
target_link_options(build_script PRIVATE -Wl,--allow-multiple-definition)

5
cmake/taskflow.cmake Normal file
View File

@@ -0,0 +1,5 @@
CPMAddPackage (
URI "gh:taskflow/taskflow@4.1.0"
OPTIONS "TF_BUILD_EXAMPLES off"
OPTIONS "TF_BUILD_TESTS off"
)

View File

@@ -1,6 +1,10 @@
#include "app.h"
#include <fstream>
#include "args.h"
#include "logging.h"
#include "taskflow/core/executor.hpp"
Application::Application(Options options)
: m_DryRun(options.dryrun.value()),
@@ -10,7 +14,7 @@ Application::Application(Options options)
createAllLoggers();
}
void Application::run() {
void Application::assemble() {
spdlog::get("app")->debug("Running command");
switch (m_Command) {
case build:
@@ -29,7 +33,20 @@ void Application::run() {
rebuildProject();
break;
}
}
void Application::save_graph(std::string filename) {
spdlog::get("app")->info("Saving task flow graph to '{}'", filename);
spdlog::get("app")->info(
"You can use a website like "
"'https://dreampuf.github.io/GraphvizOnline/?engine=dot' to view it.");
std::ofstream os(filename);
m_Taskflow.dump(os);
}
void Application::run() {
tf::Executor executor;
executor.run(m_Taskflow).wait();
spdlog::get("app")->info("All work done!");
}

View File

@@ -2,14 +2,19 @@
#define BUILD_SCRIPT_APP
#include <filesystem>
#include <taskflow/taskflow.hpp>
#include "args.h"
#include "logging.h"
#include "taskflow/core/executor.hpp"
#include "taskflow/core/taskflow.hpp"
#include "types.h"
class Application {
public:
Application(Options options);
void assemble();
void save_graph(std::string filename);
void run();
private:
@@ -18,6 +23,8 @@ class Application {
BuildType m_BuildType;
Command m_Command;
tf::Taskflow m_Taskflow;
void createAllLoggers();
void buildProject();

View File

@@ -1,6 +1,7 @@
#ifndef BUILD_SCRIPT_ARGS
#define BUILD_SCRIPT_ARGS
#include <optional>
#include <structopt/app.hpp>
#include "types.h"
@@ -11,8 +12,9 @@ struct Options {
std::optional<bool> verbose = false;
std::optional<bool> dryrun = false;
std::optional<std::string> graphFilename;
};
STRUCTOPT(Options, command, buildType, verbose, dryrun);
STRUCTOPT(Options, command, buildType, verbose, dryrun, graphFilename);
Options parse(int argc, char** argv);

View File

@@ -1,87 +1,247 @@
#include <stdexcept>
#include "app.h"
#include "types.h"
void Application::buildProject() {
checkBuildDirs();
switch (m_BuildType) {
case none:
configureDir("build/debug", "Debug");
buildDir("build/debug");
configureDir("build/release", "Release");
buildDir("build/release");
configureDir("build/relwithdeb", "RelWithDeb");
buildDir("build/relwithdeb");
configureDir("build/minsizerel", "MinSizeRel");
buildDir("build/minsizerel");
break;
case debug:
configureDir("build/debug", "Debug");
buildDir("build/debug");
break;
case release:
configureDir("build/release", "Release");
buildDir("build/release");
break;
case relwithdeb:
configureDir("build/relwithdeb", "RelWithDeb");
buildDir("build/relwithdeb");
break;
case minsizerel:
configureDir("build/minsizerel", "MinSizeRel");
buildDir("build/minsizerel");
break;
auto checkBuildDirsTask =
m_Taskflow.emplace([this]() { this->checkBuildDirs(); })
.name("checkBuildDirs");
if (m_BuildType == BuildType::none) {
auto configureDirDebugTask =
m_Taskflow
.emplace(
[this]() { this->configureDir("build/debug", "debug"); })
.name("configureDir(build/debug)");
auto buildDirDebugTask =
m_Taskflow.emplace([this]() { this->buildDir("build/debug"); })
.name("buildDir(build/debug)");
configureDirDebugTask.precede(buildDirDebugTask);
checkBuildDirsTask.precede(configureDirDebugTask);
auto configureDirReleaseTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/release", "Release");
})
.name("configureDir(build/release)");
auto buildDirReleaseTask =
m_Taskflow.emplace([this]() { this->buildDir("build/release"); })
.name("buildDir(build/release)");
configureDirReleaseTask.precede(buildDirReleaseTask);
checkBuildDirsTask.precede(configureDirReleaseTask);
auto configureDirRelWithDebTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/relwithdeb", "RelWithDeb");
})
.name("configureDir(build/relwithdeb)");
auto buildDirRelWithDebTask =
m_Taskflow.emplace([this]() { this->buildDir("build/relwithdeb"); })
.name("buildDir(build/relwithdeb)");
configureDirRelWithDebTask.precede(buildDirRelWithDebTask);
checkBuildDirsTask.precede(configureDirRelWithDebTask);
auto configureDirMinSizeRelTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/minsizerel", "MinSizeRel");
})
.name("configureDir(build/minsizerel)");
auto buildDirMinSizeRelTask =
m_Taskflow.emplace([this]() { this->buildDir("build/minsizerel"); })
.name("buildDir(build/minsizerel)");
configureDirMinSizeRelTask.precede(buildDirMinSizeRelTask);
checkBuildDirsTask.precede(configureDirMinSizeRelTask);
} else if (m_BuildType == BuildType::debug) {
auto configureDirTask =
m_Taskflow
.emplace(
[this]() { this->configureDir("build/debug", "debug"); })
.name("configureDir(build/debug)");
auto buildDirTask =
m_Taskflow.emplace([this]() { this->buildDir("build/debug"); })
.name("buildDir(build/debug)");
configureDirTask.precede(buildDirTask);
checkBuildDirsTask.precede(configureDirTask);
} else if (m_BuildType == BuildType::release) {
auto configureDirTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/release", "Release");
})
.name("configureDir(build/release)");
auto buildDirTask =
m_Taskflow.emplace([this]() { this->buildDir("build/release"); })
.name("buildDir(build/release)");
configureDirTask.precede(buildDirTask);
checkBuildDirsTask.precede(configureDirTask);
} else if (m_BuildType == BuildType::relwithdeb) {
auto configureDirTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/relwithdeb", "RelWithDeb");
})
.name("configureDir(build/relwithdeb)");
auto buildDirTask =
m_Taskflow.emplace([this]() { this->buildDir("build/relwithdeb"); })
.name("buildDir(build/relwithdeb)");
configureDirTask.precede(buildDirTask);
checkBuildDirsTask.precede(configureDirTask);
} else if (m_BuildType == BuildType::minsizerel) {
auto configureDirTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/minsizerel", "MinSizeRel");
})
.name("configureDir(build/minsizerel)");
auto buildDirTask =
m_Taskflow.emplace([this]() { this->buildDir("build/minsizerel"); })
.name("buildDir(build/minsizerel)");
configureDirTask.precede(buildDirTask);
checkBuildDirsTask.precede(configureDirTask);
}
}
void Application::configureProject() {
checkBuildDirs();
switch (m_BuildType) {
case none:
configureDir("build/debug", "Debug");
configureDir("build/release", "Release");
configureDir("build/relwithdeb", "RelWithDeb");
configureDir("build/minsizerel", "MinSizeRel");
break;
case debug:
configureDir("build/debug", "Debug");
break;
case release:
configureDir("build/release", "Release");
break;
case relwithdeb:
configureDir("build/relwithbeb", "RelWithDeb");
break;
case minsizerel:
configureDir("build/minsizerel", "MinSizeRel");
break;
auto checkBuildDirsTask =
m_Taskflow.emplace([this]() { this->checkBuildDirs(); })
.name("checkBuildDirs");
if (m_BuildType == BuildType::none) {
auto configureDirDebugTask =
m_Taskflow
.emplace(
[this]() { this->configureDir("build/debug", "debug"); })
.name("configureDir(build/debug)");
checkBuildDirsTask.precede(configureDirDebugTask);
auto configureDirReleaseTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/release", "Release");
})
.name("configureDir(build/release)");
checkBuildDirsTask.precede(configureDirReleaseTask);
auto configureDirRelWithDebTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/relwithdeb", "RelWithDeb");
})
.name("configureDir(build/relwithdeb)");
checkBuildDirsTask.precede(configureDirRelWithDebTask);
auto configureDirMinSizeRelTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/minsizerel", "MinSizeRel");
})
.name("configureDir(build/minsizerel)");
checkBuildDirsTask.precede(configureDirMinSizeRelTask);
} else if (m_BuildType == BuildType::debug) {
auto configureDirDebugTask =
m_Taskflow
.emplace(
[this]() { this->configureDir("build/debug", "debug"); })
.name("configureDir(build/debug)");
checkBuildDirsTask.precede(configureDirDebugTask);
} else if (m_BuildType == BuildType::release) {
auto configureDirReleaseTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/release", "Release");
})
.name("configureDir(build/release)");
checkBuildDirsTask.precede(configureDirReleaseTask);
} else if (m_BuildType == BuildType::relwithdeb) {
auto configureDirRelWithDebTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/relwithdeb", "RelWithDeb");
})
.name("configureDir(build/relwithdeb)");
checkBuildDirsTask.precede(configureDirRelWithDebTask);
} else if (m_BuildType == BuildType::minsizerel) {
auto configureDirMinSizeRelTask =
m_Taskflow
.emplace([this]() {
this->configureDir("build/minsizerel", "MinSizeRel");
})
.name("configureDir(build/minsizerel)");
checkBuildDirsTask.precede(configureDirMinSizeRelTask);
}
}
void Application::cleanProject() {
checkBuildDirs();
auto checkBuildDirsTask =
m_Taskflow.emplace([this]() { this->checkBuildDirs(); })
.name("checkBuildDirs");
switch (m_BuildType) {
case none:
cleanDir("build/debug");
cleanDir("build/release");
cleanDir("build/relwithdeb");
cleanDir("build/minsizerel");
break;
case debug:
cleanDir("build/debug");
break;
case release:
cleanDir("build/release");
break;
case relwithdeb:
cleanDir("build/relwithdeb");
break;
case minsizerel:
cleanDir("build/minsizerel");
break;
if (m_BuildType == BuildType::none) {
auto cleanDirDebugTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/debug"); })
.name("cleanDir(build/debug)");
checkBuildDirsTask.precede(cleanDirDebugTask);
auto cleanDirReleaseTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/release"); })
.name("cleanDir(build/release)");
checkBuildDirsTask.precede(cleanDirReleaseTask);
auto cleanDirRelWithDebTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/relwithdeb"); })
.name("cleanDir(build/relwithdeb)");
checkBuildDirsTask.precede(cleanDirRelWithDebTask);
auto cleanDirMinSizeRelTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/minsizerel"); })
.name("cleanDir(build/minsizerel)");
checkBuildDirsTask.precede(cleanDirMinSizeRelTask);
} else if (m_BuildType == BuildType::debug) {
auto cleanDirDebugTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/debug"); })
.name("cleanDir(build/debug)");
checkBuildDirsTask.precede(cleanDirDebugTask);
} else if (m_BuildType == BuildType::release) {
auto cleanDirReleaseTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/release"); })
.name("cleanDir(build/release)");
checkBuildDirsTask.precede(cleanDirReleaseTask);
} else if (m_BuildType == BuildType::relwithdeb) {
auto cleanDirRelWithDebTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/relwithdeb"); })
.name("cleanDir(build/relwithdeb)");
checkBuildDirsTask.precede(cleanDirRelWithDebTask);
} else if (m_BuildType == BuildType::minsizerel) {
auto cleanDirMinSizeRelTask =
m_Taskflow.emplace([this]() { this->cleanDir("build/minsizerel"); })
.name("cleanDir(build/minsizerel)");
checkBuildDirsTask.precede(cleanDirMinSizeRelTask);
}
}
void Application::deleteProject() {
// No point in using taskflow for this...
// In all cases its just deleting a single directory...
// Bit overkill for that
switch (m_BuildType) {
case none:
deleteDir("build");
@@ -103,7 +263,5 @@ void Application::deleteProject() {
void Application::rebuildProject() {
deleteProject();
checkBuildDirs();
configureProject();
buildProject();
}

View File

@@ -35,7 +35,7 @@ void createLogger(const char* name, const char* filename, const bool verbose) {
if (verbose)
logger->set_level(spdlog::level::debug);
else
logger->set_level(spdlog::level::warn);
logger->set_level(spdlog::level::info);
#endif
spdlog::register_logger(logger);

View File

@@ -9,6 +9,12 @@
int main(const int argc, char** argv) {
Options options = parse(argc, argv);
Application app(options);
app.assemble();
if (options.graphFilename.has_value()) {
app.save_graph(options.graphFilename.value());
spdlog::get("app")->info("Exiting..");
return 0;
}
app.run();
return 0;