1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 08:34:22 +03:00
inform7/inbuild/inbuild-module/Chapter 2/Build Graphs.w

113 lines
3.6 KiB
OpenEdge ABL
Raw Normal View History

[Graphs::] Build Graphs.
Graphs in which vertices correspond to files or copies, and arrows to
dependencies between them.
@h Build graphs.
These are directed acyclic graphs which show what depends on what in the
building process. If an arrow leads from A to B, then B must be built before
A can be built.
There can be two sorts of vertex in such a graph: copy vertices, each of which
belongs to a single copy, and internal vertices, each of which represents
a different file inside the copy.
=
typedef struct build_graph {
struct inbuild_copy *buildable_if_copy;
struct filename *buildable_if_internal_file;
struct linked_list *arrows; /* of pointers to other |build_graph| nodes */
struct build_script *script;
time_t timestamp;
MEMORY_MANAGEMENT
} build_graph;
build_graph *Graphs::internal_vertex(filename *F) {
build_graph *G = CREATE(build_graph);
G->buildable_if_copy = NULL;
G->buildable_if_internal_file = F;
G->arrows = NEW_LINKED_LIST(build_graph);
G->timestamp = (time_t) 0;
G->script = BuildSteps::new_script();
return G;
}
build_graph *Graphs::copy_vertex(inbuild_copy *C) {
if (C == NULL) internal_error("no copy");
if (C->graph == NULL) {
C->graph = Graphs::internal_vertex(NULL);
C->graph->buildable_if_copy = C;
}
return C->graph;
}
void Graphs::arrow(build_graph *from, build_graph *to) {
if (from == NULL) internal_error("no from");
if (to == NULL) internal_error("no to");
if (from == to) internal_error("graph node depends on itself");
build_graph *G;
LOOP_OVER_LINKED_LIST(G, build_graph, from->arrows)
if (G == to) return;
ADD_TO_LINKED_LIST(to, build_graph, from->arrows);
}
void Graphs::describe(OUTPUT_STREAM, build_graph *G, int recurse) {
Graphs::describe_r(OUT, 0, G, recurse);
}
void Graphs::describe_r(OUTPUT_STREAM, int depth, build_graph *V, int recurse) {
for (int i=0; i<depth; i++) WRITE(" ");
if (V->buildable_if_copy) {
WRITE("[copy%d] ", V->allocation_id);
2020-01-31 02:13:50 +02:00
Model::write_copy(OUT, V->buildable_if_copy);
WRITE("\n");
} else {
Graphs::update_timestamp(V);
WRITE("[int%d] %f", V->allocation_id, V->buildable_if_internal_file);
if (V->timestamp != (time_t) 0) WRITE(" %s", ctime(&(V->timestamp)));
else WRITE("\n");
}
if (recurse) {
build_graph *W;
LOOP_OVER_LINKED_LIST(W, build_graph, V->arrows)
Graphs::describe_r(OUT, depth+1, W, TRUE);
}
}
void Graphs::update_timestamp(build_graph *V) {
if (V == NULL) return;
if (V->buildable_if_internal_file == NULL) return;
char transcoded_pathname[4*MAX_FILENAME_LENGTH];
TEMPORARY_TEXT(FN);
WRITE_TO(FN, "%f", V->buildable_if_internal_file);
Str::copy_to_locale_string(transcoded_pathname, FN, 4*MAX_FILENAME_LENGTH);
DISCARD_TEXT(FN);
struct stat filestat;
if (stat(transcoded_pathname, &filestat) == -1) { V->timestamp = (time_t) 0; return; }
V->timestamp = filestat.st_mtime;
}
void Graphs::build(build_graph *G, build_methodology *meth) {
Graphs::build_r(FALSE, G, meth);
}
void Graphs::rebuild(build_graph *G, build_methodology *meth) {
Graphs::build_r(TRUE, G, meth);
}
void Graphs::build_r(int forcing_build, build_graph *V, build_methodology *meth) {
int needs_building = forcing_build;
if (V->buildable_if_internal_file)
if (TextFiles::exists(V->buildable_if_internal_file) == FALSE)
needs_building = TRUE;
build_graph *W;
LOOP_OVER_LINKED_LIST(W, build_graph, V->arrows)
Graphs::build_r(forcing_build, W, meth);
if (needs_building == FALSE) {
Graphs::update_timestamp(V);
LOOP_OVER_LINKED_LIST(W, build_graph, V->arrows) {
Graphs::update_timestamp(W);
double since = difftime(V->timestamp, W->timestamp);
if (since < 0) { needs_building = TRUE; break; }
}
}
if (needs_building) BuildSteps::execute(V->script, meth);
}