diff options
| -rw-r--r-- | src/bootstrap.cc | 1 | ||||
| -rw-r--r-- | src/configure.cc | 101 | ||||
| -rw-r--r-- | src/configure.h | 10 | ||||
| -rw-r--r-- | src/libctor.cc | 1 | ||||
| -rw-r--r-- | src/libctor.h | 2 | ||||
| -rw-r--r-- | src/rebuild.cc | 43 | ||||
| -rw-r--r-- | src/rebuild.h | 7 | ||||
| -rw-r--r-- | src/task.h | 8 | ||||
| -rw-r--r-- | src/task_cc.cc | 5 | ||||
| -rw-r--r-- | src/task_cc.h | 2 | ||||
| -rw-r--r-- | src/tasks.cc | 77 | ||||
| -rw-r--r-- | test/suite/ctor_files/ctor.cc.bar | 58 | ||||
| -rw-r--r-- | test/suite/ctor_files/ctor.cc.base | 58 | ||||
| -rw-r--r-- | test/suite/hello.cc | 6 | ||||
| -rwxr-xr-x | test/suite/test.sh | 77 | 
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); @@ -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} | 
