|
|
|
@@ -7,6 +7,11 @@
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <thread>
|
|
|
|
|
#include <mutex>
|
|
|
|
|
#include <queue>
|
|
|
|
|
#include <condition_variable>
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
|
|
#include "version.h"
|
|
|
|
|
|
|
|
|
@@ -16,20 +21,23 @@ std::string executable = "out";
|
|
|
|
|
std::string source_path = "";
|
|
|
|
|
std::vector<std::string> source_paths;
|
|
|
|
|
std::string build_path = "";
|
|
|
|
|
std::string compiler = "g++";
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
std::string folder_char = "\\";
|
|
|
|
|
char folder_char = '\\';
|
|
|
|
|
#else
|
|
|
|
|
std::string folder_char = "/";
|
|
|
|
|
char folder_char = '/';
|
|
|
|
|
#endif
|
|
|
|
|
std::string loaded_section = "";
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> exclude;
|
|
|
|
|
std::vector<std::string> keys = {"libs", "cppflags", "executable", "sourcepath", "buildpath", "exclude"};
|
|
|
|
|
enum tokens {LIBS, CPPFLAGS, EXECUTABLE, SOURCEPATH, BUILDPATH, EXCLUDE};
|
|
|
|
|
std::vector<std::string> keys = {"libs", "cppflags", "executable", "sourcepath", "buildpath", "exclude", "compiler"};
|
|
|
|
|
enum tokens {LIBS, CPPFLAGS, EXECUTABLE, SOURCEPATH, BUILDPATH, EXCLUDE, COMPILER};
|
|
|
|
|
|
|
|
|
|
bool must_link = false;
|
|
|
|
|
bool must_recompile_all = false;
|
|
|
|
|
|
|
|
|
|
std::mutex progress_mtx;
|
|
|
|
|
|
|
|
|
|
struct FileInfo {
|
|
|
|
|
std::string filename;
|
|
|
|
|
std::filesystem::file_time_type time;
|
|
|
|
@@ -168,14 +176,18 @@ bool loadLagueirtoFile(const std::string §ion_to_load)
|
|
|
|
|
if (end == std::string::npos) continue;
|
|
|
|
|
|
|
|
|
|
current_section = line.substr(1, end - 1);
|
|
|
|
|
|
|
|
|
|
// Detectar si es default
|
|
|
|
|
std::string rest = trim_copy(line.substr(end + 1));
|
|
|
|
|
found_any_section = true;
|
|
|
|
|
if (rest == "default") found_default = true;
|
|
|
|
|
if (section_to_load.empty() && rest == "default") active = true;
|
|
|
|
|
else active = (current_section == section_to_load);
|
|
|
|
|
if (active) loaded_section = current_section;
|
|
|
|
|
if (active) {
|
|
|
|
|
loaded_section = current_section;
|
|
|
|
|
std::cout << " > " << current_section << " < " << std::endl;
|
|
|
|
|
} else {
|
|
|
|
|
std::cout << " - " << current_section << std::endl;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -195,6 +207,7 @@ bool loadLagueirtoFile(const std::string §ion_to_load)
|
|
|
|
|
else if (key == "sourcepath") source_path = value;
|
|
|
|
|
else if (key == "buildpath") build_path = value;
|
|
|
|
|
else if (key == "exclude") exclude = split(value);
|
|
|
|
|
else if (key == "compiler") compiler = value;
|
|
|
|
|
}
|
|
|
|
|
return !(found_any_section && section_to_load.empty() && !found_default);
|
|
|
|
|
}
|
|
|
|
@@ -311,9 +324,17 @@ bool HeadersNeedRecompile(FileInfo file, std::filesystem::file_time_type object_
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MustRecompile(FileInfo file) {
|
|
|
|
|
std::string object_file = build_path + folder_char + std::filesystem::path(file.filename).stem().string() + ".o";
|
|
|
|
|
std::string generate_object_file_name(std::string filename) {
|
|
|
|
|
std::filesystem::path cwd = std::filesystem::weakly_canonical(std::filesystem::current_path());
|
|
|
|
|
std::filesystem::path target = std::filesystem::weakly_canonical(filename);
|
|
|
|
|
std::string out = std::filesystem::relative(target, cwd).replace_extension("o").generic_string();
|
|
|
|
|
for (char& c : out) if (c == '/') c = '.';
|
|
|
|
|
return build_path + folder_char + out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MustRecompile(FileInfo file) {
|
|
|
|
|
std::string object_file = generate_object_file_name(file.filename);
|
|
|
|
|
|
|
|
|
|
// si el objecte no existeix, fa falta recompilar
|
|
|
|
|
if (!std::filesystem::exists(object_file)) {
|
|
|
|
|
return true;
|
|
|
|
@@ -333,9 +354,9 @@ bool MustRecompile(FileInfo file) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Recompile(std::string source_file) {
|
|
|
|
|
std::string object_file = build_path + folder_char + std::filesystem::path(source_file).stem().string() + ".o";
|
|
|
|
|
std::string object_file = generate_object_file_name(source_file);
|
|
|
|
|
must_link = true;
|
|
|
|
|
std::string command = "g++ " + source_file + " " + cppflags + " -c -o " + object_file;
|
|
|
|
|
std::string command = compiler + " " + source_file + " " + cppflags + " -c -o " + object_file;
|
|
|
|
|
//std::cout << command << std::endl;
|
|
|
|
|
|
|
|
|
|
if (system(command.c_str()) != 0) {
|
|
|
|
@@ -429,9 +450,79 @@ void processCommand(std::string arg) {
|
|
|
|
|
if (arg == "-r") must_recompile_all = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void parallel_compile(int thread_count)
|
|
|
|
|
{
|
|
|
|
|
std::queue<std::string> work;
|
|
|
|
|
std::mutex mtx;
|
|
|
|
|
std::condition_variable cv;
|
|
|
|
|
bool done = false;
|
|
|
|
|
|
|
|
|
|
// Omplim la cua amb els arxius que necessiten recompilarse
|
|
|
|
|
for (auto &file : cpp_files) {
|
|
|
|
|
if (MustRecompile(file)) {
|
|
|
|
|
work.push(file.filename);
|
|
|
|
|
must_link = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::atomic<int> completed = 0;
|
|
|
|
|
int total = work.size();
|
|
|
|
|
progress_bar(0);
|
|
|
|
|
|
|
|
|
|
auto worker = [&]() {
|
|
|
|
|
while (true) {
|
|
|
|
|
std::string job;
|
|
|
|
|
|
|
|
|
|
// Extraure treball
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(mtx);
|
|
|
|
|
cv.wait(lock, [&]() { return !work.empty() || done; });
|
|
|
|
|
|
|
|
|
|
if (work.empty()) return; // ja no hi ha res més que fer
|
|
|
|
|
|
|
|
|
|
job = work.front();
|
|
|
|
|
work.pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compilar
|
|
|
|
|
Recompile(job);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(progress_mtx);
|
|
|
|
|
int done_now = ++completed;
|
|
|
|
|
progress_bar(100 * done_now / total);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Llançar threads
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
|
for (int i = 0; i < thread_count; i++)
|
|
|
|
|
threads.emplace_back(worker);
|
|
|
|
|
|
|
|
|
|
// Notificar als threads
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
|
|
|
done = true;
|
|
|
|
|
}
|
|
|
|
|
cv.notify_all();
|
|
|
|
|
|
|
|
|
|
// Esperem a que acaben
|
|
|
|
|
for (auto &t : threads)
|
|
|
|
|
t.join();
|
|
|
|
|
|
|
|
|
|
progress_bar(100);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
std::cout << "Lagueirto v" << LAGUEIRTO_VERSION << std::endl;
|
|
|
|
|
std::cout << " _ _ _ " << std::endl;
|
|
|
|
|
std::cout << "| | __ _ __ _ _ _ ___(_)_ __| |_ ___ " << std::endl;
|
|
|
|
|
std::cout << "| |/ _` |/ _` | | | |/ _ \\ | '__| __/ _ \\ " << std::endl;
|
|
|
|
|
std::cout << "| | (_| | (_| | |_| | __/ | | | || (_) |" << std::endl;
|
|
|
|
|
std::cout << "|_|\\__,_|\\__, |\\__,_|\\___|_|_| \\__\\___/ " << std::endl;
|
|
|
|
|
std::cout << " |___/ v" << LAGUEIRTO_VERSION << std::endl;
|
|
|
|
|
|
|
|
|
|
std::string configuration_to_use;
|
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
|
|
@@ -459,7 +550,7 @@ int main(int argc, char *argv[])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (must_recompile_all) {
|
|
|
|
|
std::cout << "remove: '" << build_path << "'" << std::endl;
|
|
|
|
|
std::cout << "Doing a full rebuild" << std::endl;
|
|
|
|
|
std::filesystem::remove_all(build_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -533,19 +624,25 @@ int main(int argc, char *argv[])
|
|
|
|
|
|
|
|
|
|
//print_file_tree(0, cpp_files);
|
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
int total = cpp_files.size();
|
|
|
|
|
progress_bar(0);
|
|
|
|
|
for (auto& file : cpp_files) {
|
|
|
|
|
if (MustRecompile(file)) Recompile(file.filename);
|
|
|
|
|
progress_bar(100*float(float(i)/float(total)));
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
progress_bar(100);
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
int threads = std::thread::hardware_concurrency();
|
|
|
|
|
//printf("threads: %i\n", threads);
|
|
|
|
|
if (threads == 0) threads = 4; // fallback
|
|
|
|
|
|
|
|
|
|
parallel_compile(threads);
|
|
|
|
|
|
|
|
|
|
// int i = 0;
|
|
|
|
|
// int total = cpp_files.size();
|
|
|
|
|
// progress_bar(0);
|
|
|
|
|
// for (auto& file : cpp_files) {
|
|
|
|
|
// if (MustRecompile(file)) Recompile(file.filename);
|
|
|
|
|
// progress_bar(100*float(float(i)/float(total)));
|
|
|
|
|
// i++;
|
|
|
|
|
// }
|
|
|
|
|
// progress_bar(100);
|
|
|
|
|
// std::cout << std::endl;
|
|
|
|
|
|
|
|
|
|
if (must_link) {
|
|
|
|
|
std::string command = "g++ " + build_path + folder_char + "*.o " + libs + " -o " + executable;
|
|
|
|
|
std::string command = compiler + " " + build_path + folder_char + "*.o " + libs + " -o " + executable;
|
|
|
|
|
//std::cout << command << std::endl;
|
|
|
|
|
std::cout << "Linking..."; fflush(stdout);
|
|
|
|
|
if (system(command.c_str()) != 0) {
|
|
|
|
|