diff --git a/main.cpp b/main.cpp index d1159ab..3e6959f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -40,38 +41,7 @@ std::mutex progress_mtx; struct FileInfo { std::string filename; - std::filesystem::file_time_type time; - std::vector included_headers; }; -std::vector headers; -std::unordered_map header_index; - -bool has_header(const std::string& name) { - return header_index.find(name) != header_index.end(); -} -int get_header_index(const std::string& name) { - auto it = header_index.find(name); - return (it != header_index.end()) ? it->second : -1; -} -int add_header(const std::string& name) { - auto it = header_index.find(name); - if (it != header_index.end()) - return it->second; - - int index = headers.size(); - headers.push_back({name, std::filesystem::last_write_time(name), {}}); - header_index[name] = index; - return index; -} -void add_include_to_header(int header_id, const std::string& header_name) { - int h = add_header(header_name); - headers[header_id].included_headers.push_back(h); -} -/*bool is_header_changed(const std::string& name) { - auto it = header_index.find(name); - if (it == header_index.end()) return false; - return headers[it->second].changed; -}*/ std::vector cpp_files; std::unordered_map cpp_index; @@ -89,15 +59,10 @@ int add_cpp(const std::string& name) { return it->second; int index = cpp_files.size(); - cpp_files.push_back({name, std::filesystem::last_write_time(name), {}}); + cpp_files.push_back({name}); cpp_index[name] = index; return index; } -void add_include_to_cpp(int cpp_id, const std::string& header_name) { - int h = add_header(header_name); - cpp_files[cpp_id].included_headers.push_back(h); -} - bool contains(const std::vector& v, const std::string& s) { return std::find(v.begin(), v.end(), s) != v.end(); } @@ -243,87 +208,6 @@ const bool textFound(char *buffer, const char *text) return equal; } -std::vector getIncludes(const std::string &filename) { - std::ifstream f(filename); - if (!f) return {}; - - std::vector includes; - std::string line; - bool inBlockComment = false; - - while (std::getline(f, line)) { - std::string processed; - processed.reserve(line.size()); - - for (size_t i = 0; i < line.size(); ++i) { - // Detectar inicio de comentario de bloque - if (!inBlockComment && i + 1 < line.size() && line[i] == '/' && line[i+1] == '*') { - inBlockComment = true; - i++; // saltar '*' - continue; - } - - // Detectar fin de comentario de bloque - if (inBlockComment && i + 1 < line.size() && line[i] == '*' && line[i+1] == '/') { - inBlockComment = false; - i++; // saltar '/' - continue; - } - - // Si estamos dentro de un bloque, ignorar todo - if (inBlockComment) - continue; - - // Detectar comentario de línea - if (i + 1 < line.size() && line[i] == '/' && line[i+1] == '/') { - break; // ignorar el resto de la línea - } - - processed.push_back(line[i]); - } - - // Si la línea quedó vacía tras limpiar comentarios, saltar - if (processed.find("#include") == std::string::npos) - continue; - - // Buscar #include - size_t pos = processed.find("#include"); - pos += 8; - - // Saltar espacios - while (pos < processed.size() && (processed[pos] == ' ' || processed[pos] == '\t')) - pos++; - - // Solo includes con comillas - if (pos >= processed.size() || processed[pos] != '"') - continue; - - pos++; // saltar comilla inicial - size_t start = pos; - - // Buscar comilla final - while (pos < processed.size() && processed[pos] != '"') - pos++; - - if (pos < processed.size()) - includes.push_back(processed.substr(start, pos - start)); - } - - return includes; -} - -bool HeadersNeedRecompile(FileInfo file, std::filesystem::file_time_type object_file_write_time) { - for (auto include : file.included_headers) { - auto include_file_write_time = headers[include].time; - if (include_file_write_time > object_file_write_time) { - return true; - } else { - if (HeadersNeedRecompile(headers[include], object_file_write_time)) return true; - } - } - return false; -} - 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); @@ -332,31 +216,11 @@ std::string generate_object_file_name(std::string filename) { 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; - } else { - // Si sí que existeix, agafem la data de modificació - auto object_file_write_time = std::filesystem::last_write_time(object_file); - - // Si la data de modificació del cpp es major que la del objecte, fa falta recompilar - auto source_file_write_time = file.time; - if (source_file_write_time > object_file_write_time) { - return true; - } else { - if (HeadersNeedRecompile(file, object_file_write_time)) return true; - } - } - return false; -} void Recompile(std::string source_file) { std::string object_file = generate_object_file_name(source_file); must_link = true; - std::string command = compiler + " " + source_file + " " + cppflags + " -c -o " + object_file; + std::string command = compiler + " " + source_file + " " + cppflags + " -MMD -MP -c -o " + object_file; //std::cout << command << std::endl; if (system(command.c_str()) != 0) { @@ -365,70 +229,87 @@ void Recompile(std::string source_file) { } } -void process_includes(int index, std::string& file, bool is_cpp = false) +std::string generate_dependency_file_name( + const std::string& source_file) { - // Trobem els includes en l'arxiu - auto include_files = getIncludes(file); + std::string name = generate_object_file_name(source_file); - // Per a cada include... - for (auto& include : include_files) { - // montem la ruta al include a partir de la del arxiu que l'inclou - std::string include_file = std::filesystem::path(file).remove_filename().string() + include; - // Comprobem si existeix relativament a l'arxiu que l'inclou - bool found = std::filesystem::exists(include_file); - if (!found) { - // Si no, comprobem si existeix relativament a cada un dels source paths especificats - for (auto path : source_paths) { - include_file = path + "/" + include; - if (std::filesystem::exists(include_file)) { - found = true; - break; - } - } - } - // Si existeix l'incloguem - if (found) { - auto header_absolute_path = std::filesystem::weakly_canonical(include_file).string(); - const bool already_exists = (has_header(header_absolute_path)); - if (is_cpp) - add_include_to_cpp(index, header_absolute_path); - else - add_include_to_header(index, header_absolute_path); - if (!already_exists) process_includes(get_header_index(header_absolute_path), header_absolute_path); + name.replace(name.size() - 1, 1, "d"); + + return name; +} + +std::vector parse_dependency_file(const std::string& filename) +{ + std::ifstream file(filename); + + if (!file) return {}; + + std::string merged; + std::string line; + + while (std::getline(file, line)) + { + if (!line.empty() && line.back() == '\\') { + line.pop_back(); + merged += line; + merged += ' '; } else { - std::cout << "WARNING: file '" << include <<"' not found" << std::endl; + merged += line; + merged += '\n'; } } + + auto colon = merged.find(':'); + if (colon == std::string::npos) return {}; + + std::string deps = merged.substr(colon + 1); + auto newline = deps.find('\n'); + if (newline != std::string::npos) deps.resize(newline); + + std::vector result; + std::stringstream ss(deps); + std::string dep; + while (ss >> dep) result.push_back(dep); + return result; +} + +bool DependenciesNeedRecompile( + const std::string& object_file, + const std::string& dependency_file) +{ + if (!std::filesystem::exists(object_file)) return true; + if (!std::filesystem::exists(dependency_file)) return true; + + auto object_time = std::filesystem::last_write_time(object_file); + + auto dependencies = parse_dependency_file( dependency_file); + + for (auto dep : dependencies) { + try { + dep = std::filesystem::weakly_canonical(dep).string(); + } catch (...) { + return true; // dependency disappeared + } + if (!std::filesystem::exists(dep)) return true; + if (std::filesystem::last_write_time(dep) > object_time) return true; + } + + return false; +} + +bool MustRecompile(const FileInfo& file) +{ + std::string object_file = generate_object_file_name(file.filename); + std::string dependency_file = generate_dependency_file_name(file.filename); + return DependenciesNeedRecompile( object_file, dependency_file); } void process_cpp(std::string& file) { std::string absolute_path = std::filesystem::weakly_canonical(file).string(); //std::cout << absolute_path << std::endl; - int index = add_cpp(absolute_path); - - process_includes(index, absolute_path, true); -} - -void print_header_tree(int indent, const std::vector& files) -{ - for (auto index : files) { - std::cout << std::string(indent*2, ' ') << headers[index].filename << std::endl; - auto &include_list = headers[index].included_headers; - if (!include_list.empty()) print_header_tree(indent+1, include_list); - } -} -void print_file_tree(int indent, const std::vector& files) -{ - for (auto& file : files) { - std::cout << std::string(indent*2, ' ') << file.filename << std::endl; - auto &include_list = file.included_headers; - if (!include_list.empty()) { - print_header_tree(indent+1, include_list); - } else { - std::cout << std::string((indent+1)*2, ' ') << "" << std::endl; - } - } + add_cpp(absolute_path); } void progress_bar(int percent) { @@ -644,11 +525,30 @@ std::cout << " |___/ v" << LAGUEIRTO_VERSION << std::endl; if (must_link) { 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) { - std::cout << "ABORTED!" << std::endl; - exit(1); - } + std::cout << "Linking..." << std::endl; fflush(stdout); + +int status = system(command.c_str()); + +if (status == -1) { + std::cerr << "system() failed\n"; +} +else if (WIFEXITED(status)) { + int code = WEXITSTATUS(status); + + std::cout << "exit code = " << code << '\n'; + + if (code != 0) { + std::cerr << "ABORTED!\n"; + exit(code); + } +} +// int result = system(command.c_str()); +// if (result != 0) { +// std::cout << "ABORTED!" << std::endl; +// exit(result); +// } + + std::cout << "DONE!" << std::endl; std::chrono::steady_clock::time_point end_all = std::chrono::steady_clock::now(); float t = float(std::chrono::duration_cast(end_all - begin_all).count())/1000000; diff --git a/version.h b/version.h index 0210e67..5319073 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ #pragma once -#define LAGUEIRTO_VERSION "2.1.4" +#define LAGUEIRTO_VERSION "2.2.0"