summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2021-06-23 07:37:08 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2021-06-23 07:37:08 +0200
commite4c0168e4e8834aea0cfe06b8b2fc8bd63f591bb (patch)
treeaa8060de3abd73dfbf89ed35d054fc470cf445ea
parent68bf2848332fd15a2b6dfa49f3a58fccd899dbd7 (diff)
Split libcppbuild.cc into multiple files/modules.
-rw-r--r--.gitignore3
-rw-r--r--Makefile3
-rw-r--r--configure.cc153
-rw-r--r--configure.h19
-rw-r--r--libcppbuild.cc401
-rw-r--r--rebuild.cc137
-rw-r--r--rebuild.h24
-rw-r--r--tasks.cc123
-rw-r--r--tasks.h18
-rw-r--r--toolchain.cc17
-rw-r--r--toolchain.h14
11 files changed, 515 insertions, 397 deletions
diff --git a/.gitignore b/.gitignore
index 7d69636..94dd838 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,6 @@ build/
cppbuild
*.a
*.o
+*.d
+configuration.cc
+config.h
diff --git a/Makefile b/Makefile
index 14d909e..59e883e 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,9 @@ SRC = \
task_so.cc \
task.cc \
execute.cc \
+ configure.cc \
+ rebuild.cc \
+ tasks.cc \
OBJ = $(patsubst %.cc,%.o,$(SRC))
diff --git a/configure.cc b/configure.cc
new file mode 100644
index 0000000..e84f808
--- /dev/null
+++ b/configure.cc
@@ -0,0 +1,153 @@
+#include "configure.h"
+
+#include <iostream>
+#include <filesystem>
+#include <fstream>
+
+#include <getoptpp/getoptpp.hpp>
+
+#include "settings.h"
+#include "execute.h"
+#include "libcppbuild.h"
+#include "tasks.h"
+
+std::filesystem::path configurationFile("configuration.cc");
+std::filesystem::path configHeaderFile("config.h");
+
+const std::map<std::string, std::string> default_configuration{};
+const std::map<std::string, std::string>& __attribute__((weak)) configuration()
+{
+ return default_configuration;
+}
+
+bool hasConfiguration(const std::string& key)
+{
+ const auto& c = configuration();
+ return c.find(key) != c.end();
+}
+
+const std::string& getConfiguration(const std::string& key,
+ const std::string& defaultValue)
+{
+ const auto& c = configuration();
+ if(hasConfiguration(key))
+ {
+ return c.at(key);
+ }
+
+ return defaultValue;
+}
+
+int configure(int argc, char* argv[])
+{
+ Settings settings;
+
+ settings.builddir = "build";
+
+ std::string cmd_str;
+ for(int i = 0; i < argc; ++i)
+ {
+ if(i > 0)
+ {
+ cmd_str += " ";
+ }
+ cmd_str += argv[i];
+ }
+
+ dg::Options opt;
+ int key{256};
+
+ std::string build_arch;
+ std::string host_arch;
+
+ opt.add("build-dir", required_argument, 'b',
+ "Set output directory for build files (default: '" +
+ settings.builddir + "').",
+ [&]() {
+ settings.builddir = optarg;
+ return 0;
+ });
+
+ opt.add("verbose", no_argument, 'v',
+ "Be verbose. Add multiple times for more verbosity.",
+ [&]() {
+ settings.verbose++;
+ return 0;
+ });
+
+ opt.add("build", required_argument, key++,
+ "Configure for building on specified architecture.",
+ [&]() {
+ build_arch = optarg;
+ return 0;
+ });
+
+ opt.add("host", required_argument, key++,
+ "Cross-compile to build programs to run on specified architecture.",
+ [&]() {
+ host_arch = optarg;
+ return 0;
+ });
+
+ opt.add("help", no_argument, 'h',
+ "Print this help text.",
+ [&]() {
+ std::cout << "configure usage stuff\n";
+ opt.help();
+ exit(0);
+ return 0;
+ });
+
+ opt.process(argc, argv);
+
+ if(host_arch.empty())
+ {
+ host_arch = build_arch;
+ }
+
+ auto tasks = getTasks(settings);
+
+ bool needs_cpp{false};
+ bool needs_c{false};
+ bool needs_ar{false};
+ for(const auto& task :tasks)
+ {
+ switch(task->sourceLanguage())
+ {
+ case Language::Auto:
+ std::cerr << "TargetLanguage not deduced!\n";
+ exit(1);
+ break;
+ case Language::C:
+ needs_cpp = false;
+ break;
+ case Language::Cpp:
+ needs_c = true;
+ break;
+ }
+ }
+
+ {
+ std::ofstream istr(configurationFile);
+ istr << "#include \"libcppbuild.h\"\n\n";
+ istr << "const std::map<std::string, std::string>& configuration()\n";
+ istr << "{\n";
+ istr << " static std::map<std::string, std::string> c =\n";
+ istr << " {\n";
+ istr << " { \"cmd\", \"" << cmd_str << "\" },\n";
+ istr << " { \"" << cfg::builddir << "\", \"" << settings.builddir << "\" },\n";
+ istr << " { \"" << cfg::target_cc << "\", \"/usr/bin/gcc\" },\n";
+ istr << " { \"" << cfg::target_cpp << "\", \"/usr/bin/g++\" },\n";
+ istr << " { \"" << cfg::target_ar << "\", \"/usr/bin/ar\" },\n";
+ istr << " { \"" << cfg::target_ld << "\", \"/usr/bin/ld\" },\n";
+ istr << " { \"" << cfg::host_cc << "\", \"/usr/bin/gcc\" },\n";
+ istr << " { \"" << cfg::host_cpp << "\", \"/usr/bin/g++\" },\n";
+ istr << " { \"" << cfg::host_ar << "\", \"/usr/bin/ar\" },\n";
+ istr << " { \"" << cfg::host_ld << "\", \"/usr/bin/ld\" },\n";
+ istr << " };\n";
+ istr << " return c;\n";
+ istr << "}\n";
+ }
+
+ return 0;
+}
diff --git a/configure.h b/configure.h
new file mode 100644
index 0000000..95b6765
--- /dev/null
+++ b/configure.h
@@ -0,0 +1,19 @@
+// -*- c++ -*-
+#pragma once
+
+#include <filesystem>
+#include <string>
+#include <map>
+
+extern std::filesystem::path configurationFile;;
+extern std::filesystem::path configHeaderFile;
+
+int configure(int argc, char* argv[]);
+
+bool hasConfiguration(const std::string& key);
+const std::string& getConfiguration(const std::string& key,
+ const std::string& defaultValue);
+
+const std::map<std::string, std::string>& configuration();
+
+extern const std::map<std::string, std::string> default_configuration;
diff --git a/libcppbuild.cc b/libcppbuild.cc
index 2a2c40d..6d1d6e5 100644
--- a/libcppbuild.cc
+++ b/libcppbuild.cc
@@ -14,411 +14,18 @@
#include <fstream>
#include <cstdlib>
#include <set>
+#include <future>
#include <getoptpp/getoptpp.hpp>
#include "libcppbuild.h"
-#include "task_cc.h"
-#include "task_ld.h"
-#include "task_ar.h"
-#include "task_so.h"
#include "settings.h"
-#include "execute.h"
-
-#include <unistd.h>
-
-
-namespace
-{
-std::filesystem::path configurationFile("configuration.cc");
-const std::map<std::string, std::string> default_configuration{};
-}
-const std::map<std::string, std::string>& __attribute__((weak)) configuration()
-{
- return default_configuration;
-}
-
-bool hasConfiguration(const std::string& key)
-{
- const auto& c = configuration();
- return c.find(key) != c.end();
-}
-
-const std::string& getConfiguration(const std::string& key,
- const std::string& defaultValue)
-{
- const auto& c = configuration();
- if(hasConfiguration(key))
- {
- return c.at(key);
- }
-
- return defaultValue;
-}
+#include "configure.h"
+#include "rebuild.h"
+#include "tasks.h"
using namespace std::chrono_literals;
-std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
- const Settings& settings,
- const std::string& sourceDir)
-{
- std::filesystem::path targetFile(config.target);
-
- TargetType target_type{config.type};
- if(target_type == TargetType::Auto)
- {
- if(targetFile.extension() == ".a")
- {
- target_type = TargetType::StaticLibrary;
- }
- else if(targetFile.extension() == ".so")
- {
- target_type = TargetType::DynamicLibrary;
- }
- else if(targetFile.extension() == "")
- {
- target_type = TargetType::Executable;
- }
- else
- {
- std::cerr << "Could not deduce target type from target " <<
- targetFile.string() << " please specify.\n";
- exit(1);
- }
- }
-
- std::vector<std::string> objects;
- std::list<std::shared_ptr<Task>> tasks;
- for(const auto& file : config.sources)
- {
- tasks.emplace_back(std::make_shared<TaskCC>(config, settings,
- sourceDir, file));
- objects.push_back(tasks.back()->target());
- }
-
- switch(target_type)
- {
- case TargetType::StaticLibrary:
- tasks.emplace_back(std::make_shared<TaskAR>(config, settings, config.target,
- objects));
- break;
-
- case TargetType::DynamicLibrary:
- if(targetFile.stem().string().substr(0, 3) != "lib")
- {
- std::cerr << "Dynamic library target must have 'lib' prefix\n";
- exit(1);
- }
- tasks.emplace_back(std::make_shared<TaskSO>(config, settings, config.target,
- objects));
- break;
-
- case TargetType::Executable:
- tasks.emplace_back(std::make_shared<TaskLD>(config, settings, config.target,
- objects));
- break;
- }
-
- return tasks;
-}
-
-std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks,
- std::list<std::shared_ptr<Task>>& dirtyTasks)
-{
- for(auto dirtyTask = dirtyTasks.begin();
- dirtyTask != dirtyTasks.end();
- ++dirtyTask)
- {
- //std::cout << "Examining target " << (*dirtyTask)->target() << "\n";
- if((*dirtyTask)->ready())
- {
- dirtyTasks.erase(dirtyTask);
- return *dirtyTask;
- }
- }
-
- //std::cout << "No task ready ... \n";
- return nullptr;
-}
-
-namespace
-{
-struct BuildConfigurationEntry
-{
- const char* file;
- std::vector<BuildConfiguration> (*cb)();
-};
-std::array<BuildConfigurationEntry, 1024> configFiles;
-std::size_t numConfigFiles{0};
-}
-
-// TODO: Use c++20 when ready, somehing like this:
-//int reg(const std::source_location location = std::source_location::current())
-int reg(const char* location, std::vector<BuildConfiguration> (*cb)())
-{
- // NOTE: std::cout cannot be used here
- if(numConfigFiles >= configFiles.size())
- {
- fprintf(stderr, "Max %d build configurations currently supported.\n",
- (int)configFiles.size());
- exit(1);
- }
-
- configFiles[numConfigFiles].file = location;
- configFiles[numConfigFiles].cb = cb;
- ++numConfigFiles;
-
- return 0;
-}
-
-int unreg(const char* location)
-{
- std::size_t found{0};
- for(std::size_t i = 0; i < numConfigFiles;)
- {
- if(std::string(location) == configFiles[i].file)
- {
- ++found;
- for(std::size_t j = i; j < numConfigFiles; ++j)
- {
- configFiles[j] = configFiles[j + 1];
- }
- --numConfigFiles;
- }
- else
- {
- ++i;
- }
- }
-
- return found;
-}
-
-void recompileCheck(const Settings& settings, int argc, char* argv[],
- bool force = false)
-{
- bool dirty{force};
-
- std::vector<std::string> args;
- args.push_back("-s");
- args.push_back("-O3");
- args.push_back("-std=c++17");
- args.push_back("-pthread");
-
- std::filesystem::path binFile("cppbuild");
-
- if(std::filesystem::exists(configurationFile))
- {
- args.push_back(configurationFile.string());
-
- if(std::filesystem::last_write_time(binFile) <=
- std::filesystem::last_write_time(configurationFile))
- {
- dirty = true;
- }
-
- const auto& c = configuration();
- if(&c == &default_configuration)
- {
- // configuration.cc exists, but currently compiled with the default one.
- dirty = true;
- }
- }
-
- if(settings.verbose > 1)
- {
- std::cout << "Recompile check (" << numConfigFiles << "):\n";
- }
-
- for(std::size_t i = 0; i < numConfigFiles; ++i)
- {
- std::string location = configFiles[i].file;
- if(settings.verbose > 1)
- {
- std::cout << " - " << location << "\n";
- }
- std::filesystem::path configFile(location);
- if(std::filesystem::last_write_time(binFile) <=
- std::filesystem::last_write_time(configFile))
- {
- dirty = true;
- }
-
- // Support adding multiple config functions from the same file
- if(std::find(args.begin(), args.end(), location) == std::end(args))
- {
- args.push_back(location);
- }
- }
- args.push_back("libcppbuild.a");
- args.push_back("-o");
- args.push_back(binFile.string());
-
- if(dirty)
- {
- std::cout << "Rebuilding config\n";
- auto tool = getConfiguration(cfg::host_cpp, "/usr/bin/g++");
- auto ret = execute(tool, args, settings.verbose > 0);
- if(ret != 0)
- {
- std::cerr << "Failed: ." << ret << "\n";
- exit(1);
- }
- else
- {
- std::cout << "Re-launch\n";
- std::vector<std::string> args;
- for(int i = 1; i < argc; ++i)
- {
- args.push_back(argv[i]);
- }
- exit(execute(argv[0], args, settings.verbose > 0));
- }
- }
-}
-
-std::list<std::shared_ptr<Task>> getTasks(const Settings& settings)
-{
- static std::deque<BuildConfiguration> build_configs;
- std::list<std::shared_ptr<Task>> tasks;
- for(std::size_t i = 0; i < numConfigFiles; ++i)
- {
- std::string path =
- std::filesystem::path(configFiles[i].file).parent_path();
- if(settings.verbose > 1)
- {
- std::cout << configFiles[i].file << " in path " << path << "\n";
- }
- auto configs = configFiles[i].cb();
- for(const auto& config : configs)
- {
- build_configs.push_back(config);
- const auto& build_config = build_configs.back();
- std::vector<std::string> objects;
- auto t = taskFactory(build_config, settings, path);
- tasks.insert(tasks.end(), t.begin(), t.end());
- }
- }
-
- return tasks;
-}
-
-/*
-int configure(int argc, char* argv[])
-{
- Settings settings;
-
- settings.builddir = "build";
-
- std::string cmd_str;
- for(int i = 0; i < argc; ++i)
- {
- if(i > 0)
- {
- cmd_str += " ";
- }
- cmd_str += argv[i];
- }
-
- dg::Options opt;
- int key{256};
-
- std::string build_arch;
- std::string host_arch;
-
- opt.add("build-dir", required_argument, 'b',
- "Set output directory for build files (default: '" +
- settings.builddir + "').",
- [&]() {
- settings.builddir = optarg;
- return 0;
- });
-
- opt.add("verbose", no_argument, 'v',
- "Be verbose. Add multiple times for more verbosity.",
- [&]() {
- settings.verbose++;
- return 0;
- });
-
- opt.add("build", required_argument, key++,
- "Configure for building on specified architecture.",
- [&]() {
- build_arch = optarg;
- return 0;
- });
-
- opt.add("host", required_argument, key++,
- "Cross-compile to build programs to run on specified architecture.",
- [&]() {
- host_arch = optarg;
- return 0;
- });
-
- opt.add("help", no_argument, 'h',
- "Print this help text.",
- [&]() {
- std::cout << "configure usage stuff\n";
- opt.help();
- exit(0);
- return 0;
- });
-
- opt.process(argc, argv);
-
- if(host_arch.empty())
- {
- host_arch = build_arch;
- }
-
- auto tasks = getTasks(settings);
-
- bool needs_cpp{false};
- bool needs_c{false};
- bool needs_ar{false};
- for(const auto& task :tasks)
- {
- switch(task->sourceLanguage())
- {
- case Language::Auto:
- std::cerr << "TargetLanguage not deduced!\n";
- exit(1);
- break;
- case Language::C:
- needs_cpp = false;
- break;
- case Language::Cpp:
- needs_c = true;
- break;
- }
- }
-
- {
- std::ofstream istr(configurationFile);
- istr << "#include \"libcppbuild.h\"\n\n";
- istr << "const std::map<std::string, std::string>& configuration()\n";
- istr << "{\n";
- istr << " static std::map<std::string, std::string> c =\n";
- istr << " {\n";
- istr << " { \"cmd\", \"" << cmd_str << "\" },\n";
- istr << " { \"" << cfg::builddir << "\", \"" << settings.builddir << "\" },\n";
- istr << " { \"" << cfg::target_cc << "\", \"/usr/bin/gcc\" },\n";
- istr << " { \"" << cfg::target_cpp << "\", \"/usr/bin/g++\" },\n";
- istr << " { \"" << cfg::target_ar << "\", \"/usr/bin/ar\" },\n";
- istr << " { \"" << cfg::target_ld << "\", \"/usr/bin/ld\" },\n";
- istr << " { \"" << cfg::host_cc << "\", \"/usr/bin/gcc\" },\n";
- istr << " { \"" << cfg::host_cpp << "\", \"/usr/bin/g++\" },\n";
- istr << " { \"" << cfg::host_ar << "\", \"/usr/bin/ar\" },\n";
- istr << " { \"" << cfg::host_ld << "\", \"/usr/bin/ld\" },\n";
- istr << " };\n";
- istr << " return c;\n";
- istr << "}\n";
- }
-
-
- return 0;
-}
-
int main(int argc, char* argv[])
{
if(argc > 1 && std::string(argv[1]) == "configure")
diff --git a/rebuild.cc b/rebuild.cc
new file mode 100644
index 0000000..0978eb1
--- /dev/null
+++ b/rebuild.cc
@@ -0,0 +1,137 @@
+#include "rebuild.h"
+
+#include <iostream>
+#include <filesystem>
+#include <algorithm>
+
+#include "execute.h"
+#include "configure.h"
+#include "settings.h"
+#include "libcppbuild.h"
+
+std::array<BuildConfigurationEntry, 1024> configFiles;
+std::size_t numConfigFiles{0};
+
+// TODO: Use c++20 when ready, somehing like this:
+//int reg(const std::source_location location = std::source_location::current())
+int reg(const char* location, std::vector<BuildConfiguration> (*cb)())
+{
+ // NOTE: std::cout cannot be used here
+ if(numConfigFiles >= configFiles.size())
+ {
+ fprintf(stderr, "Max %d build configurations currently supported.\n",
+ (int)configFiles.size());
+ exit(1);
+ }
+
+ configFiles[numConfigFiles].file = location;
+ configFiles[numConfigFiles].cb = cb;
+ ++numConfigFiles;
+
+ return 0;
+}
+
+int unreg(const char* location)
+{
+ std::size_t found{0};
+ for(std::size_t i = 0; i < numConfigFiles;)
+ {
+ if(std::string(location) == configFiles[i].file)
+ {
+ ++found;
+ for(std::size_t j = i; j < numConfigFiles; ++j)
+ {
+ configFiles[j] = configFiles[j + 1];
+ }
+ --numConfigFiles;
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ return found;
+}
+
+void recompileCheck(const Settings& settings, int argc, char* argv[], bool force)
+{
+ bool dirty{force};
+
+ std::vector<std::string> args;
+ args.push_back("-s");
+ args.push_back("-O3");
+ args.push_back("-std=c++17");
+ args.push_back("-pthread");
+
+ std::filesystem::path binFile("cppbuild");
+
+ if(std::filesystem::exists(configurationFile))
+ {
+ args.push_back(configurationFile.string());
+
+ if(std::filesystem::last_write_time(binFile) <=
+ std::filesystem::last_write_time(configurationFile))
+ {
+ dirty = true;
+ }
+
+ const auto& c = configuration();
+ if(&c == &default_configuration)
+ {
+ // configuration.cc exists, but currently compiled with the default one.
+ dirty = true;
+ }
+ }
+
+ if(settings.verbose > 1)
+ {
+ std::cout << "Recompile check (" << numConfigFiles << "):\n";
+ }
+
+ for(std::size_t i = 0; i < numConfigFiles; ++i)
+ {
+ std::string location = configFiles[i].file;
+ if(settings.verbose > 1)
+ {
+ std::cout << " - " << location << "\n";
+ }
+ std::filesystem::path configFile(location);
+ if(std::filesystem::last_write_time(binFile) <=
+ std::filesystem::last_write_time(configFile))
+ {
+ dirty = true;
+ }
+
+ // Support adding multiple config functions from the same file
+ if(std::find(args.begin(), args.end(), location) == std::end(args))
+ {
+ args.push_back(location);
+ }
+ }
+ args.push_back("libcppbuild.a");
+ args.push_back("-o");
+ args.push_back(binFile.string());
+
+ if(dirty)
+ {
+ std::cout << "Rebuilding config\n";
+ auto tool = getConfiguration(cfg::host_cpp, "/usr/bin/g++");
+ auto ret = execute(tool, args, settings.verbose > 0);
+ if(ret != 0)
+ {
+ std::cerr << "Failed: ." << ret << "\n";
+ exit(1);
+ }
+ else
+ {
+ std::cout << "Re-launch\n";
+ std::vector<std::string> args;
+ for(int i = 1; i < argc; ++i)
+ {
+ args.push_back(argv[i]);
+ }
+ exit(execute(argv[0], args, settings.verbose > 0));
+ }
+ }
+}
diff --git a/rebuild.h b/rebuild.h
new file mode 100644
index 0000000..d7720c9
--- /dev/null
+++ b/rebuild.h
@@ -0,0 +1,24 @@
+// -*- c++ -*-
+#pragma once
+
+#include <vector>
+#include <array>
+
+#include "libcppbuild.h"
+
+class Settings;
+
+struct BuildConfigurationEntry
+{
+ const char* file;
+ std::vector<BuildConfiguration> (*cb)();
+};
+
+extern std::array<BuildConfigurationEntry, 1024> configFiles;
+extern std::size_t numConfigFiles;
+
+//int reg(const char* location, std::vector<BuildConfiguration> (*cb)());
+int unreg(const char* location);
+
+void recompileCheck(const Settings& settings, int argc, char* argv[],
+ bool force = false);
diff --git a/tasks.cc b/tasks.cc
new file mode 100644
index 0000000..641e05b
--- /dev/null
+++ b/tasks.cc
@@ -0,0 +1,123 @@
+#include "tasks.h"
+
+#include <filesystem>
+#include <deque>
+#include <iostream>
+
+#include "settings.h"
+#include "libcppbuild.h"
+#include "task.h"
+#include "task_cc.h"
+#include "task_ld.h"
+#include "task_ar.h"
+#include "task_so.h"
+#include "rebuild.h"
+
+std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
+ const Settings& settings,
+ const std::string& sourceDir)
+{
+ std::filesystem::path targetFile(config.target);
+
+ TargetType target_type{config.type};
+ if(target_type == TargetType::Auto)
+ {
+ if(targetFile.extension() == ".a")
+ {
+ target_type = TargetType::StaticLibrary;
+ }
+ else if(targetFile.extension() == ".so")
+ {
+ target_type = TargetType::DynamicLibrary;
+ }
+ else if(targetFile.extension() == "")
+ {
+ target_type = TargetType::Executable;
+ }
+ else
+ {
+ std::cerr << "Could not deduce target type from target " <<
+ targetFile.string() << " please specify.\n";
+ exit(1);
+ }
+ }
+
+ std::vector<std::string> objects;
+ std::list<std::shared_ptr<Task>> tasks;
+ for(const auto& file : config.sources)
+ {
+ tasks.emplace_back(std::make_shared<TaskCC>(config, settings,
+ sourceDir, file));
+ objects.push_back(tasks.back()->target());
+ }
+
+ switch(target_type)
+ {
+ case TargetType::StaticLibrary:
+ tasks.emplace_back(std::make_shared<TaskAR>(config, settings, config.target,
+ objects));
+ break;
+
+ case TargetType::DynamicLibrary:
+ if(targetFile.stem().string().substr(0, 3) != "lib")
+ {
+ std::cerr << "Dynamic library target must have 'lib' prefix\n";
+ exit(1);
+ }
+ tasks.emplace_back(std::make_shared<TaskSO>(config, settings, config.target,
+ objects));
+ break;
+
+ case TargetType::Executable:
+ tasks.emplace_back(std::make_shared<TaskLD>(config, settings, config.target,
+ objects));
+ break;
+ }
+
+ return tasks;
+}
+
+std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks,
+ std::list<std::shared_ptr<Task>>& dirtyTasks)
+{
+ for(auto dirtyTask = dirtyTasks.begin();
+ dirtyTask != dirtyTasks.end();
+ ++dirtyTask)
+ {
+ //std::cout << "Examining target " << (*dirtyTask)->target() << "\n";
+ if((*dirtyTask)->ready())
+ {
+ dirtyTasks.erase(dirtyTask);
+ return *dirtyTask;
+ }
+ }
+
+ //std::cout << "No task ready ... \n";
+ return nullptr;
+}
+
+std::list<std::shared_ptr<Task>> getTasks(const Settings& settings)
+{
+ static std::deque<BuildConfiguration> build_configs;
+ std::list<std::shared_ptr<Task>> tasks;
+ for(std::size_t i = 0; i < numConfigFiles; ++i)
+ {
+ std::string path =
+ std::filesystem::path(configFiles[i].file).parent_path();
+ if(settings.verbose > 1)
+ {
+ std::cout << configFiles[i].file << " in path " << path << "\n";
+ }
+ auto configs = configFiles[i].cb();
+ for(const auto& config : configs)
+ {
+ build_configs.push_back(config);
+ const auto& build_config = build_configs.back();
+ std::vector<std::string> objects;
+ auto t = taskFactory(build_config, settings, path);
+ tasks.insert(tasks.end(), t.begin(), t.end());
+ }
+ }
+
+ return tasks;
+}
diff --git a/tasks.h b/tasks.h
new file mode 100644
index 0000000..119c7d6
--- /dev/null
+++ b/tasks.h
@@ -0,0 +1,18 @@
+// -*- c++ -*-
+#pragma once
+
+#include <string>
+#include <list>
+#include <memory>
+
+#include "task.h"
+
+class BuildConfiguration;
+class Settings;
+
+std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
+ const Settings& settings,
+ const std::string& sourceDir);
+std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks,
+ std::list<std::shared_ptr<Task>>& dirtyTasks);
+std::list<std::shared_ptr<Task>> getTasks(const Settings& settings);
diff --git a/toolchain.cc b/toolchain.cc
new file mode 100644
index 0000000..0a8ea98
--- /dev/null
+++ b/toolchain.cc
@@ -0,0 +1,17 @@
+#include "toolchain.h"
+
+#include "libcppbuild.h"
+
+std::string getTool(Tool tool)
+{
+ auto prefix = getConfiguration("prefix");
+
+ switch(tool)
+ {
+ case Tool::CCompiler:
+ case Tool::CppCompiler:
+ case Tool::Archiver:
+ case Tool::Linker:
+ break;
+ }
+}
diff --git a/toolchain.h b/toolchain.h
new file mode 100644
index 0000000..d3de9a1
--- /dev/null
+++ b/toolchain.h
@@ -0,0 +1,14 @@
+// -*- c++ -*-
+#pragma once
+
+#include <string>
+
+enum class Tool
+{
+ CCompiler,
+ CppCompiler,
+ Archiver,
+ Linker,
+}
+
+std::string getTool(Tool tool);