CBuild
C++ build system with scripts written in c++
Loading...
Searching...
No Matches
cbuild_hash.cpp
Go to the documentation of this file.
1
22// C++ libraries
23#include "../../headers/map.hpp"
24#include "fstream"
25#include "inttypes.h"
26#include "regex"
27#include "string"
28#include "sys/resource.h"
29#include "vector"
30// Project includes
35/* Some helper code */
46std::regex cpp_comment("[^\'\"]\\/\\/.*\n",
47 std::regex_constants::optimize | std::regex_constants::ECMAScript);
48std::regex c_comment("\\/\\*([\\s\\S]*?)\\*\\/",
49 std::regex_constants::optimize | std::regex_constants::ECMAScript);
50std::regex include_detector("#include [\"<]([^\">]+)[\">]",
51 std::regex_constants::optimize | std::regex_constants::ECMAScript);
52void parse_file(internal_data* data, std::string target_id, std::string file, std::string object) {
53 CBuild::print_full(std::string("Start, file: ") + file);
55 // Get old metadata
56 int err = CBuild::read_file_metadata(target_id, file, &(m.old_meta));
57 m.old_meta_available = (err == 0);
58 CBuild::print_full(std::string("Metadata read"));
59 // Get new metadata: file and object
60 m.new_meta.source = file;
61 m.new_meta.object = object;
62 // Read file content
63 std::ifstream f(file);
64 std::string file_content;
65 std::getline(f, file_content, '\0');
66 // Strip comments from file
67 file_content = std::regex_replace(file_content, cpp_comment, "");
68 file_content = std::regex_replace(file_content, c_comment, "");
69 CBuild::print_full(std::string("Comments removed"));
70 // Get new metadata: hash
71 m.new_meta.hash = CBuild::hash_fnv_1a(file_content);
72 // Get new metadata: get dependencies and add new headers for parsing
73 m.new_meta.deps = {};
74 std::smatch match;
75 std::string::const_iterator start(file_content.cbegin());
76 CBuild::print_full(std::string("Include search start"));
77 while (std::regex_search(start, file_content.cend(), match, include_detector)) {
78 CBuild::print_full(std::string("Include found, include: ") + match[1].str());
79 std::string tmp = "";
80 try {
82 } catch (std::exception& e) {
83 }
84 if (tmp != std::string("") && CBuild::fs::exists(tmp)) {
85 CBuild::print_full(std::string("Include added, include: ") + tmp);
86 m.new_meta.deps.push_back(tmp);
87 try {
88 data->headers_to_parse.push_back_check(tmp, false);
89 } catch (std::exception& e) {
90 }
91 }
92 start = match.suffix().first;
93 }
94 CBuild::print_full("Metadata store");
95 // Store metadata into a shared data
96 if (object == std::string("header")) {
97 try {
98 data->headers_metadata.push_back_check(file, m);
99 } catch (std::exception& e) {
100 }
101 } else {
102 try {
103 data->sources_metadata.push_back_check(file, m);
104 } catch (std::exception& e) {
105 }
106 }
107 // Rewrite metadata with new data
108 CBuild::write_file_metadata(target_id, file, &(m.new_meta));
109 CBuild::print_full(std::string("End"));
110}
112 CBuild::printf_full(CBuild::WHITE, "File: '%s'\nObject: '%s'\nDeps [new]:\n",
113 m->new_meta.source.c_str(), m->new_meta.object.c_str());
114 for (auto dep : m->new_meta.deps) {
115 CBuild::printf_full(CBuild::WHITE, "\t%s\n", dep.c_str());
116 }
117 CBuild::printf_full(CBuild::WHITE, "Deps [old]: %s\n",
118 (m->old_meta_available == true) ? "" : "null");
119 if (m->old_meta_available) {
120 for (auto dep : m->old_meta.deps) {
121 CBuild::printf_full(CBuild::WHITE, "\t%s\n", dep.c_str());
122 }
123 }
125 "Hash [new]: '0x%" PRIx64 "'\nHash [old]: ", m->new_meta.hash);
126 if (m->old_meta_available) {
127 CBuild::printf_full(CBuild::WHITE, "'0x%" PRIx64 "'\n", m->old_meta.hash);
128 } else {
130 }
131}
132
134 // std::printf("Checking file '%s'\n", file->new_meta.source.c_str());
135 if (file->old_meta_available == false) {
136 // std::printf("File: '%s' -> no_old_meta\n", file->new_meta.source.c_str());
137 return true;
138 }
139 if (file->new_meta.object != file->old_meta.object) {
140 // std::printf("File: '%s' -> mismatch object\n", file->new_meta.source.c_str());
141 return true;
142 }
143 if (file->new_meta.hash != file->old_meta.hash) {
144 // std::printf("File: '%s' -> mismatch hash\n", file->new_meta.source.c_str());
145 return true;
146 }
147 if (file->new_meta.deps != file->old_meta.deps) {
148 // std::printf("File: '%s' -> mismatch deps\n", file->new_meta.source.c_str());
149 return true;
150 }
151 for (auto dep : file->new_meta.deps) {
152 auto header = data->headers_metadata.get(dep);
153 if (header != NULL) {
154 if (check_mismatch_recursive(header, data)) {
155 return true;
156 }
157 }
158 auto source = data->sources_metadata.get(dep);
159 if (source != NULL) {
160 if (check_mismatch_recursive(source, data)) {
161 return true;
162 }
163 }
164 }
165 return false;
166}
167/* build_hash.hpp */
170 std::vector<std::string> objects) {
171 if (sources.size() != objects.size()) {
172 return {};
173 }
174 internal_data data;
175 CBuild::print_full("Parsing files");
176 // Get sources metadata
177 for (size_t i = 0; i < sources.size(); i++) {
178 parse_file(&data, target_id, sources.at(i), objects.at(i));
179 }
180 CBuild::print_full("Parsing headers");
181 // Get headers metadata
182 for (size_t i = 0; i < data.headers_to_parse.size(); i++) {
183 auto elem = data.headers_to_parse.ptr_at(i);
184 parse_file(&data, target_id, elem->key, "header");
185 elem->data = true;
186 }
187 // Fancy prints
188 CBuild::print_full("Source files:");
189 for (auto elem : data.sources_metadata) {
190 print_metadata(&(elem.data));
191 }
192 CBuild::print_full("Header files:");
193 for (auto elem : data.headers_metadata) {
194 print_metadata(&(elem.data));
195 }
197 // Get files for recompilation
198 for (auto file : data.sources_metadata) {
199 if (check_mismatch_recursive(&(file.data), &data)) {
200 ret.push_back(file.data.new_meta.source, file.data.new_meta.object);
201 }
202 }
203 return ret;
204}
Build metadata config file.
void parse_file(internal_data *data, std::string target_id, std::string file, std::string object)
std::regex c_comment("\\/\\*([\\s\\S]*?)\\*\\/", std::regex_constants::optimize|std::regex_constants::ECMAScript)
std::regex cpp_comment("[^\'\"]\\/\\/.*\n", std::regex_constants::optimize|std::regex_constants::ECMAScript)
std::regex include_detector("#include [\"<]([^\">]+)[\">]", std::regex_constants::optimize|std::regex_constants::ECMAScript)
void print_metadata(extended_metadata *m)
bool check_mismatch_recursive(const extended_metadata *file, internal_data *data)
Improved CBuild hasher.
virtual lib::map< std::string, std::string > get_files_for_recompilation(std::vector< std::string > file_list, std::vector< std::string > objects_list) override
Pass a list of source files and coresponding object files and get a map of source-object that need to...
std::string target_id
Definition hasher.hpp:64
Simple map implementation with some stack operation added.
Definition map.hpp:79
void push_back_check(lib::mapData< _K, _D > element)
Add data, but check if key exists, if exist - trow exception.
Definition map.hpp:129
lib::mapData< _K, _D > * ptr_at(__SIZE_TYPE__ i)
Array operation, get pointer to an element at specified index.
Definition map.hpp:232
__SIZE_TYPE__ size()
Size of map.
Definition map.hpp:275
void push_back(lib::mapData< _K, _D > element)
Push new element to map, stack operation ! Dangerous not perform chak if this elemnt exists in map.
Definition map.hpp:111
const _D * get(_K key)
Get element by it's key.
Definition map.hpp:159
filesystem++ api
Custom implementation of map datatype.
bool exists(std::string path)
Check if file exists.
std::string base(std::string file)
Get base file path (path to dir in what file is)
std::string normalize_relative_path(std::string path, std::string base_path="")
Get absolute path to file using relative path and base path.
void void printf_full(color fg, const char *fmt,...) __attribute__((format(printf
Some poor printf implementation for verbouse-only prints.
Definition print.cpp:89
uint64_t hash_fnv_1a(std::string str)
FNV-1a hashing function for std::string.
Definition hasher.hpp:54
@ WHITE
Definition print.hpp:40
int write_file_metadata(std::string target_id, std::string src_file, CBuild::source_metadata_file *metadata)
Write a metadata for a file to a file.
int read_file_metadata(std::string target_id, std::string src_file, CBuild::source_metadata_file *metadata)
Load metadata for source file.
void print_full(std::string msg, color fg=CBuild::WHITE)
Print colored text to STDOUT if verbose flag is set.
Definition print.cpp:75
Custom print that support color codes.
Metadata for source files (.cpp/.c/etc) Structure of file:
std::string object
Object file name.
std::string source
Source file path (relative to CBuild.run)
std::vector< std::string > deps
On what files this file depends.
uint64_t hash
Hash of this file.
CBuild::source_metadata_file old_meta
CBuild::source_metadata_file new_meta
lib::map< std::string, extended_metadata > sources_metadata
lib::map< std::string, extended_metadata > headers_metadata
lib::map< std::string, bool > headers_to_parse