diplomska_naloga/build.hpp
2024-03-30 00:39:00 +01:00

171 lines
3.5 KiB
C++

#include <cstdio>
#include <cassert>
#include <cstring>
#include <ctime>
#include <sys/wait.h>
#include <sys/stat.h>
#include <vector>
#include <string>
#include <list>
#include <filesystem>
void print_command(std::vector<std::string> &arguments)
{
for (auto &&i : arguments)
{
printf("%s ", i.c_str());
}
printf("\n");
}
int nob_cmd_run_async(std::vector<std::string> &arguments)
{
std::vector<char *> argument_list;
for (const auto &arg : arguments)
{
argument_list.push_back(const_cast<char *>(arg.c_str()));
}
argument_list.push_back(NULL);
pid_t cpid = fork();
if (cpid < 0)
{
printf("Could not fork child process: %s\n", strerror(errno));
return -1;
}
if (cpid == 0)
{
if (execvp(argument_list[0], argument_list.data()) < 0)
{
print_command(arguments);
printf("Could not exec child process: %s\n", strerror(errno));
exit(1);
}
assert(0 && "unreachable");
}
return cpid;
}
bool nob_proc_wait(int proc)
{
if (proc == -1)
return false;
for (;;)
{
int wstatus = 0;
if (waitpid(proc, &wstatus, 0) < 0)
{
printf("could not wait on command (pid %d): %s\n", proc, strerror(errno));
return false;
}
if (WIFEXITED(wstatus))
{
int exit_status = WEXITSTATUS(wstatus);
if (exit_status != 0)
{
printf("command exited with exit code %d\n", exit_status);
return false;
}
break;
}
if (WIFSIGNALED(wstatus))
{
printf("command process was terminated by %s\n", strsignal(WTERMSIG(wstatus)));
return false;
}
}
return true;
}
bool nob_cmd_run_sync(std::vector<std::string> &arguments)
{
print_command(arguments);
int p = nob_cmd_run_async(arguments);
if (p == -1)
return false;
return nob_proc_wait(p);
}
bool check_if_rebuild(std::filesystem::path &org_path, std::filesystem::path &new_path)
{
struct stat file_stat_one;
if (stat(org_path.c_str(), &file_stat_one))
return false;
struct stat file_stat_two;
if (stat(new_path.c_str(), &file_stat_two))
return true;
return file_stat_one.st_ctime > file_stat_two.st_ctime;
}
bool rebuild_my_self(std::filesystem::path src_path, int argc, const char **exec_path)
{
std::vector<std::string> input;
for (int i = 0; i < argc; ++i)
input.push_back(exec_path[i]);
std::filesystem::path exec = input[0];
if (!check_if_rebuild(src_path, exec))
return false;
std::vector<std::string> comand = {"g++", src_path, "-o", exec_path[0], "-g"};
if (!nob_cmd_run_sync(comand))
return false;
if (!nob_cmd_run_sync(input))
return false;
printf("rebuild\n");
return true;
}
struct nob_directory
{
std::vector<std::filesystem::path> files;
std::vector<std::filesystem::path> dirs;
};
nob_directory get_all_files_in_dir(std::filesystem::path directory_path)
{
namespace fs = std::filesystem;
nob_directory dir;
if (!fs::is_directory(directory_path))
return dir;
std::list<fs::path> dirs;
dirs.push_back(directory_path);
dir.dirs.push_back(directory_path);
while (!dirs.empty())
{
for (const auto &entry : fs::directory_iterator(dirs.front()))
{
// Check if the entry is a regular file
if (fs::is_regular_file(entry))
{
dir.files.push_back(entry.path());
}
// Check if the entry is a directory
else if (fs::is_directory(entry))
{
dirs.push_back(entry.path());
dir.dirs.push_back(entry.path());
}
}
dirs.pop_front();
}
return dir;
}