Refactor ConfigFile.cpp to be simpler

This commit is contained in:
Thraix
2026-05-09 22:46:18 +02:00
parent 5d00ada431
commit 8ff0411952
17 changed files with 843 additions and 506 deletions
+10 -10
View File
@@ -1,4 +1,4 @@
# This Makefile was generated using MakeGen v1.3.9 made by Tim Håkansson # This Makefile was generated using MakeGen v1.3.10 made by Tim Håkansson
# and is licensed under MIT. Full source of the project can be found at # and is licensed under MIT. Full source of the project can be found at
# https://gitea.timha.se/Thraix/MakeGen # https://gitea.timha.se/Thraix/MakeGen
CC=@g++ CC=@g++
@@ -34,33 +34,33 @@ $(OUTPUT): $(OBJECTS)
install: all install: all
$(info Installing MakeGen to /usr/bin/) $(info Installing MakeGen to /usr/bin/)
@cp $(OUTPUT) /usr/bin/makegen @cp $(OUTPUT) /usr/bin/makegen
$(OBJPATH)/src/ConfigCLI.o: src/ConfigCLI.cpp src/Common.h src/ConfigCLI.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/ConfigCLI.o: src/ConfigCLI.cpp src/Common.h src/AssertException.h src/ConfigCLI.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h
$(info -[10%]- $<) $(info -[10%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/ConfigFile.o: src/ConfigFile.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h src/xml/XML.h $(OBJPATH)/src/ConfigFile.o: src/ConfigFile.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/AssertException.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h src/xml/XML.h
$(info -[20%]- $<) $(info -[20%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/HFileGen.o: src/HFileGen.cpp src/FileUtils.h src/Common.h src/Utils.h src/HFileGen.h src/ConfigFile.h src/ConfigUtils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/HFileGen.o: src/HFileGen.cpp src/FileUtils.h src/Common.h src/AssertException.h src/Utils.h src/HFileGen.h src/ConfigFile.h src/ConfigUtils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h
$(info -[30%]- $<) $(info -[30%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/IncludeDeps.o: src/IncludeDeps.cpp src/Common.h src/IncludeDeps.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/IncludeDeps.o: src/IncludeDeps.cpp src/Common.h src/AssertException.h src/IncludeDeps.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h
$(info -[40%]- $<) $(info -[40%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/Makefile.o: src/Makefile.cpp src/Common.h src/IncludeDeps.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/Makefile.h $(OBJPATH)/src/Makefile.o: src/Makefile.cpp src/Common.h src/AssertException.h src/IncludeDeps.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/Makefile.h
$(info -[50%]- $<) $(info -[50%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/Utils.o: src/Utils.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/Utils.o: src/Utils.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/AssertException.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h
$(info -[60%]- $<) $(info -[60%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/compatibility/ConfigFileConf.o: src/compatibility/ConfigFileConf.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h $(OBJPATH)/src/compatibility/ConfigFileConf.o: src/compatibility/ConfigFileConf.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/AssertException.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h
$(info -[70%]- $<) $(info -[70%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/main.o: src/main.cpp src/Common.h src/ConfigCLI.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/HFileGen.h src/Makefile.h src/Timer.h $(OBJPATH)/src/main.o: src/main.cpp src/Common.h src/AssertException.h src/ConfigCLI.h src/ConfigFile.h src/ConfigUtils.h src/FileUtils.h src/Utils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/HFileGen.h src/Makefile.h src/Timer.h
$(info -[80%]- $<) $(info -[80%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/xml/XML.o: src/xml/XML.cpp src/xml/XML.h src/xml/XMLObject.h src/xml/XMLException.h $(OBJPATH)/src/xml/XML.o: src/xml/XML.cpp src/xml/XML.h src/xml/XMLObject.h src/xml/XMLException.h
$(info -[90%]- $<) $(info -[90%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/xml/XMLObject.o: src/xml/XMLObject.cpp src/Common.h src/Utils.h src/xml/XMLException.h src/xml/XMLObject.h $(OBJPATH)/src/xml/XMLObject.o: src/xml/XMLObject.cpp src/Common.h src/AssertException.h src/Utils.h src/xml/XMLException.h src/xml/XMLObject.h
$(info -[100%]- $<) $(info -[100%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
+1 -3
View File
@@ -1,6 +1,5 @@
<makegen> <makegen>
<configuration name="Release"> <configuration name="Release">
<generatehfile>false</generatehfile>
<outputdir>bin/Release/</outputdir> <outputdir>bin/Release/</outputdir>
<outputname>makegen</outputname> <outputname>makegen</outputname>
<outputtype>executable</outputtype> <outputtype>executable</outputtype>
@@ -11,7 +10,6 @@
<cflag>-g3</cflag> <cflag>-g3</cflag>
<cflag>-w</cflag> <cflag>-w</cflag>
<define>_DEBUG</define> <define>_DEBUG</define>
<generatehfile>false</generatehfile>
<outputdir>bin/Debug/</outputdir> <outputdir>bin/Debug/</outputdir>
<outputname>makegen</outputname> <outputname>makegen</outputname>
<outputtype>executable</outputtype> <outputtype>executable</outputtype>
@@ -19,5 +17,5 @@
<srcdir>src/</srcdir> <srcdir>src/</srcdir>
</configuration> </configuration>
<target>Release</target> <target>Release</target>
<version>v1.3.9</version> <version>v1.3.10</version>
</makegen> </makegen>
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <stdexcept>
struct AssertException : public std::runtime_error
{
AssertException()
: std::runtime_error{"assertion failed"}
{
}
};
+19 -2
View File
@@ -4,6 +4,8 @@
#include <set> #include <set>
#include <vector> #include <vector>
#include "AssertException.h"
#define BIT(x) (1 << x) #define BIT(x) (1 << x)
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
@@ -14,7 +16,7 @@
// Release, should be backwards compatible with any minor version // Release, should be backwards compatible with any minor version
#define MAKEGEN_VERSION_RELEASE 3 #define MAKEGEN_VERSION_RELEASE 3
// Minor changes, generally bug fixes // Minor changes, generally bug fixes
#define MAKEGEN_VERSION_MINOR 9 #define MAKEGEN_VERSION_MINOR 10
#define MAKEGEN_VERSION ("v" STR(MAKEGEN_VERSION_MAJOR) "." STR(MAKEGEN_VERSION_RELEASE) "." STR(MAKEGEN_VERSION_MINOR)) #define MAKEGEN_VERSION ("v" STR(MAKEGEN_VERSION_MAJOR) "." STR(MAKEGEN_VERSION_RELEASE) "." STR(MAKEGEN_VERSION_MINOR))
@@ -33,7 +35,22 @@ const static unsigned int FLAG_TARGET = BIT(11);
#define LOG_INFO(...) LogHelper(__VA_ARGS__) #define LOG_INFO(...) LogHelper(__VA_ARGS__)
#define LOG_WARNING(...) LogHelper(__VA_ARGS__) #define LOG_WARNING(...) LogHelper(__VA_ARGS__)
#define LOG_ERROR(...) LogHelper(__VA_ARGS__) #define LOG_ERROR(...) LogHelper("\033[1;31m[ERROR] ", __VA_ARGS__, "\033[0m")
#define ASSERT(expr, ...) \
if (!(expr)) \
{ \
LOG_ERROR(__VA_ARGS__); \
throw AssertException{}; \
} \
{ \
} \
while (false)
#define ABORT(...) \
{ \
LOG_ERROR(__VA_ARGS__); \
throw AssertException{}; \
} \
while (false)
template <typename T> template <typename T>
void Log(const T& var) void Log(const T& var)
+32 -40
View File
@@ -54,8 +54,8 @@ Valid settings are:
dependency Project which current project depends on dependency Project which current project depends on
excludesource Exclude source file from compiling excludesource Exclude source file from compiling
excludeheader Exclude header file from project h-file excludeheader Exclude header file from project h-file
argument Command line argument for the executable argument Command line argument for the executable
preargument Command line argument before the executabe, e.g. gdb)"); preargument Command line argument before the executabe, e.g. gdb)");
} }
void ConfigCLI::DisplayRemoveHelp() void ConfigCLI::DisplayRemoveHelp()
@@ -75,8 +75,8 @@ Valid settings are
dependency Project which current project depends on dependency Project which current project depends on
excludesource Exclude source file from compiling excludesource Exclude source file from compiling
excludeheader Exclude header file from project h-file excludeheader Exclude header file from project h-file
argument Command line argument for the executable argument Command line argument for the executable
preargument Command line argument before the executabe, e.g. gdb)"); preargument Command line argument before the executabe, e.g. gdb)");
} }
void ConfigCLI::DisplaySetHelp() void ConfigCLI::DisplaySetHelp()
@@ -151,8 +151,7 @@ ConfigSetting ConfigCLI::CLIStringToSetting(const std::string& s)
{"genhfile", ConfigSetting::GenerateHFile}, {"genhfile", ConfigSetting::GenerateHFile},
}; };
auto it = map.find(s); auto it = map.find(s);
if (it == map.end()) ASSERT(it != map.end(), "Invalid config setting: ", s)
return ConfigSetting::Invalid;
return it->second; return it->second;
} }
@@ -202,15 +201,8 @@ int ConfigCLI::Add(int argc, char** argv, ConfigFile& config)
ConfigSetting setting = CLIStringToSetting(argv[1]); ConfigSetting setting = CLIStringToSetting(argv[1]);
if (!ConfigUtils::IsVectorSetting(setting)) if (!ConfigUtils::IsVectorSetting(setting))
{ {
if (setting == ConfigSetting::Invalid) LOG_ERROR("Cannot remove setting which only supports one argument");
{ LOG_ERROR("use set instead.");
LOG_ERROR("No such setting: ", argv[1]);
}
else
{
LOG_ERROR("Cannot remove setting which only supports one argument");
LOG_ERROR("use set instead.");
}
return 1; return 1;
} }
for (int i = 2; i < argc; ++i) for (int i = 2; i < argc; ++i)
@@ -238,15 +230,8 @@ int ConfigCLI::Remove(int argc, char** argv, ConfigFile& config)
ConfigSetting setting = CLIStringToSetting(argv[1]); ConfigSetting setting = CLIStringToSetting(argv[1]);
if (!ConfigUtils::IsVectorSetting(setting)) if (!ConfigUtils::IsVectorSetting(setting))
{ {
if (setting == ConfigSetting::Invalid) LOG_ERROR("Cannot remove setting which only supports one argument");
{ LOG_ERROR("use set instead.");
LOG_ERROR("No such setting: ", argv[1]);
}
else
{
LOG_ERROR("Cannot remove setting which only supports one argument");
LOG_ERROR("use set instead.");
}
return 1; return 1;
} }
@@ -275,15 +260,8 @@ int ConfigCLI::Set(int argc, char** argv, ConfigFile& config)
ConfigSetting setting = CLIStringToSetting(argv[1]); ConfigSetting setting = CLIStringToSetting(argv[1]);
if (!ConfigUtils::IsStringSetting(setting) && !ConfigUtils::IsBoolSetting(setting)) if (!ConfigUtils::IsStringSetting(setting) && !ConfigUtils::IsBoolSetting(setting))
{ {
if (setting == ConfigSetting::Invalid) LOG_ERROR("Cannot set setting which supports multiple arguments");
{ LOG_ERROR("use add or remove instead.");
LOG_ERROR("No such setting: ", argv[1]);
}
else
{
LOG_ERROR("Cannot set setting which supports multiple arguments");
LOG_ERROR("use add or remove instead.");
}
return 1; return 1;
} }
@@ -321,8 +299,22 @@ int ConfigCLI::Main(int argc, char** argv)
DisplayCLIHelp(); DisplayCLIHelp();
return 0; return 0;
} }
std::optional<ConfigFile> config = ConfigFile::GetConfigFile("./", FlagData{}); std::string target = "";
std::string command = argv[1]; int commandIndex = 1;
if (argc >= 1 && Utils::StartsWith(argv[1], "--target="))
{
std::string prefix("--target=");
std::string flag(argv[1]);
if (flag.size() < prefix.size() + 1)
{
LOG_ERROR("No target specified in --target=<target>");
return 1;
}
target = flag.substr(std::string("--target=").size());
commandIndex++;
}
std::optional<ConfigFile> config = ConfigFile::GetConfigFile("./", FlagData{target == "" ? 0 : FLAG_TARGET, target});
std::string command = argv[commandIndex];
if (command == "gen") if (command == "gen")
{ {
if (config) if (config)
@@ -330,18 +322,18 @@ int ConfigCLI::Main(int argc, char** argv)
LOG_ERROR("Config file already exist (", CONFIG_FILENAME, ")"); LOG_ERROR("Config file already exist (", CONFIG_FILENAME, ")");
return 1; return 1;
} }
return Gen(argc - 1, &argv[1]); return Gen(argc - commandIndex, &argv[commandIndex]);
} }
else if (config) else if (config)
{ {
if (command == "add") if (command == "add")
return Add(argc - 1, &argv[1], *config); return Add(argc - commandIndex, &argv[commandIndex], *config);
else if (command == "remove") else if (command == "remove")
return Remove(argc - 1, &argv[1], *config); return Remove(argc - commandIndex, &argv[commandIndex], *config);
else if (command == "set") else if (command == "set")
return Set(argc - 1, &argv[1], *config); return Set(argc - commandIndex, &argv[commandIndex], *config);
else if (command == "get") else if (command == "get")
return Get(argc - 1, &argv[1], *config); return Get(argc - commandIndex, &argv[commandIndex], *config);
else else
{ {
LOG_ERROR("Unknown config command: ", command); LOG_ERROR("Unknown config command: ", command);
+545 -281
View File
@@ -7,21 +7,20 @@
#include "xml/XML.h" #include "xml/XML.h"
ConfigFile::ConfigFile(const std::string& path, const FlagData& flagData, int) ConfigFile::ConfigFile(const std::string& path, const FlagData& flagData, int)
: configPath{path} : makegen{"makegen", {}, std::map<std::string, std::vector<XMLObject>>{}},
configPath{std::filesystem::canonical(path)}
{ {
// Converts project name (current directory) to lowercase
// and replace whitespace with underscore
// Create xml
XMLObject makegen("makegen", {}, std::map<std::string, std::vector<XMLObject>>{});
// Version, target and configuration is probably going to be used in the future // Version, target and configuration is probably going to be used in the future
makegen.AddXMLObject(XMLObject("version", {}, "v1.3.0")); makegen.AddXMLObject(XMLObject("version", {}, MAKEGEN_VERSION));
std::string target;
if (flagData.flags & FLAG_TARGET) if (flagData.flags & FLAG_TARGET)
makegen.AddXMLObject(XMLObject("target", {}, flagData.target)); target = flagData.target;
else else
makegen.AddXMLObject(XMLObject("target", {}, "Release")); target = "Release";
XMLObject configuration("configuration", {{"name", "Release"}}, std::map<std::string, std::vector<XMLObject>>{}); makegen.AddXMLObject(XMLObject("target", {}, target));
XMLObject configuration("configuration", {{"name", target}}, std::map<std::string, std::vector<XMLObject>>{});
configuration.AddXMLObject(XMLObject("projectname", {}, ConfigUtils::GetDefaultProjectName(configPath))); configuration.AddXMLObject(XMLObject("projectname", {}, ConfigUtils::GetDefaultProjectName(configPath)));
configuration.AddXMLObject(XMLObject("outputname", {}, ConfigUtils::GetDefaultOutputName(configPath))); configuration.AddXMLObject(XMLObject("outputname", {}, ConfigUtils::GetDefaultOutputName(configPath)));
configuration.AddXMLObject(XMLObject("srcdir", {}, "src/")); configuration.AddXMLObject(XMLObject("srcdir", {}, "src/"));
@@ -31,50 +30,109 @@ ConfigFile::ConfigFile(const std::string& path, const FlagData& flagData, int)
configuration.AddXMLObject(XMLObject("generatehfile", {}, "false")); configuration.AddXMLObject(XMLObject("generatehfile", {}, "false"));
makegen.AddXMLObject(configuration); makegen.AddXMLObject(configuration);
config = makegen;
Init(flagData); Init(flagData);
} }
ConfigFile::ConfigFile(const std::string& path, const FlagData& flagData) ConfigFile::ConfigFile(const std::string& path, const FlagData& flagData)
: config{XML::FromFile(path + CONFIG_FILENAME)}, : makegen{XML::FromFile(path + CONFIG_FILENAME)},
configPath{path} configPath{std::filesystem::canonical(path)}
{ {
Init(flagData); Init(flagData);
} }
ConfigFile::ConfigFile(XMLObject& config, const std::string& path, const FlagData& flagData) ConfigFile::ConfigFile(XMLObject& config, const std::string& path, const FlagData& flagData)
: config{config}, : makegen{config},
configPath{path} configPath{std::filesystem::canonical(path)}
{ {
Init(flagData); Init(flagData);
} }
void ConfigFile::Init(const FlagData& flagData) void ConfigFile::Init(const FlagData& flagData)
{
InitTarget(flagData);
InitTargetConfig();
InitDependencies();
InitStringSetting("outputname", &outputName);
InitStringSetting("outputtype", &outputType);
InitStringSetting("outputdir", &outputDir);
InitStringSetting("projectname", &projectName);
InitOptionalStringSetting("srcdir", &sourceDir);
InitOptionalStringSetting("hfilename", &hFileName);
InitStringListSetting("librarydir", &libraryDirs);
InitStringListSetting("includedir", &includeDirs);
InitStringListSetting("library", &libraries);
InitStringListSetting("define", &defines);
InitStringListSetting("cflag", &cFlags);
InitStringListSetting("lflag", &lFlags);
InitStringListSetting("excludeheader", &excludeHeaders);
InitStringListSetting("excludesource", &excludeSources);
InitStringListSetting("sourcefile", &sourceFiles);
InitStringListSetting("preargument", &preArguments);
InitStringListSetting("argument", &arguments);
InitStringListSetting("includedirexcldep", &includeDirExclDeps);
InitBoolSetting("generatehfile", &generateHFile);
InitDir(outputDir);
InitOptionalDir(sourceDir);
InitDirs(libraryDirs);
InitDirs(includeDirs);
}
void ConfigFile::InitTarget(const FlagData& flagData)
{ {
if (flagData.flags & FLAG_TARGET) if (flagData.flags & FLAG_TARGET)
{ {
target = flagData.target; target = flagData.target;
return;
} }
else
const std::vector<XMLObject>& targetXml = makegen.GetObjects("target");
if (targetXml.empty())
{ {
const std::vector<XMLObject>* targetXml = config.GetObjectPtr("target");
target = "Release"; target = "Release";
if (!targetXml || targetXml->size() == 0) LOG_ERROR("No target found in makegen file. Using target=", target);
{ return;
LOG_ERROR("No target found in config file. Using target=", target);
return;
}
if (targetXml->size() > 1)
LOG_ERROR("To many targets in config file. Using target=", (*targetXml)[0].GetText());
if (targetXml->size() > 0)
target = (*targetXml)[0].GetText();
} }
InitDependencies();
if (targetXml.size() > 1)
LOG_ERROR("Too many targets in makegen file. Using target=", targetXml.front().GetText());
target = targetXml.front().GetText();
}
void ConfigFile::InitTargetConfig()
{
config = GetTargetConfig();
}
XMLObject& ConfigFile::GetTargetConfig()
{
std::vector<XMLObject>& configurations = makegen.GetObjects("configuration");
ASSERT(!configurations.empty(), "No configuration in makegen.xml");
for (auto& configuration : configurations)
{
if (!configuration.HasAttribute("name"))
{
LOG_ERROR("No name attribute in configuration tag");
continue;
}
if (configuration.GetAttribute("name") == target)
{
return configuration;
}
}
LOG_ERROR("Couldn\'t find given target=",
target,
" in config file. Using target=",
configurations.front().GetAttribute("name", ""));
return configurations.front();
} }
void ConfigFile::InitDependencies() void ConfigFile::InitDependencies()
{ {
const std::vector<XMLObject>& values = GetConfiguration().GetObjects("dependency"); const std::vector<XMLObject>& values = config.GetObjects("dependency");
for (const auto& value : values) for (const auto& value : values)
{ {
@@ -83,275 +141,498 @@ void ConfigFile::InitDependencies()
} }
} }
std::string& ConfigFile::GetSettingString(ConfigSetting setting) void ConfigFile::InitStringSetting(const std::string& name, std::string* output)
{ {
// Adding it to the cache since we need to return a reference const std::vector<XMLObject>& values = config.GetObjects(name);
if (!ConfigUtils::IsStringSetting(setting)) ASSERT(!values.empty(), "No ", name, " defined in makegen.xml")
if (values.size() > 1)
{ {
LOG_ERROR("Invalid string setting"); LOG_ERROR("Only one instance of ", name, " allowed using ", values.front().GetText());
return cache.strings.emplace("invalid", "").first->second;
} }
std::string sSetting = ConfigUtils::GetSettingName(setting); *output = values.front().GetText();
auto it = cache.strings.find(sSetting);
if (it != cache.strings.end())
return it->second;
const std::vector<XMLObject>* values = GetConfiguration().GetObjectPtr(sSetting);
// No value found, using default
if (values == nullptr)
return cache.strings.emplace(sSetting, ConfigUtils::GetDefaultSettingString(setting, configPath)).first->second;
if (values->size() != 1)
{
LOG_ERROR("To many arguments for setting using first: ", (int)setting, "=", (*values)[0].GetText());
}
std::string s = (*values)[0].GetText();
if (ConfigUtils::IsDirectory(setting) && !s.empty() && s[s.size() - 1] != '/')
s += '/';
return cache.strings.emplace(sSetting, s).first->second;
} }
bool ConfigFile::GetSettingBool(ConfigSetting setting) void ConfigFile::InitOptionalStringSetting(const std::string& name, std::optional<std::string>* output)
{ {
if (setting == ConfigSetting::Invalid) const std::vector<XMLObject>& values = config.GetObjects(name);
if (values.empty())
{ {
LOG_ERROR("Invalid config setting"); *output = std::nullopt;
return false; return;
} }
std::string sSetting = ConfigUtils::GetSettingName(setting);
auto it = cache.bools.find(sSetting);
if (it != cache.bools.end())
return it->second;
const std::vector<XMLObject>* values = GetConfiguration().GetObjectPtr(sSetting); //, if (values.size() > 1)
if (values == nullptr)
return cache.bools.emplace(sSetting, ConfigUtils::GetDefaultSettingBool(setting)).first->second;
if (values->size() != 1)
{ {
LOG_ERROR("To many arguments for setting using first: ", (int)setting, "=", (*values)[0].GetText()); LOG_ERROR("Only one instance of ", name, " allowed using ", values.front().GetText());
} }
return cache.bools.emplace(sSetting, (*values)[0].GetText() == "true").first->second;
if (values.front().GetText().empty())
{
*output = std::nullopt;
return;
}
*output = values.front().GetText();
} }
std::vector<std::string>& ConfigFile::GetSettingVectorString(ConfigSetting setting) void ConfigFile::InitStringListSetting(const std::string& name, std::vector<std::string>* output)
{ {
std::string sSetting = ConfigUtils::GetSettingName(setting); const std::vector<XMLObject>& objects = config.GetObjects(name);
auto it = cache.vecStrings.find(sSetting); for (const auto& object : objects)
if (it != cache.vecStrings.end())
return it->second;
const std::vector<XMLObject>* values = GetConfiguration().GetObjectPtr(sSetting);
if (values == nullptr)
return cache.vecStrings.emplace(sSetting, std::vector<std::string>{}).first->second;
std::vector<std::string> strings;
strings.reserve(values->size());
for (auto it = values->begin(); it != values->end(); ++it)
{ {
if (it->GetText() == "") output->emplace_back(object.GetText());
continue;
std::string s = it->GetText();
if (ConfigUtils::IsDirectory(setting) && s[s.size() - 1] != '/')
s += '/';
strings.push_back(s);
} }
return cache.vecStrings.emplace(sSetting, strings).first->second;
} }
std::vector<std::string> ConfigFile::GetSetting(ConfigSetting setting) void ConfigFile::InitBoolSetting(const std::string& name, bool* output)
{ {
if (ConfigUtils::IsStringSetting(setting)) const std::vector<XMLObject>& values = config.GetObjects(name);
return {GetSettingString(setting)}; if (values.empty())
else if (ConfigUtils::IsVectorSetting(setting)) {
return GetSettingVectorString(setting); return;
else if (ConfigUtils::IsBoolSetting(setting)) }
return {GetSettingBool(setting) ? "true" : "false"};
if (values.size() > 1)
{
LOG_ERROR("Only one instance of ", name, " allowed using ", values.front().GetText());
}
if (values.front().GetText() == "true")
*output = true;
else if (values.front().GetText() == "false")
*output = false;
else else
LOG_ERROR("Invalid bool value: ", values.front().GetText(), " for ", name);
}
void ConfigFile::InitDir(std::string& dir) const
{
if (!dir.empty() && dir.back() != '/')
{ {
LOG_ERROR("Invalid config setting"); dir += '/';
return {};
} }
} }
void ConfigFile::InitOptionalDir(std::optional<std::string>& dir) const
{
if (dir.has_value() && !dir.value().empty() && dir.value().back() != '/')
{
dir.value() += '/';
}
}
void ConfigFile::InitDirs(std::vector<std::string>& dirs) const
{
for (auto& dir : dirs)
{
InitDir(dir);
}
}
const std::string& ConfigFile::GetOutputDir() const
{
return outputDir;
}
const std::string& ConfigFile::GetOutputName() const
{
return outputName;
}
const std::string& ConfigFile::GetProjectName() const
{
return projectName;
}
const std::string& ConfigFile::GetOutputType() const
{
return outputType;
}
const std::optional<std::string>& ConfigFile::GetSourceDir() const
{
return sourceDir;
}
const std::optional<std::string>& ConfigFile::GetHFileName() const
{
return hFileName;
}
const std::vector<std::string>& ConfigFile::GetLibraryDirs() const
{
return libraryDirs;
}
const std::vector<std::string>& ConfigFile::GetIncludeDirs() const
{
return includeDirs;
}
const std::vector<std::string>& ConfigFile::GetLibraries() const
{
return libraries;
}
const std::vector<std::string>& ConfigFile::GetDefines() const
{
return defines;
}
const std::vector<std::string>& ConfigFile::GetCFlags() const
{
return cFlags;
}
const std::vector<std::string>& ConfigFile::GetLFlags() const
{
return lFlags;
}
const std::vector<std::string>& ConfigFile::GetExcludeHeaders() const
{
return excludeHeaders;
}
const std::vector<std::string>& ConfigFile::GetExcludeSources() const
{
return excludeSources;
}
const std::vector<std::string>& ConfigFile::GetSourceFiles() const
{
return sourceFiles;
}
const std::vector<std::string>& ConfigFile::GetPreArguments() const
{
return preArguments;
}
const std::vector<std::string>& ConfigFile::GetArguments() const
{
return arguments;
}
const std::vector<std::string>& ConfigFile::GetIncludeDirExclDeps() const
{
return includeDirExclDeps;
}
const std::vector<Dependency>& ConfigFile::GetDependencies() const const std::vector<Dependency>& ConfigFile::GetDependencies() const
{ {
return dependencies; return dependencies;
} }
bool ConfigFile::SetSettingString(ConfigSetting setting, const std::string& value) bool ConfigFile::IsGenerateHFile() const
{
return generateHFile;
}
std::vector<std::string> ConfigFile::GetSetting(ConfigSetting setting) const
{
switch (setting)
{
case ConfigSetting::SourceDir:
{
if (sourceDir.has_value())
return {sourceDir.value()};
return {};
}
case ConfigSetting::OutputDir:
return {outputDir};
case ConfigSetting::OutputName:
return {outputName};
case ConfigSetting::OutputType:
return {outputType};
case ConfigSetting::ProjectName:
return {projectName};
case ConfigSetting::HFileName:
{
if (hFileName.has_value())
return {hFileName.value()};
return {};
}
case ConfigSetting::LibraryDir:
return libraryDirs;
case ConfigSetting::IncludeDir:
return includeDirs;
case ConfigSetting::Dependency:
{
std::vector<std::string> list;
for (const auto& [path, target] : dependencies)
{
list.emplace_back(path);
}
return list;
}
case ConfigSetting::Library:
return libraries;
case ConfigSetting::Define:
return defines;
case ConfigSetting::CFlag:
return cFlags;
case ConfigSetting::LFlag:
return lFlags;
case ConfigSetting::ExcludeSource:
return excludeSources;
case ConfigSetting::ExcludeHeader:
return excludeHeaders;
case ConfigSetting::ExecPreArgument:
return preArguments;
case ConfigSetting::ExecArgument:
return arguments;
case ConfigSetting::GenerateHFile:
return {generateHFile ? "true" : "false"};
case ConfigSetting::SourceFile:
return sourceFiles;
case ConfigSetting::IncludeDirExclDep:
return includeDirExclDeps;
}
return {};
}
bool ConfigFile::SetSettingString(ConfigSetting setting, std::string value)
{ {
// Check if valid enum // Check if valid enum
std::string s = value;
std::string sSetting = ConfigUtils::GetSettingName(setting); std::string sSetting = ConfigUtils::GetSettingName(setting);
if (ConfigUtils::IsStringSetting(setting)) if (ConfigUtils::IsDirectory(setting))
{ {
if (ConfigUtils::IsDirectory(setting) && s[s.size() - 1] != '/') InitDir(value);
{
s += '/';
}
auto it = cache.strings.find(sSetting);
// Update cache
if (it != cache.strings.end())
it->second = s;
else
cache.strings.emplace(sSetting, s);
} }
else if (ConfigUtils::IsBoolSetting(setting))
if (ConfigUtils::IsBoolSetting(setting))
{ {
if (s == "true" || s == "t" || s == "yes" || s == "y") if (value == "true" || value == "t" || value == "yes" || value == "y")
s = "true"; {
else if (s == "false" || s == "f" || s == "no" || s == "n") value = "true";
s = "false"; }
else if (value == "false" || value == "f" || value == "no" || value == "n")
{
value = "false";
}
else else
{ {
LOG_ERROR("Invalid boolean value: ", s); LOG_ERROR("Invalid boolean value: ", value);
return false;
}
auto it = cache.bools.find(sSetting);
// Update cache
if (it != cache.bools.end())
it->second = s == "true";
else
cache.bools.emplace(sSetting, value == "true");
}
else
{
LOG_ERROR("Not a string setting");
return false;
}
XMLObject& configuration = GetConfiguration();
std::vector<XMLObject>* values = configuration.GetObjectPtr(sSetting);
if (values == nullptr)
configuration.AddXMLObject({sSetting, {}, s});
else if (values->size() > 1)
LOG_ERROR("Multiple values of setting, changing first: ", sSetting, "=", s);
else
(*values)[0].SetText(s);
return true;
}
bool ConfigFile::AddSettingVectorString(ConfigSetting setting, const std::string& value)
{
// Check if valid enum
if (ConfigUtils::IsVectorSetting(setting))
{
std::string s = value;
if (ConfigUtils::IsDirectory(setting) && s[s.size() - 1] != '/')
{
s += '/';
}
std::string sSetting = ConfigUtils::GetSettingName(setting);
auto it = cache.vecStrings.find(sSetting);
// Update cache
if (it != cache.vecStrings.end())
it->second.push_back(s);
else
cache.vecStrings.emplace(sSetting, std::vector<std::string>{s});
GetConfiguration().AddXMLObject({sSetting, {}, s});
}
else
{
LOG_ERROR("Not a vector setting");
return false;
}
return true;
}
bool ConfigFile::RemoveSettingVectorString(ConfigSetting setting, const std::string& value)
{
// Check if valid enum
if (ConfigUtils::IsVectorSetting(setting))
{
std::string s = value;
if (ConfigUtils::IsDirectory(setting) && s[s.size() - 1] != '/')
{
s += '/';
}
std::string sSetting = ConfigUtils::GetSettingName(setting);
auto it = cache.vecStrings.find(sSetting);
if (it != cache.vecStrings.end())
{
// Update cache
for (auto itVec = it->second.begin(); itVec != it->second.end(); ++itVec)
{
if (*itVec == s)
{
it->second.erase(itVec);
}
}
}
std::vector<XMLObject>* values = GetConfiguration().GetObjectPtr(sSetting);
bool found = false;
for (auto it = values->begin(); it != values->end(); ++it)
{
if (it->GetText() == s)
{
values->erase(it);
found = true;
break;
}
}
if (!found)
{
LOG_ERROR("Couldn't find value: ", s);
return false; return false;
} }
} }
else
switch (setting)
{ {
LOG_ERROR("Not a vector setting"); case ConfigSetting::SourceDir:
sourceDir = value;
break;
case ConfigSetting::OutputDir:
outputDir = value;
break;
case ConfigSetting::OutputName:
outputName = value;
break;
case ConfigSetting::OutputType:
outputType = value;
break;
case ConfigSetting::ProjectName:
projectName = value;
break;
case ConfigSetting::HFileName:
hFileName = value;
break;
case ConfigSetting::GenerateHFile:
generateHFile = value == "true";
break;
default:
LOG_ERROR("Not a string setting");
return false;
}
XMLObject& config = GetTargetConfig();
std::vector<XMLObject>& values = config.GetObjects(sSetting);
if (values.empty())
{
config.AddXMLObject({sSetting, {}, value});
return true;
}
if (values.size() > 1)
LOG_ERROR("Multiple values of setting, changing first: ", sSetting, "=", value);
values.front().SetText(value);
return true;
}
bool ConfigFile::AddSettingVectorString(ConfigSetting setting, std::string value)
{
if (ConfigUtils::IsDirectory(setting))
{
InitDir(value);
}
switch (setting)
{
case ConfigSetting::LibraryDir:
libraryDirs.emplace_back(value);
break;
case ConfigSetting::IncludeDir:
includeDirs.emplace_back(value);
break;
case ConfigSetting::Dependency:
dependencies.emplace_back(value, target);
break;
case ConfigSetting::Library:
libraries.emplace_back(value);
break;
case ConfigSetting::Define:
defines.emplace_back(value);
break;
case ConfigSetting::CFlag:
cFlags.emplace_back(value);
break;
case ConfigSetting::LFlag:
lFlags.emplace_back(value);
break;
case ConfigSetting::ExcludeHeader:
excludeHeaders.emplace_back(value);
break;
case ConfigSetting::ExcludeSource:
excludeSources.emplace_back(value);
break;
case ConfigSetting::ExecPreArgument:
preArguments.emplace_back(value);
break;
case ConfigSetting::ExecArgument:
arguments.emplace_back(value);
break;
case ConfigSetting::SourceFile:
sourceFiles.emplace_back(value);
break;
case ConfigSetting::IncludeDirExclDep:
includeDirExclDeps.emplace_back(value);
break;
default:
LOG_ERROR("Not a vector setting");
return false;
}
std::string sSetting = ConfigUtils::GetSettingName(setting);
XMLObject& config = GetTargetConfig();
config.AddXMLObject({sSetting, {}, value});
return true;
}
bool ConfigFile::RemoveSettingVectorString(ConfigSetting setting, std::string value)
{
switch (setting)
{
case ConfigSetting::LibraryDir:
RemoveFromVector(libraryDirs, value);
break;
case ConfigSetting::IncludeDir:
RemoveFromVector(includeDirs, value);
break;
case ConfigSetting::Dependency:
RemoveFromVector(dependencies, value);
break;
case ConfigSetting::Library:
RemoveFromVector(libraries, value);
break;
case ConfigSetting::Define:
RemoveFromVector(defines, value);
break;
case ConfigSetting::CFlag:
RemoveFromVector(cFlags, value);
break;
case ConfigSetting::LFlag:
RemoveFromVector(lFlags, value);
break;
case ConfigSetting::ExcludeHeader:
RemoveFromVector(excludeHeaders, value);
break;
case ConfigSetting::ExcludeSource:
RemoveFromVector(excludeSources, value);
break;
case ConfigSetting::ExecPreArgument:
RemoveFromVector(preArguments, value);
break;
case ConfigSetting::ExecArgument:
RemoveFromVector(arguments, value);
break;
case ConfigSetting::SourceFile:
RemoveFromVector(sourceFiles, value);
break;
case ConfigSetting::IncludeDirExclDep:
RemoveFromVector(includeDirExclDeps, value);
break;
default:
LOG_ERROR("Not a vector setting");
return false;
}
std::string sSetting = ConfigUtils::GetSettingName(setting);
XMLObject& config = GetTargetConfig();
std::vector<XMLObject>& values = config.GetObjects(sSetting);
bool found = false;
for (auto it = values.begin(); it != values.end(); ++it)
{
if (it->GetText() == value)
{
values.erase(it);
found = true;
break;
}
}
if (!found)
{
LOG_ERROR("Couldn't find value: ", value);
return false; return false;
} }
return false;
return true;
} }
XMLObject& ConfigFile::GetConfiguration() void ConfigFile::RemoveFromVector(std::vector<std::string>& vector, const std::string& string)
{ {
std::vector<XMLObject>* configurations = config.GetObjectPtr("configuration"); for (auto it = vector.begin(); it != vector.end(); it++)
if (configurations == nullptr || configurations->size() == 0)
{ {
LOG_ERROR("No configuration in makegen.xml"); if (*it == string)
assert(false);
}
for (auto it = configurations->begin(); it != configurations->end(); ++it)
{
if (!it->HasAttribute("name"))
{ {
LOG_ERROR("No name attribute in configuration tag"); vector.erase(it);
continue; return;
}
if (it->GetAttribute("name") == target)
{
return *it;
} }
} }
LOG_ERROR("Couldn\'t find given target=",
target,
" in config file. Using target=",
(*configurations)[0].HasAttribute("name") ? (*configurations)[0].GetAttribute("name") : "");
return (*configurations)[0];
} }
const std::string& ConfigFile::GetConfigPath() const void ConfigFile::RemoveFromVector(std::vector<Dependency>& vector, const std::string& string)
{
for (auto it = vector.begin(); it != vector.end(); it++)
{
if (it->path == string)
{
vector.erase(it);
return;
}
}
}
const std::filesystem::path& ConfigFile::GetConfigPath() const
{ {
return configPath; return configPath;
} }
ConfigFile& ConfigFile::GetDependencyConfig(size_t i) ConfigFile& ConfigFile::GetDependencyConfig(const std::string& path)
{ {
return dependencyConfigs[i]; std::filesystem::path fullPath = std::filesystem::canonical(path);
for (auto& config : dependencyConfigs)
{
if (config.configPath == fullPath)
return config;
}
ABORT("Failed to find config file: ", fullPath.string());
} }
std::optional<ConfigFile> ConfigFile::GetConfigFile(const std::string& filepath, const FlagData& flagData) std::optional<ConfigFile> ConfigFile::GetConfigFile(const std::string& filepath, const FlagData& flagData)
@@ -364,57 +645,39 @@ std::optional<ConfigFile> ConfigFile::GetConfigFile(const std::string& filepath,
std::map<std::string, ConfigFile>& loadedConfigs, std::map<std::string, ConfigFile>& loadedConfigs,
const FlagData& flagData) const FlagData& flagData)
{ {
std::string realPath = FileUtils::GetRealPath(filepath); std::filesystem::path configPath = std::filesystem::canonical(filepath) / CONFIG_FILENAME;
if (realPath == "")
return {}; auto it = loadedConfigs.find(configPath);
auto it = loadedConfigs.find(realPath);
if (it != loadedConfigs.end()) if (it != loadedConfigs.end())
return std::nullopt;
if (!FileUtils::FileExists(configPath))
{ {
return {}; ConfigFileConf::CreateXMLFile(configPath);
if (!FileUtils::FileExists(configPath))
return std::nullopt;
} }
bool oldFile = false; ConfigFile config{filepath, flagData};
std::ifstream f(filepath + CONFIG_FILENAME); loadedConfigs.emplace(configPath, config);
if (!f.good())
{
ConfigFileConf::CreateXMLFile(realPath);
// try to read an old config file
f.close();
f = std::ifstream(filepath + CONFIG_FILENAME);
}
// Check if the file exists const std::vector<Dependency>& dependencies = config.GetDependencies();
if (f.good()) for (size_t i = 0; i < dependencies.size(); ++i)
{ {
f.close(); FlagData dependencyFlagData = flagData;
ConfigFile conf = ConfigFile(filepath, flagData); if (!dependencies[i].target.empty())
if (conf.hasInitError)
return {};
loadedConfigs.emplace(realPath, conf);
std::vector<Dependency> dependencies = conf.GetDependencies();
// Create dependency config files.
for (size_t i = 0; i < dependencies.size(); ++i)
{ {
FlagData dependencyFlagData = flagData;
dependencyFlagData.target = dependencies[i].target; dependencyFlagData.target = dependencies[i].target;
std::optional<ConfigFile> dep = dependencyFlagData.flags |= FLAG_TARGET;
GetConfigFile(conf.configPath + dependencies[i].path, loadedConfigs, dependencyFlagData); }
if (dep) std::filesystem::path dependencyFilePath = config.configPath / dependencies[i].path;
{ std::optional<ConfigFile> dependencyConfig = GetConfigFile(dependencyFilePath, loadedConfigs, dependencyFlagData);
conf.dependencyConfigs.push_back(*dep); if (dependencyConfig.has_value())
dependencies[i].path = dep->configPath; {
} config.dependencyConfigs.emplace_back(dependencyConfig.value());
else
{
// Remove the dependency since it is already accounted for
dependencies.erase(dependencies.begin() + i);
--i;
}
} }
return conf;
} }
return {}; return config;
} }
void ConfigFile::InputBoolean(const std::string& inputText, bool& b) void ConfigFile::InputBoolean(const std::string& inputText, bool& b)
@@ -461,6 +724,7 @@ void ConfigFile::InputMultiple(const std::string& inputText, std::vector<std::st
} }
} }
// TODO: Will probably remove this, as it is not kept up to date, and I feel like it is rather unuseful
ConfigFile ConfigFile::Gen(const FlagData& flagData) ConfigFile ConfigFile::Gen(const FlagData& flagData)
{ {
bool executable, shared, generateHFile; bool executable, shared, generateHFile;
@@ -534,5 +798,5 @@ ConfigFile ConfigFile::Gen(const FlagData& flagData)
void ConfigFile::Save() const void ConfigFile::Save() const
{ {
std::ofstream file("makegen.xml"); std::ofstream file("makegen.xml");
file << config; file << makegen;
} }
+71 -29
View File
@@ -14,20 +14,6 @@ static const std::string CONFIG_FILENAME = "makegen.xml";
class ConfigFile class ConfigFile
{ {
private:
ConfigCache cache;
XMLObject config;
// Current configuration
std::string target;
std::string configPath;
std::vector<ConfigFile> dependencyConfigs;
std::vector<Dependency> dependencies;
bool hasInitError = false;
public: public:
// Generates a new default config file // Generates a new default config file
ConfigFile(const std::string& path, const FlagData& flagData, int); ConfigFile(const std::string& path, const FlagData& flagData, int);
@@ -36,33 +22,89 @@ public:
void Save() const; void Save() const;
std::string& GetSettingString(ConfigSetting setting); const std::string& GetOutputDir() const;
bool GetSettingBool(ConfigSetting setting); const std::string& GetOutputName() const;
std::vector<std::string>& GetSettingVectorString(ConfigSetting setting); const std::string& GetProjectName() const;
std::vector<std::string> GetSetting(ConfigSetting setting); const std::string& GetOutputType() const;
const std::optional<std::string>& GetSourceDir() const;
const std::optional<std::string>& GetHFileName() const;
const std::vector<std::string>& GetLibraryDirs() const;
const std::vector<std::string>& GetIncludeDirs() const;
const std::vector<std::string>& GetLibraries() const;
const std::vector<std::string>& GetDefines() const;
const std::vector<std::string>& GetCFlags() const;
const std::vector<std::string>& GetLFlags() const;
const std::vector<std::string>& GetExcludeHeaders() const;
const std::vector<std::string>& GetExcludeSources() const;
const std::vector<std::string>& GetSourceFiles() const;
const std::vector<std::string>& GetPreArguments() const;
const std::vector<std::string>& GetArguments() const;
const std::vector<std::string>& GetIncludeDirExclDeps() const;
const std::vector<Dependency>& GetDependencies() const; const std::vector<Dependency>& GetDependencies() const;
bool IsGenerateHFile() const;
bool SetSettingString(ConfigSetting setting, const std::string& value); std::vector<std::string> GetSetting(ConfigSetting setting) const;
bool AddSettingVectorString(ConfigSetting setting, const std::string& value);
bool RemoveSettingVectorString(ConfigSetting setting, const std::string& value);
XMLObject& GetConfiguration(); bool SetSettingString(ConfigSetting setting, std::string value);
const std::string& GetConfigPath() const; bool AddSettingVectorString(ConfigSetting setting, std::string value);
ConfigFile& GetDependencyConfig(size_t i); bool RemoveSettingVectorString(ConfigSetting setting, std::string value);
private: const std::filesystem::path& GetConfigPath() const;
void Init(const FlagData& flagData); ConfigFile& GetDependencyConfig(const std::string& path);
void InitDependencies();
public:
static ConfigFile Gen(const FlagData& flagData); static ConfigFile Gen(const FlagData& flagData);
static std::optional<ConfigFile> GetConfigFile(const std::string& filepath, const FlagData& flagData); static std::optional<ConfigFile> GetConfigFile(const std::string& filepath, const FlagData& flagData);
private: private:
XMLObject makegen;
XMLObject config;
// Current configuration
std::string target;
std::filesystem::path configPath;
std::vector<ConfigFile> dependencyConfigs;
std::vector<Dependency> dependencies;
std::string outputName;
std::string outputDir;
std::string projectName;
std::string outputType;
std::optional<std::string> sourceDir;
std::optional<std::string> hFileName;
std::vector<std::string> libraryDirs;
std::vector<std::string> includeDirs;
std::vector<std::string> libraries;
std::vector<std::string> defines;
std::vector<std::string> cFlags;
std::vector<std::string> lFlags;
std::vector<std::string> excludeHeaders;
std::vector<std::string> excludeSources;
std::vector<std::string> sourceFiles;
std::vector<std::string> preArguments;
std::vector<std::string> arguments;
std::vector<std::string> includeDirExclDeps;
bool generateHFile{false};
private:
void Init(const FlagData& flagData);
void InitTarget(const FlagData& flagData);
void InitTargetConfig();
XMLObject& GetTargetConfig();
void InitDependencies();
void InitStringSetting(const std::string& name, std::string* output);
void InitOptionalStringSetting(const std::string& name, std::optional<std::string>* output);
void InitStringListSetting(const std::string& name, std::vector<std::string>* output);
void InitBoolSetting(const std::string& name, bool* output);
void InitDir(std::string& dir) const;
void InitOptionalDir(std::optional<std::string>& dir) const;
void InitDirs(std::vector<std::string>& dirs) const;
void RemoveFromVector(std::vector<std::string>& vector, const std::string& string);
void RemoveFromVector(std::vector<Dependency>& vector, const std::string& string);
static std::optional<ConfigFile> GetConfigFile(const std::string& filepath, static std::optional<ConfigFile> GetConfigFile(const std::string& filepath,
std::map<std::string, ConfigFile>& loadedConfigs, std::map<std::string, ConfigFile>& loadedConfigs,
const FlagData& flagData); const FlagData& flagData);
static std::optional<ConfigFile> Load(const std::string& filename);
static void InputBoolean(const std::string& inputText, bool& b); static void InputBoolean(const std::string& inputText, bool& b);
static void InputMultiple(const std::string& inputText, std::vector<std::string>& vec, bool needEnding); static void InputMultiple(const std::string& inputText, std::vector<std::string>& vec, bool needEnding);
static void InputString(const std::string& inputText, std::string& vec, bool needEnding, bool allowEmpty); static void InputString(const std::string& inputText, std::string& vec, bool needEnding, bool allowEmpty);
+2 -14
View File
@@ -1,7 +1,5 @@
#pragma once #pragma once
#include <assert.h>
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -41,8 +39,6 @@ enum class ConfigSetting
HFileName = 37, HFileName = 37,
// Bools // Bools
GenerateHFile = 64, GenerateHFile = 64,
// Other
Invalid = 1024
}; };
struct ConfigUtils struct ConfigUtils
@@ -91,8 +87,6 @@ struct ConfigUtils
return "sourcefile"; return "sourcefile";
case ConfigSetting::IncludeDirExclDep: case ConfigSetting::IncludeDirExclDep:
return "includedirexcldep"; return "includedirexcldep";
case ConfigSetting::Invalid:
return "invalid";
} }
return ""; return "";
} }
@@ -122,7 +116,6 @@ struct ConfigUtils
case ConfigSetting::ExecArgument: case ConfigSetting::ExecArgument:
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
case ConfigSetting::SourceFile: case ConfigSetting::SourceFile:
case ConfigSetting::Invalid:
return false; return false;
} }
return false; return false;
@@ -153,7 +146,6 @@ struct ConfigUtils
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
case ConfigSetting::SourceFile: case ConfigSetting::SourceFile:
case ConfigSetting::IncludeDirExclDep: case ConfigSetting::IncludeDirExclDep:
case ConfigSetting::Invalid:
return false; return false;
} }
return false; return false;
@@ -184,7 +176,6 @@ struct ConfigUtils
case ConfigSetting::ProjectName: case ConfigSetting::ProjectName:
case ConfigSetting::HFileName: case ConfigSetting::HFileName:
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
case ConfigSetting::Invalid:
return false; return false;
} }
return false; return false;
@@ -214,7 +205,6 @@ struct ConfigUtils
case ConfigSetting::ExecPreArgument: case ConfigSetting::ExecPreArgument:
case ConfigSetting::ExecArgument: case ConfigSetting::ExecArgument:
case ConfigSetting::SourceFile: case ConfigSetting::SourceFile:
case ConfigSetting::Invalid:
case ConfigSetting::IncludeDirExclDep: case ConfigSetting::IncludeDirExclDep:
return false; return false;
} }
@@ -240,8 +230,7 @@ struct ConfigUtils
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
return GetDefaultSettingBool(setting) ? "true" : "false"; return GetDefaultSettingBool(setting) ? "true" : "false";
default: default:
LOG_ERROR("INVALID STRING ENUM: ", (int)setting); ASSERT(false, "INVALID STRING ENUM: ", (int)setting);
assert(false);
} }
return ""; return "";
} }
@@ -253,8 +242,7 @@ struct ConfigUtils
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
return false; return false;
default: default:
LOG_ERROR("NOT BOOLEAN VALUE: ", (int)setting); ASSERT(false, "NOT BOOLEAN VALUE: ", (int)setting);
assert(false);
} }
} }
+4 -28
View File
@@ -1,6 +1,5 @@
#pragma once #pragma once
#include <assert.h>
#include <dirent.h> #include <dirent.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -42,42 +41,19 @@ struct FileUtils
static std::string GetTopDirectory(const std::string& dir) static std::string GetTopDirectory(const std::string& dir)
{ {
if (dir.size() == 0) ASSERT(!dir.empty(), "Cannot send empty string to FileUtils::GetTopDirectory()");
{
LOG_ERROR("Cannot send empty string to FileUtils::GetTopDirectory()");
assert(false);
}
size_t dirEnd = std::string::npos; size_t dirEnd = std::string::npos;
if (dir[dir.size() - 1] == '/') if (dir[dir.size() - 1] == '/')
dirEnd = dir.size() - 2; dirEnd = dir.size() - 2;
size_t pos = dir.find_last_of("/", dirEnd); size_t pos = dir.find_last_of("/", dirEnd);
if (pos == std::string::npos) ASSERT(pos != std::string::npos, "Couldn't find / (slash) in directory. This shouldn't occur.");
{
LOG_ERROR("Couldn't find / (slash) in directory. This shouldn't occur.");
assert(false);
}
return dir.substr(pos + 1, dirEnd - pos); return dir.substr(pos + 1, dirEnd - pos);
} }
static std::string GetRealPath(const std::string& filename) static std::string GetRealPath(const std::string& filename)
{ {
#if defined(__linux__) return std::filesystem::canonical(filename).string();
if (access(filename.c_str(), F_OK) != -1)
{
char* path = realpath(filename.c_str(), NULL);
std::string sPath = path;
sPath += "/";
free(path);
return sPath;
}
else
{
LOG_ERROR("Directory doesn't exist: ", filename);
return "";
}
#endif
LOG_ERROR("GetRealPath not supported");
return "";
} }
static std::string GetRelativePath(std::string from, std::string to) static std::string GetRelativePath(std::string from, std::string to)
+20 -6
View File
@@ -4,11 +4,22 @@
#include "FileUtils.h" #include "FileUtils.h"
// TODO: Consider removing this functionality, since its not really used anyways
void HFileGen::Create(ConfigFile& conf) void HFileGen::Create(ConfigFile& conf)
{ {
const std::optional<std::string>& hFileName = conf.GetHFileName();
if (!hFileName.has_value())
{
LOG_ERROR("hfilename is not specified but generatehfile is true");
return;
}
std::set<std::string> hFiles; std::set<std::string> hFiles;
std::vector<std::string> files; std::vector<std::string> files;
std::string path = conf.GetConfigPath() + conf.GetSettingString(ConfigSetting::SourceDir); const std::optional<std::string>& sourceDir = conf.GetSourceDir();
std::string path = conf.GetConfigPath();
if (sourceDir.has_value())
path += sourceDir.value();
FileUtils::GetAllFiles(path, files); FileUtils::GetAllFiles(path, files);
// include paramenter with the path of the file // include paramenter with the path of the file
// For example src/graphics/Window.h -> graphics/Window.h if src is a src folder // For example src/graphics/Window.h -> graphics/Window.h if src is a src folder
@@ -18,8 +29,7 @@ void HFileGen::Create(ConfigFile& conf)
if (extensionPos != std::string::npos) if (extensionPos != std::string::npos)
{ {
std::string filename = it->substr(path.length()); std::string filename = it->substr(path.length());
if (Utils::IsHeaderFile(filename) && if (Utils::IsHeaderFile(filename) && filename != conf.GetConfigPath() / hFileName.value())
filename != conf.GetConfigPath() + conf.GetSettingString(ConfigSetting::HFileName))
{ {
// Make files sorted in alphabetical order // Make files sorted in alphabetical order
hFiles.emplace(filename); hFiles.emplace(filename);
@@ -27,12 +37,16 @@ void HFileGen::Create(ConfigFile& conf)
} }
} }
const std::vector<std::string>& excludeHeaders = conf.GetSettingVectorString(ConfigSetting::ExcludeHeader); const std::vector<std::string>& excludeHeaders = conf.GetExcludeHeaders();
std::ofstream os(path + "/" + conf.GetSettingString(ConfigSetting::HFileName)); std::ofstream os(path + "/" + hFileName.value());
os << "#pragma once" << std::endl << std::endl; os << "#pragma once" << std::endl << std::endl;
for (auto&& hFile : hFiles) for (auto&& hFile : hFiles)
{ {
std::string headerFile = conf.GetSettingString(ConfigSetting::SourceDir) + hFile; const std::optional<std::string>& srcDir = conf.GetSourceDir();
std::string headerFile = hFile;
if (srcDir.has_value())
headerFile = srcDir.value() + headerFile;
auto it = std::find(excludeHeaders.begin(), excludeHeaders.end(), headerFile); auto it = std::find(excludeHeaders.begin(), excludeHeaders.end(), headerFile);
if (it == excludeHeaders.end()) if (it == excludeHeaders.end())
os << "#include <" << hFile << ">" << std::endl; os << "#include <" << hFile << ">" << std::endl;
+1 -1
View File
@@ -33,7 +33,7 @@ public:
{ {
std::string filePathInMakeFile = filepath; std::string filePathInMakeFile = filepath;
if (!filepath.is_absolute()) if (!filepath.is_absolute())
filePathInMakeFile = std::filesystem::relative(conf.GetConfigPath() + "/" + filepath.string(), "./").string(); filePathInMakeFile = std::filesystem::relative(conf.GetConfigPath() / filepath.string(), "./").string();
if (printSet.find(filePathInMakeFile) != printSet.end()) if (printSet.find(filePathInMakeFile) != printSet.end())
return stream; return stream;
+39 -34
View File
@@ -16,13 +16,13 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
else else
Utils::GetCppAndHFiles(conf, hFiles, cppFiles); Utils::GetCppAndHFiles(conf, hFiles, cppFiles);
std::ofstream outputFile(conf.GetConfigPath() + "Makefile"); std::ofstream outputFile(conf.GetConfigPath() / "Makefile");
outputFile << "# This Makefile was generated using MakeGen " << MAKEGEN_VERSION << " made by Tim Håkansson" outputFile << "# This Makefile was generated using MakeGen " << MAKEGEN_VERSION << " made by Tim Håkansson"
<< std::endl; << std::endl;
outputFile << "# and is licensed under MIT. Full source of the project can be found at" << std::endl; outputFile << "# and is licensed under MIT. Full source of the project can be found at" << std::endl;
outputFile << "# https://gitea.timha.se/Thraix/MakeGen" << std::endl; outputFile << "# https://gitea.timha.se/Thraix/MakeGen" << std::endl;
outputFile << "CC=@g++" << std::endl; outputFile << "CC=@g++" << std::endl;
std::string outputtype = conf.GetSettingString(ConfigSetting::OutputType); std::string outputtype = conf.GetOutputType();
if (outputtype != "executable") if (outputtype != "executable")
{ {
if (outputtype == "sharedlibrary") if (outputtype == "sharedlibrary")
@@ -34,19 +34,19 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
outputFile << "CO=@g++ -o" << std::endl; outputFile << "CO=@g++ -o" << std::endl;
outputFile << "MKDIR_P=mkdir -p" << std::endl; outputFile << "MKDIR_P=mkdir -p" << std::endl;
outputFile << "BIN=" << conf.GetSettingString(ConfigSetting::OutputDir) << std::endl; outputFile << "BIN=" << conf.GetOutputDir() << std::endl;
outputFile << "OBJPATH=$(BIN)intermediates" << std::endl; outputFile << "OBJPATH=$(BIN)intermediates" << std::endl;
outputFile << "INCLUDES="; outputFile << "INCLUDES=";
std::vector<std::string>& includedirs = conf.GetSettingVectorString(ConfigSetting::IncludeDir); const std::vector<std::string>& includeDirs = conf.GetIncludeDirs();
for (auto it = includedirs.begin(); it != includedirs.end(); ++it) for (const auto& includeDir : includeDirs)
{ {
outputFile << "-I " << *it << " "; outputFile << "-I " << includeDir << " ";
} }
std::vector<std::string>& includedirsexcldep = conf.GetSettingVectorString(ConfigSetting::IncludeDirExclDep); const std::vector<std::string>& includeDirExclDeps = conf.GetIncludeDirExclDeps();
for (auto it = includedirsexcldep.begin(); it != includedirsexcldep.end(); ++it) for (const auto& includeDirExclDep : includeDirExclDeps)
{ {
outputFile << "-I " << *it << " "; outputFile << "-I " << includeDirExclDeps << " ";
} }
outputFile << std::endl; outputFile << std::endl;
outputFile << "OBJECTS="; outputFile << "OBJECTS=";
@@ -67,42 +67,42 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
{ {
outputFile << "CFLAGS=$(INCLUDES) -fPIC -std=c++17 -c "; outputFile << "CFLAGS=$(INCLUDES) -fPIC -std=c++17 -c ";
} }
std::vector<std::string>& defines = conf.GetSettingVectorString(ConfigSetting::Define); const std::vector<std::string>& defines = conf.GetDefines();
for (auto it = defines.begin(); it != defines.end(); ++it) for (const auto& define : defines)
{ {
outputFile << "-D" << *it << " "; outputFile << "-D" << define << " ";
} }
std::vector<std::string>& cflags = conf.GetSettingVectorString(ConfigSetting::CFlag); const std::vector<std::string>& cFlags = conf.GetCFlags();
for (auto it = cflags.begin(); it != cflags.end(); ++it) for (const auto& cFlag : cFlags)
{ {
outputFile << *it << " "; outputFile << cFlag << " ";
} }
outputFile << std::endl; outputFile << std::endl;
if (outputtype == "executable") if (outputtype == "executable")
{ {
std::vector<std::string>& libdirs = conf.GetSettingVectorString(ConfigSetting::LibraryDir); const std::vector<std::string>& libraryDirs = conf.GetLibraryDirs();
outputFile << "LIBDIR="; outputFile << "LIBDIR=";
for (auto it = libdirs.begin(); it != libdirs.end(); ++it) for (const auto& libraryDir : libraryDirs)
{ {
outputFile << "-L " << *it << " "; outputFile << "-L " << libraryDir << " ";
} }
outputFile << std::endl; outputFile << std::endl;
std::vector<std::string>& lflags = conf.GetSettingVectorString(ConfigSetting::LFlag); const std::vector<std::string>& lFlags = conf.GetLFlags();
outputFile << "LDFLAGS="; outputFile << "LDFLAGS=";
for (auto it = lflags.begin(); it != lflags.end(); ++it) for (const auto& lFlag : lFlags)
{ {
outputFile << *it << " "; outputFile << lFlag << " ";
} }
for (auto it = libdirs.begin(); it != libdirs.end(); ++it) for (const auto& libraryDir : libraryDirs)
{ {
outputFile << "-Wl,-rpath=" << *it << " "; outputFile << "-Wl,-rpath=" << libraryDir << " ";
} }
outputFile << std::endl; outputFile << std::endl;
std::vector<std::string>& libs = conf.GetSettingVectorString(ConfigSetting::Library); const std::vector<std::string>& libraries = conf.GetLibraries();
outputFile << "LIBS=$(LIBDIR) "; outputFile << "LIBS=$(LIBDIR) ";
for (auto it = libs.begin(); it != libs.end(); ++it) for (const auto& library : libraries)
{ {
outputFile << "-l" << *it << " "; outputFile << "-l" << library << " ";
} }
outputFile << std::endl; outputFile << std::endl;
const std::vector<Dependency>& dependencies = conf.GetDependencies(); const std::vector<Dependency>& dependencies = conf.GetDependencies();
@@ -116,7 +116,7 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
outputFile << std::endl; outputFile << std::endl;
} }
} }
outputFile << "OUTPUT=$(BIN)" << conf.GetSettingString(ConfigSetting::OutputName) << std::endl; outputFile << "OUTPUT=$(BIN)" << conf.GetOutputName() << std::endl;
outputFile << ".PHONY: all directories rebuild clean run" << std::endl; outputFile << ".PHONY: all directories rebuild clean run" << std::endl;
// All // All
@@ -142,13 +142,19 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
outputFile << "run: all" << std::endl; outputFile << "run: all" << std::endl;
if (outputtype == "executable") if (outputtype == "executable")
{ {
std::vector<std::string>& prearguments = conf.GetSettingVectorString(ConfigSetting::ExecPreArgument); const std::vector<std::string>& prearguments = conf.GetPreArguments();
std::vector<std::string>& arguments = conf.GetSettingVectorString(ConfigSetting::ExecArgument); const std::vector<std::string>& arguments = conf.GetArguments();
outputFile << "\t@"; outputFile << "\t@";
for (auto&& preargument : prearguments) outputFile << preargument << " "; for (const auto& preargument : prearguments)
{
outputFile << preargument << " ";
}
outputFile << "./$(OUTPUT)"; outputFile << "./$(OUTPUT)";
for (auto&& argument : arguments) outputFile << " " << argument; for (const auto& argument : arguments)
{
outputFile << " " << argument;
}
outputFile << std::endl; outputFile << std::endl;
} }
@@ -170,9 +176,8 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
// Install // Install
outputFile << "install: all" << std::endl; outputFile << "install: all" << std::endl;
outputFile << "\t$(info Installing " << conf.GetSettingString(ConfigSetting::ProjectName) << " to /usr/bin/)" outputFile << "\t$(info Installing " << conf.GetProjectName() << " to /usr/bin/)" << std::endl;
<< std::endl; outputFile << "\t@cp $(OUTPUT) /usr/bin/" << conf.GetOutputName() << std::endl;
outputFile << "\t@cp $(OUTPUT) /usr/bin/" << conf.GetSettingString(ConfigSetting::OutputName) << std::endl;
std::map<std::string, IncludeDeps*> dependencies; std::map<std::string, IncludeDeps*> dependencies;
size_t i = 0; size_t i = 0;
+55 -52
View File
@@ -70,18 +70,17 @@ std::string Utils::CommonPrefix(const std::string& s1, const std::string& s2)
void Utils::GetCppFiles(ConfigFile& conf, std::set<std::string>& cppFiles) void Utils::GetCppFiles(ConfigFile& conf, std::set<std::string>& cppFiles)
{ {
std::vector<std::string> files; std::vector<std::string> files;
std::string sourceDir = conf.GetSettingString(ConfigSetting::SourceDir); const std::optional<std::string>& sourceDir = conf.GetSourceDir();
std::string path = conf.GetConfigPath() + sourceDir; if (sourceDir.has_value())
if (!sourceDir.empty())
{ {
FileUtils::GetAllFiles(path, files); FileUtils::GetAllFiles(conf.GetConfigPath() / sourceDir.value(), files);
} }
const std::vector<std::string>& excludeSources = conf.GetSettingVectorString(ConfigSetting::ExcludeSource); const std::vector<std::string>& excludeSources = conf.GetExcludeSources();
for (const auto& sourceFile : conf.GetSettingVectorString(ConfigSetting::SourceFile)) for (const auto& sourceFile : conf.GetSourceFiles())
{ {
if (FileUtils::FileExists(conf.GetConfigPath() + sourceFile)) if (FileUtils::FileExists(conf.GetConfigPath() / sourceFile))
cppFiles.emplace(conf.GetConfigPath() + sourceFile); cppFiles.emplace(sourceFile);
else else
LOG_WARNING("Source file doesn't exist: ", sourceFile); LOG_WARNING("Source file doesn't exist: ", sourceFile);
} }
@@ -102,61 +101,60 @@ void Utils::GetCppFiles(ConfigFile& conf, std::set<std::string>& cppFiles)
void Utils::GetCppAndHFiles(ConfigFile& conf, std::set<HFile>& hFiles, std::set<std::string>& cppFiles) void Utils::GetCppAndHFiles(ConfigFile& conf, std::set<HFile>& hFiles, std::set<std::string>& cppFiles)
{ {
std::vector<std::string> files; const std::vector<std::string>& excludeSources = conf.GetExcludeSources();
std::string sourceDir = conf.GetSettingString(ConfigSetting::SourceDir); for (const auto& sourceFile : conf.GetSourceFiles())
std::string path = conf.GetConfigPath() + sourceDir;
if (!sourceDir.empty())
{ {
FileUtils::GetAllFiles(path, files); if (FileUtils::FileExists(conf.GetConfigPath() / sourceFile))
} cppFiles.emplace(sourceFile);
const std::vector<std::string>& excludeSources = conf.GetSettingVectorString(ConfigSetting::ExcludeSource);
for (const auto& sourceFile : conf.GetSettingVectorString(ConfigSetting::SourceFile))
{
if (FileUtils::FileExists(conf.GetConfigPath() + sourceFile))
cppFiles.emplace(conf.GetConfigPath() + sourceFile);
else else
LOG_WARNING("Source file doesn't exist: ", sourceFile); LOG_WARNING("Source file doesn't exist: ", sourceFile);
} }
for (const auto& filename : files)
{
if (IsSourceFile(filename))
{
std::filesystem::path filepath = std::filesystem::relative(filename, "./");
auto it = std::find(excludeSources.begin(), excludeSources.end(), filepath.string());
if (it == excludeSources.end())
{
cppFiles.emplace(filepath.string());
}
}
else if (IsHeaderFile(filename))
{
std::filesystem::path path = std::filesystem::relative(filename, sourceDir);
hFiles.emplace(HFile{path.string(), sourceDir, false});
}
}
for (const auto& includePath : conf.GetSettingVectorString(ConfigSetting::IncludeDir)) const std::optional<std::string>& sourceDir = conf.GetSourceDir();
if (sourceDir.has_value())
{ {
std::vector<std::string> files; std::vector<std::string> files;
FileUtils::GetAllFiles(includePath, files); FileUtils::GetAllFiles(conf.GetConfigPath() / sourceDir.value(), files);
for (const auto& file : files) for (const auto& filename : files)
{ {
std::filesystem::path path = std::filesystem::relative(file, includePath); if (IsSourceFile(filename))
if (IsHeaderFile(path.string()))
{ {
hFiles.emplace(HFile{path.string(), includePath, false}); std::filesystem::path filepath = std::filesystem::relative(filename, "./");
auto it = std::find(excludeSources.begin(), excludeSources.end(), filepath.string());
if (it == excludeSources.end())
{
cppFiles.emplace(filepath.string());
}
}
else if (IsHeaderFile(filename))
{
std::filesystem::path path = std::filesystem::relative(filename, sourceDir.value());
hFiles.emplace(HFile{path.string(), sourceDir.value(), false});
}
}
for (const auto& includePath : conf.GetIncludeDirs())
{
std::vector<std::string> files;
FileUtils::GetAllFiles(includePath, files);
for (const auto& file : files)
{
std::filesystem::path path = std::filesystem::relative(file, includePath);
if (IsHeaderFile(path.string()))
{
hFiles.emplace(HFile{path.string(), includePath, false});
}
} }
} }
} }
const std::vector<Dependency>& dependencies = conf.GetDependencies(); const std::vector<Dependency>& dependencies = conf.GetDependencies();
for (size_t i = 0; i < dependencies.size(); ++i) for (size_t i = 0; i < dependencies.size(); ++i)
{ {
GetHFiles(dependencies[i].path, conf.GetDependencyConfig(i), hFiles); GetHFiles(conf.GetDependencyConfig(dependencies[i].path), hFiles);
} }
} }
void Utils::GetHFiles(const std::string& dependencyDir, ConfigFile& conf, std::set<HFile>& hFiles) void Utils::GetHFiles(ConfigFile& conf, std::set<HFile>& hFiles)
{ {
// TODO: Fix so that cyclic dependencies doesn't crash the tool. // TODO: Fix so that cyclic dependencies doesn't crash the tool.
// Cyclic dependencies probably shouldn't exist. // Cyclic dependencies probably shouldn't exist.
@@ -164,11 +162,19 @@ void Utils::GetHFiles(const std::string& dependencyDir, ConfigFile& conf, std::s
const std::vector<Dependency>& dependencies = conf.GetDependencies(); const std::vector<Dependency>& dependencies = conf.GetDependencies();
for (size_t i = 0; i < dependencies.size(); ++i) for (size_t i = 0; i < dependencies.size(); ++i)
{ {
GetHFiles(dependencyDir + dependencies[i].path, conf.GetDependencyConfig(i), hFiles); std::filesystem::path dependencyConfigPath =
std::filesystem::canonical(conf.GetConfigPath() / dependencies[i].path);
GetHFiles(conf.GetDependencyConfig(dependencyConfigPath), hFiles);
}
const std::optional<std::string>& sourceDir = conf.GetSourceDir();
if (!sourceDir.has_value())
{
return;
} }
std::vector<std::string> files; std::vector<std::string> files;
std::string depSrcDir = dependencyDir + conf.GetSettingString(ConfigSetting::SourceDir); std::string depSrcDir = conf.GetConfigPath() / sourceDir.value();
FileUtils::GetAllFiles(depSrcDir, files); FileUtils::GetAllFiles(depSrcDir, files);
for (auto it = files.begin(); it != files.end(); ++it) for (auto it = files.begin(); it != files.end(); ++it)
{ {
@@ -178,7 +184,7 @@ void Utils::GetHFiles(const std::string& dependencyDir, ConfigFile& conf, std::s
auto it = hFiles.find({filename, "", false}); auto it = hFiles.find({filename, "", false});
if (it != hFiles.end()) if (it != hFiles.end())
{ {
if (filename == conf.GetSettingString(ConfigSetting::HFileName) && !it->isProjectHFile) if (filename == conf.GetHFileName() && !it->isProjectHFile)
{ {
HFile hfile = *it; HFile hfile = *it;
hfile.isProjectHFile = true; hfile.isProjectHFile = true;
@@ -188,10 +194,7 @@ void Utils::GetHFiles(const std::string& dependencyDir, ConfigFile& conf, std::s
} }
else else
{ {
hFiles.emplace(HFile{filename, hFiles.emplace(HFile{filename, depSrcDir, conf.IsGenerateHFile() && filename == conf.GetHFileName()});
depSrcDir,
conf.GetSettingBool(ConfigSetting::GenerateHFile) &&
filename == conf.GetSettingString(ConfigSetting::HFileName)});
} }
} }
} }
+1 -1
View File
@@ -43,7 +43,7 @@ struct Utils
static void Replace(std::string& str, const std::string& from, const std::string& to); static void Replace(std::string& str, const std::string& from, const std::string& to);
static void GetCppFiles(ConfigFile& conf, std::set<std::string>& cppFiles); static void GetCppFiles(ConfigFile& conf, std::set<std::string>& cppFiles);
static void GetCppAndHFiles(ConfigFile& conf, std::set<HFile>& hFiles, std::set<std::string>& cppFiles); static void GetCppAndHFiles(ConfigFile& conf, std::set<HFile>& hFiles, std::set<std::string>& cppFiles);
static void GetHFiles(const std::string& dependencyDir, ConfigFile& conf, std::set<HFile>& hFiles); static void GetHFiles(ConfigFile& conf, std::set<HFile>& hFiles);
// Used for parsing xml // Used for parsing xml
static bool IsWhiteSpace(char c); static bool IsWhiteSpace(char c);
+20 -5
View File
@@ -51,7 +51,7 @@ Usage: makegen [options]
void GenMakefile(ConfigFile& conf, unsigned int flags) void GenMakefile(ConfigFile& conf, unsigned int flags)
{ {
if (conf.GetSettingBool(ConfigSetting::GenerateHFile)) if (conf.IsGenerateHFile())
HFileGen::Create(conf); HFileGen::Create(conf);
Makefile::Save(conf, flags); Makefile::Save(conf, flags);
} }
@@ -145,7 +145,7 @@ bool RunMake(const std::string& filepath, unsigned int flags, ConfigFile& conf)
{ {
RETURN_IF(system(std::string(make + " install").c_str()) != 0, false); RETURN_IF(system(std::string(make + " install").c_str()) != 0, false);
} }
if (flags & FLAG_RUN && conf.GetSettingString(ConfigSetting::OutputType) == "executable") if (flags & FLAG_RUN && conf.GetOutputType() == "executable")
{ {
RETURN_IF(system(std::string(make + " run").c_str()) != 0, false); RETURN_IF(system(std::string(make + " run").c_str()) != 0, false);
} }
@@ -175,14 +175,14 @@ bool MakeGen(const std::string& filepath, const FlagData& flagData, ConfigFile&
std::filesystem::current_path(currentPath); std::filesystem::current_path(currentPath);
} }
LOG_INFO("-----------------------------------"); LOG_INFO("-----------------------------------");
LOG_INFO("Building ", conf.GetSettingString(ConfigSetting::ProjectName)); LOG_INFO("Building ", conf.GetProjectName());
LOG_INFO("Generating Makefile..."); LOG_INFO("Generating Makefile...");
Timer timer; Timer timer;
GenMakefile(conf, flagData.flags); GenMakefile(conf, flagData.flags);
LOG_INFO("Took ", round(timer.Elapsed() * 1000.0) / 1000.0, "s"); LOG_INFO("Took ", round(timer.Elapsed() * 1000.0) / 1000.0, "s");
LOG_INFO("Running Makefile..."); LOG_INFO("Running Makefile...");
std::string outputPath = conf.GetConfigPath() + conf.GetSettingString(ConfigSetting::OutputDir); std::string outputPath = conf.GetConfigPath() / conf.GetOutputDir();
if (!FileUtils::HasPath(outputPath)) if (!FileUtils::HasPath(outputPath))
{ {
FileUtils::CreateDirectory(outputPath); FileUtils::CreateDirectory(outputPath);
@@ -193,7 +193,7 @@ bool MakeGen(const std::string& filepath, const FlagData& flagData, ConfigFile&
return RunMake(filepath, flagData.flags, conf); return RunMake(filepath, flagData.flags, conf);
} }
int main(int argc, char** argv) int Run(int argc, char** argv)
{ {
FlagData flagData = ReadFlags(argc, argv); FlagData flagData = ReadFlags(argc, argv);
if (flagData.flags & FLAG_HELP) if (flagData.flags & FLAG_HELP)
@@ -221,4 +221,19 @@ int main(int argc, char** argv)
{ {
LOG_ERROR("Couldn\'t load config file"); LOG_ERROR("Couldn\'t load config file");
} }
return 0;
}
#include <filesystem>
int main(int argc, char** argv)
{
try
{
return Run(argc, argv);
}
catch (const AssertException& exception)
{
return 1;
}
} }
+10
View File
@@ -81,6 +81,16 @@ std::vector<XMLObject>* XMLObject::GetObjectPtr(const std::string& name)
return &it->second; return &it->second;
} }
std::vector<XMLObject>& XMLObject::GetObjects(const std::string& name)
{
static std::vector<XMLObject> empty{};
auto it = objects.find(name);
if (it == objects.end())
return empty;
return it->second;
}
const std::vector<XMLObject>& XMLObject::GetObjects(const std::string& name) const const std::vector<XMLObject>& XMLObject::GetObjects(const std::string& name) const
{ {
static std::vector<XMLObject> empty{}; static std::vector<XMLObject> empty{};
+2
View File
@@ -43,6 +43,8 @@ public:
unsigned int GetObjectCount() const; unsigned int GetObjectCount() const;
std::vector<XMLObject>* GetObjectPtr(const std::string& name); std::vector<XMLObject>* GetObjectPtr(const std::string& name);
std::vector<XMLObject>& GetObjects(const std::string& name);
const std::vector<XMLObject>& GetObjects(const std::string& name) const; const std::vector<XMLObject>& GetObjects(const std::string& name) const;
const std::map<std::string, std::vector<XMLObject>>& GetObjects() const; const std::map<std::string, std::vector<XMLObject>>& GetObjects() const;
const std::string& GetName() const; const std::string& GetName() const;