A build step is a task which exercises one of the build skills.
§1. Build skills. A "skill" is a single atomic task which we know how to perform. For example, assimilating a binary for a kit is a skill.
Each different skill is an instance of:
classdef build_skill { struct text_stream *name; struct method_set *methods; } build_skill *BuildSteps::new_skill(text_stream *name) { build_skill *S = CREATE(build_skill); S->name = Str::duplicate(name); S->methods = Methods::new_set(); return S; }
- The structure build_skill is accessed in 2/gnr, 7/tm, 7/dc, 7/dr, 7/il, 7/ei and here.
§2. Skills provide two method functions: one constructs a shell command to perform the skill, and the other performs the skill directly by calling some function within the current executable. These methods are optional, and if one is absent then the skill can't be performed that way.
enumerate BUILD_SKILL_COMMAND_MTID
enumerate BUILD_SKILL_INTERNAL_MTID
VOID_METHOD_TYPE(BUILD_SKILL_COMMAND_MTID, build_skill *S, build_step *BS, text_stream *command, build_methodology *meth, linked_list *search) INT_METHOD_TYPE(BUILD_SKILL_INTERNAL_MTID, build_skill *S, build_step *BS, build_methodology *meth, linked_list *search)
§3. Build steps. These are essentially just skills, but with a docket of contextual data. The
idea is that a function outside the supervisor module can carry out a skill
for us using only the contextual information in this structure, without having
to access any of inbuild's variables directly.
classdef build_step { struct build_skill *what_to_do; struct build_vertex *vertex; /* what to do it to */ struct target_vm *for_vm; struct inter_architecture *for_arch; int for_release; struct inbuild_copy *associated_copy; /* e.g., the Inform project causing this work */ }
- The structure build_step is accessed in 2/cps, 3/bg, 3/is, 3/is2, 3/is3, 3/is4, 4/em, 4/ebm, 4/km, 5/es, 5/ks, 5/ls, 5/ps2, 6/hdn, 6/inc and here.
build_step *BuildSteps::attach(build_vertex *vertex, build_skill *to_do, int rel, target_vm *VM, inter_architecture *arch, inbuild_copy *assoc) { build_step *S = CREATE(build_step); S->what_to_do = to_do; S->vertex = vertex; 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; }
§5. Execution. Note that this prints a log of shell commands generated to stdout when
we are running inside Inbuild at the command line, but not when we are running
inside the inform7 executable, where we are silent throughout.
int BuildSteps::execute(build_vertex *V, build_step *S, build_methodology *BM, linked_list *search_list) { int rv = TRUE; TEMPORARY_TEXT(command) Work out a shell command, and perhaps print or call it5.1; Perform the skill internally if that's called for5.2; #ifndef CORE_MODULE if (rv == FALSE) WRITE_TO(STDERR, "Build failed at '%S'\n", command); #endif DISCARD_TEXT(command) return rv; }
§5.1. Work out a shell command, and perhaps print or call it5.1 =
VOID_METHOD_CALL(S->what_to_do, BUILD_SKILL_COMMAND_MTID, S, command, BM, search_list); if (Str::len(command) > 0) rv = BuildSteps::shell(command, BM);
- This code is used in §5.
§5.2. Perform the skill internally if that's called for5.2 =
if (BM->methodology == INTERNAL_METHODOLOGY) { int returned = 0; INT_METHOD_CALL(returned, S->what_to_do, BUILD_SKILL_INTERNAL_MTID, S, BM, search_list); if (returned != TRUE) rv = FALSE; }
- This code is used in §5.
§6. This prints a shell command to stdout (except when inside inform7)
and also executes it if the methodology allows, returning the result. Note
that shell commands return 0 to indicate happiness.
int BuildSteps::shell(text_stream *command, build_methodology *BM) { int rv = TRUE; #ifndef CORE_MODULE WRITE_TO(STDOUT, "%S\n", command); #endif if (BM->methodology == SHELL_METHODOLOGY) rv = (Shell::run(command) == 0)?TRUE:FALSE; return rv; }