Compare commits

..

6 Commits

Author SHA1 Message Date
Thraix d39536213b Add makegen.xml as dependency to all *.o compilations 2026-05-12 23:08:37 +02:00
Thraix 577ac677db Add generate-compile-flags as argument
- generate-compile-flags (or shorthand gcf), will generate a
  compile_flags.txt file based on the makegen.xml configuration.
- Fix IncludeDirExclDep not generating in the Makefile correctly
2026-05-12 21:53:50 +02:00
Thraix 736aae3d39 Add cppversion as makegen config parameter
- Add cppversion as makegen config parameter, making it possible to
  specify which cpp version to use
- General cleanup of unused code
2026-05-10 16:27:26 +02:00
Thraix 8ff0411952 Refactor ConfigFile.cpp to be simpler 2026-05-09 23:58:34 +02:00
Thraix 5d00ada431 Add support for specifying target for dependencies
- Use <dependency target="target"> to specify which target the dependency
should be compiled for.
- Fix binary not being removed when doing makegen clean
2026-05-08 19:09:00 +02:00
Thraix c0d6afbf1a Remove github reference in README.md 2026-05-06 21:10:26 +02:00
23 changed files with 1093 additions and 731 deletions
+1
View File
@@ -1,2 +1,3 @@
bin/* bin/*
.ycm_extra_conf.py .ycm_extra_conf.py
compile_flags.txt
+27 -24
View File
@@ -1,13 +1,13 @@
# This Makefile was generated using MakeGen v1.3.8 made by Tim Håkansson # This Makefile was generated using MakeGen v1.3.12 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://github.com/Thraix/MakeGen # https://gitea.timha.se/Thraix/MakeGen
CC=@g++ CC=@g++
CO=@g++ -o CO=@g++ -o
MKDIR_P=mkdir -p MKDIR_P=mkdir -p
BIN=bin/ BIN=bin/Release/
OBJPATH=$(BIN)intermediates OBJPATH=$(BIN)intermediates
INCLUDES= INCLUDES=
OBJECTS=$(OBJPATH)/src/ConfigCLI.o $(OBJPATH)/src/ConfigFile.o $(OBJPATH)/src/HFileGen.o $(OBJPATH)/src/IncludeDeps.o $(OBJPATH)/src/Makefile.o $(OBJPATH)/src/Utils.o $(OBJPATH)/src/compatibility/ConfigFileConf.o $(OBJPATH)/src/main.o $(OBJPATH)/src/xml/XML.o $(OBJPATH)/src/xml/XMLObject.o OBJECTS=$(OBJPATH)/src/CompileFlags.o $(OBJPATH)/src/ConfigCLI.o $(OBJPATH)/src/ConfigFile.o $(OBJPATH)/src/HFileGen.o $(OBJPATH)/src/IncludeDeps.o $(OBJPATH)/src/Makefile.o $(OBJPATH)/src/Utils.o $(OBJPATH)/src/compatibility/ConfigFileConf.o $(OBJPATH)/src/main.o $(OBJPATH)/src/xml/XML.o $(OBJPATH)/src/xml/XMLObject.o
CFLAGS=$(INCLUDES) -std=c++17 -c CFLAGS=$(INCLUDES) -std=c++17 -c
LIBDIR= LIBDIR=
LDFLAGS= LDFLAGS=
@@ -26,41 +26,44 @@ run: all
@./$(OUTPUT) @./$(OUTPUT)
rebuild: clean all rebuild: clean all
clean: clean:
$(info Removing $(OBJPATH)) $(info Removing $(OBJPATH) and $(OUTPUT))
@rm -rf $(OBJPATH)/ @rm -rf $(OBJPATH)/ $(OUTPUT)
$(OUTPUT): $(OBJECTS) $(OUTPUT): $(OBJECTS)
$(info Generating output file $(OUTPUT)) $(info Generating output file $(OUTPUT))
$(CO) $(OUTPUT) $(OBJECTS) $(LDFLAGS) $(LIBS) $(CO) $(OUTPUT) $(OBJECTS) $(LDFLAGS) $(LIBS)
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/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/CompileFlags.o: src/CompileFlags.cpp src/CompileFlags.h src/ConfigFile.h src/ConfigUtils.h src/Common.h src/AssertException.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h makegen.xml
$(info -[10%]- $<) $(info -[9%]- $<)
$(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/FlagData.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h src/xml/XML.h $(OBJPATH)/src/ConfigCLI.o: src/ConfigCLI.cpp src/Common.h src/AssertException.h src/ConfigCLI.h src/ConfigFile.h src/ConfigUtils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h makegen.xml
$(info -[20%]- $<) $(info -[18%]- $<)
$(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/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/ConfigFile.o: src/ConfigFile.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/AssertException.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h src/compatibility/ConfigFileConf.h src/xml/XML.h makegen.xml
$(info -[30%]- $<) $(info -[27%]- $<)
$(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/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 makegen.xml
$(info -[40%]- $<) $(info -[36%]- $<)
$(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/FlagData.h src/xml/XMLObject.h src/Makefile.h $(OBJPATH)/src/IncludeDeps.o: src/IncludeDeps.cpp src/Common.h src/AssertException.h src/IncludeDeps.h src/ConfigFile.h src/ConfigUtils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h makegen.xml
$(info -[50%]- $<) $(info -[45%]- $<)
$(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/FlagData.h src/xml/XMLObject.h $(OBJPATH)/src/Makefile.o: src/Makefile.cpp src/Common.h src/AssertException.h src/IncludeDeps.h src/ConfigFile.h src/ConfigUtils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h src/Makefile.h makegen.xml
$(info -[60%]- $<) $(info -[54%]- $<)
$(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/FlagData.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h $(OBJPATH)/src/Utils.o: src/Utils.cpp src/ConfigFile.h src/ConfigUtils.h src/Common.h src/AssertException.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h makegen.xml
$(info -[70%]- $<) $(info -[63%]- $<)
$(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/FlagData.h src/xml/XMLObject.h src/HFileGen.h src/Makefile.h src/Timer.h $(OBJPATH)/src/compatibility/ConfigFileConf.o: src/compatibility/ConfigFileConf.cpp src/Common.h src/AssertException.h src/xml/XMLObject.h src/compatibility/ConfigFileConf.h makegen.xml
$(info -[80%]- $<) $(info -[72%]- $<)
$(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/main.o: src/main.cpp src/Common.h src/AssertException.h src/CompileFlags.h src/ConfigFile.h src/ConfigUtils.h src/Dependency.h src/FlagData.h src/xml/XMLObject.h src/ConfigCLI.h src/HFileGen.h src/Makefile.h src/Timer.h src/Utils.h makegen.xml
$(info -[81%]- $<)
$(CC) $(CFLAGS) -o $@ $<
$(OBJPATH)/src/xml/XML.o: src/xml/XML.cpp src/xml/XML.h src/xml/XMLObject.h src/xml/XMLException.h makegen.xml
$(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 makegen.xml
$(info -[100%]- $<) $(info -[100%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
+1 -4
View File
@@ -16,10 +16,7 @@ After MakeGen is installed it will always be able to generate a Makefile (even w
However it will not compile your code if those programs don't exist. However it will not compile your code if those programs don't exist.
## Installation ## Installation
To install MakeGen make sure you have the dependencies listed above. To install MakeGen make sure you have the dependencies listed above and clone this repository.
Then clone this repository:
git clone git@github.com:Thraix/MakeGen.git
Then navigate into the MakeGen folder (`cd MakeGen`) and run: Then navigate into the MakeGen folder (`cd MakeGen`) and run:
+5 -5
View File
@@ -1,7 +1,7 @@
<makegen> <makegen>
<configuration name="Release"> <configuration name="Release">
<generatehfile>false</generatehfile> <cppversion>c++17</cppversion>
<outputdir>bin/</outputdir> <outputdir>bin/Release/</outputdir>
<outputname>makegen</outputname> <outputname>makegen</outputname>
<outputtype>executable</outputtype> <outputtype>executable</outputtype>
<projectname>MakeGen</projectname> <projectname>MakeGen</projectname>
@@ -10,14 +10,14 @@
<configuration name="Debug"> <configuration name="Debug">
<cflag>-g3</cflag> <cflag>-g3</cflag>
<cflag>-w</cflag> <cflag>-w</cflag>
<cppversion>c++17</cppversion>
<define>_DEBUG</define> <define>_DEBUG</define>
<generatehfile>false</generatehfile> <outputdir>bin/Debug/</outputdir>
<outputdir>bin/</outputdir>
<outputname>makegen</outputname> <outputname>makegen</outputname>
<outputtype>executable</outputtype> <outputtype>executable</outputtype>
<projectname>MakeGen</projectname> <projectname>MakeGen</projectname>
<srcdir>src/</srcdir> <srcdir>src/</srcdir>
</configuration> </configuration>
<target>Release</target> <target>Release</target>
<version>v1.3.8</version> <version>v1.3.11</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"}
{
}
};
+18 -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 8 #define MAKEGEN_VERSION_MINOR 12
#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))
@@ -30,10 +32,24 @@ const static unsigned int FLAG_DEPENDENCY = BIT(8);
const static unsigned int FLAG_SIMPLE = BIT(9); const static unsigned int FLAG_SIMPLE = BIT(9);
const static unsigned int FLAG_CONFIG = BIT(10); const static unsigned int FLAG_CONFIG = BIT(10);
const static unsigned int FLAG_TARGET = BIT(11); const static unsigned int FLAG_TARGET = BIT(11);
const static unsigned int FLAG_GEN_COMP_FLAGS = BIT(12);
#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{}; \
} \
false
#define ABORT(...) \
{ \
LOG_ERROR(__VA_ARGS__); \
throw AssertException{}; \
} \
false
template <typename T> template <typename T>
void Log(const T& var) void Log(const T& var)
+28
View File
@@ -0,0 +1,28 @@
#include "CompileFlags.h"
#include <fstream>
void CompileFlags::Save(ConfigFile& conf)
{
std::ofstream file{"compile_flags.txt"};
file << "-xc++" << std::endl;
file << "-std=" << conf.GetCppVersion() << std::endl;
const std::vector<std::string>& includeDirs = conf.GetIncludeDirs();
for (const auto& includeDir : includeDirs)
{
file << "-I" << includeDir << std::endl;
}
const std::vector<std::string>& includeDirExclDeps = conf.GetIncludeDirExclDeps();
for (const auto& includeDirExclDep : includeDirExclDeps)
{
file << "-I" << includeDirExclDep << std::endl;
}
const std::vector<std::string>& defines = conf.GetDefines();
for (const auto& defines : defines)
{
file << "-D" << defines << std::endl;
}
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "ConfigFile.h"
class CompileFlags
{
public:
static void Save(ConfigFile& conf);
};
+29 -32
View File
@@ -2,6 +2,7 @@
#include "Common.h" #include "Common.h"
#include "ConfigFile.h" #include "ConfigFile.h"
#include "FileUtils.h"
void ConfigCLI::DisplayCLIHelp() void ConfigCLI::DisplayCLIHelp()
{ {
@@ -93,6 +94,7 @@ Valid string settings are:
outputtype Type of the output, valid values are executable, sharedlibrary outputtype Type of the output, valid values are executable, sharedlibrary
and staticlibrary and staticlibrary
hfile Name of the generated project h-file hfile Name of the generated project h-file
cppversion Version of the c++ to use
Valid boolean settings are: Valid boolean settings are:
genhfile Specifies if MakeGen should generate a project h-file genhfile Specifies if MakeGen should generate a project h-file
@@ -125,7 +127,9 @@ Valid settings are:
and staticlibrary and staticlibrary
projectname Name of the project projectname Name of the project
hfile Name of the generated project h-file hfile Name of the generated project h-file
genhfile Specifies if MakeGen should generate a project h-file)"); genhfile Specifies if MakeGen should generate a project h-file
cppversion Specifies the version of c++ to use (default=c++17)
)");
} }
ConfigSetting ConfigCLI::CLIStringToSetting(const std::string& s) ConfigSetting ConfigCLI::CLIStringToSetting(const std::string& s)
@@ -149,10 +153,10 @@ ConfigSetting ConfigCLI::CLIStringToSetting(const std::string& s)
{"argument", ConfigSetting::ExecArgument}, {"argument", ConfigSetting::ExecArgument},
{"dependency", ConfigSetting::Dependency}, {"dependency", ConfigSetting::Dependency},
{"genhfile", ConfigSetting::GenerateHFile}, {"genhfile", ConfigSetting::GenerateHFile},
{"cppversion", ConfigSetting::CppVersion},
}; };
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;
} }
@@ -176,7 +180,7 @@ int ConfigCLI::Gen(int argc, char** argv)
} }
if (option == "default") if (option == "default")
{ {
ConfigFile{FileUtils::GetRealPath("."), FlagData{}, 0}.Save(); ConfigFile{std::filesystem::current_path(), FlagData{}, 0}.Save();
return 0; return 0;
} }
else else
@@ -201,16 +205,9 @@ 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("No such setting: ", argv[1]);
}
else
{ {
LOG_ERROR("Cannot remove setting which only supports one argument"); LOG_ERROR("Cannot remove setting which only supports one argument");
LOG_ERROR("use set instead."); LOG_ERROR("use set instead.");
}
return 1; return 1;
} }
for (int i = 2; i < argc; ++i) for (int i = 2; i < argc; ++i)
@@ -237,16 +234,9 @@ 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("No such setting: ", argv[1]);
}
else
{ {
LOG_ERROR("Cannot remove setting which only supports one argument"); LOG_ERROR("Cannot remove setting which only supports one argument");
LOG_ERROR("use set instead."); LOG_ERROR("use set instead.");
}
return 1; return 1;
} }
@@ -274,16 +264,9 @@ 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("No such setting: ", argv[1]);
}
else
{ {
LOG_ERROR("Cannot set setting which supports multiple arguments"); LOG_ERROR("Cannot set setting which supports multiple arguments");
LOG_ERROR("use add or remove instead."); LOG_ERROR("use add or remove instead.");
}
return 1; return 1;
} }
@@ -321,8 +304,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 +327,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);
+625 -308
View File
File diff suppressed because it is too large Load Diff
+76 -26
View File
@@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include "ConfigUtils.h" #include "ConfigUtils.h"
#include "Dependency.h"
#include "FlagData.h" #include "FlagData.h"
#include "xml/XMLObject.h" #include "xml/XMLObject.h"
@@ -13,18 +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;
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);
@@ -33,31 +22,92 @@ 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::string& GetCppVersion() 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;
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);
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::string cppVersion;
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 InitStringSetting(const std::string& name, const std::string& defaultVal, 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);
+31 -66
View File
@@ -1,48 +1,39 @@
#pragma once #pragma once
#include <assert.h> #include <algorithm>
#include <filesystem>
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include "Common.h" #include "Common.h"
#include "FileUtils.h"
struct ConfigCache
{
std::map<std::string, std::string> strings;
std::map<std::string, std::vector<std::string>> vecStrings;
std::map<std::string, bool> bools;
};
enum class ConfigSetting enum class ConfigSetting
{ {
// vectors // vectors
Library = 0, Library,
LibraryDir = 1, LibraryDir,
IncludeDir = 2, IncludeDir,
Define = 3, Define,
Dependency = 4, Dependency,
CFlag = 5, CFlag,
LFlag = 6, LFlag,
ExcludeSource = 7, ExcludeSource,
ExcludeHeader = 8, ExcludeHeader,
ExecPreArgument = 9, ExecPreArgument,
ExecArgument = 10, ExecArgument,
SourceFile = 11, SourceFile,
IncludeDirExclDep = 12, IncludeDirExclDep,
// Strings // Strings
SourceDir = 32, SourceDir,
OutputDir = 33, OutputDir,
OutputName = 34, OutputName,
OutputType = 35, OutputType,
ProjectName = 36, ProjectName,
HFileName = 37, HFileName,
CppVersion,
// Bools // Bools
GenerateHFile = 64, GenerateHFile,
// Other
Invalid = 1024
}; };
struct ConfigUtils struct ConfigUtils
@@ -91,8 +82,8 @@ struct ConfigUtils
return "sourcefile"; return "sourcefile";
case ConfigSetting::IncludeDirExclDep: case ConfigSetting::IncludeDirExclDep:
return "includedirexcldep"; return "includedirexcldep";
case ConfigSetting::Invalid: case ConfigSetting::CppVersion:
return "invalid"; return "cppversion";
} }
return ""; return "";
} }
@@ -122,7 +113,7 @@ struct ConfigUtils
case ConfigSetting::ExecArgument: case ConfigSetting::ExecArgument:
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
case ConfigSetting::SourceFile: case ConfigSetting::SourceFile:
case ConfigSetting::Invalid: case ConfigSetting::CppVersion:
return false; return false;
} }
return false; return false;
@@ -138,6 +129,7 @@ struct ConfigUtils
case ConfigSetting::OutputType: case ConfigSetting::OutputType:
case ConfigSetting::ProjectName: case ConfigSetting::ProjectName:
case ConfigSetting::HFileName: case ConfigSetting::HFileName:
case ConfigSetting::CppVersion:
return true; return true;
case ConfigSetting::LibraryDir: case ConfigSetting::LibraryDir:
case ConfigSetting::IncludeDir: case ConfigSetting::IncludeDir:
@@ -153,7 +145,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 +175,7 @@ struct ConfigUtils
case ConfigSetting::ProjectName: case ConfigSetting::ProjectName:
case ConfigSetting::HFileName: case ConfigSetting::HFileName:
case ConfigSetting::GenerateHFile: case ConfigSetting::GenerateHFile:
case ConfigSetting::Invalid: case ConfigSetting::CppVersion:
return false; return false;
} }
return false; return false;
@@ -214,38 +205,13 @@ 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:
case ConfigSetting::CppVersion:
return false; return false;
} }
return false; return false;
} }
static std::string GetDefaultSettingString(ConfigSetting setting, const std::string& path)
{
switch (setting)
{
case ConfigSetting::SourceDir:
return "src/";
case ConfigSetting::OutputDir:
return "bin/";
case ConfigSetting::OutputName:
return GetDefaultOutputName(path);
case ConfigSetting::OutputType:
return "executable";
case ConfigSetting::ProjectName:
return GetDefaultProjectName(path);
case ConfigSetting::HFileName:
return GetDefaultHFileName(path);
case ConfigSetting::GenerateHFile:
return GetDefaultSettingBool(setting) ? "true" : "false";
default:
LOG_ERROR("INVALID STRING ENUM: ", (int)setting);
assert(false);
}
return "";
}
static bool GetDefaultSettingBool(ConfigSetting setting) static bool GetDefaultSettingBool(ConfigSetting setting)
{ {
switch (setting) switch (setting)
@@ -253,14 +219,13 @@ 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);
} }
} }
static std::string GetDefaultProjectName(const std::string& path) static std::string GetDefaultProjectName(const std::string& path)
{ {
return FileUtils::GetTopDirectory(path); return std::filesystem::canonical(path).filename();
} }
static std::string GetDefaultOutputName(const std::string& path) static std::string GetDefaultOutputName(const std::string& path)
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <string>
struct Dependency
{
std::string path;
std::string target;
Dependency(const std::string& path, const std::string& target)
: path{path},
target{target}
{
}
};
+1 -114
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>
@@ -18,121 +17,9 @@
struct FileUtils struct FileUtils
{ {
static bool HasPath(const std::string& path)
{
struct stat info;
if (stat(path.c_str(), &info) != 0)
return false;
else
return true;
}
static bool CreateDirectory(const std::string& path)
{
return mkdir(path.c_str(), 0777);
}
static std::string GetCurrentDirectory()
{
static char path[256]; // Usual maximum filename
getcwd(path, sizeof(path));
return GetTopDirectory(path);
}
static std::string GetTopDirectory(const std::string& dir)
{
if (dir.size() == 0)
{
LOG_ERROR("Cannot send empty string to FileUtils::GetTopDirectory()");
assert(false);
}
size_t dirEnd = std::string::npos;
if (dir[dir.size() - 1] == '/')
dirEnd = dir.size() - 2;
size_t pos = dir.find_last_of("/", dirEnd);
if (pos == std::string::npos)
{
LOG_ERROR("Couldn't find / (slash) in directory. This shouldn't occur.");
assert(false);
}
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)
{
std::string result;
if (to[to.size() - 1] == '/')
to.pop_back();
if (from[from.size() - 1] == '/')
from.pop_back();
// Check if the directory is inside 'from'
if (strncmp(to.c_str(), from.c_str(), from.size()) == 0)
{
// Same directory
if (to.size() == from.size())
return "";
// Remove the 'from' path
return to.substr(from.size() + 1);
}
// Check if the directory is a child of from
else if (strncmp(from.c_str(), to.c_str(), to.size()) == 0)
{
std::string sub = from.substr(to.size());
size_t n = std::count(sub.begin(), sub.end(), '/');
for (int i = 0; i < n; i++)
{
result += "..";
if (i != n - 1)
result += "/";
}
return result;
}
// Otherwise it's a path in another directory
else
{
// Find the most common directory
std::string commonPath = Utils::CommonPrefix(from, to);
if (commonPath.empty())
return "";
while (commonPath.back() != '/') commonPath.pop_back();
commonPath.pop_back();
// Go back to the common directory
std::string sub = from.substr(commonPath.size());
size_t n = std::count(sub.begin(), sub.end(), '/');
for (int i = 0; i < n; i++)
{
result += "..";
if (i != n - 1)
result += "/";
}
// Add the path which diverges
result += to.substr(commonPath.size());
return result;
}
} }
static void GetAllFiles(const std::string& folder, std::vector<std::string>& files) static void GetAllFiles(const std::string& folder, std::vector<std::string>& files)
+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;
+49 -44
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://github.com/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 " << includeDirExclDep << " ";
} }
outputFile << std::endl; outputFile << std::endl;
outputFile << "OBJECTS="; outputFile << "OBJECTS=";
@@ -61,62 +61,62 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
outputFile << std::endl; outputFile << std::endl;
if (outputtype == "executable" || outputtype != "sharedlibrary") if (outputtype == "executable" || outputtype != "sharedlibrary")
{ {
outputFile << "CFLAGS=$(INCLUDES) -std=c++17 -c "; outputFile << "CFLAGS=$(INCLUDES) -std=" + conf.GetCppVersion() + " -c ";
} }
else else
{ {
outputFile << "CFLAGS=$(INCLUDES) -fPIC -std=c++17 -c "; outputFile << "CFLAGS=$(INCLUDES) -fPIC -std=" + conf.GetCppVersion() + " -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;
std::vector<std::string>& dependencies = conf.GetSettingVectorString(ConfigSetting::Dependency); const std::vector<Dependency>& dependencies = conf.GetDependencies();
if (!dependencies.empty()) if (!dependencies.empty())
{ {
outputFile << "DEPENDENCIES="; outputFile << "DEPENDENCIES=";
for (auto it = dependencies.begin(); it != dependencies.end(); ++it) for (const auto& [path, target] : dependencies)
{ {
outputFile << *it << " "; outputFile << path << " ";
} }
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;
} }
@@ -157,8 +163,8 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
// Clean // Clean
outputFile << "clean:" << std::endl; outputFile << "clean:" << std::endl;
outputFile << "\t$(info Removing $(OBJPATH))" << std::endl; outputFile << "\t$(info Removing $(OBJPATH) and $(OUTPUT))" << std::endl;
outputFile << "\t@rm -rf $(OBJPATH)/" << std::endl; outputFile << "\t@rm -rf $(OBJPATH)/ $(OUTPUT)" << std::endl;
// Output file // Output file
outputFile << "$(OUTPUT): $(OBJECTS)" << std::endl; outputFile << "$(OUTPUT): $(OBJECTS)" << 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;
@@ -189,14 +194,14 @@ void Makefile::Save(ConfigFile& conf, unsigned int flags)
outputFile << "$(OBJPATH)/" << oFileStr << ":"; outputFile << "$(OBJPATH)/" << oFileStr << ":";
if (flags & FLAG_SIMPLE) if (flags & FLAG_SIMPLE)
{ {
outputFile << " " << *it; outputFile << " " << *it << " makegen.xml" << std::endl;
} }
else else
{ {
IncludeDeps* deps = new IncludeDeps(*it, hFiles, dependencies); IncludeDeps* deps = new IncludeDeps(*it, hFiles, dependencies);
deps->Output(outputFile, conf); deps->Output(outputFile, conf);
outputFile << " makegen.xml" << std::endl;
} }
outputFile << std::endl;
outputFile << "\t$(info -[" << (int)(i / (float)cppFiles.size() * 100) << "%]- $<)" << std::endl; outputFile << "\t$(info -[" << (int)(i / (float)cppFiles.size() * 100) << "%]- $<)" << std::endl;
outputFile << "\t$(CC) $(CFLAGS) -o $@ $<" << std::endl; outputFile << "\t$(CC) $(CFLAGS) -o $@ $<" << std::endl;
} }
+37 -34
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,21 +101,20 @@ 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);
} }
const std::optional<std::string>& sourceDir = conf.GetSourceDir();
if (sourceDir.has_value())
{
std::vector<std::string> files;
FileUtils::GetAllFiles(conf.GetConfigPath() / sourceDir.value(), files);
for (const auto& filename : files) for (const auto& filename : files)
{ {
if (IsSourceFile(filename)) if (IsSourceFile(filename))
@@ -130,12 +128,12 @@ void Utils::GetCppAndHFiles(ConfigFile& conf, std::set<HFile>& hFiles, std::set<
} }
else if (IsHeaderFile(filename)) else if (IsHeaderFile(filename))
{ {
std::filesystem::path path = std::filesystem::relative(filename, sourceDir); std::filesystem::path path = std::filesystem::relative(filename, sourceDir.value());
hFiles.emplace(HFile{path.string(), sourceDir, false}); hFiles.emplace(HFile{path.string(), sourceDir.value(), false});
} }
} }
for (const auto& includePath : conf.GetSettingVectorString(ConfigSetting::IncludeDir)) for (const auto& includePath : conf.GetIncludeDirs())
{ {
std::vector<std::string> files; std::vector<std::string> files;
FileUtils::GetAllFiles(includePath, files); FileUtils::GetAllFiles(includePath, files);
@@ -148,27 +146,35 @@ void Utils::GetCppAndHFiles(ConfigFile& conf, std::set<HFile>& hFiles, std::set<
} }
} }
} }
}
std::vector<std::string>& dependencies = conf.GetSettingVectorString(ConfigSetting::Dependency); 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], 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.
// so just warn the user that it does and terminate. // so just warn the user that it does and terminate.
std::vector<std::string>& dependencies = conf.GetSettingVectorString(ConfigSetting::Dependency); 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], 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);
+6 -5
View File
@@ -3,10 +3,11 @@
const std::string CONFIG_FILENAME_CONF = "makegen.conf"; const std::string CONFIG_FILENAME_CONF = "makegen.conf";
#include <algorithm> #include <algorithm>
#include <filesystem>
#include <fstream> #include <fstream>
#include "../ConfigFile.h" #include "../Common.h"
#include "../FileUtils.h" #include "../xml/XMLObject.h"
#define FLAG_NONE 0 #define FLAG_NONE 0
#define FLAG_VECTOR 1 #define FLAG_VECTOR 1
@@ -14,10 +15,10 @@ const std::string CONFIG_FILENAME_CONF = "makegen.conf";
#define FLAG_BOOL 3 #define FLAG_BOOL 3
ConfigFileConf::ConfigFileConf() ConfigFileConf::ConfigFileConf()
: outputdir("bin/"), : outputdir("bin/Release"),
srcdir("src/"), srcdir("src/"),
outputname(""), outputname(""),
projectname(FileUtils::GetCurrentDirectory()), projectname(std::filesystem::current_path().filename()),
hFile(""), hFile(""),
executable(true), executable(true),
shared(true), shared(true),
@@ -161,7 +162,7 @@ void ConfigFileConf::CreateXMLFile(const std::string& filepath)
XMLObject makegen("makegen", {}, std::map<std::string, std::vector<XMLObject>>{}); 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.2")); makegen.AddXMLObject(XMLObject("version", {}, MAKEGEN_VERSION));
makegen.AddXMLObject(XMLObject("target", {}, "Release")); makegen.AddXMLObject(XMLObject("target", {}, "Release"));
XMLObject configuration("configuration", {{"name", "Release"}}, std::map<std::string, std::vector<XMLObject>>{}); XMLObject configuration("configuration", {{"name", "Release"}}, std::map<std::string, std::vector<XMLObject>>{});
+44 -24
View File
@@ -1,15 +1,18 @@
#include <string.h>
#include <cmath> #include <cmath>
#include <filesystem> #include <filesystem>
#include <thread> #include <thread>
#include "Common.h" #include "Common.h"
#include "CompileFlags.h"
#include "ConfigCLI.h" #include "ConfigCLI.h"
#include "ConfigFile.h" #include "ConfigFile.h"
#include "FileUtils.h"
#include "FlagData.h" #include "FlagData.h"
#include "HFileGen.h" #include "HFileGen.h"
#include "Makefile.h" #include "Makefile.h"
#include "Timer.h" #include "Timer.h"
#include "Utils.h"
#define RETURN_IF(x, b) \ #define RETURN_IF(x, b) \
if (x) \ if (x) \
@@ -42,6 +45,8 @@ Usage: makegen [options]
(no --jobs=X flag) (no --jobs=X flag)
--simple Creates a simple Makefile without include dependencies --simple Creates a simple Makefile without include dependencies
--target=<target> Run the makegen.xml file with the specified target --target=<target> Run the makegen.xml file with the specified target
gcf, generate-compile-flags
Generates a Makefile and runs
If no option is given it will run "make all" If no option is given it will run "make all"
@@ -51,7 +56,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);
} }
@@ -101,6 +106,10 @@ FlagData ReadFlags(int argc, char** argv)
{ {
flagData.flags |= FLAG_SINGLE_THREAD; flagData.flags |= FLAG_SINGLE_THREAD;
} }
else if (flag == "gcf" || flag == "generate-compile-flags")
{
flagData.flags |= FLAG_GEN_COMP_FLAGS;
}
else if (flag == "--simple") else if (flag == "--simple")
{ {
flagData.flags |= FLAG_SIMPLE; flagData.flags |= FLAG_SIMPLE;
@@ -145,7 +154,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);
} }
@@ -154,16 +163,18 @@ bool RunMake(const std::string& filepath, unsigned int flags, ConfigFile& conf)
bool MakeGen(const std::string& filepath, const FlagData& flagData, ConfigFile& conf) bool MakeGen(const std::string& filepath, const FlagData& flagData, ConfigFile& conf)
{ {
std::vector<std::string>& dependencies = conf.GetSettingVectorString(ConfigSetting::Dependency); 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)
{ {
std::filesystem::path currentPath = std::filesystem::current_path(); std::filesystem::path currentPath = std::filesystem::current_path();
std::filesystem::current_path(dependencies[i]); std::filesystem::current_path(dependencies[i].path);
FlagData dependencyFlagData = flagData;
dependencyFlagData.target = dependencies[i].target;
auto conf = ConfigFile::GetConfigFile("./", flagData); std::optional<ConfigFile> conf = ConfigFile::GetConfigFile("./", dependencyFlagData);
if (conf) if (conf)
{ {
bool success = MakeGen("./", flagData, conf.value()); bool success = MakeGen("./", dependencyFlagData, conf.value());
if (!success) if (!success)
{ {
std::filesystem::current_path(currentPath); std::filesystem::current_path(currentPath);
@@ -173,25 +184,17 @@ 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);
if (!FileUtils::HasPath(outputPath))
{
FileUtils::CreateDirectory(outputPath);
std::string intermediatePath = outputPath + "intermediates";
if (!FileUtils::HasPath(intermediatePath))
FileUtils::CreateDirectory(intermediatePath);
}
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)
@@ -208,15 +211,32 @@ int main(int argc, char** argv)
{ {
return ConfigCLI::Main(argc - 1, &argv[1]); return ConfigCLI::Main(argc - 1, &argv[1]);
} }
std::map<std::string, ConfigFile> files{};
auto conf = ConfigFile::GetConfigFile("./", flagData); auto conf = ConfigFile::GetConfigFile("./", flagData);
if (conf) if (!conf.has_value())
{
bool success = MakeGen("./", flagData, *conf);
return success ? 0 : 1;
}
else
{ {
LOG_ERROR("Couldn\'t load config file"); LOG_ERROR("Couldn\'t load config file");
return 1;
}
if (flagData.flags & FLAG_GEN_COMP_FLAGS)
{
CompileFlags::Save(conf.value());
return 0;
}
bool success = MakeGen("./", flagData, conf.value());
return success ? 0 : 1;
}
int main(int argc, char** argv)
{
try
{
return Run(argc, argv);
}
catch (const AssertException& exception)
{
return 1;
} }
} }
+21 -1
View File
@@ -59,7 +59,7 @@ const std::string& XMLObject::GetAttribute(const std::string& property) const
return it->second; return it->second;
} }
const std::string& XMLObject::GetAttribute(const std::string& property, const std::string& defaultValue) const std::string XMLObject::GetAttribute(const std::string& property, const std::string& defaultValue) const
{ {
auto it = attributes.find(property); auto it = attributes.find(property);
if (it == attributes.end()) if (it == attributes.end())
@@ -81,6 +81,26 @@ 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
{
static std::vector<XMLObject> empty{};
auto it = objects.find(name);
if (it == objects.end())
return empty;
return it->second;
}
const std::map<std::string, std::vector<XMLObject>>& XMLObject::GetObjects() const const std::map<std::string, std::vector<XMLObject>>& XMLObject::GetObjects() const
{ {
return objects; return objects;
+4 -1
View File
@@ -39,10 +39,13 @@ public:
bool HasAttribute(const std::string& property) const; bool HasAttribute(const std::string& property) const;
const std::string& GetAttribute(const std::string& property) const; const std::string& GetAttribute(const std::string& property) const;
const std::string& GetAttribute(const std::string& property, const std::string& defaultValue) const; std::string GetAttribute(const std::string& property, const std::string& defaultValue) const;
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::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;
const std::string& GetText() const; const std::string& GetText() const;