Logo

index : jinit

---

  • summary
  • about
  • tree
  • log
  • branches
<< path: root/public/jinit.git/html/build.jai blob: 55d363eea9671025055050b97fb39f4fe091c497 [raw] [clear marker]

        
0#import "Basic";
1#import "String";
2#import "Compiler";
3#import "File";
4#import "File_Utilities";
5#import "Autorun";
6
7
8
9// ----------------------------------------
10// config
11// ------
12
13
14// For a template example, visit `templates/minimal/rules_minimal.jai`
15
16
17// Which template should be used by default
18// (You can list all templates with `jinit -l`)
19SET_DEFAULT_TEMPLATE :: "arg";
20
21
22// You can include this "marker" in your templates/rules
23// and replace them at runtime with `jinit -t <template> -r <your new string>`
24SET_RENAME_MARKER :: "__RENAME_PLACEHOLDER__";
25
26
27// If you don't use a SCM, you can turn it off here
28SET_SCM_IS_TURNED_OFF :: false;
29
30
31// Define the initializing commands for your SCM
32SET_SCM_COMMANDS :: string.[ "git", "init" ];
33
34
35// [ ! IMPORTANT ! ]: Some SCMs define a directory where they store all refs
36// and other internals.
37// You have to set the directory name here, otherwise it
38// will overwrite your SCM repository at every invocation!
39SET_SCM_DOT_DIR :: ".git";
40
41
42SET_BUILD_FILE_NAME :: "build.jai";
43
44// ----------------------------------------
45
46
47#placeholder TEMPLATES_AND_RULES;
48#placeholder TR_EXEC_BUF_MAX;
49#placeholder TR_EXEC_BODY;
50#placeholder DEFAULT_TEMPLATE;
51#placeholder BUILD_FN;
52#placeholder SCM_IS_TURNED_OFF;
53#placeholder SCM_COMMANDS;
54#placeholder SCM_DOT_DIR;
55#placeholder RENAME_MARKER;
56
57TEMPLATE_DIR :: "templates";
58
59
60build :: () {
61 args := get_build_options().compile_time_command_line;
62
63 // args
64 args_help := array_find(args, "help");
65 args_compiler_silent := array_find(args, "silent");
66 args_program_run := array_find(args, "run");
67 args_build_release := array_find(args, "release");
68
69 // program args
70 program_args := program_args_collect(args);
71 defer array_free(program_args);
72
73 // -----------------------------------------
74 w := compiler_create_workspace();
75
76 if !w {
77 log("Workspace creation failed.");
78 return;
79 }
80
81 set_build_options_dc(.{ do_output = false });
82
83 if args_help {
84 args_help_print();
85 return;
86 }
87
88
89 print("The workspace w is %\n", w);
90 make_directory_if_it_does_not_exist("bin");
91 make_directory_if_it_does_not_exist("bin/debug");
92 make_directory_if_it_does_not_exist("bin/release");
93
94 target_options := get_build_options(w);
95 target_options.output_executable_name = "jinit";
96
97 if args_compiler_silent target_options.text_output_flags = 0;
98
99 if args_build_release {
100 build_release(w, *target_options);
101 } else {
102 build_debug(w, *target_options);
103 }
104
105
106 compiler_begin_intercept(w);
107 add_build_file(tprint("%src/main.jai", #filepath), w);
108
109 template_rules := template_rules_find();
110 defer array_free(template_rules);
111 template_rules_inject(template_rules, w);
112
113 add_build_string(
114 tprint("RENAME_MARKER :: \"%\";", SET_RENAME_MARKER),
115 w
116 );
117
118 add_build_string(
119 tprint("SCM_IS_TURNED_OFF :: %;", SET_SCM_IS_TURNED_OFF),
120 w
121 );
122
123 add_build_string(
124 tprint("SCM_COMMANDS :: %.%;", "string", SET_SCM_COMMANDS),
125 w
126 );
127
128 #assert(SET_SCM_DOT_DIR) "[ERR]: NO SCM REF DIRECTORY IS SET!";
129
130 add_build_string(
131 tprint("SCM_DOT_DIR :: \"%\";", SET_SCM_DOT_DIR),
132 w
133 );
134
135 add_build_string(
136 tprint("BUILD_FN :: \"%\";", SET_BUILD_FILE_NAME),
137 w
138 );
139
140 add_build_string(
141 tprint("DEFAULT_TEMPLATE :: \"%\";", SET_DEFAULT_TEMPLATE),
142 w
143 );
144
145 compiler_response := compiler_message();
146 compiler_end_intercept(w);
147
148 if !compiler_response {
149 log("Compiler response failed.");
150 return;
151 }
152
153 if args_program_run run_build_result_of_workspace(w, program_args);
154}
155
156
157build_debug :: (w: Workspace, target_options: *Build_Options) {
158 log("Choosing debug options...");
159 target_options.backend =.X64;
160 target_options.output_path = "bin/debug";
161 set_optimization(target_options, Optimization_Type.DEBUG, true);
162 set_build_options(target_options.*, w);
163}
164
165build_release :: (w: Workspace, target_options: *Build_Options) {
166 log("Choosing release options...");
167 target_options.backend = .LLVM;
168 target_options.output_path = "bin/release";
169 set_optimization(target_options, Optimization_Type.VERY_OPTIMIZED);
170 set_build_options(target_options.*, w);
171}
172
173
174args_help_print :: () {
175 help_message := #string _END_
176Usage: jai build.jai - [ARGS]
177
178Options:
179 help Prints this help menu
180 silent Disables compiler/linker statistics
181 run Runs your program afterwards
182 release Builds with release options. If omitted, it builds a debug build.
183
184Passing Args to your Program:
185 If you want to supply args to your program, pass it like that:
186
187 `jai build.jai - run :: my_arg1 foo bar abc ABC`
188
189 Everything after the `::` get's forwarded to your program.
190
191_END_;
192 log(help_message);
193}
194
195compiler_message :: () -> success: bool {
196 while true {
197 message := compiler_wait_for_message();
198 if !message break;
199 if message.kind == {
200 case .COMPLETE;
201 message_complete := cast(*Message_Complete) message;
202 return message_complete.error_code == 0;
203 }
204 }
205 return false;
206}
207
208program_args_collect :: (args: []string, divider: string = "::") -> [..]string {
209 buf: [..]string;
210
211 success, match := array_find(args, divider);
212 if success for i: match+1..args.count-1 array_add(*buf, args[i]);
213
214 return buf;
215}
216
217template_rules_find :: () -> [..]string {
218 templates: [..]string;
219
220 collect_template_files :: (using info: *File_Visit_Info, templates: *[..]string) {
221 if starts_with(short_name, "rules_") && ends_with(short_name, ".jai") {
222 content, success := read_entire_file(full_name);
223
224 if !success {
225 log("Cannot read file: %", full_name);
226 exit(1);
227 }
228
229 array_add(templates, content);
230 }
231 }
232
233 complete := visit_files(
234 TEMPLATE_DIR,
235 recursive = true,
236 *templates, collect_template_files,
237 visit_files = true
238 );
239
240 assert(complete, "Some error occured while traversing the file tree");
241 return templates;
242}
243
244template_rules_inject :: (templates: [..]string, w: Workspace) {
245 count := templates.count;
246
247 inject_proc_body :: () #expand {
248 add_build_string(tprint("TR_EXEC_BUF_MAX :: %;", count), `w);
249
250 sb: String_Builder;
251 init_string_builder(*sb);
252
253 template_arr :: "buf[%1] = #insert,scope(FILE_SCOPE) TEMPLATES_AND_RULES[%2]; ";
254 template_creator :: "buf[%1].template = create_template(buf[%2].template); ";
255
256 for i: 0..count-1 {
257 append(*sb, tprint(template_arr, i, i));
258 append(*sb, tprint(template_creator, i, i));
259 }
260
261 tr_exec_body := builder_to_string(*sb);
262 s := trim(tr_exec_body,, temp);
263
264 add_build_string(tprint("TR_EXEC_BODY :: \"%\";", s), `w);
265 }
266
267 inject_rules_array :: () #expand {
268 sb: String_Builder;
269 init_string_builder(*sb);
270
271 append(*sb, "string.");
272
273 escaped: [..]string;
274 escaped.allocator = temp;
275
276 for templates {
277 array_add(*escaped, replace(it, "\"", "\\\""));
278 }
279
280 append(*sb, tprint("%", escaped));
281 append(*sb, ";");
282
283 s := builder_to_string(*sb);
284 st := trim(s,, temp);
285
286 add_build_string(tprint("TEMPLATES_AND_RULES :: %;", st), `w);
287 }
288
289 inject_proc_body();
290 inject_rules_array();
291}
292
293
294main :: () {}
295
296#run build();
297
298
Copyright 2026  E766CB298A6D1E64 | Git-Thing heavily inspired by cgit