summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2021-10-14 22:19:26 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2021-10-14 22:19:26 +0200
commitc0eacf8e85003844b95e71b9004fa464d4586a38 (patch)
treea407dc8ec3830cb01faf3d5153c8741f9b19e1c1
parent87aad8c76eb2371720c9aceef7516ecb0859ecdf (diff)
Use dependency system and build system for compiling ctor on config changes.
-rwxr-xr-xbootstrap.sh5
-rw-r--r--src/build.cc5
-rw-r--r--src/configure.cc7
-rw-r--r--src/configure.h4
-rw-r--r--src/libctor.cc21
-rw-r--r--src/libctor.h15
-rw-r--r--src/rebuild.cc110
-rw-r--r--src/settings.h6
-rw-r--r--src/task.cc7
-rw-r--r--src/task_cc.cc27
-rw-r--r--src/tasks.cc3
-rw-r--r--src/tasks.h6
-rw-r--r--test/ctor.cc3
-rw-r--r--test/tasks_test.cc22
14 files changed, 136 insertions, 105 deletions
diff --git a/bootstrap.sh b/bootstrap.sh
index fd9b605..06cd903 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -1,6 +1,7 @@
#!/bin/sh
echo "Bootstrapping..."
-g++ -std=c++17 -O3 -Isrc -pthread src/bootstrap.cc ctor.cc test/ctor.cc -o ctor && \
+g++ -std=c++17 -Wall -O3 -Isrc -pthread src/bootstrap.cc ctor.cc test/ctor.cc -o ctor && \
./ctor && \
-g++ -std=c++17 -O3 -Isrc -pthread ctor.cc test/ctor.cc -Lbuild -lctor -o ctor && \
+g++ -std=c++17 -Wall -O3 -Isrc -pthread ctor.cc test/ctor.cc -Lbuild -lctor -o ctor && \
+./ctor configure --ctor-includedir=src --ctor-libdir=build && \
echo "Done. Now run ./ctor to (re)build."
diff --git a/src/build.cc b/src/build.cc
index 777f5e8..2412b84 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -33,7 +33,10 @@ int build(const Settings& settings,
if(dirtyTasks.empty())
{
- std::cout << "Nothing to be done for '"<< name << "'\n";
+ if(settings.verbose > -1)
+ {
+ std::cout << "Nothing to be done for '"<< name << "'\n";
+ }
return 0;
}
diff --git a/src/configure.cc b/src/configure.cc
index 9eca0d6..675699d 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -120,12 +120,9 @@ std::string locate(const std::string& arch, const std::string& app)
return {};
}
-int configure(int argc, char* argv[])
+int configure(const Settings& global_settings, int argc, char* argv[])
{
- Settings settings;
-
- settings.builddir = "build";
-
+ Settings settings{global_settings};
std::string cmd_str;
for(int i = 0; i < argc; ++i)
{
diff --git a/src/configure.h b/src/configure.h
index de1b7e0..a350820 100644
--- a/src/configure.h
+++ b/src/configure.h
@@ -7,10 +7,12 @@
#include <string>
#include <map>
+struct Settings;
+
extern std::filesystem::path configurationFile;;
extern std::filesystem::path configHeaderFile;
-int configure(int argc, char* argv[]);
+int configure(const Settings& settings, int argc, char* argv[]);
bool hasConfiguration(const std::string& key);
const std::string& getConfiguration(const std::string& key,
diff --git a/src/libctor.cc b/src/libctor.cc
index 4d0d6d9..ca60de2 100644
--- a/src/libctor.cc
+++ b/src/libctor.cc
@@ -26,19 +26,19 @@
#include "tasks.h"
#include "build.h"
#include "unittest.h"
+
int main(int argc, char* argv[])
{
- if(argc > 1 && std::string(argv[1]) == "configure")
- {
- return configure(argc, argv);
- }
-
Settings settings{};
- settings.builddir = getConfiguration(cfg::builddir, "build");
+ settings.builddir = getConfiguration(cfg::builddir, settings.builddir);
settings.parallel_processes =
std::max(1u, std::thread::hardware_concurrency() * 2 - 1);
- settings.verbose = 0;
+
+ if(argc > 1 && std::string(argv[1]) == "configure")
+ {
+ return configure(settings, argc, argv);
+ }
bool write_compilation_database{false};
std::string compilation_database;
@@ -85,6 +85,13 @@ int main(int argc, char* argv[])
return 0;
});
+ opt.add("quiet", no_argument, 'q',
+ "Be completely silent.",
+ [&]() {
+ settings.verbose = -1;
+ return 0;
+ });
+
opt.add("add", required_argument, 'a',
"Add specified file to the build configurations.",
[&]() {
diff --git a/src/libctor.h b/src/libctor.h
index 6026ffb..5c22614 100644
--- a/src/libctor.h
+++ b/src/libctor.h
@@ -35,14 +35,10 @@ enum class OutputSystem
struct Source
{
- Source(const char* file)
- : file(file) {}
- Source(const std::string& file)
- : file(file) {}
- Source(const char* file, Language language)
- : file(file), language(language) {}
- Source(const std::string& file, Language language)
- : file(file), language(language) {}
+ Source(const char* file) : file(file) {}
+ Source(const std::string& file) : file(file) {}
+ Source(const char* file, Language lang) : file(file), language(lang) {}
+ Source(const std::string& file, Language lang) : file(file), language(lang) {}
std::string file;
Language language{Language::Auto};
@@ -50,9 +46,10 @@ struct Source
struct BuildConfiguration
{
+ std::string name; // Name - used for referring in other configurations.
TargetType type{TargetType::Auto};
OutputSystem system{OutputSystem::Host};
- std::string target;
+ std::string target; // Output target file for this configuration
std::vector<Source> sources; // source list
std::vector<std::string> depends; // internal dependencies
std::vector<std::string> cxxflags; // flags for c++ compiler
diff --git a/src/rebuild.cc b/src/rebuild.cc
index 7c90fca..e017d92 100644
--- a/src/rebuild.cc
+++ b/src/rebuild.cc
@@ -7,10 +7,11 @@
#include <filesystem>
#include <algorithm>
-#include "execute.h"
#include "configure.h"
#include "settings.h"
#include "libctor.h"
+#include "tasks.h"
+#include "build.h"
std::array<BuildConfigurationEntry, 1024> configFiles;
std::size_t numConfigFiles{0};
@@ -57,100 +58,87 @@ int unreg(const char* location)
return found;
}
-void recompileCheck(const Settings& settings, int argc, char* argv[],
+namespace
+{
+bool contains(const std::vector<Source>& sources, const std::string& file)
+{
+ for(const auto& source : sources)
+ {
+ if(source.file == file)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+}
+
+void recompileCheck(const Settings& global_settings, int argc, char* argv[],
bool force, bool relaunch_allowed)
{
using namespace std::string_literals;
- bool dirty{force};
+ if(global_settings.verbose > 1)
+ {
+ std::cout << "Recompile check (" << numConfigFiles << "):\n";
+ }
- std::vector<std::string> args;
- args.push_back("-s");
- args.push_back("-O3");
- args.push_back("-std=c++17");
+ BuildConfiguration config;
+ config.name = "ctor";
+ config.cxxflags = std::vector<std::string>({ "-s", "-O3", "-std=c++17" });
if(hasConfiguration(cfg::ctor_includedir))
{
- args.push_back("-I"s + getConfiguration(cfg::ctor_includedir));
+ config.cxxflags.push_back("-I"s + getConfiguration(cfg::ctor_includedir));
}
if(hasConfiguration(cfg::ctor_libdir))
{
- args.push_back("-L"s + getConfiguration(cfg::ctor_libdir));
+ config.ldflags.push_back("-L"s + getConfiguration(cfg::ctor_libdir));
}
- args.push_back("-lctor");
- args.push_back("-pthread");
+ config.ldflags.push_back("-lctor");
+ config.ldflags.push_back("-pthread");
- std::filesystem::path binFile(argv[0]);
- if(std::filesystem::exists(configurationFile))
- {
- args.push_back(configurationFile.string());
+ Settings settings{global_settings};
+ settings.verbose = -1; // Make check completely silent.
+ settings.builddir += "/ctor"; // override builddir to use ctor subdir
- 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;
- }
+ {
+ std::filesystem::path buildfile = settings.builddir;
+ std::filesystem::path currentfile = argv[0];
+ config.target = std::filesystem::relative(currentfile, buildfile).string();
}
- if(settings.verbose > 1)
+ if(std::filesystem::exists(configurationFile))
{
- std::cout << "Recompile check (" << numConfigFiles << "):\n";
+ config.sources.push_back(configurationFile.string());
}
for(std::size_t i = 0; i < numConfigFiles; ++i)
{
std::string location = configFiles[i].file;
- if(settings.verbose > 1)
+ if(global_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))
+ // Ensure that files containing multiple configurations are only added once.
+ if(!contains(config.sources, location))
{
- args.push_back(location);
+ config.sources.push_back(location);
}
}
- args.push_back("-o");
- args.push_back(binFile.string());
+ auto tasks = taskFactory({config}, settings, {});
- if(dirty)
+ for(auto task : tasks)
{
- std::cout << "Rebuilding config\n";
- auto tool = getConfiguration(cfg::build_cxx, "/usr/bin/g++");
- auto ret = execute(tool, args, settings.verbose > 0);
- if(ret != 0)
+ if(task->registerDepTasks(tasks))
{
- std::cerr << "Failed: ." << ret << "\n";
- exit(1);
- }
- else
- {
- if(relaunch_allowed)
- {
- 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));
- }
+ return;
}
}
+
+ build(settings, "ctor", tasks);
}
diff --git a/src/settings.h b/src/settings.h
index d71717a..48e3619 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -7,7 +7,7 @@
struct Settings
{
- std::string builddir;
- std::size_t parallel_processes;
- int verbose{1};
+ std::string builddir{"build"};
+ std::size_t parallel_processes{1};
+ int verbose{0}; // -1: completely silent, 0: normal, 1: verbose, ...
};
diff --git a/src/task.cc b/src/task.cc
index 1c6c233..8a9eefa 100644
--- a/src/task.cc
+++ b/src/task.cc
@@ -38,7 +38,12 @@ int Task::registerDepTasks(const std::list<std::shared_ptr<Task>>& tasks)
std::string Task::name() const
{
- return config.target;
+ // If config name is not set, use target instead.
+ if(config.name.empty())
+ {
+ return config.target;
+ }
+ return config.name;
}
bool Task::dirty()
diff --git a/src/task_cc.cc b/src/task_cc.cc
index 73297f2..e4bd7aa 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -12,6 +12,31 @@
#include "execute.h"
#include "util.h"
+namespace
+{
+bool isClean(char c)
+{
+ return c != '.' && c != '/';
+}
+
+std::string cleanUp(const std::string& path)
+{
+ std::string cleaned;
+ for(const auto& c : path)
+ {
+ if(isClean(c))
+ {
+ cleaned += c;
+ }
+ else
+ {
+ cleaned += '_';
+ }
+ }
+ return cleaned;
+}
+}
+
TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,
const std::string& sourceDir, const Source& source)
: Task(config)
@@ -26,7 +51,7 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings,
base /= sourceFile.parent_path();
std::filesystem::create_directories(base);
- base /= config.target;
+ base /= cleanUp(config.target);
base += "-";
base += sourceFile.stem();
diff --git a/src/tasks.cc b/src/tasks.cc
index c280fb2..56988f9 100644
--- a/src/tasks.cc
+++ b/src/tasks.cc
@@ -43,8 +43,6 @@ const std::deque<Target>& getTargets(const Settings& settings)
return targets;
}
-namespace
-{
std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
const Settings& settings,
const std::string& sourceDir)
@@ -121,7 +119,6 @@ std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
return tasks;
}
-}
std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTasks,
std::list<std::shared_ptr<Task>>& dirtyTasks)
diff --git a/src/tasks.h b/src/tasks.h
index 54591a4..aaa3510 100644
--- a/src/tasks.h
+++ b/src/tasks.h
@@ -33,3 +33,9 @@ std::shared_ptr<Task> getNextTask(const std::list<std::shared_ptr<Task>>& allTas
//! dependency tasks (ie. objects tasks from their sources).
std::list<std::shared_ptr<Task>> getTasks(const Settings& settings,
const std::vector<std::string> names = {});
+
+//! Generate list of targets from a single configuration, including the final
+//! link target and all its objects files (if any).
+std::list<std::shared_ptr<Task>> taskFactory(const BuildConfiguration& config,
+ const Settings& settings,
+ const std::string& sourceDir);
diff --git a/test/ctor.cc b/test/ctor.cc
index 3d05e7f..61c3515 100644
--- a/test/ctor.cc
+++ b/test/ctor.cc
@@ -22,6 +22,7 @@ BuildConfigurations ctorTestConfigs()
"-I../src", "-Iuunit",
"-DOUTPUT=\"execute\"",
},
+ .ldflags = { "-pthread" },
},
{
.type = TargetType::UnitTest,
@@ -36,6 +37,7 @@ BuildConfigurations ctorTestConfigs()
"-I../src", "-Iuunit",
"-DOUTPUT=\"tasks\"",
},
+ .ldflags = { "-pthread" },
},
{
.type = TargetType::UnitTest,
@@ -50,6 +52,7 @@ BuildConfigurations ctorTestConfigs()
"-I../src", "-Iuunit",
"-DOUTPUT=\"source_type\"",
},
+ .ldflags = { "-pthread" },
},
};
}
diff --git a/test/tasks_test.cc b/test/tasks_test.cc
index 612d899..3c9243c 100644
--- a/test/tasks_test.cc
+++ b/test/tasks_test.cc
@@ -95,34 +95,34 @@ public:
void getTasks_test()
{
using namespace std::string_literals;
- Settings settings{};
+ Settings settings{ .builddir = "foo" };
{
auto tasks = getTasks(settings);
uASSERT_EQUAL(6u, tasks.size());
auto task = tasks.begin();
- uASSERT_EQUAL("test/target1-foo_cc.o"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target1-foo_cc.o"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target1-bar_c.o"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target1-bar_c.o"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target1"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target1"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target2"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target2"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target3"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target3"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target4"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target4"s, (*task)->target());
}
{
auto tasks = getTasks(settings, {"target1", "target3"});
uASSERT_EQUAL(4u, tasks.size());
auto task = tasks.begin();
- uASSERT_EQUAL("test/target1-foo_cc.o"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target1-foo_cc.o"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target1-bar_c.o"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target1-bar_c.o"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target1"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target1"s, (*task)->target());
task++;
- uASSERT_EQUAL("test/target3"s, (*task)->target());
+ uASSERT_EQUAL("foo/test/target3"s, (*task)->target());
}
{
auto tasks = getTasks(settings, {"no-such-target"});