summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap.cc1
-rw-r--r--src/configure.cc101
-rw-r--r--src/configure.h10
-rw-r--r--src/libctor.cc1
-rw-r--r--src/libctor.h2
-rw-r--r--src/rebuild.cc43
-rw-r--r--src/rebuild.h7
-rw-r--r--src/task.h8
-rw-r--r--src/task_cc.cc5
-rw-r--r--src/task_cc.h2
-rw-r--r--src/tasks.cc77
-rw-r--r--test/suite/ctor_files/ctor.cc.bar58
-rw-r--r--test/suite/ctor_files/ctor.cc.base58
-rw-r--r--test/suite/hello.cc6
-rwxr-xr-xtest/suite/test.sh77
15 files changed, 416 insertions, 40 deletions
diff --git a/src/bootstrap.cc b/src/bootstrap.cc
index 53018cc..0846907 100644
--- a/src/bootstrap.cc
+++ b/src/bootstrap.cc
@@ -18,7 +18,6 @@
#include "tasks.cc"
#include "build.cc"
-
std::filesystem::path configurationFile("configuration.cc");
std::filesystem::path configHeaderFile("config.h");
diff --git a/src/configure.cc b/src/configure.cc
index 13409ef..98f68d7 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -325,6 +325,17 @@ int regenerateCache(const Settings& default_settings,
std::string build_ar = locate(build_arch, ar_prog);
std::string build_ld = locate(build_arch, ld_prog);
+ // TODO: Centralize
+ // Resolv externals
+ ExternalConfigurations externalConfigs;
+ for(std::size_t i = 0; i < numExternalConfigFiles; ++i)
+ {
+ auto newExternalConfigs = externalConfigFiles[i].cb();
+ externalConfigs.insert(externalConfigs.end(),
+ newExternalConfigs.begin(),
+ newExternalConfigs.end());
+ }
+
std::cout << "Writing results to: " << configurationFile.string() << "\n";
{
std::ofstream istr(configurationFile);
@@ -368,9 +379,75 @@ int regenerateCache(const Settings& default_settings,
}
istr << " },\n";
+ istr << " .externals = {\n";
+
+ for(const auto& externalConfig : externalConfigs)
+ {
+ if(!externalConfig.cflags.empty())
+ {
+ istr << " { \"" << externalConfig.name << "-cflags\",\n";
+ istr << " {\n";
+ for(const auto& cflag : externalConfig.cflags)
+ {
+ istr << " \"" << cflag << "\",\n";
+ }
+ istr << " },\n";
+ istr << " },\n";
+ }
+
+ if(!externalConfig.cxxflags.empty())
+ {
+ istr << " { \"" << externalConfig.name << "-cxxflags\",\n";
+ istr << " {\n";
+ for(const auto& cxxflag : externalConfig.cxxflags)
+ {
+ istr << " \"" << cxxflag << "\",\n";
+ }
+ istr << " },\n";
+ istr << " },\n";
+ }
+
+ if(!externalConfig.ldflags.empty())
+ {
+ istr << " { \"" << externalConfig.name << "-ldflags\",\n";
+ istr << " {\n";
+ for(const auto& ldflag : externalConfig.ldflags)
+ {
+ istr << " \"" << ldflag << "\",\n";
+ }
+ istr << " },\n";
+ istr << " },\n";
+ }
+
+ if(!externalConfig.libs.empty())
+ {
+ istr << " { \"" << externalConfig.name << "-libs\",\n";
+ istr << " {\n";
+ for(const auto& lib : externalConfig.libs)
+ {
+ istr << " \"" << lib << "\",\n";
+ }
+ istr << " },\n";
+ istr << " },\n";
+ }
+
+ if(!externalConfig.asmflags.empty())
+ {
+ istr << " { \"" << externalConfig.name << "-asmflags\",\n";
+ istr << " {\n";
+ for(const auto& asmflag : externalConfig.asmflags)
+ {
+ istr << " \"" << asmflag << "\",\n";
+ }
+ istr << " },\n";
+ istr << " },\n";
+ }
+ }
+
+ istr << " },\n";
istr << " };\n";
istr << " return cfg;\n";
- istr << "}\n";
+ istr << "}\n\n";
}
{
@@ -424,13 +501,26 @@ int configure(const Settings& global_settings, int argc, char* argv[])
return ret;
}
- recompileCheck(settings, 1, argv, false);
+ recompileCheck(settings, argc, argv, false);
return 0;
}
int reconfigure(const Settings& settings, int argc, char* argv[])
{
+ bool no_rerun{false};
+
+ std::vector<std::string> args;
+ for(int i = 2; i < argc; ++i) // skip executable name and 'reconfigure' arg
+ {
+ if(i == 2 && std::string(argv[i]) == "--no-rerun")
+ {
+ no_rerun = true;
+ continue;
+ }
+ args.push_back(argv[i]);
+ }
+
const auto& cfg = configuration();
std::cout << "Re-running configure:\n";
@@ -451,10 +541,11 @@ int reconfigure(const Settings& settings, int argc, char* argv[])
return ret;
}
- std::vector<std::string> args;
- for(int i = 2; i < argc; ++i) // skip command and the first 'reconfigure' arg
+ recompileCheck(settings, 1, argv, false);
+
+ if(no_rerun)
{
- args.push_back(argv[i]);
+ return 0; // this was originally invoked by configure, don't loop
}
return execute(argv[0], args);
diff --git a/src/configure.h b/src/configure.h
index d9160a5..16499d6 100644
--- a/src/configure.h
+++ b/src/configure.h
@@ -6,6 +6,7 @@
#include <filesystem>
#include <string>
#include <map>
+#include <vector>
struct Settings;
@@ -14,12 +15,3 @@ extern std::filesystem::path configHeaderFile;
int configure(const Settings& settings, int argc, char* argv[]);
int reconfigure(const Settings& settings, 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/src/libctor.cc b/src/libctor.cc
index fcd3a95..a2c873e 100644
--- a/src/libctor.cc
+++ b/src/libctor.cc
@@ -34,6 +34,7 @@ int main(int argc, char* argv[])
settings.builddir = getConfiguration(cfg::builddir, settings.builddir);
settings.parallel_processes =
std::max(1u, std::thread::hardware_concurrency()) * 2 - 1;
+
if(argc > 1 && std::string(argv[1]) == "configure")
{
return configure(settings, argc, argv);
diff --git a/src/libctor.h b/src/libctor.h
index bcbe3a5..a5fd249 100644
--- a/src/libctor.h
+++ b/src/libctor.h
@@ -73,6 +73,7 @@ struct ExternalConfiguration
std::vector<std::string> cflags; // flags for c compiler
std::vector<std::string> ldflags; // flags for linker
std::vector<std::string> asmflags; // flags for asm translator
+ std::vector<std::string> libs; // libraries
};
using ExternalConfigurations = std::vector<ExternalConfiguration>;
@@ -111,6 +112,7 @@ struct Configuration
std::map<std::string, std::string> env; // env used when last calling configure
std::map<std::string, std::string> tools; // tools
+ std::map<std::string, std::vector<std::string>> externals;
};
const Configuration& configuration();
diff --git a/src/rebuild.cc b/src/rebuild.cc
index fc95b16..ff61695 100644
--- a/src/rebuild.cc
+++ b/src/rebuild.cc
@@ -13,11 +13,12 @@
#include "libctor.h"
#include "tasks.h"
#include "build.h"
+#include "execute.h"
std::array<BuildConfigurationEntry, 1024> configFiles;
std::size_t numConfigFiles{0};
-int reg(std::vector<BuildConfiguration> (*cb)(),
+int reg(BuildConfigurations (*cb)(),
const std::source_location location)
{
// NOTE: std::cout cannot be used here
@@ -96,7 +97,7 @@ int unreg(const char* location)
std::array<ExternalConfigurationEntry, 1024> externalConfigFiles;
std::size_t numExternalConfigFiles{0};
-int reg(std::vector<ExternalConfiguration> (*cb)(),
+int reg(ExternalConfigurations (*cb)(),
const std::source_location location)
{
// NOTE: std::cout cannot be used here
@@ -130,7 +131,7 @@ bool contains(const std::vector<Source>& sources, const std::string& file)
}
}
-void recompileCheck(const Settings& global_settings, int argc, char* argv[],
+bool recompileCheck(const Settings& global_settings, int argc, char* argv[],
bool relaunch_allowed)
{
using namespace std::string_literals;
@@ -207,7 +208,19 @@ void recompileCheck(const Settings& global_settings, int argc, char* argv[],
{
if(task->registerDepTasks(tasks))
{
- return;
+ return false;
+ }
+ }
+
+ // Find out if reconfigure is needed
+ bool reconfigure{false};
+ for(auto task : tasks)
+ {
+ if(task->dirty() &&
+ task->source() != "" && // only look at source files
+ task->source() != "configuration.cc") // don't reconfigure if only configuration.cc is changed.
+ {
+ reconfigure |= true;
}
}
@@ -217,4 +230,26 @@ void recompileCheck(const Settings& global_settings, int argc, char* argv[],
std::cout << "Rebuilding config.\n";
build(settings, "ctor", tasks); // run for real
}
+
+ if(reconfigure)
+ {
+ std::vector<std::string> args;
+ args.push_back("reconfigure");
+ if(!relaunch_allowed)
+ {
+ args.push_back("--no-rerun");
+ }
+ for(int i = 1; i < argc; ++i)
+ {
+ args.push_back(argv[i]);
+ }
+ auto ret = execute(argv[0], args);
+ //if(ret != 0)
+ {
+ exit(ret);
+ }
+
+ }
+
+ return dirty_tasks;
}
diff --git a/src/rebuild.h b/src/rebuild.h
index f14236e..0845d30 100644
--- a/src/rebuild.h
+++ b/src/rebuild.h
@@ -13,13 +13,13 @@ class Settings;
struct BuildConfigurationEntry
{
const char* file;
- std::vector<BuildConfiguration> (*cb)();
+ BuildConfigurations (*cb)();
};
struct ExternalConfigurationEntry
{
const char* file;
- std::vector<ExternalConfiguration> (*cb)();
+ ExternalConfigurations (*cb)();
};
extern std::array<BuildConfigurationEntry, 1024> configFiles;
@@ -31,5 +31,6 @@ extern std::size_t numExternalConfigFiles;
int reg(const char* location);
int unreg(const char* location);
-void recompileCheck(const Settings& settings, int argc, char* argv[],
+//! Returns true of recompilation was needed.
+bool recompileCheck(const Settings& settings, int argc, char* argv[],
bool relaunch_allowed = true);
diff --git a/src/task.h b/src/task.h
index 7068c8a..4cbd126 100644
--- a/src/task.h
+++ b/src/task.h
@@ -35,10 +35,16 @@ public:
virtual int clean() = 0 ;
virtual std::vector<std::string> depends() const = 0;
virtual std::string target() const = 0;
+
+ //! Returns true for tasks that are non-target tasks, ie. for example derived
+ //! objects files from target sources.
virtual bool derived() const = 0;
virtual std::string toJSON() const { return {}; };
+ //! Returns a reference to the originating build config.
+ //! Note: the build config of a derived task will be that of its parent
+ //! (target) task.
const BuildConfiguration& buildConfig() const;
TargetType targetType() const;
@@ -48,6 +54,8 @@ public:
std::list<std::shared_ptr<Task>> getDependsTasks();
+ virtual std::string source() const { return {}; }
+
protected:
std::atomic<State> task_state{State::Unknown};
virtual int runInner() { return 0; };
diff --git a/src/task_cc.cc b/src/task_cc.cc
index a9be475..61f5977 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -236,6 +236,11 @@ std::string TaskCC::toJSON() const
return json;
}
+std::string TaskCC::source() const
+{
+ return sourceFile.string();
+}
+
std::vector<std::string> TaskCC::flags() const
{
switch(sourceLanguage())
diff --git a/src/task_cc.h b/src/task_cc.h
index 0589ea4..c309abd 100644
--- a/src/task_cc.h
+++ b/src/task_cc.h
@@ -34,6 +34,8 @@ public:
std::string toJSON() const override;
+ std::string source() const override;
+
protected:
std::vector<std::string> flags() const;
std::string flagsString() const;
diff --git a/src/tasks.cc b/src/tasks.cc
index 8efc98e..8a85fc8 100644
--- a/src/tasks.cc
+++ b/src/tasks.cc
@@ -16,6 +16,7 @@
#include "task_ar.h"
#include "task_so.h"
#include "rebuild.h"
+#include "configure.h"
const std::deque<Target>& getTargets(const Settings& settings)
{
@@ -23,9 +24,9 @@ const std::deque<Target>& getTargets(const Settings& settings)
static std::deque<Target> targets;
if(!initialised)
{
-
- // Generate externals
- std::vector<ExternalConfiguration> externalConfigs;
+ // TODO: Centralize
+ // Resolv externals
+ ExternalConfigurations externalConfigs;
for(std::size_t i = 0; i < numExternalConfigFiles; ++i)
{
auto newExternalConfigs = externalConfigFiles[i].cb();
@@ -34,6 +35,7 @@ const std::deque<Target>& getTargets(const Settings& settings)
newExternalConfigs.end());
}
+ const auto& extMap = configuration().externals;
for(std::size_t i = 0; i < numConfigFiles; ++i)
{
std::string path =
@@ -46,7 +48,6 @@ const std::deque<Target>& getTargets(const Settings& settings)
for(auto& config : configs)
{
-
// Resolv config externals
for(const auto& external : config.externals)
{
@@ -56,18 +57,60 @@ const std::deque<Target>& getTargets(const Settings& settings)
if(externalConfig.name == external)
{
found = true;
- config.cflags.insert(config.cflags.end(),
- externalConfig.cflags.begin(),
- externalConfig.cflags.end());
- config.cxxflags.insert(config.cxxflags.end(),
- externalConfig.cxxflags.begin(),
- externalConfig.cxxflags.end());
- config.ldflags.insert(config.ldflags.end(),
- externalConfig.ldflags.begin(),
- externalConfig.ldflags.end());
- config.asmflags.insert(config.asmflags.end(),
- externalConfig.asmflags.begin(),
- externalConfig.asmflags.end());
+ try
+ {
+ auto cflags = extMap.at(external+"-cflags");
+ config.cflags.insert(config.cflags.end(),
+ cflags.begin(),
+ cflags.end());
+ }
+ catch(...)
+ {
+ }
+
+ try
+ {
+ auto cxxflags = extMap.at(external+"-cxxflags");
+ config.cxxflags.insert(config.cxxflags.end(),
+ cxxflags.begin(),
+ cxxflags.end());
+ }
+ catch(...)
+ {
+ }
+
+ try
+ {
+ auto ldflags = extMap.at(external+"-ldflags");
+ config.ldflags.insert(config.ldflags.end(),
+ ldflags.begin(),
+ ldflags.end());
+ }
+ catch(...)
+ {
+ }
+
+ try
+ {
+ auto asmflags = extMap.at(external+"-asmflags");
+ config.asmflags.insert(config.asmflags.end(),
+ asmflags.begin(),
+ asmflags.end());
+ }
+ catch(...)
+ {
+ }
+
+ try
+ {
+ auto libs = extMap.at(external+"-libs");
+ //config.libs.insert(config.libs.end(),
+ // libs.begin(),
+ // libs.end());
+ }
+ catch(...)
+ {
+ }
}
}
if(!found)
@@ -75,10 +118,8 @@ const std::deque<Target>& getTargets(const Settings& settings)
std::cout << "External '" << external << "' not found.\n";
exit(1);
}
-
}
-
targets.push_back({config, path});
}
}
diff --git a/test/suite/ctor_files/ctor.cc.bar b/test/suite/ctor_files/ctor.cc.bar
new file mode 100644
index 0000000..2c9df2a
--- /dev/null
+++ b/test/suite/ctor_files/ctor.cc.bar
@@ -0,0 +1,58 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include <libctor.h>
+//#include "config.h"
+
+namespace
+{
+BuildConfigurations ctorConfigs()
+{
+ return
+ {
+ {
+ .name = "hello",
+ .target = "hello",
+ .sources = {
+ "hello.cc",
+ },
+ .cxxflags = {
+ "-std=c++20",
+ "-O3",
+ "-g",
+ "-Wall",
+ "-Werror",
+ },
+ .externals = {"bar"},
+ }
+ };
+}
+
+ExternalConfigurations ctorExtConfigs()
+{
+ return
+ {
+ {
+ .name = "bar",
+ .cxxflags = { "-D_A_", "-DBAR"},
+ .cflags = { "-D_B_" },
+ .ldflags = { "-D_C_" },
+ .asmflags = { "-D_D_" },
+ // Creates --with-foo-prefix arg to configure which will be used for
+ // -L and -I flags.
+ // If not specified configure will try to find them in the system paths.
+ },
+// {
+// .name = "bar",
+// .type = TargetType::ExternalPkgConfig,
+// .min_version = "0.1",
+// .max_version = "0.9",
+// // cflags, cxxflags and ldflags deduced by pkg-config tool (or parsed
+// // directly from .pc if faster)
+// },
+ };
+}
+}
+
+REG(ctorConfigs);
+REG(ctorExtConfigs);
diff --git a/test/suite/ctor_files/ctor.cc.base b/test/suite/ctor_files/ctor.cc.base
new file mode 100644
index 0000000..d9b8e4d
--- /dev/null
+++ b/test/suite/ctor_files/ctor.cc.base
@@ -0,0 +1,58 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include <libctor.h>
+//#include "config.h"
+
+namespace
+{
+BuildConfigurations ctorConfigs()
+{
+ return
+ {
+ {
+ .name = "hello",
+ .target = "hello",
+ .sources = {
+ "hello.cc",
+ },
+ .cxxflags = {
+ "-std=c++20",
+ "-O3",
+ "-g",
+ "-Wall",
+ "-Werror",
+ },
+ .externals = {"bar"},
+ }
+ };
+}
+
+ExternalConfigurations ctorExtConfigs()
+{
+ return
+ {
+ {
+ .name = "bar",
+ .cxxflags = { "-D_A_", "-DFOO"},
+ .cflags = { "-D_B_" },
+ .ldflags = { "-D_C_" },
+ .asmflags = { "-D_D_" },
+ // Creates --with-foo-prefix arg to configure which will be used for
+ // -L and -I flags.
+ // If not specified configure will try to find them in the system paths.
+ },
+// {
+// .name = "bar",
+// .type = TargetType::ExternalPkgConfig,
+// .min_version = "0.1",
+// .max_version = "0.9",
+// // cflags, cxxflags and ldflags deduced by pkg-config tool (or parsed
+// // directly from .pc if faster)
+// },
+ };
+}
+}
+
+REG(ctorConfigs);
+REG(ctorExtConfigs);
diff --git a/test/suite/hello.cc b/test/suite/hello.cc
new file mode 100644
index 0000000..06e3deb
--- /dev/null
+++ b/test/suite/hello.cc
@@ -0,0 +1,6 @@
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello\n";
+}
diff --git a/test/suite/test.sh b/test/suite/test.sh
new file mode 100755
index 0000000..8d22206
--- /dev/null
+++ b/test/suite/test.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+function fail
+{
+ echo "*** Failure at line $1"
+ exit 1
+}
+
+function ctor
+{
+ echo "*** Running: ./ctor $*"
+ ./ctor $*
+}
+
+# Wipe the board
+rm -Rf build
+rm -f configuration.cc
+rm -f ctor
+
+cp ctor_files/ctor.cc.base ctor.cc
+
+# Compile bootstrap binary
+g++ -pthread -std=c++20 -L../../build -lctor -I../../src ctor.cc -o ctor || fail ${LINENO}
+
+# No build files should have been created yet
+[ -d build ] && fail ${LINENO}
+
+# capture md5 sum of ctor binary before configure is called
+MD5=`md5sum ctor`
+ctor configure --ctor-includedir ../../src --ctor-libdir ../../build
+
+# ctor should be rebuilt at this point, so md5 sum should have changed
+(echo $MD5 | md5sum --status -c) && fail ${LINENO}
+
+# configuration.cc should have been generated now
+[ ! -f configuration.cc ] && fail ${LINENO}
+
+# Shouldn't compile anything yet - only configure
+[ -f build/hello-hello_cc.o ] && fail ${LINENO}
+
+MD5=`md5sum ctor`
+
+# Run normally to build project
+ctor -v
+
+# Compiled object should now exist
+[ ! -f build/hello-hello_cc.o ] && fail ${LINENO}
+
+# ctor should not have been rebuilt, so md5 sum should be the same
+(echo $MD5 | md5sum --status -c) || fail ${LINENO}
+
+MOD1=`stat -c %Y build/hello-hello_cc.o`
+touch hello.cc
+sleep 1.1
+
+# Run normally to rebuild hello.cc
+ctor -v
+
+# Object file should have been recompiled
+MOD2=`stat -c %Y build/hello-hello_cc.o`
+[[ $MOD1 == $MOD2 ]] && fail ${LINENO}
+
+# Replacve -DFOO with -DBAR in foo external.cxxflags
+cp ctor_files/ctor.cc.bar ctor.cc
+
+MD5C=`md5sum configuration.cc`
+MD5=`md5sum ctor`
+MOD1=`stat -c %Y build/hello-hello_cc.o`
+sleep 1.1
+
+# Run normally to reconfigure, rebuild ctor and rebuild hello.cc
+ctor -v
+
+MOD2=`stat -c %Y build/hello-hello_cc.o`
+[[ $MOD1 == $MOD2 ]] && fail ${LINENO}
+(echo $MD5C | md5sum --status -c) && fail ${LINENO}
+(echo $MD5 | md5sum --status -c) && fail ${LINENO}