summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jenkinsfile66
-rw-r--r--ctor.cc5
-rw-r--r--src/bootstrap.cc41
-rw-r--r--src/build.cc32
-rw-r--r--src/configure.cc43
-rw-r--r--src/configure.h4
-rw-r--r--src/ctor.h63
-rw-r--r--src/deps.cc120
-rw-r--r--src/deps.h12
-rw-r--r--src/execute.cc13
-rw-r--r--src/execute.h9
-rw-r--r--src/externals_manual.cc8
m---------src/getoptpp0
-rw-r--r--src/libctor.cc21
-rw-r--r--src/rebuild.cc48
-rw-r--r--src/task.cc21
-rw-r--r--src/task.h4
-rw-r--r--src/task_ar.cc23
-rw-r--r--src/task_cc.cc39
-rw-r--r--src/task_fn.cc21
-rw-r--r--src/task_ld.cc24
-rw-r--r--src/task_ld.h4
-rw-r--r--src/task_so.cc22
-rw-r--r--src/tasks.cc34
-rw-r--r--src/tasks.h3
-rw-r--r--src/tools.cc121
-rw-r--r--src/tools.h15
-rw-r--r--src/unittest.cc2
-rw-r--r--src/util.cc64
-rw-r--r--src/util.h1
-rw-r--r--test/ctor.cc20
-rw-r--r--test/deps_test.cc97
-rw-r--r--test/deps_test_data/empty.d0
-rw-r--r--test/deps_test_data/missing_colon.d1
-rw-r--r--test/deps_test_data/multiline.d4
-rw-r--r--test/deps_test_data/no_deps.d1
-rw-r--r--test/deps_test_data/no_newline.d1
-rw-r--r--test/deps_test_data/spaces.d1
-rw-r--r--test/deps_test_data/trivial.d1
-rw-r--r--test/execute_test.cc14
40 files changed, 692 insertions, 331 deletions
diff --git a/Jenkinsfile b/Jenkinsfile
index c95b0eb..290f412 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,56 +1,48 @@
pipeline {
- agent { label 'c++20' }
-
+ agent any
stages {
- stage('Clean') {
+ ////////////////////////////////////////////////////
+ stage('Linux gcc') {
+ agent { label 'linux && gcc && c++20' }
steps {
echo 'Cleaning workspace ...'
- sh 'rm -Rf build*'
- }
- }
- stage('Build-gcc') {
- steps {
+ sh 'git clean -d -x -f'
echo 'Building (gcc) ...'
- sh 'BUILDDIR=build-gcc CXX=g++ ./bootstrap.sh'
- }
- }
- stage('Test-gcc') {
- steps {
+ sh 'CXX=g++ ./bootstrap.sh'
echo 'Testing (gcc) ...'
sh './ctor check'
- }
- }
- stage('Test-suite-gcc') {
- steps {
echo 'Testing suite (gcc) ...'
- sh '(cd test/suite; CTORDIR=../../build-gcc CXX=g++ ./test.sh)'
+ sh '(cd test/suite; CTORDIR=../../build CXX=g++ ./test.sh)'
}
- }
- stage('Build-clang') {
- steps {
- echo 'Building (clang) ...'
- sh 'BUILDDIR=build-clang CXX=clang++ ./bootstrap.sh'
+ post {
+ always {
+ xunit(thresholds: [ skipped(failureThreshold: '0'),
+ failed(failureThreshold: '0') ],
+ tools: [ CppUnit(pattern: 'build/test/*.xml') ])
+ }
}
}
- stage('Test-clang') {
+ ////////////////////////////////////////////////////
+ stage('Linux clang') {
+ agent { label 'linux && clang && c++20' }
steps {
+ echo 'Cleaning workspace ...'
+ sh 'git clean -d -x -f'
+ echo 'Building (clang) ...'
+ sh 'CXX=clang++ ./bootstrap.sh'
echo 'Testing (clang) ...'
sh './ctor check'
- }
- }
- stage('Test-suite-clang') {
- steps {
echo 'Testing suite (clang) ...'
- sh '(cd test/suite; CTORDIR=../../build-clang CXX=clang++ ./test.sh)'
+ sh '(cd test/suite; CTORDIR=../../build CXX=clang++ ./test.sh)'
+ }
+ post {
+ always {
+ xunit(thresholds: [ skipped(failureThreshold: '0'),
+ failed(failureThreshold: '0') ],
+ tools: [ CppUnit(pattern: 'build/test/*.xml') ])
+ }
}
}
- }
-
- post {
- always {
- xunit(thresholds: [ skipped(failureThreshold: '0'),
- failed(failureThreshold: '0') ],
- tools: [ CppUnit(pattern: 'build-*/test/*.xml') ])
- }
+ ////////////////////////////////////////////////////
}
}
diff --git a/ctor.cc b/ctor.cc
index d0d53d8..0edd877 100644
--- a/ctor.cc
+++ b/ctor.cc
@@ -15,6 +15,7 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)
.sources = {
"src/build.cc",
"src/configure.cc",
+ "src/deps.cc",
"src/execute.cc",
"src/externals_manual.cc",
"src/libctor.cc",
@@ -37,6 +38,10 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)
"-g",
"-Wall",
"-Werror",
+ "-Wextra",
+ "-Wshadow",
+ "-Wconversion",
+// "-Wnrvo",
"-Isrc",
},
},
diff --git a/src/bootstrap.cc b/src/bootstrap.cc
index 55bd3e0..aa50561 100644
--- a/src/bootstrap.cc
+++ b/src/bootstrap.cc
@@ -4,6 +4,7 @@
#include <iostream>
#include <array>
#include <cstdlib>
+#include <span>
#define BOOTSTRAP
@@ -19,8 +20,8 @@
#include "build.cc"
#include "tools.cc"
-std::filesystem::path configurationFile("configuration.cc");
-std::filesystem::path configHeaderFile("config.h");
+const std::filesystem::path configurationFile("configuration.cc");
+const std::filesystem::path configHeaderFile("config.h");
const ctor::configuration& ctor::get_configuration()
{
@@ -42,44 +43,56 @@ bool ctor::configuration::has(const std::string& key) const
const std::string& ctor::configuration::get(const std::string& key, const std::string& default_value) const
{
- if(key == ctor::cfg::build_cxx && std::getenv("CXX"))
+ auto cxx_env = std::getenv("CXX");
+ if(key == ctor::cfg::build_cxx && cxx_env)
{
- static std::string s = std::getenv("CXX");
+ static std::string s = cxx_env;
return s;
}
- if(key == ctor::cfg::build_cc && std::getenv("CC"))
+ auto cc_env = std::getenv("CC");
+ if(key == ctor::cfg::build_cc && cc_env)
{
- static std::string s = std::getenv("CC");
+ static std::string s = cc_env;
return s;
}
- if(key == ctor::cfg::build_ld && std::getenv("LD"))
+ auto ld_env = std::getenv("LD");
+ if(key == ctor::cfg::build_ld && ld_env)
{
- static std::string s = std::getenv("LD");
+ static std::string s = ld_env;
return s;
}
- if(key == ctor::cfg::build_ar && std::getenv("AR"))
+ auto ar_env = std::getenv("AR");
+ if(key == ctor::cfg::build_ar && ar_env)
{
- static std::string s = std::getenv("AR");
+ static std::string s = ar_env;
return s;
}
- if(key == ctor::cfg::builddir && std::getenv("BUILDDIR"))
+ auto builddir_env = std::getenv("BUILDDIR");
+ if(key == ctor::cfg::builddir && builddir_env)
{
- static std::string s = std::getenv("BUILDDIR");
+ static std::string s = builddir_env;
return s;
}
return default_value;
}
+std::vector<std::string> readDeps(const std::string& depFile,
+ ctor::toolchain toolchain)
+{
+ return {};
+}
+
int main(int argc, char* argv[])
{
- if(argc > 1)
+ auto args = std::span(argv, static_cast<std::size_t>(argc));
+ if(args.size() > 1)
{
- std::cerr << "This is a minimal bootstrap version of " << argv[0] <<
+ std::cerr << "This is a minimal bootstrap version of " << args[0] <<
" which doesn't support any arguments\n";
return 1;
}
diff --git a/src/build.cc b/src/build.cc
index ea65656..906c3ea 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -38,7 +38,7 @@ int build(const ctor::settings& settings,
// Dry-run returns number of dirty tasks but otherwise does nothing.
if(dryrun)
{
- return dirtyTasks.size();
+ return static_cast<int>(dirtyTasks.size());
}
if(dirtyTasks.empty())
@@ -114,17 +114,15 @@ int build(const ctor::settings& settings,
}
}
- for(auto process = processes.begin();
- process != processes.end();
- ++process)
+ for(auto& process : processes)
{
- if(process->valid() == false)
+ if(process.valid() == false)
{
continue;
}
- process->wait();
- auto ret = process->get();
- if(ret != 0)
+ process.wait();
+ auto ret = process.get();
+ if (ret != 0)
{
return ret;
}
@@ -144,11 +142,11 @@ std::vector<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task)
for(const auto& dep : deps)
{
auto depSet = getDepTasks(dep);
- for(const auto& dep : depSet)
+ for(const auto& dep_inner : depSet)
{
- if(std::find(tasks.begin(), tasks.end(), dep) == tasks.end())
+ if(std::find(tasks.begin(), tasks.end(), dep_inner) == tasks.end())
{
- tasks.push_back(dep);
+ tasks.push_back(dep_inner);
}
}
}
@@ -171,11 +169,11 @@ int build(const ctor::settings& settings,
auto depSet = getDepTasks(task);
std::vector<std::shared_ptr<Task>> ts;
- for(const auto& task : depSet)
+ for(const auto& task_inner : depSet)
{
- if(std::find(ts.begin(), ts.end(), task) == ts.end())
+ if(std::find(ts.begin(), ts.end(), task_inner) == ts.end())
{
- ts.push_back(task);
+ ts.push_back(task_inner);
}
}
@@ -217,11 +215,11 @@ int build(const ctor::settings& settings,
task_found = true;
auto depSet = getDepTasks(task);
- for(const auto& task : depSet)
+ for(const auto& task_inner : depSet)
{
- if(std::find(ts.begin(), ts.end(), task) == ts.end())
+ if(std::find(ts.begin(), ts.end(), task_inner) == ts.end())
{
- ts.push_back(task);
+ ts.push_back(task_inner);
}
}
}
diff --git a/src/configure.cc b/src/configure.cc
index c08ed88..995e340 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -7,6 +7,7 @@
#include <filesystem>
#include <fstream>
#include <optional>
+#include <span>
#include <getoptpp/getoptpp.hpp>
@@ -18,8 +19,8 @@
#include "tools.h"
#include "util.h"
-std::filesystem::path configurationFile("configuration.cc");
-std::filesystem::path configHeaderFile("config.h");
+const std::filesystem::path configurationFile("configuration.cc");
+const std::filesystem::path configHeaderFile("config.h");
std::map<std::string, std::string> external_includedir;
std::map<std::string, std::string> external_libdir;
@@ -321,19 +322,19 @@ int regenerateCache(ctor::settings& settings,
}
auto add_path_args =
- [&](const std::string& name)
+ [&](const std::string& arg_name)
{
- opt.add(name + "-includedir", required_argument, key++,
- "Set path to " + name + " header file.",
+ opt.add(arg_name + "-includedir", required_argument, key++,
+ "Set path to " + arg_name + " header file.",
[&]() {
- external_includedir[name] = optarg;
+ external_includedir[arg_name] = optarg;
return 0;
});
- opt.add(name + "-libdir", required_argument, key++,
- "Set path to " + name + " libraries.",
+ opt.add(arg_name + "-libdir", required_argument, key++,
+ "Set path to " + arg_name + " libraries.",
[&]() {
- external_libdir[name] = optarg;
+ external_libdir[arg_name] = optarg;
return 0;
});
};
@@ -366,7 +367,7 @@ int regenerateCache(ctor::settings& settings,
return 0;
});
- opt.process(vargs.size(), vargs.data());
+ opt.process(static_cast<int>(vargs.size()), vargs.data());
if(host_arch_prefix.empty())
{
@@ -821,12 +822,14 @@ int regenerateCache(ctor::settings& settings,
int configure(const ctor::settings& global_settings, int argc, char* argv[])
{
+ auto args_span = std::span(argv, static_cast<std::size_t>(argc));
+
ctor::settings settings{global_settings};
std::vector<std::string> args;
- for(int i = 2; i < argc; ++i) // skip command and the first 'configure' arg
+ for(std::size_t i = 2; i < args_span.size(); ++i) // skip command and the first 'configure' arg
{
- args.push_back(argv[i]);
+ args.emplace_back(args_span[i]);
}
std::map<std::string, std::string> env;
@@ -860,7 +863,7 @@ int configure(const ctor::settings& global_settings, int argc, char* argv[])
env["PATH"] = path_env;
}
- auto ret = regenerateCache(settings, argv[0], args, env);
+ auto ret = regenerateCache(settings, args_span[0], args, env);
if(ret != 0)
{
return ret;
@@ -873,19 +876,21 @@ int configure(const ctor::settings& global_settings, int argc, char* argv[])
int reconfigure(const ctor::settings& global_settings, int argc, char* argv[])
{
+ auto args_span = std::span(argv, static_cast<std::size_t>(argc));
+
ctor::settings settings{global_settings};
bool no_rerun{false};
std::vector<std::string> args;
- for(int i = 2; i < argc; ++i) // skip executable name and 'reconfigure' arg
+ for(std::size_t i = 2; i < args_span.size(); ++i) // skip executable name and 'reconfigure' arg
{
- if(i == 2 && std::string(argv[i]) == "--no-rerun")
+ if(i == 2 && std::string(args_span[i]) == "--no-rerun")
{
no_rerun = true;
continue;
}
- args.push_back(argv[i]);
+ args.emplace_back(args_span[i]);
}
const auto& cfg = ctor::get_configuration();
@@ -895,14 +900,14 @@ int reconfigure(const ctor::settings& global_settings, int argc, char* argv[])
{
std::cout << e.first << "=\"" << e.second << "\" ";
}
- std::cout << argv[0] << " configure ";
+ std::cout << args_span[0] << " configure ";
for(const auto& arg : cfg.args)
{
std::cout << arg << " ";
}
std::cout << "\n";
- auto ret = regenerateCache(settings, argv[0], cfg.args, cfg.env);
+ auto ret = regenerateCache(settings, args_span[0], cfg.args, cfg.env);
if(ret != 0)
{
return ret;
@@ -915,5 +920,5 @@ int reconfigure(const ctor::settings& global_settings, int argc, char* argv[])
return 0; // this was originally invoked by configure, don't loop
}
- return execute(argv[0], args);
+ return execute(settings, args_span[0], args);
}
diff --git a/src/configure.h b/src/configure.h
index ac8d721..5344646 100644
--- a/src/configure.h
+++ b/src/configure.h
@@ -12,8 +12,8 @@ namespace ctor {
struct settings;
} // namespace ctor::
-extern std::filesystem::path configurationFile;;
-extern std::filesystem::path configHeaderFile;
+extern const std::filesystem::path configurationFile;
+extern const std::filesystem::path configHeaderFile;
int configure(const ctor::settings& settings, int argc, char* argv[]);
int reconfigure(const ctor::settings& settings, int argc, char* argv[]);
diff --git a/src/ctor.h b/src/ctor.h
index 3b64cb5..0892364 100644
--- a/src/ctor.h
+++ b/src/ctor.h
@@ -10,6 +10,7 @@
#include <variant>
#include <cstddef>
#include <functional>
+#include <string_view>
namespace ctor {
@@ -52,31 +53,37 @@ enum class arch
unknown, //!< Target platform architecture has not yet detected or was not possible to detect
};
+enum class toolchain
+{
+ any,
+ none,
+ gcc,
+ clang,
+};
+
struct source
{
- source(const char* file) : file(file) {}
- source(const std::string& file) : file(file) {}
- source(const char* file, ctor::language lang) : file(file), language(lang) {}
- source(const std::string& file, ctor::language lang) : file(file), language(lang) {}
+ source(const char* file_) : file(file_) {} // convenience ctor
+
+ source(std::string_view file_) : source(file_, ctor::language::automatic) {}
+ source(std::string_view file_, ctor::language lang_) : file(file_), language(lang_) {}
+
+ source(std::string_view file_, std::string_view output_) : file(file_), output(output_) {}
+ source(std::string_view file_, ctor::language lang_, std::string_view output_) : file(file_), language(lang_), output(output_) {}
+
+ source(ctor::toolchain toolchain_, std::string_view file_) : file(file_), toolchain(toolchain_) {}
+ source(ctor::toolchain toolchain_, std::string_view file_, ctor::language lang_) : file(file_), toolchain(toolchain_), language(lang_) {}
- source(const char* file, const char* output) : file(file), output(output) {}
- source(const std::string& file, const std::string& output) : file(file), output(output) {}
- source(const char* file, ctor::language lang, const char* output) : file(file), language(lang), output(output) {}
- source(const std::string& file, ctor::language lang, const std::string& output) : file(file), language(lang), output(output) {}
+ source(ctor::toolchain toolchain_, std::string_view file_, std::string_view output_) : file(file_), toolchain(toolchain_), output(output_) {}
+
+ source(ctor::toolchain toolchain_, std::string_view file_, ctor::language lang_, std::string_view output_) : file(file_), toolchain(toolchain_), language(lang_), output(output_) {}
std::string file;
+ ctor::toolchain toolchain{ctor::toolchain::any};
ctor::language language{ctor::language::automatic};
std::string output{};
};
-enum class toolchain
-{
- any,
- none,
- gcc,
- clang,
-};
-
enum class cxx_opt
{
// gcc/clang
@@ -91,6 +98,7 @@ enum class cxx_opt
optimization, // -O<arg>
position_independent_code, // -fPIC
position_independent_executable, // -fPIE
+ define, // -D<arg>[=<arg2>]
custom, // entire option taken verbatim from <arg>
};
@@ -108,6 +116,7 @@ enum class c_opt
optimization, // -O<arg>
position_independent_code, // -fPIC
position_independent_executable, // -fPIE
+ define, // -D<arg>[=<arg2>]
custom, // entire option taken verbatim from <arg>
};
@@ -149,18 +158,24 @@ template<typename T>
class flag
{
public:
- flag(const std::string& str);
+ flag(std::string_view str);
flag(const char* str);
- flag(T opt) : opt(opt) {}
- flag(T opt, const std::string& arg) : opt(opt), arg(arg) {}
- flag(T opt, const char* arg) : opt(opt), arg(arg) {}
- flag(ctor::toolchain toolchain, T opt) : toolchain(toolchain), opt(opt) {}
- flag(ctor::toolchain toolchain, T opt, const char* arg) : toolchain(toolchain), opt(opt), arg(arg) {}
- flag(ctor::toolchain toolchain, T opt, const std::string& arg) : toolchain(toolchain), opt(opt), arg(arg) {}
+ flag(T opt_) : opt(opt_) {}
+ flag(T opt_, std::string_view arg_, std::string_view arg2_ = "")
+ : opt(opt_), arg(arg_), arg2(arg2_) {}
+ flag(T opt_, const char* arg_, const char* arg2_ = "")
+ : opt(opt_), arg(arg_), arg2(arg2_) {}
+ flag(ctor::toolchain toolchain_, T opt_)
+ : toolchain(toolchain_), opt(opt_) {}
+ flag(ctor::toolchain toolchain_, T opt_, const char* arg_, const char* arg2_ = "")
+ : toolchain(toolchain_), opt(opt_), arg(arg_), arg2(arg2_) {}
+ flag(ctor::toolchain toolchain_, T opt_, std::string_view arg_, std::string_view arg2_ = "")
+ : toolchain(toolchain_), opt(opt_), arg(arg_), arg2(arg2_) {}
ctor::toolchain toolchain{ctor::toolchain::any};
- T opt;
+ T opt{};
std::string arg;
+ std::string arg2;
};
using c_flag = ctor::flag<ctor::c_opt>;
diff --git a/src/deps.cc b/src/deps.cc
new file mode 100644
index 0000000..9400b35
--- /dev/null
+++ b/src/deps.cc
@@ -0,0 +1,120 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include "deps.h"
+
+#include "util.h"
+
+#include <fstream>
+
+namespace {
+/* Format example:
+build/src/libctor_a-libctor_cc.o: src/libctor.cc \
+ src/getoptpp/getoptpp.hpp src/ctor.h src/configure.h src/rebuild.h \
+ src/A\ B\ C.h src/task.h src/build.h src/unittest.h
+ */
+std::vector<std::string> readDepsMake(const std::string& dep_file)
+{
+ auto str = readFile(dep_file);
+
+ std::vector<std::string> output;
+ std::string tmp;
+
+ enum class State
+ {
+ pre_colon,
+ post_colon,
+ in_escape,
+ } state{State::pre_colon};
+
+ auto old_state{state};
+ for(const auto& c : str)
+ {
+ if(c == '\r')
+ {
+ // just always ignore windows extra newline char
+ continue;
+ }
+
+ switch(state)
+ {
+ case State::pre_colon:
+ if(c == ':') // ignore everything until the colon
+ {
+ state = State::post_colon;
+ continue;
+ }
+ continue;
+
+ case State::post_colon:
+ if(c == '\n')
+ {
+ // done
+ if(!tmp.empty())
+ {
+ output.emplace_back(tmp);
+ }
+ return output;
+ }
+ if(c == '\\')
+ {
+ old_state = state;
+ state = State::in_escape;
+ continue;
+ }
+ if(c == '\t' || c == ' ') // new token
+ {
+ if(!tmp.empty())
+ {
+ output.emplace_back(tmp);
+ }
+ tmp.clear();
+ continue;
+ }
+ break;
+
+ case State::in_escape:
+ if(c == '\n')
+ {
+ // linewrap
+ state = old_state;
+ continue;
+ }
+ state = old_state;
+ break;
+ }
+
+ tmp += c;
+ }
+
+ if(!tmp.empty())
+ {
+ output.emplace_back(tmp);
+ }
+
+ return output;
+}
+}
+
+std::vector<std::string> readDeps(const std::string& dep_file,
+ ctor::toolchain toolchain)
+{
+ if(!std::filesystem::exists(dep_file))
+ {
+ return {};
+ }
+
+ switch(toolchain)
+ {
+ case ctor::toolchain::any:
+ case ctor::toolchain::none:
+ return {};
+
+ // makefile .d file based:
+ case ctor::toolchain::gcc:
+ case ctor::toolchain::clang:
+ return readDepsMake(dep_file);
+ }
+
+ return {};
+}
diff --git a/src/deps.h b/src/deps.h
new file mode 100644
index 0000000..be0dfb2
--- /dev/null
+++ b/src/deps.h
@@ -0,0 +1,12 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#pragma once
+
+#include "ctor.h"
+
+#include <vector>
+#include <string>
+
+std::vector<std::string> readDeps(const std::string& dep_file,
+ ctor::toolchain toolchain);
diff --git a/src/execute.cc b/src/execute.cc
index b4013d0..cbae899 100644
--- a/src/execute.cc
+++ b/src/execute.cc
@@ -3,6 +3,8 @@
// See accompanying file LICENSE for details.
#include "execute.h"
+#include "ctor.h"
+
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
@@ -44,7 +46,7 @@ public:
int parent_waitpid(pid_t pid)
{
- int status;
+ int status{};
if(waitpid(pid, &status, 0) != pid)
{
@@ -57,10 +59,11 @@ int parent_waitpid(pid_t pid)
extern char **environ; // see 'man environ'
-int execute(const std::string& command,
+int execute(const ctor::settings& settings,
+ const std::string& command,
const std::vector<std::string>& args,
const std::map<std::string, std::string>& env,
- bool verbose)
+ [[maybe_unused]] bool terminate)
{
std::vector<const char*> argv;
argv.push_back(command.data());
@@ -84,7 +87,7 @@ int execute(const std::string& command,
cmd += arg;
}
- if(verbose)
+ if(settings.verbose)
{
std::cout << cmd << std::endl;
}
@@ -101,7 +104,7 @@ int execute(const std::string& command,
for(auto current = environ; *current; ++current)
{
- venv.push_back(*current);
+ venv.emplace_back(*current);
}
Env penv(venv);
diff --git a/src/execute.h b/src/execute.h
index 336c3ef..4288bb7 100644
--- a/src/execute.h
+++ b/src/execute.h
@@ -7,7 +7,12 @@
#include <vector>
#include <map>
-int execute(const std::string& command,
+namespace ctor {
+struct settings;
+}//ctor::
+
+int execute(const ctor::settings& settings,
+ const std::string& command,
const std::vector<std::string>& args = {},
const std::map<std::string, std::string>& env = {},
- bool verbose = true);
+ bool terminate = false);
diff --git a/src/externals_manual.cc b/src/externals_manual.cc
index 3b96263..0563a5e 100644
--- a/src/externals_manual.cc
+++ b/src/externals_manual.cc
@@ -13,7 +13,7 @@
extern std::map<std::string, std::string> external_includedir;
extern std::map<std::string, std::string> external_libdir;
-int resolv(const ctor::settings& settings, const ctor::external_configuration& config,
+int resolv([[maybe_unused]]const ctor::settings& settings, const ctor::external_configuration& config,
const ctor::external_manual& ext, ctor::flags& flags)
{
flags = ext.flags;
@@ -21,14 +21,14 @@ int resolv(const ctor::settings& settings, const ctor::external_configuration& c
auto inc = external_includedir.find(config.name);
if(inc != external_includedir.end())
{
- flags.cflags.push_back({ctor::c_opt::include_path, inc->second});
- flags.cxxflags.push_back({ctor::cxx_opt::include_path, inc->second});
+ flags.cflags.emplace_back(ctor::c_opt::include_path, inc->second);
+ flags.cxxflags.emplace_back(ctor::cxx_opt::include_path, inc->second);
}
auto lib = external_libdir.find(config.name);
if(lib != external_libdir.end())
{
- flags.ldflags.push_back({ctor::ld_opt::library_path, lib->second});
+ flags.ldflags.emplace_back(ctor::ld_opt::library_path, lib->second);
}
return 0;
diff --git a/src/getoptpp b/src/getoptpp
-Subproject 9ff20ef857429619267e3f156a4f81ad9e1eb8c
+Subproject 5aba94355ec638c6f8612f86be309ed684979ae
diff --git a/src/libctor.cc b/src/libctor.cc
index 3eb6c6f..b1fbaea 100644
--- a/src/libctor.cc
+++ b/src/libctor.cc
@@ -15,6 +15,7 @@
#include <deque>
#include <fstream>
#include <cstdlib>
+#include <span>
#include <getoptpp/getoptpp.hpp>
@@ -27,6 +28,8 @@
int main(int argc, char* argv[])
{
+ auto args = std::span(argv, static_cast<std::size_t>(argc));
+
ctor::settings settings{};
const auto& c = ctor::get_configuration();
@@ -34,12 +37,12 @@ int main(int argc, char* argv[])
settings.parallel_processes =
std::max(1u, std::thread::hardware_concurrency()) * 2 - 1;
- if(argc > 1 && std::string(argv[1]) == "configure")
+ if(args.size() > 1 && std::string(args[1]) == "configure")
{
return configure(settings, argc, argv);
}
- if(argc > 1 && std::string(argv[1]) == "reconfigure")
+ if(args.size() > 1 && std::string(args[1]) == "reconfigure")
{
return reconfigure(settings, argc, argv);
}
@@ -64,7 +67,8 @@ int main(int argc, char* argv[])
[&]() {
try
{
- settings.parallel_processes = std::stoi(optarg);
+ settings.parallel_processes =
+ static_cast<std::size_t>(std::stoi(optarg));
}
catch(...)
{
@@ -100,7 +104,7 @@ int main(int argc, char* argv[])
"Add specified file to the build configurations.",
[&]() {
no_relaunch = true;
- add_files.push_back(optarg);
+ add_files.emplace_back(optarg);
return 0;
});
@@ -108,7 +112,7 @@ int main(int argc, char* argv[])
"Remove specified file from the build configurations.",
[&]() {
no_relaunch = true;
- remove_files.push_back(optarg);
+ remove_files.emplace_back(optarg);
return 0;
});
@@ -156,7 +160,7 @@ int main(int argc, char* argv[])
opt.add("help", no_argument, 'h',
"Print this help text.",
[&]() {
- std::cout << "Usage: " << argv[0] << " [options] [target] ...\n";
+ std::cout << "Usage: " << args[0] << " [options] [target] ...\n";
std::cout <<
R"_( where target can be either:
configure - run configuration step (cannot be used with other targets).
@@ -187,12 +191,12 @@ Options:
std::vector<std::string> files;
for(std::size_t i = 0; i < numConfigFiles; ++i)
{
- files.push_back(configFiles[i].file);
+ files.emplace_back(configFiles[i].file);
}
for(std::size_t i = 0; i < numExternalConfigFiles; ++i)
{
- files.push_back(externalConfigFiles[i].file);
+ files.emplace_back(externalConfigFiles[i].file);
}
std::sort(files.begin(), files.end());
@@ -270,7 +274,6 @@ Options:
if(print_configure_db)
{
no_default_build = true;
- const auto& c = ctor::get_configuration();
for(const auto& config : c.tools)
{
std::cout << config.first << ": " << config.second << "\n";
diff --git a/src/rebuild.cc b/src/rebuild.cc
index f0d52d9..4ca1809 100644
--- a/src/rebuild.cc
+++ b/src/rebuild.cc
@@ -8,6 +8,7 @@
#include <algorithm>
#include <source_location>
#include <cstring>
+#include <span>
#include "configure.h"
#include "ctor.h"
@@ -105,7 +106,7 @@ int unreg(const char* location)
}
}
- return found;
+ return static_cast<int>(found);
}
std::array<ExternalConfigurationEntry, 1024> externalConfigFiles;
@@ -150,6 +151,8 @@ bool contains(const std::vector<ctor::source>& sources, const std::string& file)
bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[],
bool relaunch_allowed)
{
+ auto args_span = std::span(argv, static_cast<std::size_t>(argc));
+
using namespace std::string_literals;
if(global_settings.verbose > 1)
@@ -163,36 +166,40 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[
config.name = "ctor";
config.system = ctor::output_system::build;
- config.flags.cxxflags.push_back({ctor::cxx_opt::optimization, "3"});
- config.flags.cxxflags.push_back({ctor::cxx_opt::cpp_std, "c++20"});
+ config.flags.cxxflags.emplace_back(ctor::cxx_opt::optimization, "3");
+ config.flags.cxxflags.emplace_back(ctor::cxx_opt::cpp_std, "c++20");
const auto& c = ctor::get_configuration();
if(c.has(ctor::cfg::ctor_includedir))
{
- config.flags.cxxflags.push_back({ctor::cxx_opt::include_path,
- c.get(ctor::cfg::ctor_includedir)});
+ config.flags.cxxflags.emplace_back(ctor::cxx_opt::include_path,
+ c.get(ctor::cfg::ctor_includedir));
}
if(c.has(ctor::cfg::ctor_libdir))
{
- config.flags.ldflags.push_back({ctor::ld_opt::library_path, c.get(ctor::cfg::ctor_libdir)});
+ config.flags.ldflags.emplace_back(ctor::ld_opt::library_path,
+ c.get(ctor::cfg::ctor_libdir));
}
- config.flags.ldflags.push_back({ctor::ld_opt::link, "ctor"});
- config.flags.ldflags.push_back({ctor::ld_opt::strip});
- config.flags.ldflags.push_back({ctor::ld_opt::threads});
+ config.flags.ldflags.emplace_back(ctor::ld_opt::link, "ctor");
+ config.flags.ldflags.emplace_back(ctor::ld_opt::strip);
+ config.flags.ldflags.emplace_back(ctor::ld_opt::threads);
ctor::settings settings{global_settings};
settings.verbose = -1; // Make check completely silent.
- settings.builddir += "/ctor"; // override builddir to use ctor subdir
+
+ // override builddir to use ctor subdir
+ auto ctor_builddir = std::filesystem::path(settings.builddir) / "ctor";
+ settings.builddir = ctor_builddir.string();
{
std::filesystem::path buildfile = settings.builddir;
- std::filesystem::path currentfile = argv[0];
+ std::filesystem::path currentfile = args_span[0];
config.target = std::filesystem::relative(currentfile, buildfile).string();
}
if(std::filesystem::exists(configurationFile))
{
- config.sources.push_back(configurationFile.string());
+ config.sources.emplace_back(configurationFile.string());
}
for(std::size_t i = 0; i < numConfigFiles; ++i)
@@ -206,7 +213,7 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[
// Ensure that files containing multiple configurations are only added once.
if(!contains(config.sources, location))
{
- config.sources.push_back(location);
+ config.sources.emplace_back(location);
}
}
@@ -221,11 +228,11 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[
// Ensure that files containing multiple configurations are only added once.
if(!contains(config.sources, location))
{
- config.sources.push_back(location);
+ config.sources.emplace_back(location);
}
}
- auto tasks = taskFactory({config}, settings, {});
+ auto tasks = taskFactory({config}, settings, {}, true);
for(auto task : tasks)
{
@@ -261,16 +268,17 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[
if(reconfigure)
{
std::vector<std::string> args;
- args.push_back("reconfigure");
+ args.emplace_back("reconfigure");
if(!relaunch_allowed)
{
- args.push_back("--no-rerun");
+ args.emplace_back("--no-rerun");
}
- for(int i = 1; i < argc; ++i)
+ for(std::size_t i = 1; i < args_span.size(); ++i)
{
- args.push_back(argv[i]);
+ args.emplace_back(args_span[i]);
}
- auto ret = execute(argv[0], args);
+
+ auto ret = execute(settings, args_span[0], args);
//if(ret != 0)
{
exit(ret);
diff --git a/src/task.cc b/src/task.cc
index 7813235..cd03fce 100644
--- a/src/task.cc
+++ b/src/task.cc
@@ -3,16 +3,16 @@
// See accompanying file LICENSE for details.
#include "task.h"
-#include <unistd.h>
#include <iostream>
#include <algorithm>
+#include <utility>
-Task::Task(const ctor::build_configuration& config, const ctor::settings& settings,
- const std::string& sourceDir)
- : config(config)
+Task::Task(const ctor::build_configuration& config_, const ctor::settings& settings_,
+ std::string sourceDir_)
+ : config(config_)
, output_system(config.system)
- , settings(settings)
- , sourceDir(sourceDir)
+ , settings(settings_)
+ , sourceDir(std::move(sourceDir_))
{
}
@@ -45,10 +45,12 @@ int Task::registerDepTasks(const std::vector<std::shared_ptr<Task>>& tasks)
bool Task::operator==(const std::string& depStr)
{
+ std::filesystem::path generated_output = sourceDir;
+ generated_output /= target();
return
name() == depStr ||
target() == depStr ||
- sourceDir + "/" + target() == depStr ||
+ generated_output == depStr ||
targetFile().string() == depStr
;
}
@@ -144,6 +146,7 @@ std::string Task::compiler() const
case ctor::output_system::build:
return c.get(ctor::cfg::build_cc, "/usr/bin/gcc");
}
+ break;
case ctor::language::cpp:
switch(outputSystem())
{
@@ -152,11 +155,15 @@ std::string Task::compiler() const
case ctor::output_system::build:
return c.get(ctor::cfg::build_cxx, "/usr/bin/g++");
}
+ break;
default:
std::cerr << "Unknown CC target type\n";
exit(1);
break;
}
+
+ std::cerr << "Unhandled compiler!\n";
+ exit(1);
}
std::vector<std::shared_ptr<Task>> Task::getDependsTasks()
diff --git a/src/task.h b/src/task.h
index 6fe1686..e930a54 100644
--- a/src/task.h
+++ b/src/task.h
@@ -24,11 +24,11 @@ class Task
{
public:
Task(const ctor::build_configuration& config, const ctor::settings& settings,
- const std::string& sourceDir);
+ std::string sourceDir);
virtual ~Task() = default;
int registerDepTasks(const std::vector<std::shared_ptr<Task>>& tasks);
- virtual int registerDepTasksInner(const std::vector<std::shared_ptr<Task>>& tasks) { return 0; }
+ virtual int registerDepTasksInner([[maybe_unused]]const std::vector<std::shared_ptr<Task>>& tasks) { return 0; }
bool operator==(const std::string& dep);
diff --git a/src/task_ar.cc b/src/task_ar.cc
index 19a65ae..09403bb 100644
--- a/src/task_ar.cc
+++ b/src/task_ar.cc
@@ -11,20 +11,20 @@
#include "util.h"
#include "tools.h"
-TaskAR::TaskAR(const ctor::build_configuration& config,
- const ctor::settings& settings,
+TaskAR::TaskAR(const ctor::build_configuration& config_,
+ const ctor::settings& settings_,
const std::string& target,
const std::vector<std::string>& objects,
- const std::string& sourceDir)
- : Task(config, settings, sourceDir)
- , config(config)
- , settings(settings)
- , sourceDir(sourceDir)
+ const std::string& sourceDir_)
+ : Task(config_, settings_, sourceDir_)
+ , _targetFile(target)
+ , config(config_)
+ , settings(settings_)
+ , sourceDir(sourceDir_)
{
target_type = ctor::target_type::static_library;
output_system = config.system;
- _targetFile = target;
auto toolchain = getToolChain(config.system);
_targetFile = extension(toolchain, target_type, config.system, _targetFile);
for(const auto& object : objects)
@@ -36,7 +36,7 @@ TaskAR::TaskAR(const ctor::build_configuration& config,
for(const auto& dep : config.depends)
{
- depFiles.push_back(dep);
+ depFiles.emplace_back(dep);
}
flagsFile = std::filesystem::path(settings.builddir) / cleanUp(sourceDir) / targetFile().stem();
@@ -105,7 +105,8 @@ int TaskAR::runInner()
if(settings.verbose == 0)
{
- std::cout << "AR => " << targetFile().string() << std::endl;
+ std::string output = "AR => " + targetFile().string() + '\n';
+ std::cout << output << std::flush;
}
const auto& c = ctor::get_configuration();
@@ -120,7 +121,7 @@ int TaskAR::runInner()
break;
}
- return execute(tool, args, {}, settings.verbose > 0);
+ return execute(settings, tool, args, c.env);
}
int TaskAR::clean()
diff --git a/src/task_cc.cc b/src/task_cc.cc
index 4eb07ae..9de2657 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -12,16 +12,17 @@
#include "execute.h"
#include "util.h"
#include "tools.h"
-
-TaskCC::TaskCC(const ctor::build_configuration& config, const ctor::settings& settings,
- const std::string& sourceDir, const ctor::source& source)
- : Task(config, settings, sourceDir)
- , config(config)
- , settings(settings)
- , sourceDir(sourceDir)
+#include "deps.h"
+
+TaskCC::TaskCC(const ctor::build_configuration& config_, const ctor::settings& settings_,
+ const std::string& sourceDir_, const ctor::source& source)
+ : Task(config_, settings_, sourceDir_)
+ , sourceFile(sourceDir_)
+ , config(config_)
+ , settings(settings_)
+ , sourceDir(sourceDir_)
, _source(source)
{
- sourceFile = sourceDir;
sourceFile /= source.file;
std::filesystem::path base = sourceFile.parent_path();
@@ -136,7 +137,8 @@ bool TaskCC::dirtyInner()
}
}
- auto depList = readDeps(depsFile.string());
+ auto toolchain = getToolChain(config.system);
+ auto depList = readDeps(depsFile.string(), toolchain);
for(const auto& dep : depList)
{
if(!std::filesystem::exists(dep) ||
@@ -175,25 +177,27 @@ int TaskCC::runInner()
if(settings.verbose == 0)
{
+ std::string output;
switch(sourceLanguage())
{
case ctor::language::c:
- std::cout << "CC ";
+ output = "CC ";
break;
case ctor::language::cpp:
- std::cout << "CXX ";
+ output = "CXX ";
break;
case ctor::language::automatic:
case ctor::language::assembler:
// Only c/c++ handled by this task type.
break;
}
- std::cout <<
- sourceFile.lexically_normal().string() << " => " <<
- targetFile().lexically_normal().string() << std::endl;
+ output += sourceFile.lexically_normal().string() + " => " +
+ targetFile().lexically_normal().string() + '\n';
+ std::cout << output << std::flush;
}
- return execute(compiler(), args, {}, settings.verbose > 0);
+ const auto& cfg = ctor::get_configuration();
+ return execute(settings, compiler(), args, cfg.env);
}
int TaskCC::clean()
@@ -286,6 +290,7 @@ std::vector<std::string> TaskCC::flags() const
exit(1);
break;
}
+
}
std::string TaskCC::flagsString() const
@@ -309,7 +314,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
{
case ctor::language::c:
{
- append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree));
+ append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree, depsFile.string()));
if(std::filesystem::path(config.target).extension() == ".so")
{
@@ -351,7 +356,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
case ctor::language::cpp:
{
- append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree));
+ append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree, depsFile.string()));
if(std::filesystem::path(config.target).extension() == ".so")
{
diff --git a/src/task_fn.cc b/src/task_fn.cc
index b11ff15..1ff72f9 100644
--- a/src/task_fn.cc
+++ b/src/task_fn.cc
@@ -11,13 +11,13 @@
#include "execute.h"
#include "util.h"
-TaskFn::TaskFn(const ctor::build_configuration& config, const ctor::settings& settings,
- const std::string& sourceDir, const ctor::source& source)
- : Task(config, settings, sourceDir)
- , config(config)
- , settings(settings)
+TaskFn::TaskFn(const ctor::build_configuration& config_, const ctor::settings& settings_,
+ const std::string& sourceDir_, const ctor::source& source)
+ : Task(config_, settings_, sourceDir_)
+ , sourceFile(sourceDir_)
+ , config(config_)
+ , settings(settings_)
{
- sourceFile = sourceDir;
sourceFile /= source.file;
std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceFile.parent_path());
@@ -68,9 +68,10 @@ int TaskFn::runInner()
if(settings.verbose >= 0)
{
- std::cout << "Fn" << " " <<
- sourceFile.lexically_normal().string() << " => " <<
- targetFile().lexically_normal().string() << std::endl;
+ std::string output = "Fn " +
+ sourceFile.lexically_normal().string() + " => " +
+ targetFile().lexically_normal().string() + '\n';
+ std::cout << output << std::flush;
}
return config.function(sourceFile.string(),
@@ -97,7 +98,7 @@ std::vector<std::string> TaskFn::depends() const
std::string TaskFn::target() const
{
- return _targetFile;
+ return _targetFile.string();
}
std::filesystem::path TaskFn::targetFile() const
diff --git a/src/task_ld.cc b/src/task_ld.cc
index b0aa4ae..31ee8c0 100644
--- a/src/task_ld.cc
+++ b/src/task_ld.cc
@@ -11,15 +11,17 @@
#include "util.h"
#include "tools.h"
-TaskLD::TaskLD(const ctor::build_configuration& config,
- const ctor::settings& settings,
+TaskLD::TaskLD(const ctor::build_configuration& config_,
+ const ctor::settings& settings_,
const std::string& target,
const std::vector<std::string>& objects,
- const std::string& sourceDir)
- : Task(config, settings, sourceDir)
- , config(config)
- , settings(settings)
- , sourceDir(sourceDir)
+ const std::string& sourceDir_,
+ bool is_self_)
+ : Task(config_, settings_, sourceDir_)
+ , config(config_)
+ , settings(settings_)
+ , sourceDir(sourceDir_)
+ , is_self(is_self_)
{
target_type = config.type;
output_system = config.system;
@@ -41,7 +43,7 @@ TaskLD::TaskLD(const ctor::build_configuration& config,
for(const auto& dep : config.depends)
{
- depFiles.push_back(dep);
+ depFiles.emplace_back(dep);
}
flagsFile = std::filesystem::path(settings.builddir) / cleanUp(sourceDir) / targetFile().stem();
@@ -121,11 +123,13 @@ int TaskLD::runInner()
if(settings.verbose == 0)
{
- std::cout << "LD => " << targetFile().string() << std::endl;
+ std::string output = "LD => " + targetFile().string() + '\n';
+ std::cout << output << std::flush;
}
auto tool = compiler();
- return execute(tool, args, {}, settings.verbose > 0);
+ const auto& c = ctor::get_configuration();
+ return execute(settings, tool, args, c.env, is_self);
}
int TaskLD::clean()
diff --git a/src/task_ld.h b/src/task_ld.h
index dbe7db1..c0e3ebb 100644
--- a/src/task_ld.h
+++ b/src/task_ld.h
@@ -18,7 +18,8 @@ public:
const ctor::settings& settings,
const std::string& target,
const std::vector<std::string>& objects,
- const std::string& _sourceDir);
+ const std::string& _sourceDir,
+ bool is_self);
virtual ~TaskLD() = default;
bool dirtyInner() override;
@@ -44,4 +45,5 @@ private:
const ctor::build_configuration& config;
const ctor::settings& settings;
std::string sourceDir;
+ bool is_self;
};
diff --git a/src/task_so.cc b/src/task_so.cc
index ba96388..eecd7aa 100644
--- a/src/task_so.cc
+++ b/src/task_so.cc
@@ -11,15 +11,15 @@
#include "util.h"
#include "tools.h"
-TaskSO::TaskSO(const ctor::build_configuration& config,
- const ctor::settings& settings,
+TaskSO::TaskSO(const ctor::build_configuration& config_,
+ const ctor::settings& settings_,
const std::string& target,
const std::vector<std::string>& objects,
- const std::string& sourceDir)
- : Task(config, settings, sourceDir)
- , config(config)
- , settings(settings)
- , sourceDir(sourceDir)
+ const std::string& sourceDir_)
+ : Task(config_, settings_, sourceDir_)
+ , config(config_)
+ , settings(settings_)
+ , sourceDir(sourceDir_)
{
std::filesystem::path base = sourceDir;
@@ -38,7 +38,7 @@ TaskSO::TaskSO(const ctor::build_configuration& config,
for(const auto& dep : config.depends)
{
- depFiles.push_back(dep);
+ depFiles.emplace_back(dep);
}
flagsFile = std::filesystem::path(settings.builddir) / cleanUp(sourceDir) / targetFile().stem();
@@ -110,11 +110,13 @@ int TaskSO::runInner()
if(settings.verbose == 0)
{
- std::cout << "LD => " << targetFile().string() << std::endl;
+ std::string output = "LD => " + targetFile().string() + '\n';
+ std::cout << output << std::flush;
}
auto tool = compiler();
- return execute(tool, args, {}, settings.verbose > 0);
+ const auto& cfg = ctor::get_configuration();
+ return execute(settings, tool, args, cfg.env);
}
int TaskSO::clean()
diff --git a/src/tasks.cc b/src/tasks.cc
index 61c130b..2f9e47a 100644
--- a/src/tasks.cc
+++ b/src/tasks.cc
@@ -8,6 +8,7 @@
#include <list>
#include <iostream>
#include <algorithm>
+#include <span>
#include "ctor.h"
#include "task.h"
@@ -24,20 +25,22 @@
const std::deque<Target>& getTargets(const ctor::settings& settings,
bool resolve_externals)
{
+ auto config_files = std::span(configFiles).subspan(0, numConfigFiles);
+
static bool initialised{false};
static std::deque<Target> targets;
if(!initialised)
{
const auto& externals = ctor::get_configuration().externals;
- for(std::size_t i = 0; i < numConfigFiles; ++i)
+ for(const auto& config_file : config_files)
{
std::string path =
- std::filesystem::path(configFiles[i].file).parent_path().string();
+ std::filesystem::path(config_file.file).parent_path().string();
if(settings.verbose > 1)
{
- std::cout << configFiles[i].file << " in path " << path << "\n";
+ std::cout << config_file.file << " in path " << path << "\n";
}
- auto configs = configFiles[i].cb(settings);
+ auto configs = config_file.cb(settings);
for(auto& config : configs)
{
if(resolve_externals)
@@ -72,7 +75,8 @@ const std::deque<Target>& getTargets(const ctor::settings& settings,
std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration& config,
const ctor::settings& settings,
- const std::string& sourceDir)
+ const std::string& sourceDir,
+ bool is_self)
{
std::vector<std::shared_ptr<Task>> tasks;
@@ -91,14 +95,20 @@ std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration&
}
}
+ const auto& c = ctor::get_configuration();
std::vector<std::string> objects;
if(target_type != ctor::target_type::function)
{
- for(const auto& file : config.sources)
+ for(const auto& source : config.sources)
{
- auto task = std::make_shared<TaskCC>(config, settings, sourceDir, file);
- tasks.push_back(task);
- objects.push_back(task->targetFile().string());
+ if(source.toolchain == ctor::toolchain::any ||
+ (config.system == ctor::output_system::build && source.toolchain == c.build_toolchain) ||
+ (config.system == ctor::output_system::host && source.toolchain == c.host_toolchain))
+ {
+ auto task = std::make_shared<TaskCC>(config, settings, sourceDir, source);
+ tasks.push_back(task);
+ objects.push_back(task->targetFile().string());
+ }
}
}
#ifndef BOOTSTRAP
@@ -145,7 +155,7 @@ std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration&
case ctor::target_type::executable:
case ctor::target_type::unit_test:
tasks.push_back(std::make_shared<TaskLD>(config, settings, config.target,
- objects, sourceDir));
+ objects, sourceDir, is_self));
break;
case ctor::target_type::object:
@@ -160,7 +170,7 @@ std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration&
return tasks;
}
-std::shared_ptr<Task> getNextTask(const std::vector<std::shared_ptr<Task>>& allTasks,
+std::shared_ptr<Task> getNextTask([[maybe_unused]]const std::vector<std::shared_ptr<Task>>& allTasks,
std::vector<std::shared_ptr<Task>>& dirtyTasks)
{
for(auto dirtyTask = dirtyTasks.begin();
@@ -192,7 +202,7 @@ std::vector<std::shared_ptr<Task>> getTasks(const ctor::settings& settings,
std::find(std::begin(names), std::end(names), target.config.target) != std::end(names))
{
std::vector<std::string> objects;
- auto t = taskFactory(target.config, settings, target.path);
+ auto t = taskFactory(target.config, settings, target.path, false);
tasks.insert(tasks.end(), t.begin(), t.end());
}
}
diff --git a/src/tasks.h b/src/tasks.h
index cc34f56..6573784 100644
--- a/src/tasks.h
+++ b/src/tasks.h
@@ -36,4 +36,5 @@ std::vector<std::shared_ptr<Task>> getTasks(const ctor::settings& settings,
//! link target and all its objects files (if any).
std::vector<std::shared_ptr<Task>> taskFactory(const ctor::build_configuration& config,
const ctor::settings& settings,
- const std::string& sourceDir);
+ const std::string& sourceDir,
+ bool is_self);
diff --git a/src/tools.cc b/src/tools.cc
index be94794..eb98265 100644
--- a/src/tools.cc
+++ b/src/tools.cc
@@ -28,6 +28,7 @@ std::ostream& operator<<(std::ostream& stream, const ctor::c_opt& opt)
case ctor::c_opt::optimization: stream << "ctor::c_opt::optimization"; break;
case ctor::c_opt::position_independent_code: stream << "ctor::c_opt::position_independent_code"; break;
case ctor::c_opt::position_independent_executable: stream << "ctor::c_opt::position_independent_executable"; break;
+ case ctor::c_opt::define: stream << "ctor::c_opt::define"; break;
case ctor::c_opt::custom: stream << "ctor::c_opt::custom"; break;
}
@@ -50,6 +51,7 @@ std::ostream& operator<<(std::ostream& stream, const ctor::cxx_opt& opt)
case ctor::cxx_opt::optimization: stream << "ctor::cxx_opt::optimization"; break;
case ctor::cxx_opt::position_independent_code: stream << "ctor::cxx_opt::position_independent_code"; break;
case ctor::cxx_opt::position_independent_executable: stream << "ctor::cxx_opt::position_independent_executable"; break;
+ case ctor::cxx_opt::define: stream << "ctor::cxx_opt::define"; break;
case ctor::cxx_opt::custom: stream << "ctor::cxx_opt::custom"; break;
}
@@ -175,10 +177,11 @@ std::string get_arch(ctor::output_system system)
std::string arch;
while(!feof(pipe))
{
- char buf[1024];
- if(fgets(buf, sizeof(buf), pipe) != nullptr)
+ constexpr auto buffer_size{1024};
+ std::array<char, buffer_size> buf{};
+ if(fgets(buf.data(), buf.size(), pipe) != nullptr)
{
- arch = buf;
+ arch = buf.data();
if(arch.starts_with("Target:"))
{
break;
@@ -195,7 +198,8 @@ std::string get_arch(ctor::output_system system)
}
// Remove 'Target: ' prefix
- arch = arch.substr(8);
+ constexpr auto prefix_length{8};
+ arch = arch.substr(prefix_length);
return arch;
}
@@ -243,6 +247,19 @@ ctor::c_flag c_option(const std::string& flag)
return { ctor::c_opt::include_path, path };
}
+ if(flag.starts_with("-D"))
+ {
+ std::string def = flag.substr(2);
+ auto pos = def.find('=');
+ if(pos != def.npos)
+ {
+ return { ctor::c_opt::define, def.substr(0, pos), def.substr(pos + 1) };
+ }
+ else
+ {
+ return { ctor::c_opt::define, def };
+ }
+ }
return { ctor::c_opt::custom, flag };
}
@@ -255,6 +272,20 @@ ctor::cxx_flag cxx_option(const std::string& flag)
return { ctor::cxx_opt::include_path, path };
}
+ if(flag.starts_with("-D"))
+ {
+ std::string def = flag.substr(2);
+ auto pos = def.find('=');
+ if(pos != def.npos)
+ {
+ return { ctor::cxx_opt::define, def.substr(0, pos), def.substr(pos + 1) };
+ }
+ else
+ {
+ return { ctor::cxx_opt::define, def };
+ }
+ }
+
return { ctor::cxx_opt::custom, flag };
}
@@ -275,7 +306,8 @@ ctor::ar_flag ar_option(const std::string& flag)
return { ctor::ar_opt::custom, flag };
}
-std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg)
+std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg,
+ const std::string& arg2)
{
switch(opt)
{
@@ -301,6 +333,12 @@ std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg)
return {"-fPIC"};
case ctor::cxx_opt::position_independent_executable:
return {"-fPIE"};
+ case ctor::cxx_opt::define:
+ if(!arg2.empty())
+ {
+ return {"-D" + arg + "=" + arg2};
+ }
+ return {"-D" + arg};
case ctor::cxx_opt::custom:
return {arg};
}
@@ -309,7 +347,8 @@ std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg)
+std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg,
+ const std::string& arg2)
{
switch(opt)
{
@@ -335,6 +374,12 @@ std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg)
return {"-fPIC"};
case ctor::c_opt::position_independent_executable:
return {"-fPIE"};
+ case ctor::c_opt::define:
+ if(!arg2.empty())
+ {
+ return {"-D" + arg + "=" + arg2};
+ }
+ return {"-D" + arg};
case ctor::c_opt::custom:
return {arg};
}
@@ -343,7 +388,8 @@ std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg)
+std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg,
+ [[maybe_unused]]const std::string& arg2)
{
switch(opt)
{
@@ -377,7 +423,8 @@ std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg)
+std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg,
+ [[maybe_unused]]const std::string& arg2)
{
switch(opt)
{
@@ -397,7 +444,8 @@ std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> asm_option(ctor::asm_opt opt, const std::string& arg)
+std::vector<std::string> asm_option(ctor::asm_opt opt, const std::string& arg,
+ [[maybe_unused]]const std::string& arg2)
{
switch(opt)
{
@@ -442,13 +490,14 @@ ctor::arch get_arch(ctor::output_system system, const std::string& str)
std::vector<std::string> c_option(ctor::toolchain toolchain,
ctor::c_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::c_option(opt, arg);
+ return gcc::c_option(opt, arg, arg2);
case ctor::toolchain::any:
{
std::ostringstream ss;
@@ -457,6 +506,10 @@ std::vector<std::string> c_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -470,13 +523,14 @@ std::vector<std::string> c_option(ctor::toolchain toolchain,
std::vector<std::string> cxx_option(ctor::toolchain toolchain,
ctor::cxx_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::cxx_option(opt, arg);
+ return gcc::cxx_option(opt, arg, arg2);
case ctor::toolchain::any:
{
std::ostringstream ss;
@@ -485,6 +539,10 @@ std::vector<std::string> cxx_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -498,13 +556,14 @@ std::vector<std::string> cxx_option(ctor::toolchain toolchain,
std::vector<std::string> ld_option(ctor::toolchain toolchain,
ctor::ld_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::ld_option(opt, arg);
+ return gcc::ld_option(opt, arg, arg2);
case ctor::toolchain::any:
{
std::ostringstream ss;
@@ -513,6 +572,10 @@ std::vector<std::string> ld_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -526,13 +589,14 @@ std::vector<std::string> ld_option(ctor::toolchain toolchain,
std::vector<std::string> ar_option(ctor::toolchain toolchain,
ctor::ar_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::ar_option(opt, arg);
+ return gcc::ar_option(opt, arg, arg2);
case ctor::toolchain::any:
{
std::ostringstream ss;
@@ -541,6 +605,10 @@ std::vector<std::string> ar_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -554,13 +622,14 @@ std::vector<std::string> ar_option(ctor::toolchain toolchain,
std::vector<std::string> asm_option(ctor::toolchain toolchain,
ctor::asm_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::asm_option(opt, arg);
+ return gcc::asm_option(opt, arg, arg2);
case ctor::toolchain::any:
{
std::ostringstream ss;
@@ -569,6 +638,10 @@ std::vector<std::string> asm_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -663,7 +736,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return c_option(toolchain, flag.opt, flag.arg);
+ return c_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -675,7 +748,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return cxx_option(toolchain, flag.opt, flag.arg);
+ return cxx_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -687,7 +760,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return ld_option(toolchain, flag.opt, flag.arg);
+ return ld_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -699,7 +772,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return ar_option(toolchain, flag.opt, flag.arg);
+ return ar_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -711,7 +784,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return asm_option(toolchain, flag.opt, flag.arg);
+ return asm_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
diff --git a/src/tools.h b/src/tools.h
index 188d49f..0e7fc15 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -32,31 +32,36 @@ ctor::toolchain getToolChain(ctor::output_system system);
//! tool-chain
std::vector<std::string> c_option(ctor::toolchain toolchain,
ctor::c_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> cxx_option(ctor::toolchain toolchain,
ctor::cxx_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> ld_option(ctor::toolchain toolchain,
ctor::ld_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> ar_option(ctor::toolchain toolchain,
ctor::ar_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> asm_option(ctor::toolchain toolchain,
ctor::asm_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
diff --git a/src/unittest.cc b/src/unittest.cc
index 9e85187..b95a931 100644
--- a/src/unittest.cc
+++ b/src/unittest.cc
@@ -24,7 +24,7 @@ int runUnitTests(std::vector<std::shared_ptr<Task>>& tasks,
name = task->target();
}
std::cout << name << ": " << std::flush;
- auto ret = execute(task->targetFile(), {}, {}, settings.verbose > 0);
+ auto ret = execute(settings, task->targetFile().string(), {}, {});
ok &= ret == 0;
if(ret == 0)
{
diff --git a/src/util.cc b/src/util.cc
index 76d380b..dbd4c3c 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -22,70 +22,10 @@ std::string readFile(const std::string& fileName)
std::ifstream::pos_type fileSize = ifs.tellg();
ifs.seekg(0, std::ios::beg);
- std::vector<char> bytes(fileSize);
+ std::vector<char> bytes(static_cast<std::size_t>(fileSize));
ifs.read(bytes.data(), fileSize);
- return std::string(bytes.data(), fileSize);
-}
-
-std::vector<std::string> readDeps(const std::string& depFile)
-{
- if(!std::filesystem::exists(depFile))
- {
- return {};
- }
-
- auto str = readFile(depFile);
-
- std::vector<std::string> output;
- std::string tmp;
- bool start{false};
- bool in_whitespace{false};
- for(const auto& c : str)
- {
- if(c == '\\' || c == '\n')
- {
- continue;
- }
-
- if(c == ':')
- {
- start = true;
- continue;
- }
-
- if(!start)
- {
- continue;
- }
-
- if(c == ' ' || c == '\t')
- {
- if(in_whitespace)
- {
- continue;
- }
-
- if(!tmp.empty())
- {
- output.push_back(tmp);
- }
- tmp.clear();
- in_whitespace = true;
- }
- else
- {
- in_whitespace = false;
- tmp += c;
- }
- }
-
- if(!tmp.empty())
- {
- output.push_back(tmp);
- }
-
- return output;
+ return {bytes.data(), static_cast<std::size_t>(fileSize)};
}
ctor::language languageFromExtension(const std::filesystem::path& file)
diff --git a/src/util.h b/src/util.h
index af5bbd6..0a90049 100644
--- a/src/util.h
+++ b/src/util.h
@@ -12,7 +12,6 @@
std::string to_lower(const std::string& str);
std::string readFile(const std::string& fileName);
-std::vector<std::string> readDeps(const std::string& depFile);
ctor::language languageFromExtension(const std::filesystem::path& file);
std::string cleanUp(const std::string& path);
diff --git a/test/ctor.cc b/test/ctor.cc
index ccf1c31..1951a30 100644
--- a/test/ctor.cc
+++ b/test/ctor.cc
@@ -12,6 +12,25 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
{
.type = ctor::target_type::unit_test,
.system = ctor::output_system::build,
+ .target = "deps_test",
+ .sources = {
+ "deps_test.cc",
+ "testmain.cc",
+ "../src/deps.cc",
+ "../src/util.cc",
+ },
+ .depends = { "testprog", },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-Wall", "-Werror",
+ "-I../src", "-Iuunit",
+ "-DOUTPUT=\"deps\"",
+ },
+ },
+ },
+ {
+ .type = ctor::target_type::unit_test,
+ .system = ctor::output_system::build,
.target = "testprog",
.sources = {
"testprog.cc",
@@ -104,6 +123,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
.sources = {
"../src/build.cc",
"../src/configure.cc",
+ "../src/deps.cc",
"../src/execute.cc",
"../src/rebuild.cc",
"../src/tasks.cc",
diff --git a/test/deps_test.cc b/test/deps_test.cc
new file mode 100644
index 0000000..762b0e5
--- /dev/null
+++ b/test/deps_test.cc
@@ -0,0 +1,97 @@
+#include <uunit.h>
+
+#include <fstream>
+#include <map>
+#include <vector>
+
+#include <deps.h>
+#include <algorithm>
+
+#include "paths.h"
+#include "tmpfile.h"
+
+class DepsTest
+ : public uUnit
+{
+public:
+ DepsTest()
+ {
+ uTEST(DepsTest::parser_test);
+ }
+
+ void parser_test()
+ {
+ using namespace std::string_literals;
+
+ auto test_data = paths::top_srcdir / "test" / "deps_test_data";
+
+ auto empty = test_data / "empty.d";
+ auto trivial = test_data / "trivial.d";
+ auto no_newline = test_data / "no_newline.d";
+ auto no_deps = test_data / "no_deps.d";
+ auto trailing_whitespace = test_data / "trailing_whitespace.d";
+ auto spaces = test_data / "spaces.d";
+ auto multiline = test_data / "multiline.d";
+ auto no_such_file = test_data / "no_such_file.d"; // doesn't exist
+ auto missing_colon = test_data / "missing_colon.d";
+
+ {
+ auto res = readDeps(empty.string(), ctor::toolchain::gcc);
+ uASSERT(res.empty());
+ }
+
+ {
+ auto res = readDeps(trivial.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(1u, res.size());
+ uASSERT_EQUAL("x.cc"s, res[0]);
+ }
+
+ {
+ auto res = readDeps(no_newline.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(1u, res.size());
+ uASSERT_EQUAL("x.cc"s, res[0]);
+ }
+
+ {
+ auto res = readDeps(no_deps.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(0u, res.size());
+ }
+
+ {
+ auto res = readDeps(spaces.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(2u, res.size());
+ uASSERT_EQUAL("x y.cc"s, res[0]);
+ uASSERT_EQUAL("x y.h"s, res[1]);
+ }
+
+ {
+ auto res = readDeps(multiline.string(), ctor::toolchain::gcc);
+ uASSERT_EQUAL(12u, res.size());
+ uASSERT_EQUAL("src/configure.cc"s, res[0]);
+ uASSERT_EQUAL("src/configure.h"s, res[1]);
+ uASSERT_EQUAL("src/getoptpp/getoptpp.hpp"s, res[2]);
+ uASSERT_EQUAL("src/execute.h"s, res[3]);
+ uASSERT_EQUAL("src/ctor.h"s, res[4]);
+ uASSERT_EQUAL("src/tasks.h"s, res[5]);
+ uASSERT_EQUAL("src/task.h"s, res[6]);
+ uASSERT_EQUAL("src/rebuild.h"s, res[7]);
+ uASSERT_EQUAL("src/externals.h"s, res[8]);
+ uASSERT_EQUAL("src/externals_manual.h"s, res[9]);
+ uASSERT_EQUAL("src/tools.h"s, res[10]);
+ uASSERT_EQUAL("src/util.h"s, res[11]);
+ }
+
+ {
+ auto res = readDeps(no_such_file.string(), ctor::toolchain::gcc);
+ uASSERT(res.empty());
+ }
+
+ {
+ auto res = readDeps(missing_colon.string(), ctor::toolchain::gcc);
+ uASSERT(res.empty());
+ }
+ }
+};
+
+// Registers the fixture into the 'registry'
+static DepsTest test;
diff --git a/test/deps_test_data/empty.d b/test/deps_test_data/empty.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/deps_test_data/empty.d
diff --git a/test/deps_test_data/missing_colon.d b/test/deps_test_data/missing_colon.d
new file mode 100644
index 0000000..e46996c
--- /dev/null
+++ b/test/deps_test_data/missing_colon.d
@@ -0,0 +1 @@
+x.cc x.h
diff --git a/test/deps_test_data/multiline.d b/test/deps_test_data/multiline.d
new file mode 100644
index 0000000..8862ab0
--- /dev/null
+++ b/test/deps_test_data/multiline.d
@@ -0,0 +1,4 @@
+build/src/libctor_a-configure_cc.o: src/configure.cc src/configure.h \
+ src/getoptpp/getoptpp.hpp src/execute.h src/ctor.h src/tasks.h \
+ src/task.h src/rebuild.h src/externals.h src/externals_manual.h \
+ src/tools.h src/util.h
diff --git a/test/deps_test_data/no_deps.d b/test/deps_test_data/no_deps.d
new file mode 100644
index 0000000..e7cccf6
--- /dev/null
+++ b/test/deps_test_data/no_deps.d
@@ -0,0 +1 @@
+x.o:
diff --git a/test/deps_test_data/no_newline.d b/test/deps_test_data/no_newline.d
new file mode 100644
index 0000000..88829ea
--- /dev/null
+++ b/test/deps_test_data/no_newline.d
@@ -0,0 +1 @@
+x.o: x.cc \ No newline at end of file
diff --git a/test/deps_test_data/spaces.d b/test/deps_test_data/spaces.d
new file mode 100644
index 0000000..c53fd64
--- /dev/null
+++ b/test/deps_test_data/spaces.d
@@ -0,0 +1 @@
+x\ y.o: x\ y.cc x\ y.h
diff --git a/test/deps_test_data/trivial.d b/test/deps_test_data/trivial.d
new file mode 100644
index 0000000..15a0c29
--- /dev/null
+++ b/test/deps_test_data/trivial.d
@@ -0,0 +1 @@
+x.o: x.cc
diff --git a/test/execute_test.cc b/test/execute_test.cc
index d5d40c9..4c686bf 100644
--- a/test/execute_test.cc
+++ b/test/execute_test.cc
@@ -23,20 +23,25 @@ public:
void return_value()
{
+ ctor::settings s;
auto cur_path = std::filesystem::path(paths::argv_0).parent_path();
std::vector<std::string> paths{{cur_path.string()}};
auto cmd = locate("testprog", paths);
uASSERT(!cmd.empty());
- uASSERT_EQUAL(0, execute(cmd, {"retval", "0"}, {}, false));
- uASSERT_EQUAL(1, execute(cmd, {"retval", "1"}, {}, false));
- uASSERT_EQUAL(1, execute("no-such-binary", {}, {}, false));
+ auto value = execute(s, cmd, {"retval", "0"}, {}, false);
+ uASSERT_EQUAL(0, value);
+ value = execute(s, cmd, {"retval", "1"}, {}, false);
+ uASSERT_EQUAL(1, value);
+ value = execute(s, "no-such-binary", {}, {}, false);
+ uASSERT_EQUAL(1, value);
}
void env()
{
using namespace std::string_literals;
+ ctor::settings s;
auto cur_path = std::filesystem::path(paths::argv_0).parent_path();
std::vector<std::string> paths{{cur_path.string()}};
auto cmd = locate("testprog", paths);
@@ -53,7 +58,8 @@ public:
// Overwrite the exiting LANG var
env["LANG"] = "foo";
- uASSERT_EQUAL(0, execute(cmd, {"envdump", tmp.get()}, env, false));
+ auto value = execute(s, cmd, {"envdump", tmp.get()}, env, false);
+ uASSERT_EQUAL(0, value);
std::vector<std::string> vars;
{