From 313ec9b77069e0cd33fb67e6c1d0c1ad239c03d8 Mon Sep 17 00:00:00 2001 From: Thraix Date: Sun, 16 Jun 2019 11:48:08 +0200 Subject: [PATCH] Fix so that project builds dependencies Currently there is a problem where the h files in the makefile are in absolute path. This makes it so that the Makefile cannot be shared between different computers. --- Makefile | 15 ++++---- makegen.conf | 2 + src/ConfigFile.cpp | 22 ++++++++++- src/ConfigFile.h | 6 +++ src/FileUtils.h | 14 +++++++ src/IncludeDeps.cpp | 89 +++++++++++++++++++++++---------------------- src/IncludeDeps.h | 2 +- src/Makefile.cpp | 63 ++++++++++++++++++++++++++------ src/Makefile.h | 3 +- src/main.cpp | 73 ++++++++++++++++++++++--------------- 10 files changed, 193 insertions(+), 96 deletions(-) diff --git a/Makefile b/Makefile index 4c2793a..1904c7a 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,9 @@ LIBDIR= LDFLAGS= LIBS=$(LIBDIR) OUTPUT=$(BIN)makegen -.PHONY: all directories rebuild clean -all: directories $(OUTPUT) +.PHONY: all directories rebuild clean dependencies +all: dependencies directories $(OUTPUT) +dependencies: directories: $(BIN) $(OBJPATH) $(BIN): $(info Creating output directories) @@ -31,18 +32,18 @@ $(OUTPUT): $(OBJECTS) install: all $(info Installing MakeGen to /usr/bin/) @cp $(OUTPUT) /usr/bin/makegen -$(OBJPATH)/ConfigFile.o : src/ConfigFile.cpp src/Common.h src/ConfigFile.h +$(OBJPATH)/ConfigFile.o : /home/thraix/Documents/MakeGen/src/ConfigFile.cpp /home/thraix/Documents/MakeGen/src/Common.h /home/thraix/Documents/MakeGen/src/ConfigFile.h /home/thraix/Documents/MakeGen/src/FileUtils.h $(info -[20%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/HFileGen.o : src/HFileGen.cpp src/FileUtils.h src/Common.h src/HFileGen.h src/ConfigFile.h +$(OBJPATH)/HFileGen.o : /home/thraix/Documents/MakeGen/src/HFileGen.cpp /home/thraix/Documents/MakeGen/src/FileUtils.h /home/thraix/Documents/MakeGen/src/Common.h /home/thraix/Documents/MakeGen/src/HFileGen.h /home/thraix/Documents/MakeGen/src/ConfigFile.h $(info -[40%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/IncludeDeps.o : src/IncludeDeps.cpp src/IncludeDeps.h +$(OBJPATH)/IncludeDeps.o : /home/thraix/Documents/MakeGen/src/IncludeDeps.cpp /home/thraix/Documents/MakeGen/src/Common.h /home/thraix/Documents/MakeGen/src/IncludeDeps.h $(info -[60%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/Makefile.o : src/Makefile.cpp src/Common.h src/FileUtils.h src/IncludeDeps.h src/Makefile.h src/ConfigFile.h +$(OBJPATH)/Makefile.o : /home/thraix/Documents/MakeGen/src/Makefile.cpp /home/thraix/Documents/MakeGen/src/Common.h /home/thraix/Documents/MakeGen/src/FileUtils.h /home/thraix/Documents/MakeGen/src/IncludeDeps.h /home/thraix/Documents/MakeGen/src/Makefile.h /home/thraix/Documents/MakeGen/src/ConfigFile.h $(info -[80%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/main.o : src/main.cpp src/Common.h src/ConfigFile.h src/HFileGen.h src/IncludeDeps.h src/Makefile.h src/Timer.h +$(OBJPATH)/main.o : /home/thraix/Documents/MakeGen/src/main.cpp /home/thraix/Documents/MakeGen/src/Common.h /home/thraix/Documents/MakeGen/src/ConfigFile.h /home/thraix/Documents/MakeGen/src/HFileGen.h /home/thraix/Documents/MakeGen/src/IncludeDeps.h /home/thraix/Documents/MakeGen/src/Makefile.h /home/thraix/Documents/MakeGen/src/Timer.h $(info -[100%]- $<) $(CC) $(CFLAGS) -o $@ $< diff --git a/makegen.conf b/makegen.conf index 5001666..85e45e0 100644 --- a/makegen.conf +++ b/makegen.conf @@ -14,3 +14,5 @@ MakeGen makegen #executable true +#dependencies + diff --git a/src/ConfigFile.cpp b/src/ConfigFile.cpp index 810f766..d17954e 100755 --- a/src/ConfigFile.cpp +++ b/src/ConfigFile.cpp @@ -3,6 +3,7 @@ #include #include #include "Common.h" +#include "FileUtils.h" #define FLAG_NONE 0 #define FLAG_VECTOR 1 @@ -13,16 +14,17 @@ ConfigFile::ConfigFile() { } -ConfigFile ConfigFile::Load(const std::string& filename) +ConfigFile ConfigFile::Load(const std::string& filepath) { ConfigFile conf; + conf.configPath = FileUtils::GetRealPath(filepath); unsigned int loadFlag = 0; std::vector* vec; std::string* s; bool* b; - std::ifstream file(filename); + std::ifstream file(filepath+CONFIG_FILENAME); std::string line; if(file.is_open()) @@ -43,6 +45,7 @@ ConfigFile ConfigFile::Load(const std::string& filename) {"#includedirs", &conf.includedirs}, {"#compileflags", &conf.flags}, {"#defines", &conf.defines}, + {"#dependencies", &conf.dependencies}, }; std::map booleans = @@ -54,6 +57,8 @@ ConfigFile ConfigFile::Load(const std::string& filename) while(std::getline(file,line)) { + if(line == "") + continue; if(line[0]=='#') { // The format is a bit wacky, but it is this way since we do not want @@ -111,6 +116,13 @@ ConfigFile ConfigFile::Load(const std::string& filename) if(conf.hFile == "") conf.hFile = conf.projectname+".h"; + // Create dependency config files. + for(size_t i = 0; i < conf.dependencies.size();++i) + { + conf.dependencies[i] = FileUtils::GetRealPath(conf.dependencies[i]); + conf.dependencyConfigs.push_back(ConfigFile::Load(conf.dependencies[i])); + } + return conf; } @@ -167,6 +179,7 @@ ConfigFile ConfigFile::Gen() { InputMultiple("Enter library:", conf.libs,false); InputMultiple("Enter library directory:", conf.libdirs,true); + InputMultiple("Enter project dependencies:", conf.dependencies,true); } else { @@ -217,6 +230,11 @@ void ConfigFile::Save() const { file << *it << std::endl; } + file << "#dependencies" << std::endl; + for(auto it = dependencies.begin();it!=dependencies.end();++it) + { + file << *it << std::endl; + } file << "#srcdir" << std::endl; file << srcdir << std::endl; file << "#outputdir" << std::endl; diff --git a/src/ConfigFile.h b/src/ConfigFile.h index 6109b64..e4194e8 100755 --- a/src/ConfigFile.h +++ b/src/ConfigFile.h @@ -3,14 +3,19 @@ #include #include +static const std::string CONFIG_FILENAME = "makegen.conf"; + class ConfigFile { public: + std::string configPath; std::vector libs; std::vector libdirs; std::vector includedirs; std::vector defines; std::vector flags; + std::vector dependencies; + std::string outputdir; std::string srcdir; std::string outputname; @@ -19,6 +24,7 @@ class ConfigFile bool executable; bool shared; bool generateHFile; + std::vector dependencyConfigs; public: ConfigFile(); void Save() const; diff --git a/src/FileUtils.h b/src/FileUtils.h index 1f830f4..2b17838 100644 --- a/src/FileUtils.h +++ b/src/FileUtils.h @@ -6,9 +6,23 @@ #include "Common.h" #include #include +#include struct FileUtils { + static std::string GetRealPath(const std::string& filename) + { +#if defined(__linux__) + char* path = realpath(filename.c_str(), NULL); + std::string sPath = path; + sPath+="/"; + free(path); + return sPath; +#endif + LOG_ERROR("GetRealPath not supported"); + return filename; + } + static void GetAllFiles(const std::string& folder, std::vector& files) { DIR* dp; diff --git a/src/IncludeDeps.cpp b/src/IncludeDeps.cpp index 7ccc51a..2248d42 100755 --- a/src/IncludeDeps.cpp +++ b/src/IncludeDeps.cpp @@ -1,57 +1,58 @@ #include "IncludeDeps.h" +#include "Common.h" std::set IncludeDeps::printSet; int IncludeDeps::printCounter = 0; -IncludeDeps::IncludeDeps(const std::string& filename, const std::string& dir, const std::set& files, std::map& allDeps) - : filepath(dir+filename) +IncludeDeps::IncludeDeps(const std::string& filename, const std::string& dir, const std::map& files, std::map& allDeps) + : filepath(dir+filename) +{ + if(filename[filename.length() - 1] =='h') + { + allDeps.emplace(filepath, this); + } + std::ifstream file(filepath); + std::string line; + while(std::getline(file,line)) + { + size_t pos = line.find("#include"); + if(pos != std::string::npos) { - if(filename[filename.length() - 1] =='h') + std::string include = GetIncludeFile(line, pos, filename); + auto it = files.find(include); + if(it != files.end()) { - allDeps.emplace(filepath, this); - } - std::ifstream file(filepath); - std::string line; - while(std::getline(file,line)) - { - size_t pos = line.find("#include"); - if(pos != std::string::npos) + auto itD = allDeps.find(it->second + it->first); + if(itD == allDeps.end()) { - std::string include = GetIncludeFile(line, pos, filename); - auto it = files.find(include); - if(it != files.end()) - { - auto itD = allDeps.find(dir + *it); - if(itD == allDeps.end()) - { - IncludeDeps* inc = new IncludeDeps(*it, dir,files,allDeps); - dependencies.emplace(dir + *it, inc); - }else{ - dependencies.emplace(itD->first, itD->second); - } - } + IncludeDeps* inc = new IncludeDeps(it->first, it->second,files,allDeps); + dependencies.emplace(it->second + it->first, inc); + }else{ + dependencies.emplace(itD->first, itD->second); } } } + } +} - std::string IncludeDeps::GetIncludeFile(const std::string& line, size_t pos, const std::string& filename) +std::string IncludeDeps::GetIncludeFile(const std::string& line, size_t pos, const std::string& filename) +{ + size_t bracket = line.find('<',pos); + if(bracket == std::string::npos) + { + bracket = line.find('\"',pos); + if(bracket == std::string::npos) { - size_t bracket = line.find('<',pos); - if(bracket == std::string::npos) - { - bracket = line.find('\"',pos); - if(bracket == std::string::npos) - { - return ""; - } - size_t slash = filename.find_last_of("/"); - - std::string include = line.substr(bracket+1, line.find('\"',bracket+1)-bracket-1); - if(slash == std::string::npos) - slash = -1; - return filename.substr(0,slash+1)+include; - } - else - { - return line.substr(bracket+1, line.find('>',bracket+1)-bracket-1); - } + return ""; } + size_t slash = filename.find_last_of("/"); + + std::string include = line.substr(bracket+1, line.find('\"',bracket+1)-bracket-1); + if(slash == std::string::npos) + slash = -1; + return filename.substr(0,slash+1)+include; + } + else + { + return line.substr(bracket+1, line.find('>',bracket+1)-bracket-1); + } +} diff --git a/src/IncludeDeps.h b/src/IncludeDeps.h index 9511072..9e11c4b 100755 --- a/src/IncludeDeps.h +++ b/src/IncludeDeps.h @@ -17,7 +17,7 @@ class IncludeDeps static std::set printSet; static int printCounter; - IncludeDeps(const std::string& filename, const std::string& dir, const std::set& files, std::map& allDeps); + IncludeDeps(const std::string& filename, const std::string& dir, const std::map& files, std::map& allDeps); std::string GetIncludeFile(const std::string& line, size_t pos, const std::string& filename); diff --git a/src/Makefile.cpp b/src/Makefile.cpp index de131d9..11acadd 100755 --- a/src/Makefile.cpp +++ b/src/Makefile.cpp @@ -10,11 +10,11 @@ void Makefile::Save(const ConfigFile& conf) { - std::set hFiles; + std::map hFiles; // hFile, directory std::set cppFiles; - PreSave(conf,hFiles,cppFiles); + GetCppAndHFiles(conf,hFiles,cppFiles); - std::ofstream outputFile("Makefile"); + std::ofstream outputFile(conf.configPath + "Makefile"); outputFile << "# This Makefile was generated using MakeGen "<< MAKEGEN_VERSION<< " made by Tim HÃ¥kansson" << 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; @@ -83,13 +83,31 @@ void Makefile::Save(const ConfigFile& conf) outputFile << "-l" << *it << " "; } outputFile << std::endl; + if(!conf.dependencies.empty()) + { + outputFile << "DEPENDENCIES="; + for(auto it = conf.dependencies.begin();it!=conf.dependencies.end();++it) + { + outputFile << *it << " "; + } + outputFile << std::endl; + } } outputFile << "OUTPUT=$(BIN)" << conf.outputname << std::endl; - outputFile << ".PHONY: all directories rebuild clean" << std::endl; - outputFile << "all: directories $(OUTPUT)" << std::endl; + outputFile << ".PHONY: all directories rebuild clean dependencies" << std::endl; + outputFile << "all: dependencies directories $(OUTPUT)" << std::endl; //outputFile << "\t$(info ------------------------)" << std::endl; //outputFile << "\t$(info ---- Done Compiling ----)" << std::endl; //outputFile << "\t$(info ------------------------)" << std::endl; + + outputFile << "dependencies:" << std::endl; + if(!conf.dependencies.empty()) + { + //outputFile << "\t$(info Building dependencies)" << std::endl; + //outputFile << "\t@for dep in $(DEPENDENCIES); do\\" << std::endl; + //outputFile << "\t\tmakegen -C $$dep;\\" << std::endl; + //outputFile << "\tdone" << std::endl; + } outputFile << "directories: $(BIN) $(OBJPATH)" << std::endl; outputFile << "$(BIN):" << std::endl; outputFile << "\t$(info Creating output directories)" << std::endl; @@ -117,7 +135,7 @@ void Makefile::Save(const ConfigFile& conf) auto itD = dependencies.find(conf.srcdir + *it); if(itD == dependencies.end()) { - IncludeDeps* deps = new IncludeDeps(*it, conf.srcdir,hFiles,dependencies); + IncludeDeps* deps = new IncludeDeps(*it, conf.configPath+conf.srcdir,hFiles,dependencies); size_t extensionPos = it->find_last_of("."); size_t slash = it->find_last_of("/")+1; std::string oFile = it->substr(slash, extensionPos - slash)+".o "; @@ -129,10 +147,11 @@ void Makefile::Save(const ConfigFile& conf) } } -void Makefile::PreSave(const ConfigFile& conf, std::set& hFiles, std::set& cppFiles) +void Makefile::GetCppAndHFiles(const ConfigFile& conf, std::map& hFiles, std::set& cppFiles) { std::vector files; - FileUtils::GetAllFiles(conf.srcdir,files); + std::string path = conf.configPath + conf.srcdir; + FileUtils::GetAllFiles(path,files); // include paramenter with the path of the file // For example src/graphics/Window.h -> graphics/Window.h if src is a src folder for(auto it = files.begin(); it!=files.end();++it) @@ -140,13 +159,33 @@ void Makefile::PreSave(const ConfigFile& conf, std::set& hFiles, st size_t extensionPos = it->find_last_of("."); if(extensionPos != std::string::npos) { - if(it->substr(extensionPos+1) == "cpp") + std::string extension = it->substr(extensionPos+1); + std::string filename = it->substr(path.length()); + if(extension == "cpp" || extension == "c") { - cppFiles.emplace(it->substr(conf.srcdir.length())); + cppFiles.emplace(filename); } - else + else if(extension == "hpp" || extension == "h") { - hFiles.emplace(it->substr(conf.srcdir.length())); + hFiles.emplace(filename,path); + } + } + } + for(size_t i = 0; i < conf.dependencies.size(); ++i) + { + std::vector files; + std::string depSrcDir = conf.dependencies[i] + conf.dependencyConfigs[i].srcdir; + FileUtils::GetAllFiles(depSrcDir, files); + for(auto it = files.begin(); it!=files.end();++it) + { + size_t extensionPos = it->find_last_of("."); + if(extensionPos != std::string::npos) + { + std::string extension = it->substr(extensionPos+1); + if(extension == "hpp" || extension == "h") + { + hFiles.emplace(it->substr(depSrcDir.length()),depSrcDir); + } } } } diff --git a/src/Makefile.h b/src/Makefile.h index 6f5805c..0b946c1 100755 --- a/src/Makefile.h +++ b/src/Makefile.h @@ -2,11 +2,12 @@ #include "ConfigFile.h" #include +#include class Makefile { public: static void Save(const ConfigFile& conf); private: - static void PreSave(const ConfigFile& conf, std::set& hFiles, std::set& cppFiles); + static void GetCppAndHFiles(const ConfigFile& conf, std::map& hFiles, std::set& cppFiles); }; diff --git a/src/main.cpp b/src/main.cpp index 21d2367..e007557 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,27 +25,23 @@ void PrintHelp() LOG_INFO(" If no option is given it will run default make"); } -bool GenMakefile() +std::optional GetConfigFile(const std::string& filepath) { - std::ifstream f("makegen.conf"); + std::ifstream f(filepath + CONFIG_FILENAME); if(f.good()) { - ConfigFile conf = ConfigFile::Load("makegen.conf"); - if(conf.generateHFile) - HFileGen::Create(conf); - Makefile::Save(conf); - return true; + ConfigFile conf = ConfigFile::Load(filepath); + return conf; } f.close(); - f = std::ifstream("Makefile"); + return {}; +} - if(!f.good()) - { - LOG_ERROR("No makegen.conf or Makefile found."); - PrintHelp(); - return false; - } - return true; +void GenMakefile(const ConfigFile& conf) +{ + if(conf.generateHFile) + HFileGen::Create(conf); + Makefile::Save(conf); } unsigned int ReadFlags(int argc, char** argv) @@ -76,6 +72,25 @@ unsigned int ReadFlags(int argc, char** argv) return flags; } +bool MakeGen(const std::string& filepath, const std::string& args, const ConfigFile& conf) +{ + for(size_t i = 0;i