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