summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ctor.h9
-rw-r--r--src/task_fn.cc140
-rw-r--r--src/task_fn.h4
-rw-r--r--src/tasks.cc16
-rw-r--r--src/util.h4
5 files changed, 152 insertions, 21 deletions
diff --git a/src/ctor.h b/src/ctor.h
index 27b30af..0dcf56b 100644
--- a/src/ctor.h
+++ b/src/ctor.h
@@ -218,6 +218,11 @@ using GeneratorCb = std::function<int(const std::string& input,
const build_configuration& config,
const ctor::settings& settings)>;
+using GeneratorCb2 = std::function<int(const std::vector<std::string>& input,
+ const std::string& output,
+ const ctor::build_configuration& config,
+ const ctor::settings& settings)>;
+
struct build_configuration
{
std::string name; // Name - used for referring in other configurations.
@@ -228,7 +233,9 @@ struct build_configuration
std::vector<std::string> depends; // internal target dependencies
ctor::flags flags;
std::vector<std::string> externals; // externals used by this configuration
- GeneratorCb function;
+ std::variant<std::monostate,
+ GeneratorCb,
+ GeneratorCb2> function;
};
using build_configurations = std::vector<build_configuration>;
diff --git a/src/task_fn.cc b/src/task_fn.cc
index b6b50ea..a984ef8 100644
--- a/src/task_fn.cc
+++ b/src/task_fn.cc
@@ -20,6 +20,12 @@ TaskFn::TaskFn(const ctor::build_configuration& config_, const ctor::settings& s
{
sourceFile /= source.file;
+ for(const auto& src : config.sources)
+ {
+ auto _src = sourceFile / src.file;
+ sources.push_back(_src.string());
+ }
+
std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceFile.parent_path());
target_type = config.type;
@@ -27,29 +33,90 @@ TaskFn::TaskFn(const ctor::build_configuration& config_, const ctor::settings& s
if(source.output.empty())
{
- std::cerr << "Missing output file for functional target\n";
- exit(1);
+ std::filesystem::path base = sourceFile.parent_path();
+ _targetFile =
+ //std::filesystem::path(settings.builddir) /
+ base / config.target;
+ }
+ else
+ {
+ _targetFile = source.output;
}
- _targetFile = source.output;
+ sourceListFile = targetFile().parent_path() / targetFile().filename();
+ sourceListFile += ".sources";
}
bool TaskFn::dirtyInner()
{
- if(!std::filesystem::exists(sourceFile))
+ if(!std::filesystem::exists(targetFile()))
{
- //std::cout << "Missing source file: " << std::string(sourceFile) << "\n";
+ //std::cout << "Missing targetFile\n";
return true;
}
- if(!std::filesystem::exists(targetFile()))
+ if(!std::filesystem::exists(sourceListFile))
{
- //std::cout << "Missing targetFile\n";
+ //std::cout << "Missing sourceListFile\n";
return true;
}
- if(std::filesystem::last_write_time(sourceFile) >
- std::filesystem::last_write_time(targetFile()))
+ {
+ auto lastSourceList = readFile(sourceListFile.string());
+ if(sourceListString() != lastSourceList)
+ {
+ //std::cout << "The compiler sourceList changed\n";
+ return true;
+ }
+ }
+
+ std::filesystem::file_time_type last_changed{};
+ bool missing{false};
+ const auto visitor = overloaded
+ {
+ [](std::monostate) {},
+ [&](ctor::GeneratorCb)
+ {
+ if(!std::filesystem::exists(sourceFile))
+ {
+ missing = true;
+ }
+ last_changed = std::filesystem::last_write_time(sourceFile);
+ },
+ [&](ctor::GeneratorCb2)
+ {
+ bool first{true};
+ for(const auto& source : sources)
+ {
+ if(!std::filesystem::exists(source))
+ {
+ missing |= true;
+ }
+ else
+ {
+ if(first)
+ {
+ last_changed = std::filesystem::last_write_time(source);
+ }
+ else
+ {
+ last_changed =
+ std::max(last_changed,
+ std::filesystem::last_write_time(source));
+ }
+ }
+ first = false;
+ }
+ },
+ };
+ std::visit(visitor, config.function);
+
+ if(missing)
+ {
+ return true;
+ }
+
+ if(last_changed > std::filesystem::last_write_time(targetFile()))
{
//std::cout << "The targetFile older than sourceFile\n";
return true;
@@ -60,10 +127,17 @@ bool TaskFn::dirtyInner()
int TaskFn::runInner()
{
- if(!std::filesystem::exists(sourceFile))
- {
- std::cout << "Missing source file: " << sourceFile.string() << "\n";
- return 1;
+// if(!std::filesystem::exists(sourceFile))
+// {
+// std::cout << "Missing source file: " << sourceFile.string() << "\n";
+// return 1;
+// }
+
+ { // Write sourceList to file.
+ std::ofstream sourceListStream(sourceListFile.string());
+ std::cout << "Write to sources file: " << sourceListFile.string() << '\n';
+ sourceListStream << sourceListString();
+ std::cout << "Content: " << sourceListString() << '\n';
}
if(settings.verbose >= 0)
@@ -74,10 +148,26 @@ int TaskFn::runInner()
std::cout << output << std::flush;
}
- auto res = config.function(sourceFile.string(),
- targetFile().string(),
- config,
- settings);
+ int res{};
+ const auto visitor = overloaded
+ {
+ [](std::monostate) {},
+ [&](ctor::GeneratorCb cb)
+ {
+ res = cb(sourceFile.string(),
+ targetFile().string(),
+ config,
+ settings);
+ },
+ [&](ctor::GeneratorCb2 cb)
+ {
+ res = cb(sources,
+ targetFile().string(),
+ config,
+ settings);
+ },
+ };
+ std::visit(visitor, config.function);
if(res != 0)
{
std::filesystem::remove(targetFile());
@@ -94,6 +184,12 @@ int TaskFn::clean()
std::filesystem::remove(targetFile());
}
+ if(std::filesystem::exists(sourceListFile))
+ {
+ std::cout << "Removing " << sourceListFile.string() << "\n";
+ std::filesystem::remove(sourceListFile);
+ }
+
return 0;
}
@@ -112,6 +208,16 @@ std::filesystem::path TaskFn::targetFile() const
return std::filesystem::path(settings.builddir) / sourceDir / _targetFile;
}
+std::string TaskFn::sourceListString() const
+{
+ std::string sourceListStr;
+ for(const auto& source : config.sources)
+ {
+ sourceListStr += " " + source.file;
+ }
+ return sourceListStr;
+}
+
bool TaskFn::derived() const
{
return false;
diff --git a/src/task_fn.h b/src/task_fn.h
index 1bad32c..7740f9e 100644
--- a/src/task_fn.h
+++ b/src/task_fn.h
@@ -28,6 +28,7 @@ public:
std::string target() const override;
std::filesystem::path targetFile() const override;
+ std::string sourceListString() const;
bool derived() const override;
std::string toJSON() const override;
@@ -37,8 +38,11 @@ public:
protected:
std::filesystem::path sourceFile;
std::filesystem::path _targetFile;
+ std::filesystem::path sourceListFile;
const ctor::build_configuration& config;
const ctor::settings& settings;
std::filesystem::path sourceDir;
+
+ std::vector<std::string> sources;
};
diff --git a/src/tasks.cc b/src/tasks.cc
index 94fe269..82d044e 100644
--- a/src/tasks.cc
+++ b/src/tasks.cc
@@ -85,7 +85,7 @@ std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration&
ctor::target_type target_type{config.type};
if(target_type == ctor::target_type::automatic)
{
- if(config.function != nullptr)
+ if(!std::holds_alternative<std::monostate>(config.function))
{
target_type = ctor::target_type::function;
}
@@ -114,12 +114,22 @@ std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration&
#ifndef BOOTSTRAP
else
{
- for(const auto& file : config.sources)
+ bool multi{std::holds_alternative<ctor::GeneratorCb2>(config.function)};
+ if(multi)
{
- auto task = std::make_shared<TaskFn>(config, settings, sourceDir, file);
+ auto task = std::make_shared<TaskFn>(config, settings, sourceDir, "");
tasks.push_back(task);
objects.push_back(task->target());
}
+ else
+ {
+ for(const auto& file : config.sources)
+ {
+ auto task = std::make_shared<TaskFn>(config, settings, sourceDir, file);
+ tasks.push_back(task);
+ objects.push_back(task->target());
+ }
+ }
}
#endif
diff --git a/src/util.h b/src/util.h
index 38d89f2..3e689eb 100644
--- a/src/util.h
+++ b/src/util.h
@@ -39,3 +39,7 @@ std::vector<std::string> argsplit(const std::string& str);
//! Calls the system getenv and sets the string if the env name it exists.
//! \returns true if the env name existed, false otherwise.
bool get_env(std::string_view name, std::string& value);
+
+// helper type for the visitor
+template<class... Ts>
+struct overloaded : Ts... { using Ts::operator()...; };