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=
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 $@ $<
+2
View File
@@ -14,3 +14,5 @@ MakeGen
makegen
#executable
true
#dependencies
+20 -2
View File
@@ -3,6 +3,7 @@
#include <fstream>
#include <map>
#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<std::string>* 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<std::string, bool*> 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;
+6
View File
@@ -3,14 +3,19 @@
#include <vector>
#include <string>
static const std::string CONFIG_FILENAME = "makegen.conf";
class ConfigFile
{
public:
std::string configPath;
std::vector<std::string> libs;
std::vector<std::string> libdirs;
std::vector<std::string> includedirs;
std::vector<std::string> defines;
std::vector<std::string> flags;
std::vector<std::string> dependencies;
std::string outputdir;
std::string srcdir;
std::string outputname;
@@ -19,6 +24,7 @@ class ConfigFile
bool executable;
bool shared;
bool generateHFile;
std::vector<ConfigFile> dependencyConfigs;
public:
ConfigFile();
void Save() const;
+14
View File
@@ -6,9 +6,23 @@
#include "Common.h"
#include <cstring>
#include <vector>
#include <stdlib.h>
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)
{
DIR* dp;
+45 -44
View File
@@ -1,57 +1,58 @@
#include "IncludeDeps.h"
#include "Common.h"
std::set<std::string> IncludeDeps::printSet;
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)
: filepath(dir+filename)
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)
{
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);
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ class IncludeDeps
static std::set<std::string> printSet;
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);
+51 -12
View File
@@ -10,11 +10,11 @@
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;
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<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;
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<std::string>& 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<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 <set>
#include <map>
class Makefile
{
public:
static void Save(const ConfigFile& conf);
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);
};
+44 -29
View File
@@ -25,27 +25,23 @@ void PrintHelp()
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())
{
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<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)
{
unsigned int flags = ReadFlags(argc,argv);
@@ -94,21 +109,21 @@ int main(int argc, char** argv)
ConfigFile::Gen().Save();
return 0;
}
LOG_INFO("Generating Makefile...");
Timer timer;
if(!GenMakefile())
return 1;
LOG_INFO("Took ", round(timer.Elapsed()*1000.0)/1000.0,"s");
LOG_INFO("Running Makefile...");
std::string args = std::string("");
for(int i = 1;i<argc;i++)
{
if(argv[i][0] != '-')
{
std::string make = std::string("make ") + argv[i];
return system(make.c_str()) == 0 ? 0 : 1;
}
args += " " + std::string(argv[i]);
}
auto conf = GetConfigFile("./");
if(conf)
{
bool success = MakeGen("./", args, *conf);
return success ? 0 : 1;
}
else
{
LOG_ERROR("No ", CONFIG_FILENAME, " or Makefile found.");
PrintHelp();
}
;
return system("make") == 0 ? 0 : 1;
}