1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-05-19 09:28:51 +03:00

Finally able to incrementally build Inform projects

This commit is contained in:
Graham Nelson 2020-02-22 14:09:13 +00:00
parent 828619fd96
commit 7cc9c598f3
18 changed files with 385 additions and 218 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@
.DS_Store
gameinfo.dbg
gametext.txt
makefile

View file

@ -36,8 +36,8 @@ int main(int argc, char **argv) {
path_to_inbuild = Pathnames::installation_path("INBUILD_PATH", I"inbuild");
build_methodology *BM;
if (path_to_tools) BM = BuildSteps::methodology(path_to_tools, FALSE);
else BM = BuildSteps::methodology(Pathnames::up(path_to_inbuild), TRUE);
if (path_to_tools) BM = BuildMethodology::new(path_to_tools, FALSE);
else BM = BuildMethodology::new(Pathnames::up(path_to_inbuild), TRUE);
if (dry_run_mode == FALSE) BM->methodology = SHELL_METHODOLOGY;
if (Str::len(unit_test) > 0) {
BM->methodology = DRY_RUN_METHODOLOGY;
@ -63,9 +63,9 @@ int main(int argc, char **argv) {
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) {
switch (inbuild_task) {
case INSPECT_TTASK: Copies::inspect(STDOUT, C); break;
case GRAPH_TTASK: Graphs::describe(STDOUT, C->vertex, TRUE); break;
case BUILD_TTASK: Graphs::build(C->vertex, BM); break;
case REBUILD_TTASK: Graphs::rebuild(C->vertex, BM); break;
case GRAPH_TTASK: Copies::show_graph(STDOUT, C); break;
case BUILD_TTASK: Copies::build(STDOUT, C, BM); break;
case REBUILD_TTASK: Copies::rebuild(STDOUT, C, BM); break;
case COPY_TO_TTASK: if (destination_nest) Nests::copy_to(C, destination_nest, FALSE, BM); break;
case SYNC_TO_TTASK: if (destination_nest) Nests::copy_to(C, destination_nest, TRUE, BM); break;
}

View file

@ -340,6 +340,7 @@ inform_project *Inbuild::create_shared_project(inbuild_copy *C) {
if (C == NULL) C = ProjectFileManager::claim_file_as_copy(filename_of_i7_source);
shared_project = ProjectFileManager::from_copy(C);
}
@<Create the default externals nest@>;
@<Create the materials nest@>;
if (shared_project) {
pathname *P = (shared_materials_nest)?(shared_materials_nest->location):NULL;
@ -350,6 +351,21 @@ inform_project *Inbuild::create_shared_project(inbuild_copy *C) {
return shared_project;
}
@<Create the default externals nest@> =
inbuild_nest *E = shared_external_nest;
if (E == NULL) {
pathname *P = home_path;
char *subfolder_within = INFORM_FOLDER_RELATIVE_TO_HOME;
if (subfolder_within[0]) {
TEMPORARY_TEXT(SF);
WRITE_TO(SF, "%s", subfolder_within);
P = Pathnames::subfolder(home_path, SF);
DISCARD_TEXT(SF);
}
P = Pathnames::subfolder(P, I"Inform");
E = Inbuild::add_nest(P, EXTERNAL_NEST_TAG);
}
@<Create the materials nest@> =
pathname *materials = NULL;
if (pathname_of_bundle) {

View file

@ -67,6 +67,16 @@ void Copies::scan(inbuild_copy *C) {
VMETHOD_CALL(C->edition->work->genre, GENRE_SCAN_COPY_MTID, C);
}
void Copies::build(OUTPUT_STREAM, inbuild_copy *C, build_methodology *BM) {
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILD_COPY_MTID, OUT, C, BM, FALSE, FALSE);
}
void Copies::rebuild(OUTPUT_STREAM, inbuild_copy *C, build_methodology *BM) {
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILD_COPY_MTID, OUT, C, BM, TRUE, FALSE);
}
void Copies::show_graph(OUTPUT_STREAM, inbuild_copy *C) {
VMETHOD_CALL(C->edition->work->genre, GENRE_BUILD_COPY_MTID, OUT, C, NULL, FALSE, TRUE);
}
wording Copies::read_source_text_for(inbuild_copy *C) {
if (C->source_text_read == FALSE) {
C->source_text_read = TRUE;

View file

@ -38,6 +38,7 @@ text_stream *Genres::name(inbuild_genre *G) {
@e GENRE_COPY_TO_NEST_MTID
@e GENRE_GO_OPERATIONAL_MTID
@e GENRE_READ_SOURCE_TEXT_FOR_MTID
@e GENRE_BUILD_COPY_MTID
=
VMETHOD_TYPE(GENRE_WRITE_WORK_MTID,
@ -57,3 +58,6 @@ VMETHOD_TYPE(GENRE_GO_OPERATIONAL_MTID,
inbuild_genre *gen, inbuild_copy *C)
VMETHOD_TYPE(GENRE_READ_SOURCE_TEXT_FOR_MTID,
inbuild_genre *gen, inbuild_copy *C)
VMETHOD_TYPE(GENRE_BUILD_COPY_MTID,
inbuild_genre *gen, text_stream *OUT, inbuild_copy *C,
build_methodology *BM, int rebuild, int describe_only)

View file

@ -27,7 +27,6 @@ typedef struct build_vertex {
struct linked_list *build_edges; /* of |build_vertex| */
struct linked_list *use_edges; /* of |build_vertex| */
struct build_script *script;
time_t timestamp;
int last_described;
int built;
MEMORY_MANAGEMENT
@ -40,8 +39,7 @@ build_vertex *Graphs::file_vertex(filename *F) {
V->buildable_if_internal_file = F;
V->build_edges = NEW_LINKED_LIST(build_vertex);
V->use_edges = NEW_LINKED_LIST(build_vertex);
V->timestamp = (time_t) 0;
V->script = BuildSteps::new_script();
V->script = BuildScripts::new();
V->annotation = NULL;
V->read_as = NULL;
V->last_described = 0;
@ -114,13 +112,7 @@ void Graphs::describe_r(OUTPUT_STREAM, int depth, build_vertex *V,
}
DISCARD_TEXT(S);
DISCARD_TEXT(T);
if (V->type == FILE_VERTEX) {
Graphs::update_timestamp(V);
if (V->timestamp != (time_t) 0) WRITE(" -- %s", ctime(&(V->timestamp)));
else WRITE(" -- no time stamp\n");
} else {
WRITE("\n");
}
WRITE("\n");
if (recurse) {
if (V->buildable_if_copy) stem = V->buildable_if_copy->location_if_path;
if (V->buildable_if_internal_file)
@ -142,17 +134,48 @@ void Graphs::describe_vertex(OUTPUT_STREAM, build_vertex *V) {
}
}
void Graphs::update_timestamp(build_vertex *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;
time_t Graphs::timestamp_for(build_vertex *V) {
time_t latest = (time_t) 0;
if (V->buildable_if_internal_file) {
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) latest = filestat.st_mtime;
} else {
latest = Graphs::time_of_most_recent_ingredient(V);
}
return latest;
}
time_t Graphs::time_of_most_recent_ingredient(build_vertex *V) {
time_t latest = (time_t) 0;
build_vertex *W;
LOOP_OVER_LINKED_LIST(W, build_vertex, V->build_edges) {
time_t inner = Graphs::timestamp_for(W);
if ((latest == (time_t) 0) || (difftime(inner, latest) > 0))
latest = inner;
}
return latest;
}
time_t Graphs::time_of_most_recent_used_resource(build_vertex *V) {
time_t latest = (time_t) 0;
build_vertex *W;
LOOP_OVER_LINKED_LIST(W, build_vertex, V->use_edges) {
time_t inner = Graphs::timestamp_for(W);
if ((latest == (time_t) 0) || (difftime(inner, latest) > 0))
latest = inner;
}
return latest;
}
@
@ -163,40 +186,61 @@ void Graphs::update_timestamp(build_vertex *V) {
@d USE_GB 4
=
void Graphs::build(build_vertex *V, build_methodology *meth) {
Graphs::build_r(BUILD_GB, V, meth);
int Graphs::build(OUTPUT_STREAM, build_vertex *V, build_methodology *meth) {
return Graphs::build_r(OUT, BUILD_GB, V, meth);
}
void Graphs::rebuild(build_vertex *V, build_methodology *meth) {
Graphs::build_r(BUILD_GB + FORCE_GB, V, meth);
int Graphs::rebuild(OUTPUT_STREAM, build_vertex *V, build_methodology *meth) {
return Graphs::build_r(OUT, BUILD_GB + FORCE_GB, V, meth);
}
void Graphs::build_r(int gb, build_vertex *V, build_methodology *meth) {
int needs_building = FALSE;
if (gb & FORCE_GB) needs_building = TRUE;
else if (V->built) return;
if (V->buildable_if_internal_file)
if (TextFiles::exists(V->buildable_if_internal_file) == FALSE)
needs_building = TRUE;
int trace_ibg = FALSE;
int Graphs::build_r(OUTPUT_STREAM, int gb, build_vertex *V, build_methodology *meth) {
if (trace_ibg) { WRITE_TO(STDOUT, "Build: "); Graphs::describe(STDOUT, V, FALSE); }
if (V->built) return TRUE;
STREAM_INDENT(STDOUT);
int rv = TRUE;
build_vertex *W;
LOOP_OVER_LINKED_LIST(W, build_vertex, V->build_edges)
Graphs::build_r(gb | USE_GB, W, meth);
if (rv)
rv = Graphs::build_r(OUT, gb | USE_GB, W, meth);
if (gb & USE_GB)
LOOP_OVER_LINKED_LIST(W, build_vertex, V->use_edges)
Graphs::build_r(gb & (BUILD_GB + FORCE_GB), W, meth);
if (needs_building == FALSE) {
Graphs::update_timestamp(V);
LOOP_OVER_LINKED_LIST(W, build_vertex, V->build_edges) {
Graphs::update_timestamp(W);
double since = difftime(V->timestamp, W->timestamp);
if (since < 0) { needs_building = TRUE; break; }
if (rv)
rv = Graphs::build_r(OUT, gb & (BUILD_GB + FORCE_GB), W, meth);
STREAM_OUTDENT(STDOUT);
if (rv) {
int needs_building = FALSE;
if (gb & FORCE_GB) needs_building = TRUE;
else @<Decide based on timestamps@>;
if (needs_building) {
if (trace_ibg) { WRITE_TO(STDOUT, "Exec\n"); }
rv = BuildScripts::execute(V, V->script, meth);
}
if (gb & USE_GB)
LOOP_OVER_LINKED_LIST(W, build_vertex, V->use_edges) {
Graphs::update_timestamp(W);
double since = difftime(V->timestamp, W->timestamp);
if (since < 0) { needs_building = TRUE; break; }
}
}
if (V->built) needs_building = FALSE;
if (needs_building) BuildSteps::execute(V, V->script, meth);
V->built = TRUE;
V->built = rv;
return rv;
}
@<Decide based on timestamps@> =
time_t last_built_at = Graphs::timestamp_for(V);
if (trace_ibg) { WRITE_TO(STDOUT, "Last built at: %08x\n", last_built_at); }
if (last_built_at == (time_t) 0)
needs_building = TRUE;
else {
time_t time_of_most_recent = Graphs::time_of_most_recent_ingredient(V);
if (time_of_most_recent != (time_t) 0) {
if (trace_ibg) { WRITE_TO(STDOUT, "Most recent: %08x\n", time_of_most_recent); }
if (difftime(time_of_most_recent, last_built_at) > 0)
needs_building = TRUE;
}
if (gb & USE_GB) {
time_t time_of_most_recent_used = Graphs::time_of_most_recent_used_resource(V);
if (time_of_most_recent_used != (time_t) 0) {
if (trace_ibg) { WRITE_TO(STDOUT, "Most recent use: %08x\n", time_of_most_recent_used); }
if (difftime(time_of_most_recent_used, last_built_at) > 0)
needs_building = TRUE;
}
}
}

View file

@ -0,0 +1,50 @@
[BuildMethodology::] Build Methodology.
Whether to run tasks internally in some merged tool, or run via the shell, or
simply trace to the standard output what we think ought to be done.
@
@e DRY_RUN_METHODOLOGY from 1
@e SHELL_METHODOLOGY
@e INTERNAL_METHODOLOGY
=
typedef struct build_methodology {
filename *to_inter;
filename *to_inform6;
filename *to_inform7;
filename *to_inblorb;
int methodology;
MEMORY_MANAGEMENT
} build_methodology;
build_methodology *BuildMethodology::new(pathname *tools_path, int dev) {
build_methodology *meth = CREATE(build_methodology);
meth->methodology = DRY_RUN_METHODOLOGY;
pathname *inter_path = tools_path;
if (dev) {
inter_path = Pathnames::subfolder(inter_path, I"inter");
inter_path = Pathnames::subfolder(inter_path, I"Tangled");
}
meth->to_inter = Filenames::in_folder(inter_path, I"inter");
pathname *inform6_path = tools_path;
if (dev) {
inform6_path = Pathnames::subfolder(inform6_path, I"inform6");
inform6_path = Pathnames::subfolder(inform6_path, I"Tangled");
}
meth->to_inform6 = Filenames::in_folder(inform6_path, I"inform6");
pathname *inform7_path = tools_path;
if (dev) {
inform7_path = Pathnames::subfolder(inform7_path, I"inform7");
inform7_path = Pathnames::subfolder(inform7_path, I"Tangled");
}
meth->to_inform7 = Filenames::in_folder(inform7_path, I"inform7");
pathname *inblorb_path = tools_path;
if (dev) {
inblorb_path = Pathnames::subfolder(inblorb_path, I"inblorb");
inblorb_path = Pathnames::subfolder(inblorb_path, I"Tangled");
}
meth->to_inblorb = Filenames::in_folder(inblorb_path, I"inblorb");
return meth;
}

View file

@ -0,0 +1,37 @@
[BuildScripts::] Build Scripts.
Scripts are nothing more than list of build steps.
@h Build scripts.
Simple lists of steps: nothing to see here...
=
typedef struct build_script {
struct linked_list *steps; /* of |build_step| */
MEMORY_MANAGEMENT
} build_script;
build_script *BuildScripts::new(void) {
build_script *BS = CREATE(build_script);
BS->steps = NEW_LINKED_LIST(build_step);
return BS;
}
void BuildScripts::add_step(build_script *BS, build_step *S) {
ADD_TO_LINKED_LIST(S, build_step, BS->steps);
}
void BuildScripts::concatenate(build_script *BT, build_script *BF) {
build_step *S;
LOOP_OVER_LINKED_LIST(S, build_step, BF->steps)
BuildScripts::add_step(BT, S);
}
int BuildScripts::execute(build_vertex *V, build_script *BS, build_methodology *meth) {
int rv = TRUE;
build_step *S;
LOOP_OVER_LINKED_LIST(S, build_step, BS->steps)
if (rv)
rv = BuildSteps::execute(V, S, meth);
return rv;
}

View file

@ -1,32 +1,8 @@
[BuildSteps::] Build Steps.
Graphs in which vertices correspond to files or copies, and arrows to
dependencies between them.
A build step is a task such as running inform7 or inblorb on some file.
@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_script {
struct linked_list *steps; /* of |build_step| */
MEMORY_MANAGEMENT
} build_script;
typedef struct build_step {
int what_to_do;
struct pathname *arg_p1;
struct text_stream *arg_t1;
struct target_vm *arg_vm;
MEMORY_MANAGEMENT
} build_step;
@
@h Build steps.
@e ASSIMILATE_BSTEP from 1
@e COMPILE_I7_TO_GEN_BSTEP
@ -34,104 +10,130 @@ typedef struct build_step {
@e BLORB_STORY_FILE_BSTEP
=
build_script *BuildSteps::new_script(void) {
build_script *BS = CREATE(build_script);
BS->steps = NEW_LINKED_LIST(build_step);
return BS;
}
build_step *BuildSteps::new_step(int to_do, pathname *P, text_stream *T) {
build_step *S = CREATE(build_step);
S->what_to_do = to_do;
S->arg_p1 = P;
S->arg_t1 = T;
S->arg_vm = NULL;
return S;
}
void BuildSteps::add_step(build_script *BS, build_step *S) {
ADD_TO_LINKED_LIST(S, build_step, BS->steps);
}
void BuildSteps::concatenate(build_script *BT, build_script *BF) {
build_step *S;
LOOP_OVER_LINKED_LIST(S, build_step, BF->steps)
BuildSteps::add_step(BT, S);
}
typedef struct build_step {
int what_to_do;
struct build_vertex *vertex;
struct linked_list *search_path; /* of |inbuild_nest| */
struct target_vm *for_vm;
struct inter_architecture *for_arch;
int for_release;
struct inbuild_copy *associated_copy;
MEMORY_MANAGEMENT
} build_step;
@
@e DRY_RUN_METHODOLOGY from 1
@e SHELL_METHODOLOGY
@e INTERNAL_METHODOLOGY
=
typedef struct build_methodology {
filename *to_inter;
filename *to_inform6;
filename *to_inform7;
filename *to_inblorb;
int methodology;
MEMORY_MANAGEMENT
} build_methodology;
build_methodology *BuildSteps::methodology(pathname *tools_path, int dev) {
build_methodology *meth = CREATE(build_methodology);
meth->methodology = DRY_RUN_METHODOLOGY;
pathname *inter_path = tools_path;
if (dev) {
inter_path = Pathnames::subfolder(inter_path, I"inter");
inter_path = Pathnames::subfolder(inter_path, I"Tangled");
}
meth->to_inter = Filenames::in_folder(inter_path, I"inter");
pathname *inform6_path = tools_path;
if (dev) {
inform6_path = Pathnames::subfolder(inform6_path, I"inform6");
inform6_path = Pathnames::subfolder(inform6_path, I"Tangled");
}
meth->to_inform6 = Filenames::in_folder(inform6_path, I"inform6");
pathname *inform7_path = tools_path;
if (dev) {
inform7_path = Pathnames::subfolder(inform7_path, I"inform7");
inform7_path = Pathnames::subfolder(inform7_path, I"Tangled");
}
meth->to_inform7 = Filenames::in_folder(inform7_path, I"inform7");
pathname *inblorb_path = tools_path;
if (dev) {
inblorb_path = Pathnames::subfolder(inblorb_path, I"inblorb");
inblorb_path = Pathnames::subfolder(inblorb_path, I"Tangled");
}
meth->to_inblorb = Filenames::in_folder(inblorb_path, I"inblorb");
return meth;
build_step *BuildSteps::attach(build_vertex *vertex, int to_do, linked_list *search,
int rel, target_vm *VM, inter_architecture *arch, inbuild_copy *assoc) {
build_step *S = CREATE(build_step);
S->vertex = vertex;
S->what_to_do = to_do;
S->search_path = search;
S->for_vm = VM;
S->for_arch = arch;
if ((VM) && (arch == NULL)) S->for_arch = TargetVMs::get_architecture(VM);
S->for_release = rel;
S->associated_copy = assoc;
BuildScripts::add_step(vertex->script, S);
return S;
}
void BuildSteps::execute(build_vertex *V, build_script *BS, build_methodology *meth) {
build_step *S;
LOOP_OVER_LINKED_LIST(S, build_step, BS->steps) {
TEMPORARY_TEXT(command);
@<Write a shell command for the step@>;
BuildSteps::shell(command, meth);
DISCARD_TEXT(command);
}
int BuildSteps::execute(build_vertex *V, build_step *S, build_methodology *meth) {
int rv = TRUE;
TEMPORARY_TEXT(command);
@<Write a shell command for the step@>;
if (rv) rv = BuildSteps::shell(command, meth);
if (rv == FALSE) WRITE_TO(STDERR, "Build failed at '%S'\n", command);
DISCARD_TEXT(command);
return rv;
}
@<Write a shell command for the step@> =
switch (S->what_to_do) {
case ASSIMILATE_BSTEP:
Shell::quote_file(command, meth->to_inter);
WRITE_TO(command, " -architecture %S -assimilate ", S->arg_t1);
Shell::quote_path(command, S->arg_p1);
break;
default: internal_error("unimplemented step");
case ASSIMILATE_BSTEP: rv = BuildSteps::use_inter(S, command, meth); break;
case COMPILE_I7_TO_GEN_BSTEP: rv = BuildSteps::use_inform7(S, command, meth); break;
case COMPILE_GEN_TO_STORY_FILE_BSTEP: rv = BuildSteps::use_inform6(S, command, meth); break;
case BLORB_STORY_FILE_BSTEP: rv = BuildSteps::use_inblorb(S, command, meth); break;
default: rv = FALSE; Errors::nowhere("unimplemented build step"); break;
}
@ =
void BuildSteps::shell(text_stream *command, build_methodology *meth) {
switch (meth->methodology) {
case DRY_RUN_METHODOLOGY:
case SHELL_METHODOLOGY: {
WRITE_TO(STDOUT, "%S\n", command);
if (meth->methodology == SHELL_METHODOLOGY) Shell::run(command);
}
}
int BuildSteps::shell(text_stream *command, build_methodology *meth) {
int rv = TRUE;
WRITE_TO(STDOUT, "%S\n", command);
if (meth->methodology == SHELL_METHODOLOGY) rv = (Shell::run(command) == 0)?TRUE:FALSE;
return rv;
}
@ =
int BuildSteps::use_inter(build_step *S, text_stream *command, build_methodology *meth) {
if (command == NULL) internal_error("not available in-app");
Shell::quote_file(command, meth->to_inter);
WRITE_TO(command, "-architecture %S ", Architectures::to_codename(S->for_arch));
WRITE_TO(command, "-assimilate ");
Shell::quote_path(command, S->associated_copy->location_if_path);
return TRUE;
}
@ =
int BuildSteps::use_inform7(build_step *S, text_stream *command, build_methodology *meth) {
if (command == NULL) internal_error("not available in-app");
Shell::quote_file(command, meth->to_inform7);
inform_project *project = ProjectBundleManager::from_copy(S->associated_copy);
if (project == NULL) project = ProjectFileManager::from_copy(S->associated_copy);
if (project == NULL) internal_error("no project");
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include) {
WRITE_TO(command, "-kit %S ", K->as_copy->edition->work->title);
}
WRITE_TO(command, "-format=%S ", TargetVMs::get_unblorbed_extension(S->for_vm));
inbuild_nest *N;
LOOP_OVER_LINKED_LIST(N, inbuild_nest, S->search_path) {
switch (Nests::get_tag(N)) {
case MATERIALS_NEST_TAG: continue;
case EXTERNAL_NEST_TAG: WRITE_TO(command, "-external "); break;
case GENERIC_NEST_TAG: WRITE_TO(command, "-nest "); break;
case INTERNAL_NEST_TAG: WRITE_TO(command, "-internal "); break;
default: internal_error("mystery nest");
}
Shell::quote_path(command, N->location);
}
WRITE_TO(command, "-project ");
Shell::quote_path(command, S->associated_copy->location_if_path);
return TRUE;
}
@ =
int BuildSteps::use_inform6(build_step *S, text_stream *command, build_methodology *meth) {
if (command == NULL) internal_error("not available in-app");
Shell::quote_file(command, meth->to_inform6);
inform_project *project = ProjectBundleManager::from_copy(S->associated_copy);
if (project == NULL) project = ProjectFileManager::from_copy(S->associated_copy);
if (project == NULL) internal_error("no project");
pathname *build_folder = Pathnames::subfolder(project->as_copy->location_if_path, I"Build");
filename *inf_F = Filenames::in_folder(build_folder, I"auto.inf");
WRITE_TO(command, "-kE2S");
if (TargetVMs::debug_enabled((S->for_vm))) WRITE_TO(command, "D");
text_stream *ext = TargetVMs::get_unblorbed_extension(S->for_vm);
if (Str::eq(ext, I"ulx")) ext = I"G";
WRITE_TO(command, "w%S ", ext);
Shell::quote_file(command, inf_F);
Shell::quote_file(command, S->vertex->buildable_if_internal_file);
return TRUE;
}
@ =
int BuildSteps::use_inblorb(build_step *S, text_stream *command, build_methodology *meth) {
if (command == NULL) internal_error("not available in-app");
WRITE_TO(command, "echo 'Not done yet'");
return TRUE;
}

View file

@ -14,6 +14,7 @@ void KitManager::start(void) {
METHOD_ADD(kit_genre, GENRE_SEARCH_NEST_FOR_MTID, KitManager::search_nest_for);
METHOD_ADD(kit_genre, GENRE_COPY_TO_NEST_MTID, KitManager::copy_to_nest);
METHOD_ADD(kit_genre, GENRE_GO_OPERATIONAL_MTID, KitManager::go_operational);
METHOD_ADD(kit_genre, GENRE_BUILD_COPY_MTID, KitManager::build);
}
void KitManager::write_work(inbuild_genre *gen, OUTPUT_STREAM, inbuild_work *work) {
@ -161,12 +162,15 @@ void KitManager::copy_to_nest(inbuild_genre *gen, inbuild_copy *C, inbuild_nest
}
@h Build graph.
The build graph for a kit is quite extensive, since a kit contains Inter
binaries for four different architectures; and each of those has a
dependency on every section file of the web of Inform 6 source for the kit.
If there are $S$ sections then the graph has $S+5$ vertices and $4(S+1)$ edges.
=
void KitManager::build(inbuild_genre *gen, text_stream *OUT, inbuild_copy *C,
build_methodology *BM, int rebuild, int describe_only) {
if (describe_only) Graphs::describe(OUT, C->vertex, TRUE);
else if (rebuild) Graphs::rebuild(OUT, C->vertex, BM);
else Graphs::build(OUT, C->vertex, BM);
}
void KitManager::build_vertex(inbuild_copy *C) {
Graphs::copy_vertex(C);
}

View file

@ -14,6 +14,7 @@ void ProjectBundleManager::start(void) {
METHOD_ADD(project_bundle_genre, GENRE_COPY_TO_NEST_MTID, ProjectBundleManager::copy_to_nest);
METHOD_ADD(project_bundle_genre, GENRE_GO_OPERATIONAL_MTID, ProjectBundleManager::go_operational);
METHOD_ADD(project_bundle_genre, GENRE_READ_SOURCE_TEXT_FOR_MTID, ProjectBundleManager::read_source_text_for);
METHOD_ADD(project_bundle_genre, GENRE_BUILD_COPY_MTID, ProjectBundleManager::build);
}
void ProjectBundleManager::write_work(inbuild_genre *gen, OUTPUT_STREAM, inbuild_work *work) {
@ -86,7 +87,18 @@ void ProjectBundleManager::copy_to_nest(inbuild_genre *gen, inbuild_copy *C, inb
}
@h Build graph.
The build graph for a project will need further thought...
=
void ProjectBundleManager::build(inbuild_genre *gen, text_stream *OUT, inbuild_copy *C,
build_methodology *BM, int rebuild, int describe_only) {
inform_project *project = ProjectBundleManager::from_copy(C);
build_vertex *V = project->chosen_build_target;
if (describe_only) Graphs::describe(OUT, V, TRUE);
else if (rebuild) Graphs::rebuild(OUT, V, BM);
else Graphs::build(OUT, V, BM);
}
@ The build graph for a project will need further thought...
=
void ProjectBundleManager::build_vertex(inbuild_copy *C) {

View file

@ -14,6 +14,7 @@ void ProjectFileManager::start(void) {
METHOD_ADD(project_file_genre, GENRE_COPY_TO_NEST_MTID, ProjectFileManager::copy_to_nest);
METHOD_ADD(project_file_genre, GENRE_GO_OPERATIONAL_MTID, ProjectFileManager::go_operational);
METHOD_ADD(project_file_genre, GENRE_READ_SOURCE_TEXT_FOR_MTID, ProjectFileManager::read_source_text_for);
METHOD_ADD(project_file_genre, GENRE_BUILD_COPY_MTID, ProjectFileManager::build);
}
void ProjectFileManager::write_work(inbuild_genre *gen, OUTPUT_STREAM, inbuild_work *work) {
@ -89,7 +90,18 @@ void ProjectFileManager::copy_to_nest(inbuild_genre *gen, inbuild_copy *C, inbui
}
@h Build graph.
The build graph for a project will need further thought.
=
void ProjectFileManager::build(inbuild_genre *gen, text_stream *OUT, inbuild_copy *C,
build_methodology *BM, int rebuild, int describe_only) {
inform_project *project = ProjectBundleManager::from_copy(C);
build_vertex *V = project->chosen_build_target;
if (describe_only) Graphs::describe(OUT, V, TRUE);
else if (rebuild) Graphs::rebuild(OUT, V, BM);
else Graphs::build(OUT, V, BM);
}
@ The build graph for a project will need further thought...
=
void ProjectFileManager::build_vertex(inbuild_copy *C) {

View file

@ -210,6 +210,12 @@ linked_list *Kits::inter_paths(void) {
return inter_paths;
}
@ The build graph for a kit is quite extensive, since a kit contains Inter
binaries for four different architectures; and each of those has a
dependency on every section file of the web of Inform 6 source for the kit.
If there are $S$ sections then the graph has $S+5$ vertices and $4(S+1)$ edges.
=
void Kits::construct_graph(inform_kit *K) {
RUN_ONLY_IN_PHASE(GOING_OPERATIONAL_INBUILD_PHASE)
if (K == NULL) return;
@ -221,9 +227,8 @@ void Kits::construct_graph(inform_kit *K) {
LOOP_OVER(A, inter_architecture) {
build_vertex *BV = Graphs::file_vertex(Architectures::canonical_binary(P, A));
Graphs::need_this_to_build(KV, BV);
build_step *BS = BuildSteps::new_step(
ASSIMILATE_BSTEP, P, Architectures::to_codename(A));
BuildSteps::add_step(BV->script, BS);
BuildSteps::attach(BV, ASSIMILATE_BSTEP,
Inbuild::nest_list(), FALSE, NULL, A, K->as_copy);
ADD_TO_LINKED_LIST(BV, build_vertex, BVL);
}

View file

@ -256,9 +256,8 @@ void Projects::construct_build_target(inform_project *project, target_vm *VM, in
filename *inf_F = Filenames::in_folder(build_folder, I"auto.inf");
build_vertex *inf_V = Graphs::file_vertex(inf_F);
Graphs::need_this_to_build(inf_V, project->as_copy->vertex);
build_step *BS = BuildSteps::new_step(COMPILE_I7_TO_GEN_BSTEP, NULL, NULL);
BS->arg_vm = VM;
BuildSteps::add_step(inf_V->script, BS);
BuildSteps::attach(inf_V, COMPILE_I7_TO_GEN_BSTEP,
Inbuild::nest_list(), releasing, VM, NULL, project->as_copy);
TEMPORARY_TEXT(story_file_leafname);
WRITE_TO(story_file_leafname, "output.%S", TargetVMs::get_unblorbed_extension(VM));
@ -266,9 +265,8 @@ void Projects::construct_build_target(inform_project *project, target_vm *VM, in
DISCARD_TEXT(story_file_leafname);
build_vertex *unblorbed_V = Graphs::file_vertex(unblorbed_F);
Graphs::need_this_to_build(unblorbed_V, inf_V);
build_step *BS2 = BuildSteps::new_step(COMPILE_GEN_TO_STORY_FILE_BSTEP, NULL, NULL);
BS2->arg_vm = VM;
BuildSteps::add_step(unblorbed_V->script, BS2);
BuildSteps::attach(unblorbed_V, COMPILE_GEN_TO_STORY_FILE_BSTEP,
Inbuild::nest_list(), releasing, VM, NULL, project->as_copy);
if (releasing) {
TEMPORARY_TEXT(story_file_leafname);
@ -277,9 +275,8 @@ void Projects::construct_build_target(inform_project *project, target_vm *VM, in
DISCARD_TEXT(story_file_leafname);
build_vertex *blorbed_V = Graphs::file_vertex(blorbed_F);
Graphs::need_this_to_build(unblorbed_V, inf_V);
build_step *BS3 = BuildSteps::new_step(BLORB_STORY_FILE_BSTEP, NULL, NULL);
BS3->arg_vm = VM;
BuildSteps::add_step(blorbed_V->script, BS3);
BuildSteps::attach(blorbed_V, BLORB_STORY_FILE_BSTEP,
Inbuild::nest_list(), releasing, VM, NULL, project->as_copy);
project->chosen_build_target = blorbed_V;
} else {

View file

@ -18,6 +18,8 @@ Chapter 2: Conceptual Framework
Chapter 3: Incremental Builds
Build Graphs
Build Methodology
Build Scripts
Build Steps
Chapter 4: Managing Genres of Work

View file

@ -4,7 +4,7 @@ PM_EnigmaticThey PM_EnigmaticPronoun PM_WordTooLong PM_TooMuchQuotedText PM_Unen
PM_BadTitleSentence PM_HeadingStopsBeforeEndOfLine PM_HeadingOverLine HEADINGS _ doc14 "2.5" "2.5. Headings"
PM_UnknownInternalTest PM_TestDoubleWith PM_TestCommandTooLong PM_TestContainsUndo PM_TestBadRequirements PM_TestDuplicate PM_TestMultiWord _ doc17 "2.8" "2.8. The TEST command"
PM_BogusExtension _ doc19 "2.10" "2.10. Installing extensions"
PM_ExtMisidentifiedEnds PM_ExtInadequateVM PM_ExtMalformedVM PM_ExtMiswordedBeginsHere PM_ExtVersionMalformed PM_IncludeExtQuoted _ doc20 "2.11" "2.11. Including extensions"
PM_ExtMisidentifiedEnds PM_ExtInadequateVM PM_ExtMiswordedBeginsHere PM_ExtVersionMalformed PM_IncludeExtQuoted _ doc20 "2.11" "2.11. Including extensions"
OPTIONS PM_UnknownUseOption PM_UONotNumerical _ doc21 "2.12" "2.12. Use options"
OPTIONSFILE _ doc22 "2.13" "2.13. Administering classroom use"
STORYFILES PM_BadICLIdentifier _ doc23 "2.14" "2.14. Limits and the Settings panel"

View file

@ -146,42 +146,12 @@ not distinguish between permanent and transient external resources.
@<External resources@> =
inbuild_nest *E = Inbuild::external();
if (E == NULL) {
pathname *P = home_path;
char *subfolder_within = INFORM_FOLDER_RELATIVE_TO_HOME;
if (subfolder_within[0]) {
TEMPORARY_TEXT(SF);
WRITE_TO(SF, "%s", subfolder_within);
P = Pathnames::subfolder(home_path, SF);
DISCARD_TEXT(SF);
}
P = Pathnames::subfolder(P, I"Inform");
E = Inbuild::add_nest(P, EXTERNAL_NEST_TAG);
}
pathname *pathname_of_external_folder = E->location;
if (Pathnames::create_in_file_system(pathname_of_external_folder) == 0) return FALSE;
@<Permanent external resources@>;
pathname *pathname_of_transient_external_resources = Inbuild::transient();
if (Pathnames::create_in_file_system(pathname_of_transient_external_resources) == 0) return FALSE;
@<Transient external resources@>;
@ The permanent resources are read-only as far as we are concerned. (The
user interface application, and the user directly, write to this area when
they (say) install new extensions. But the compiler only reads.)
Once again we have a set of EILT resources, but we also have a curiosity:
a useful little file to add source text to everything Inform compiles,
generally to set use options.
@<Permanent external resources@> =
filename_of_options =
Filenames::in_folder(pathname_of_external_folder, I"Options.txt");
@ The transient resources are all written by us.
@<Transient external resources@> =
pathname *pathname_of_transient_external_resources = Inbuild::transient();
if (Pathnames::create_in_file_system(pathname_of_transient_external_resources) == 0) return FALSE;
@<Transient documentation@>;
@<Transient telemetry@>;

View file

@ -3,6 +3,7 @@
.DS_Store
gameinfo.dbg
gametext.txt
makefile