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.
This commit is contained in:
Thraix
2019-06-16 11:48:08 +02:00
parent 3425daa792
commit 313ec9b770
10 changed files with 193 additions and 96 deletions
+8 -7
View File
@@ -13,8 +13,9 @@ LIBDIR=
LDFLAGS= LDFLAGS=
LIBS=$(LIBDIR) LIBS=$(LIBDIR)
OUTPUT=$(BIN)makegen OUTPUT=$(BIN)makegen
.PHONY: all directories rebuild clean .PHONY: all directories rebuild clean dependencies
all: directories $(OUTPUT) all: dependencies directories $(OUTPUT)
dependencies:
directories: $(BIN) $(OBJPATH) directories: $(BIN) $(OBJPATH)
$(BIN): $(BIN):
$(info Creating output directories) $(info Creating output directories)
@@ -31,18 +32,18 @@ $(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)/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%]- $<) $(info -[20%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(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%]- $<) $(info -[40%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(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%]- $<) $(info -[60%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(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%]- $<) $(info -[80%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(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%]- $<) $(info -[100%]- $<)
$(CC) $(CFLAGS) -o $@ $< $(CC) $(CFLAGS) -o $@ $<
+2
View File
@@ -14,3 +14,5 @@ MakeGen
makegen makegen
#executable #executable
true true
#dependencies
+20 -2
View File
@@ -3,6 +3,7 @@
#include <fstream> #include <fstream>
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "FileUtils.h"
#define FLAG_NONE 0 #define FLAG_NONE 0
#define FLAG_VECTOR 1 #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; ConfigFile conf;
conf.configPath = FileUtils::GetRealPath(filepath);
unsigned int loadFlag = 0; unsigned int loadFlag = 0;
std::vector<std::string>* vec; std::vector<std::string>* vec;
std::string* s; std::string* s;
bool* b; bool* b;
std::ifstream file(filename); std::ifstream file(filepath+CONFIG_FILENAME);
std::string line; std::string line;
if(file.is_open()) if(file.is_open())
@@ -43,6 +45,7 @@ ConfigFile ConfigFile::Load(const std::string& filename)
{"#includedirs", &conf.includedirs}, {"#includedirs", &conf.includedirs},
{"#compileflags", &conf.flags}, {"#compileflags", &conf.flags},
{"#defines", &conf.defines}, {"#defines", &conf.defines},
{"#dependencies", &conf.dependencies},
}; };
std::map<std::string, bool*> booleans = std::map<std::string, bool*> booleans =
@@ -54,6 +57,8 @@ ConfigFile ConfigFile::Load(const std::string& filename)
while(std::getline(file,line)) while(std::getline(file,line))
{ {
if(line == "")
continue;
if(line[0]=='#') if(line[0]=='#')
{ {
// The format is a bit wacky, but it is this way since we do not want // 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 == "") if(conf.hFile == "")
conf.hFile = conf.projectname+".h"; 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; return conf;
} }
@@ -167,6 +179,7 @@ ConfigFile ConfigFile::Gen()
{ {
InputMultiple("Enter library:", conf.libs,false); InputMultiple("Enter library:", conf.libs,false);
InputMultiple("Enter library directory:", conf.libdirs,true); InputMultiple("Enter library directory:", conf.libdirs,true);
InputMultiple("Enter project dependencies:", conf.dependencies,true);
} }
else else
{ {
@@ -217,6 +230,11 @@ void ConfigFile::Save() const
{ {
file << *it << std::endl; 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 << srcdir << std::endl; file << srcdir << std::endl;
file << "#outputdir" << std::endl; file << "#outputdir" << std::endl;
+6
View File
@@ -3,14 +3,19 @@
#include <vector> #include <vector>
#include <string> #include <string>
static const std::string CONFIG_FILENAME = "makegen.conf";
class ConfigFile class ConfigFile
{ {
public: public:
std::string configPath;
std::vector<std::string> libs; std::vector<std::string> libs;
std::vector<std::string> libdirs; std::vector<std::string> libdirs;
std::vector<std::string> includedirs; std::vector<std::string> includedirs;
std::vector<std::string> defines; std::vector<std::string> defines;
std::vector<std::string> flags; std::vector<std::string> flags;
std::vector<std::string> dependencies;
std::string outputdir; std::string outputdir;
std::string srcdir; std::string srcdir;
std::string outputname; std::string outputname;
@@ -19,6 +24,7 @@ class ConfigFile
bool executable; bool executable;
bool shared; bool shared;
bool generateHFile; bool generateHFile;
std::vector<ConfigFile> dependencyConfigs;
public: public:
ConfigFile(); ConfigFile();
void Save() const; void Save() const;
+14
View File
@@ -6,9 +6,23 @@
#include "Common.h" #include "Common.h"
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include <stdlib.h>
struct FileUtils 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<std::string>& files) static void GetAllFiles(const std::string& folder, std::vector<std::string>& files)
{ {
DIR* dp; DIR* dp;
+10 -9
View File
@@ -1,10 +1,11 @@
#include "IncludeDeps.h" #include "IncludeDeps.h"
#include "Common.h"
std::set<std::string> IncludeDeps::printSet; std::set<std::string> IncludeDeps::printSet;
int IncludeDeps::printCounter = 0; int IncludeDeps::printCounter = 0;
IncludeDeps::IncludeDeps(const std::string& filename, const std::string& dir, const std::set<std::string>& files, std::map<std::string, IncludeDeps*>& allDeps) IncludeDeps::IncludeDeps(const std::string& filename, const std::string& dir, const std::map<std::string, std::string>& files, std::map<std::string, IncludeDeps*>& allDeps)
: filepath(dir+filename) : filepath(dir+filename)
{ {
if(filename[filename.length() - 1] =='h') if(filename[filename.length() - 1] =='h')
{ {
allDeps.emplace(filepath, this); allDeps.emplace(filepath, this);
@@ -20,21 +21,21 @@ IncludeDeps::IncludeDeps(const std::string& filename, const std::string& dir, co
auto it = files.find(include); auto it = files.find(include);
if(it != files.end()) if(it != files.end())
{ {
auto itD = allDeps.find(dir + *it); auto itD = allDeps.find(it->second + it->first);
if(itD == allDeps.end()) if(itD == allDeps.end())
{ {
IncludeDeps* inc = new IncludeDeps(*it, dir,files,allDeps); IncludeDeps* inc = new IncludeDeps(it->first, it->second,files,allDeps);
dependencies.emplace(dir + *it, inc); dependencies.emplace(it->second + it->first, inc);
}else{ }else{
dependencies.emplace(itD->first, itD->second); 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); size_t bracket = line.find('<',pos);
if(bracket == std::string::npos) if(bracket == std::string::npos)
{ {
@@ -54,4 +55,4 @@ IncludeDeps::IncludeDeps(const std::string& filename, const std::string& dir, co
{ {
return line.substr(bracket+1, line.find('>',bracket+1)-bracket-1); return line.substr(bracket+1, line.find('>',bracket+1)-bracket-1);
} }
} }
+1 -1
View File
@@ -17,7 +17,7 @@ class IncludeDeps
static std::set<std::string> printSet; static std::set<std::string> printSet;
static int printCounter; static int printCounter;
IncludeDeps(const std::string& filename, const std::string& dir, const std::set<std::string>& files, std::map<std::string, IncludeDeps*>& allDeps); IncludeDeps(const std::string& filename, const std::string& dir, const std::map<std::string, std::string>& files, std::map<std::string, IncludeDeps*>& allDeps);
std::string GetIncludeFile(const std::string& line, size_t pos, const std::string& filename); std::string GetIncludeFile(const std::string& line, size_t pos, const std::string& filename);
+51 -12
View File
@@ -10,11 +10,11 @@
void Makefile::Save(const ConfigFile& conf) void Makefile::Save(const ConfigFile& conf)
{ {
std::set<std::string> hFiles; std::map<std::string, std::string> hFiles; // hFile, directory
std::set<std::string> cppFiles; std::set<std::string> 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 << "# 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 << "# 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://github.com/Thraix/MakeGen" << std::endl;
@@ -83,13 +83,31 @@ void Makefile::Save(const ConfigFile& conf)
outputFile << "-l" << *it << " "; outputFile << "-l" << *it << " ";
} }
outputFile << std::endl; 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 << "OUTPUT=$(BIN)" << conf.outputname << std::endl;
outputFile << ".PHONY: all directories rebuild clean" << std::endl; outputFile << ".PHONY: all directories rebuild clean dependencies" << std::endl;
outputFile << "all: directories $(OUTPUT)" << std::endl; outputFile << "all: dependencies directories $(OUTPUT)" << std::endl;
//outputFile << "\t$(info ------------------------)" << std::endl; //outputFile << "\t$(info ------------------------)" << std::endl;
//outputFile << "\t$(info ---- Done Compiling ----)" << std::endl; //outputFile << "\t$(info ---- Done Compiling ----)" << std::endl;
//outputFile << "\t$(info ------------------------)" << 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 << "directories: $(BIN) $(OBJPATH)" << std::endl;
outputFile << "$(BIN):" << std::endl; outputFile << "$(BIN):" << std::endl;
outputFile << "\t$(info Creating output directories)" << 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); auto itD = dependencies.find(conf.srcdir + *it);
if(itD == dependencies.end()) 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 extensionPos = it->find_last_of(".");
size_t slash = it->find_last_of("/")+1; size_t slash = it->find_last_of("/")+1;
std::string oFile = it->substr(slash, extensionPos - slash)+".o "; 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<std::string>& hFiles, std::set<std::string>& cppFiles) void Makefile::GetCppAndHFiles(const ConfigFile& conf, std::map<std::string, std::string>& hFiles, std::set<std::string>& cppFiles)
{ {
std::vector<std::string> files; std::vector<std::string> 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 // 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
for(auto it = files.begin(); it!=files.end();++it) for(auto it = files.begin(); it!=files.end();++it)
@@ -140,13 +159,33 @@ void Makefile::PreSave(const ConfigFile& conf, std::set<std::string>& hFiles, st
size_t extensionPos = it->find_last_of("."); size_t extensionPos = it->find_last_of(".");
if(extensionPos != std::string::npos) 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<std::string> 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);
}
} }
} }
} }
+2 -1
View File
@@ -2,11 +2,12 @@
#include "ConfigFile.h" #include "ConfigFile.h"
#include <set> #include <set>
#include <map>
class Makefile class Makefile
{ {
public: public:
static void Save(const ConfigFile& conf); static void Save(const ConfigFile& conf);
private: private:
static void PreSave(const ConfigFile& conf, std::set<std::string>& hFiles, std::set<std::string>& cppFiles); static void GetCppAndHFiles(const ConfigFile& conf, std::map<std::string, std::string>& hFiles, std::set<std::string>& cppFiles);
}; };
+42 -27
View File
@@ -25,27 +25,23 @@ void PrintHelp()
LOG_INFO(" If no option is given it will run default make"); LOG_INFO(" If no option is given it will run default make");
} }
bool GenMakefile() std::optional<ConfigFile> GetConfigFile(const std::string& filepath)
{ {
std::ifstream f("makegen.conf"); std::ifstream f(filepath + CONFIG_FILENAME);
if(f.good()) if(f.good())
{ {
ConfigFile conf = ConfigFile::Load("makegen.conf"); ConfigFile conf = ConfigFile::Load(filepath);
return conf;
}
f.close();
return {};
}
void GenMakefile(const ConfigFile& conf)
{
if(conf.generateHFile) if(conf.generateHFile)
HFileGen::Create(conf); HFileGen::Create(conf);
Makefile::Save(conf); Makefile::Save(conf);
return true;
}
f.close();
f = std::ifstream("Makefile");
if(!f.good())
{
LOG_ERROR("No makegen.conf or Makefile found.");
PrintHelp();
return false;
}
return true;
} }
unsigned int ReadFlags(int argc, char** argv) unsigned int ReadFlags(int argc, char** argv)
@@ -76,6 +72,25 @@ unsigned int ReadFlags(int argc, char** argv)
return flags; return flags;
} }
bool MakeGen(const std::string& filepath, const std::string& args, const ConfigFile& conf)
{
for(size_t i = 0;i<conf.dependencies.size();++i)
{
bool success = MakeGen(conf.dependencies[i], args, conf.dependencyConfigs[i]);
if(!success)
return success;
}
LOG_INFO("---------------------------");
LOG_INFO("Building ", conf.projectname);
LOG_INFO("Generating Makefile...");
Timer timer;
GenMakefile(conf);
LOG_INFO("Took ", round(timer.Elapsed()*1000.0)/1000.0,"s");
LOG_INFO("Running Makefile...");
return system(std::string("make --no-print-directory -C " + filepath + " " + args).c_str()) == 0;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
unsigned int flags = ReadFlags(argc,argv); unsigned int flags = ReadFlags(argc,argv);
@@ -94,21 +109,21 @@ int main(int argc, char** argv)
ConfigFile::Gen().Save(); ConfigFile::Gen().Save();
return 0; return 0;
} }
LOG_INFO("Generating Makefile...");
Timer timer; std::string args = std::string("");
if(!GenMakefile())
return 1;
LOG_INFO("Took ", round(timer.Elapsed()*1000.0)/1000.0,"s");
LOG_INFO("Running Makefile...");
for(int i = 1;i<argc;i++) for(int i = 1;i<argc;i++)
{ {
if(argv[i][0] != '-') args += " " + std::string(argv[i]);
}
auto conf = GetConfigFile("./");
if(conf)
{ {
std::string make = std::string("make ") + argv[i]; bool success = MakeGen("./", args, *conf);
return system(make.c_str()) == 0 ? 0 : 1; return success ? 0 : 1;
} }
else
{
LOG_ERROR("No ", CONFIG_FILENAME, " or Makefile found.");
PrintHelp();
} }
;
return system("make") == 0 ? 0 : 1;
} }