tcbuilder 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +12 -0
- package/dist/tcbuild.d.ts +91 -0
- package/dist/tcbuild.js +567 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
declare global {
|
|
3
|
+
var is_debug: boolean;
|
|
4
|
+
var is_win: boolean;
|
|
5
|
+
var is_linux: boolean;
|
|
6
|
+
var build_dir: string;
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
var build: typeof _build;
|
|
10
|
+
var extExecutable: typeof _extExecutable;
|
|
11
|
+
var extFlags: typeof _extFlags;
|
|
12
|
+
var extSuffix: typeof _extSuffix;
|
|
13
|
+
var extIncludeInFinalOutput: typeof _extIncludeInFinalOutput;
|
|
14
|
+
var srcExecutable: typeof _srcExecutable;
|
|
15
|
+
var srcFlags: typeof _srcFlags;
|
|
16
|
+
var groupFinalFlagsGenCb: typeof _groupFinalFlagsGenCb;
|
|
17
|
+
var groupFinalExecutable: typeof _groupFinalExecutable;
|
|
18
|
+
var groupFinalExecutableSuffix: typeof _groupFinalExecutableSuffix;
|
|
19
|
+
var groupFinalFlags: typeof _groupFinalFlags;
|
|
20
|
+
var groupFinalFlagsInputPattern: typeof _groupFinalFlagsInputPattern;
|
|
21
|
+
var groupFile: typeof _groupFile;
|
|
22
|
+
var group: typeof _group;
|
|
23
|
+
var groupGlob: typeof _groupGlob;
|
|
24
|
+
var needsRebuild: typeof _needsRebuild;
|
|
25
|
+
}
|
|
26
|
+
declare function _build(name?: string, cb?: () => any): Promise<void>;
|
|
27
|
+
type Flags = {
|
|
28
|
+
flag: string;
|
|
29
|
+
sort: number;
|
|
30
|
+
};
|
|
31
|
+
type ExtFlags = Record<string, Flags[]>;
|
|
32
|
+
type StringKeyValue = Record<string, string>;
|
|
33
|
+
type StringKeyBooleanValue = Record<string, boolean>;
|
|
34
|
+
type Group = {
|
|
35
|
+
name: string;
|
|
36
|
+
files: Record<string, {
|
|
37
|
+
executable: string;
|
|
38
|
+
flags: Flags[];
|
|
39
|
+
toBeRemoved: string[];
|
|
40
|
+
includeInFinalOutput: boolean;
|
|
41
|
+
depends: string[];
|
|
42
|
+
extraSuffixes: string[];
|
|
43
|
+
appendFlagsFromExtraSuffixes: boolean;
|
|
44
|
+
outPath?: string | undefined;
|
|
45
|
+
}>;
|
|
46
|
+
extFlags: ExtFlags;
|
|
47
|
+
extExecutable: StringKeyValue;
|
|
48
|
+
extSuffix: StringKeyValue;
|
|
49
|
+
extIncludeInFinalOutput: StringKeyBooleanValue;
|
|
50
|
+
finalFlags: Flags[];
|
|
51
|
+
finalExe: string;
|
|
52
|
+
finalExeSuffix: string;
|
|
53
|
+
finalInputPattern: string;
|
|
54
|
+
finalFlagsGenCb?: ((group: Group, objects: string[], finalFlags: string) => string) | undefined;
|
|
55
|
+
};
|
|
56
|
+
declare function _extExecutable(ext: string | string[], exec?: string): string | undefined;
|
|
57
|
+
declare function _extFlags(ext: string | string[], flag?: string | Flags[], sort?: number): Flags[] | undefined;
|
|
58
|
+
declare function _extSuffix(ext: string | string, suffix?: string): string | undefined;
|
|
59
|
+
declare function _extIncludeInFinalOutput(ext: string | string[], include?: boolean): boolean | undefined;
|
|
60
|
+
declare function _srcExecutable(src: string | string[], exec?: string): string | undefined;
|
|
61
|
+
declare function _srcFlags(src: string | string[], flag?: string | Flags[], sort?: number): Flags[] | undefined;
|
|
62
|
+
declare function _groupFinalFlags(flag: string | string[] | Flags[], sort?: number): Flags[];
|
|
63
|
+
declare function _groupFinalExecutable(exe: string): string;
|
|
64
|
+
declare function _groupFinalExecutableSuffix(suffix: string): string;
|
|
65
|
+
declare function _groupFinalFlagsInputPattern(pattern: string): string;
|
|
66
|
+
declare function _groupFinalFlagsGenCb(cb: Group['finalFlagsGenCb']): ((group: Group, objects: string[], finalFlags: string) => string) | undefined;
|
|
67
|
+
interface groupFileObj {
|
|
68
|
+
appendFlagsFromExtraSuffixes(bool: boolean): groupFileObj;
|
|
69
|
+
setOutPath(path?: string | undefined): groupFileObj;
|
|
70
|
+
setExtraSuffixes(suffixes?: string[]): groupFileObj;
|
|
71
|
+
setDepends(depends: string[]): groupFileObj;
|
|
72
|
+
getFlags(): Flags[];
|
|
73
|
+
setFlags(flags: string | Flags[]): groupFileObj;
|
|
74
|
+
appendFlags(flags?: string | Flags[], sort?: number): groupFileObj;
|
|
75
|
+
getFlagsToBeRemoved(): string[];
|
|
76
|
+
appendFlagsToBeRemoved(flagsToBeRemoved?: string | string[]): groupFileObj;
|
|
77
|
+
getExecutable(): string;
|
|
78
|
+
setExecutable(executable: string): groupFileObj;
|
|
79
|
+
getIncludeInFinalOutput(): boolean;
|
|
80
|
+
setIncludeInFinalOutput(includeInFinalOutput: boolean): groupFileObj;
|
|
81
|
+
}
|
|
82
|
+
declare function _groupFile(fileName: string): groupFileObj;
|
|
83
|
+
declare function _group(name: string | null, fn: () => void): Promise<void>;
|
|
84
|
+
interface groupGlobOptions {
|
|
85
|
+
globOptions?: any;
|
|
86
|
+
callBuildFiles?: boolean;
|
|
87
|
+
cb?: (_: groupFileObj) => void;
|
|
88
|
+
}
|
|
89
|
+
declare function _groupGlob(globXp: string, options?: groupGlobOptions): Promise<void>;
|
|
90
|
+
declare function _needsRebuild(src: string, obj: string, depends: string[]): boolean;
|
|
91
|
+
export {};
|
package/dist/tcbuild.js
ADDED
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
tcbuild - Build system
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2026 Umut Fahri Ozkan
|
|
6
|
+
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU General Public License
|
|
18
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
19
|
+
*/
|
|
20
|
+
import fs from 'node:fs';
|
|
21
|
+
import path from 'node:path';
|
|
22
|
+
import url from 'node:url';
|
|
23
|
+
import { execSync } from 'node:child_process';
|
|
24
|
+
import * as glob from 'glob';
|
|
25
|
+
global.is_debug = process.argv[2] !== 'release';
|
|
26
|
+
global.is_win = process.platform === 'win32';
|
|
27
|
+
global.is_linux = process.platform === 'linux';
|
|
28
|
+
//global.build_dir = `build/${is_debug ? "debug" : "release"}/${platform}`;
|
|
29
|
+
global.build_dir = `build/${is_debug ? 'debug' : 'release'}`;
|
|
30
|
+
//console.info('INFO: Current build mode: ' + (is_debug ? 'debug' : 'release'))
|
|
31
|
+
const contextStack = [];
|
|
32
|
+
async function _build(name = '', cb) {
|
|
33
|
+
let prevStack = contextStack.join('/');
|
|
34
|
+
if (name !== '')
|
|
35
|
+
contextStack.push(name);
|
|
36
|
+
if (cb) {
|
|
37
|
+
cb();
|
|
38
|
+
if (name !== '')
|
|
39
|
+
contextStack.pop();
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
try {
|
|
43
|
+
const file = path.join(process.cwd(), prevStack, name, 'build.js');
|
|
44
|
+
if (!file.startsWith(path.resolve(process.cwd())))
|
|
45
|
+
throw 'Build system outside of own working directory';
|
|
46
|
+
await import(url.pathToFileURL(file).href);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.log("Can't load build.js, is file existing?");
|
|
50
|
+
throw e;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
if (name !== '')
|
|
54
|
+
contextStack.pop();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
global.build = _build;
|
|
59
|
+
const globalExtExecutable = {};
|
|
60
|
+
const globalExtFlags = {};
|
|
61
|
+
const globalExtSuffix = {};
|
|
62
|
+
const globalExtIncludeInFinalOutput = {};
|
|
63
|
+
const globalSrcExecutable = {};
|
|
64
|
+
const globalSrcFlags = {};
|
|
65
|
+
const groups = {};
|
|
66
|
+
let currentGroup = null;
|
|
67
|
+
//
|
|
68
|
+
function _extExecutable(ext, exec) {
|
|
69
|
+
if (Array.isArray(ext)) {
|
|
70
|
+
for (const ex of ext)
|
|
71
|
+
extExecutable(ex, exec);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
let assign = globalExtExecutable;
|
|
75
|
+
if (currentGroup !== null)
|
|
76
|
+
assign = currentGroup.extExecutable;
|
|
77
|
+
if (exec)
|
|
78
|
+
assign[ext] = exec;
|
|
79
|
+
return assign[ext] ?? '';
|
|
80
|
+
}
|
|
81
|
+
global.extExecutable = _extExecutable;
|
|
82
|
+
function _extFlags(ext, flag, sort = 0) {
|
|
83
|
+
if (Array.isArray(ext)) {
|
|
84
|
+
for (const ex of ext)
|
|
85
|
+
extFlags(ex, flag, sort);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
let assign = globalExtFlags;
|
|
89
|
+
if (currentGroup !== null)
|
|
90
|
+
assign = currentGroup.extFlags;
|
|
91
|
+
if (flag && flag.length > 0) {
|
|
92
|
+
if (!assign[ext])
|
|
93
|
+
assign[ext] = [];
|
|
94
|
+
if (Array.isArray(flag)) {
|
|
95
|
+
assign[ext].push(...flag);
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
assign[ext].push({ flag, sort });
|
|
99
|
+
}
|
|
100
|
+
return assign[ext];
|
|
101
|
+
}
|
|
102
|
+
global.extFlags = _extFlags;
|
|
103
|
+
function _extSuffix(ext, suffix) {
|
|
104
|
+
if (Array.isArray(ext)) {
|
|
105
|
+
for (const ex of ext)
|
|
106
|
+
extSuffix(ex, suffix);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
let assign = globalExtSuffix;
|
|
110
|
+
if (currentGroup !== null)
|
|
111
|
+
assign = currentGroup.extSuffix;
|
|
112
|
+
if (suffix)
|
|
113
|
+
assign[ext] = suffix;
|
|
114
|
+
return assign[ext] ?? '';
|
|
115
|
+
}
|
|
116
|
+
global.extSuffix = _extSuffix;
|
|
117
|
+
function _extIncludeInFinalOutput(ext, include) {
|
|
118
|
+
if (Array.isArray(ext)) {
|
|
119
|
+
for (const ex of ext)
|
|
120
|
+
extIncludeInFinalOutput(ex, include);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
let assign = globalExtIncludeInFinalOutput;
|
|
124
|
+
if (currentGroup !== null)
|
|
125
|
+
assign = currentGroup.extIncludeInFinalOutput;
|
|
126
|
+
if (include !== undefined)
|
|
127
|
+
assign[ext] = include;
|
|
128
|
+
return assign[ext] ?? true;
|
|
129
|
+
}
|
|
130
|
+
global.extIncludeInFinalOutput = _extIncludeInFinalOutput;
|
|
131
|
+
function _srcExecutable(src, exec) {
|
|
132
|
+
if (Array.isArray(src)) {
|
|
133
|
+
for (const sr of src)
|
|
134
|
+
srcExecutable(sr, exec);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (currentGroup !== null)
|
|
138
|
+
throw 'src function called inside group';
|
|
139
|
+
const srcName = contextStack.join('/') + (contextStack.length > 0 ? '/' : '') + src;
|
|
140
|
+
if (exec)
|
|
141
|
+
globalSrcExecutable[srcName] = exec;
|
|
142
|
+
return globalSrcExecutable[srcName] ?? '';
|
|
143
|
+
}
|
|
144
|
+
global.srcExecutable = _srcExecutable;
|
|
145
|
+
function _srcFlags(src, flag, sort = 0) {
|
|
146
|
+
if (Array.isArray(src)) {
|
|
147
|
+
for (const sr of src)
|
|
148
|
+
srcFlags(sr, flag, sort);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (currentGroup !== null)
|
|
152
|
+
throw 'src function called inside group';
|
|
153
|
+
const srcName = contextStack.join('/') + (contextStack.length > 0 ? '/' : '') + src;
|
|
154
|
+
if (flag && flag.length > 0) {
|
|
155
|
+
if (!globalSrcFlags[srcName])
|
|
156
|
+
globalSrcFlags[srcName] = [];
|
|
157
|
+
if (Array.isArray(flag)) {
|
|
158
|
+
globalSrcFlags[srcName].push(...flag);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
globalSrcFlags[srcName].push({ flag, sort });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return globalSrcFlags[srcName];
|
|
165
|
+
}
|
|
166
|
+
global.srcFlags = _srcFlags;
|
|
167
|
+
function _groupFinalFlags(flag,
|
|
168
|
+
/*toBeRemoved: string | string[],*/ sort = 0) {
|
|
169
|
+
if (!currentGroup)
|
|
170
|
+
throw 'any group function called outside of group';
|
|
171
|
+
if (flag) {
|
|
172
|
+
if (flag.length > 0) {
|
|
173
|
+
if (Array.isArray(flag)) {
|
|
174
|
+
for (const subEl of flag) {
|
|
175
|
+
if (typeof subEl === 'string') {
|
|
176
|
+
currentGroup.finalFlags.push({ flag: subEl, sort });
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
currentGroup.finalFlags.push(subEl);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
currentGroup.finalFlags.push({ flag, sort });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/*
|
|
188
|
+
if (toBeRemoved) {
|
|
189
|
+
if (typeof toBeRemoved === 'string') currentGroup.finalFlagsToBeRemoved.push(toBeRemoved)
|
|
190
|
+
else if (Array.isArray(toBeRemoved)) {
|
|
191
|
+
currentGroup.finalFlagsToBeRemoved.push(...toBeRemoved)
|
|
192
|
+
} else {
|
|
193
|
+
throw 'What are you doing? ' + typeof toBeRemoved
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
*/
|
|
197
|
+
}
|
|
198
|
+
return currentGroup.finalFlags;
|
|
199
|
+
}
|
|
200
|
+
global.groupFinalFlags = _groupFinalFlags;
|
|
201
|
+
function _groupFinalExecutable(exe) {
|
|
202
|
+
if (!currentGroup)
|
|
203
|
+
throw 'any group function called outside of group';
|
|
204
|
+
if (exe)
|
|
205
|
+
currentGroup.finalExe = exe;
|
|
206
|
+
return currentGroup.finalExe;
|
|
207
|
+
}
|
|
208
|
+
global.groupFinalExecutable = _groupFinalExecutable;
|
|
209
|
+
function _groupFinalExecutableSuffix(suffix) {
|
|
210
|
+
if (!currentGroup)
|
|
211
|
+
throw 'any group function called outside of group';
|
|
212
|
+
if (suffix)
|
|
213
|
+
currentGroup.finalExeSuffix = suffix;
|
|
214
|
+
return currentGroup.finalExeSuffix;
|
|
215
|
+
}
|
|
216
|
+
global.groupFinalExecutableSuffix = _groupFinalExecutableSuffix;
|
|
217
|
+
function _groupFinalFlagsInputPattern(pattern) {
|
|
218
|
+
if (!currentGroup)
|
|
219
|
+
throw 'any group function called outside of group';
|
|
220
|
+
if (pattern)
|
|
221
|
+
currentGroup.finalInputPattern = pattern;
|
|
222
|
+
return currentGroup.finalInputPattern;
|
|
223
|
+
}
|
|
224
|
+
global.groupFinalFlagsInputPattern = _groupFinalFlagsInputPattern;
|
|
225
|
+
function _groupFinalFlagsGenCb(cb) {
|
|
226
|
+
if (!currentGroup)
|
|
227
|
+
throw 'any group function called outside of group';
|
|
228
|
+
if (cb)
|
|
229
|
+
currentGroup.finalFlagsGenCb = cb;
|
|
230
|
+
return currentGroup.finalFlagsGenCb;
|
|
231
|
+
}
|
|
232
|
+
global.groupFinalFlagsGenCb = _groupFinalFlagsGenCb;
|
|
233
|
+
function _groupFile(fileName) {
|
|
234
|
+
if (!currentGroup)
|
|
235
|
+
throw 'any group function called outside of group';
|
|
236
|
+
const file = contextStack.join('/') + (contextStack.length > 0 ? '/' : '') + fileName;
|
|
237
|
+
if (!path.resolve(path.join(process.cwd(), file)).startsWith(path.resolve(process.cwd())))
|
|
238
|
+
throw 'Build system outside of own working directory';
|
|
239
|
+
let currentGroupFile = currentGroup.files[file];
|
|
240
|
+
if (!currentGroupFile) {
|
|
241
|
+
currentGroup.files[file] = currentGroupFile = {
|
|
242
|
+
executable: '',
|
|
243
|
+
flags: [],
|
|
244
|
+
toBeRemoved: [],
|
|
245
|
+
includeInFinalOutput: true,
|
|
246
|
+
depends: [],
|
|
247
|
+
extraSuffixes: [],
|
|
248
|
+
appendFlagsFromExtraSuffixes: false
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const self = {
|
|
252
|
+
appendFlagsFromExtraSuffixes(bool) {
|
|
253
|
+
currentGroupFile.appendFlagsFromExtraSuffixes = bool;
|
|
254
|
+
return self;
|
|
255
|
+
},
|
|
256
|
+
setExtraSuffixes(suffixes) {
|
|
257
|
+
if (suffixes)
|
|
258
|
+
currentGroupFile.extraSuffixes = suffixes;
|
|
259
|
+
return self;
|
|
260
|
+
},
|
|
261
|
+
setOutPath: path => {
|
|
262
|
+
currentGroupFile.outPath = path;
|
|
263
|
+
return self;
|
|
264
|
+
},
|
|
265
|
+
setDepends: depends => {
|
|
266
|
+
currentGroupFile.depends = depends;
|
|
267
|
+
return self;
|
|
268
|
+
},
|
|
269
|
+
getFlags: () => {
|
|
270
|
+
return currentGroupFile.flags;
|
|
271
|
+
},
|
|
272
|
+
setFlags: (flag, sort = 0) => {
|
|
273
|
+
if (flag && flag.length > 0) {
|
|
274
|
+
if (Array.isArray(flag)) {
|
|
275
|
+
currentGroupFile.flags = flag;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
currentGroupFile.flags = [{ flag, sort }];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return self;
|
|
282
|
+
},
|
|
283
|
+
appendFlags: (flag, sort = 0) => {
|
|
284
|
+
if (flag && flag.length > 0) {
|
|
285
|
+
if (Array.isArray(flag)) {
|
|
286
|
+
currentGroupFile.flags.push(...flag);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
currentGroupFile.flags.push({ flag, sort });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return self;
|
|
293
|
+
},
|
|
294
|
+
getFlagsToBeRemoved: () => {
|
|
295
|
+
return currentGroupFile.toBeRemoved;
|
|
296
|
+
},
|
|
297
|
+
appendFlagsToBeRemoved: flagsToBeRemoved => {
|
|
298
|
+
if (flagsToBeRemoved && flagsToBeRemoved.length > 0) {
|
|
299
|
+
if (typeof flagsToBeRemoved === 'string')
|
|
300
|
+
currentGroupFile.toBeRemoved.push(flagsToBeRemoved);
|
|
301
|
+
else if (Array.isArray(flagsToBeRemoved)) {
|
|
302
|
+
currentGroupFile.toBeRemoved.push(...flagsToBeRemoved);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return self;
|
|
306
|
+
},
|
|
307
|
+
getExecutable: () => {
|
|
308
|
+
return currentGroupFile.executable;
|
|
309
|
+
},
|
|
310
|
+
setExecutable: executable => {
|
|
311
|
+
if (executable != undefined)
|
|
312
|
+
currentGroupFile.executable = executable;
|
|
313
|
+
return self;
|
|
314
|
+
},
|
|
315
|
+
getIncludeInFinalOutput: () => {
|
|
316
|
+
return currentGroupFile.includeInFinalOutput;
|
|
317
|
+
},
|
|
318
|
+
setIncludeInFinalOutput: includeInFinalOutput => {
|
|
319
|
+
if (includeInFinalOutput !== undefined)
|
|
320
|
+
currentGroupFile.includeInFinalOutput = includeInFinalOutput;
|
|
321
|
+
return self;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
return self;
|
|
325
|
+
}
|
|
326
|
+
global.groupFile = _groupFile;
|
|
327
|
+
async function _group(name, fn) {
|
|
328
|
+
if (name && !groups[name])
|
|
329
|
+
groups[name] = {
|
|
330
|
+
name,
|
|
331
|
+
files: {},
|
|
332
|
+
extFlags: {},
|
|
333
|
+
extExecutable: {},
|
|
334
|
+
extSuffix: {},
|
|
335
|
+
extIncludeInFinalOutput: {},
|
|
336
|
+
finalFlags: [],
|
|
337
|
+
//finalFlagsToBeRemoved: [],
|
|
338
|
+
finalExe: '',
|
|
339
|
+
finalExeSuffix: '',
|
|
340
|
+
finalInputPattern: '{in}'
|
|
341
|
+
};
|
|
342
|
+
if (!name) {
|
|
343
|
+
currentGroup = null;
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
let oldGroup = currentGroup;
|
|
347
|
+
currentGroup = groups[name] ?? null;
|
|
348
|
+
if (typeof fn === 'function') {
|
|
349
|
+
await fn();
|
|
350
|
+
currentGroup = oldGroup;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
global.group = _group;
|
|
354
|
+
async function _groupGlob(globXp, options) {
|
|
355
|
+
if (!currentGroup)
|
|
356
|
+
throw 'any group function called outside of group';
|
|
357
|
+
const globbed = glob.globSync(globXp, { cwd: contextStack.join('/'), ...options?.globOptions });
|
|
358
|
+
for (let realGlobPath of globbed) {
|
|
359
|
+
const globPath = path.join(contextStack.join('/'), realGlobPath);
|
|
360
|
+
if (!fs.statSync(path.join(process.cwd(), globPath)).isFile())
|
|
361
|
+
continue;
|
|
362
|
+
if (!path.join(process.cwd(), globPath).startsWith(path.resolve(process.cwd())))
|
|
363
|
+
console.error('glob outside of working directory: ' + globPath);
|
|
364
|
+
if (globPath.endsWith('/build.js')) {
|
|
365
|
+
if (options?.callBuildFiles === true)
|
|
366
|
+
await build(path.dirname(realGlobPath));
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
if (options?.cb) {
|
|
370
|
+
options?.cb(groupFile(realGlobPath));
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
groupFile(realGlobPath);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
global.groupGlob = _groupGlob;
|
|
379
|
+
function _import(fromName, toName, deleteOldOne = true) {
|
|
380
|
+
if (!(typeof fromName === 'string' &&
|
|
381
|
+
fromName.length > 0 &&
|
|
382
|
+
typeof toName === 'string' &&
|
|
383
|
+
toName.length > 0))
|
|
384
|
+
throw 'import function got invalid arguments';
|
|
385
|
+
const from = groups[fromName];
|
|
386
|
+
const to = groups[toName];
|
|
387
|
+
/*
|
|
388
|
+
local temp
|
|
389
|
+
|
|
390
|
+
temp="build_${from}_final_flags"
|
|
391
|
+
declare -g "build_${to}_final_flags+= ${!temp}"
|
|
392
|
+
|
|
393
|
+
for v in $(compgen -v "build_${from}_ext_"); do
|
|
394
|
+
if [[ "$v" == *_flags ]]; then
|
|
395
|
+
declare -g "${v/build_${from}_ext_/build_${to}_ext_}+=${!v:+ ${!v}}"
|
|
396
|
+
fi
|
|
397
|
+
if [[ "$v" == *_exe ]]; then
|
|
398
|
+
declare -g "${v/build_${from}_ext_/build_${to}_ext_}="
|
|
399
|
+
fi
|
|
400
|
+
declare -g "${v}="
|
|
401
|
+
done
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
temp="build_${from}_sources"
|
|
405
|
+
for source in ${!temp}; do
|
|
406
|
+
declare -g "build_${to}_sources+= $source"
|
|
407
|
+
source="${source//[\/.]/_}"
|
|
408
|
+
temp="build_${from}_src_${source}_flags"
|
|
409
|
+
declare -g "build_${to}_src_${source}_flags+= ${!temp}"
|
|
410
|
+
|
|
411
|
+
declare -g "build_${from}_src_${source}_exe="
|
|
412
|
+
declare -g "build_${from}_src_${source}_flags="
|
|
413
|
+
done
|
|
414
|
+
|
|
415
|
+
declare -g "build_${from}_sources="
|
|
416
|
+
declare -g "build_${from}_final_exe="
|
|
417
|
+
declare -g "build_${from}_final_flags="
|
|
418
|
+
|
|
419
|
+
temp="build_groups"
|
|
420
|
+
declare -g "build_groups=${!temp//${from}/}"
|
|
421
|
+
*/
|
|
422
|
+
}
|
|
423
|
+
//global.build = _build
|
|
424
|
+
build(); // Now build the tree
|
|
425
|
+
// #endregion
|
|
426
|
+
// #region Runtime
|
|
427
|
+
function _needsRebuild(src, obj, depends) {
|
|
428
|
+
if (!fs.existsSync(src))
|
|
429
|
+
throw new Error(`${src} does not existis!`);
|
|
430
|
+
if (!fs.existsSync(obj))
|
|
431
|
+
return true;
|
|
432
|
+
const srcTime = fs.statSync(src).mtimeMs;
|
|
433
|
+
const objTime = fs.statSync(obj).mtimeMs;
|
|
434
|
+
if (srcTime > objTime)
|
|
435
|
+
return true;
|
|
436
|
+
{
|
|
437
|
+
const dep = obj + '.d';
|
|
438
|
+
if (fs.existsSync(dep)) {
|
|
439
|
+
const depText = fs
|
|
440
|
+
.readFileSync(dep, 'utf-8')
|
|
441
|
+
.toString()
|
|
442
|
+
.replace(/\\\r?\n/g, ' ');
|
|
443
|
+
const depColon = depText.indexOf(':');
|
|
444
|
+
if (depColon !== -1) {
|
|
445
|
+
const deps = depText
|
|
446
|
+
.slice(depColon + 1)
|
|
447
|
+
.trim()
|
|
448
|
+
.split(/\s+/)
|
|
449
|
+
.filter(Boolean);
|
|
450
|
+
for (const dep of deps) {
|
|
451
|
+
if (!fs.existsSync(dep))
|
|
452
|
+
return true;
|
|
453
|
+
if (fs.statSync(dep).mtimeMs > objTime)
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (depends) {
|
|
460
|
+
if (Array.isArray(depends) && depends.length > 0) {
|
|
461
|
+
for (const dep of depends) {
|
|
462
|
+
if (!fs.existsSync(dep))
|
|
463
|
+
return true;
|
|
464
|
+
if (fs.statSync(dep).mtimeMs > objTime)
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
global.needsRebuild = _needsRebuild;
|
|
472
|
+
function linkNeedsRebuild(output, objects) {
|
|
473
|
+
output = path.join(process.cwd(), output);
|
|
474
|
+
if (!fs.existsSync(output))
|
|
475
|
+
return true;
|
|
476
|
+
const outputTime = fs.statSync(output).mtimeMs;
|
|
477
|
+
for (const obj of objects) {
|
|
478
|
+
if (fs.statSync(path.join(process.cwd(), obj)).mtimeMs > outputTime)
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
function findExecutable(map, exts, depth = -1) {
|
|
484
|
+
const ext = exts.at(depth);
|
|
485
|
+
if (ext === undefined) {
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
return map[ext] ?? findExecutable(map, exts, depth - 1);
|
|
489
|
+
}
|
|
490
|
+
const noSuffix = Symbol();
|
|
491
|
+
process.once('beforeExit', async () => {
|
|
492
|
+
fs.mkdirSync(path.dirname(path.join(process.cwd(), build_dir)), { recursive: true });
|
|
493
|
+
const compileCommandsFiles = [];
|
|
494
|
+
for (const [name, group] of Object.entries(groups)) {
|
|
495
|
+
const objects = [];
|
|
496
|
+
for (const [fileName, file] of Object.entries(group.files)) {
|
|
497
|
+
const fileExts = fileName.split('.').slice(1);
|
|
498
|
+
const suffix = findExecutable(group.extSuffix, fileExts) ?? findExecutable(globalExtSuffix, fileExts);
|
|
499
|
+
for (const extraSuffix of file.extraSuffixes.length > 0 ? file.extraSuffixes : [noSuffix]) {
|
|
500
|
+
const obj = file.outPath ??
|
|
501
|
+
`${build_dir}/${fileName}${extraSuffix === noSuffix ? '' : `.${extraSuffix.toString()}`}${suffix ? `.${suffix}` : ''}`;
|
|
502
|
+
if ((file.includeInFinalOutput ||
|
|
503
|
+
findExecutable(group.extIncludeInFinalOutput, fileExts) ||
|
|
504
|
+
findExecutable(globalExtIncludeInFinalOutput, fileExts)) === true)
|
|
505
|
+
objects.push(obj);
|
|
506
|
+
if (needsRebuild(path.join(process.cwd(), fileName), path.join(process.cwd(), obj), file.depends)) {
|
|
507
|
+
fs.mkdirSync(path.dirname(path.join(process.cwd(), obj)), { recursive: true });
|
|
508
|
+
const flagsArray = [];
|
|
509
|
+
flagsArray.push(...(globalSrcFlags[fileName] ?? []));
|
|
510
|
+
flagsArray.push(...(file.flags ?? []));
|
|
511
|
+
for (const ext of fileExts.concat(file.appendFlagsFromExtraSuffixes ? file.extraSuffixes : [])) {
|
|
512
|
+
if (ext.length > 0) {
|
|
513
|
+
flagsArray.push(...(globalExtFlags[ext] ?? []));
|
|
514
|
+
flagsArray.push(...(group.extFlags[ext] ?? []));
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
let objFlags = flagsArray
|
|
518
|
+
.sort((a, b) => a.sort - b.sort)
|
|
519
|
+
.map(x => x.flag)
|
|
520
|
+
.join(' ');
|
|
521
|
+
if (file.toBeRemoved.length > 0)
|
|
522
|
+
for (const remove of file.toBeRemoved)
|
|
523
|
+
objFlags = objFlags.replaceAll(remove, '');
|
|
524
|
+
const executable = (file.executable.length > 0 ? file.executable : undefined) ||
|
|
525
|
+
globalSrcExecutable[fileName] ||
|
|
526
|
+
findExecutable(group.extExecutable, fileExts) ||
|
|
527
|
+
findExecutable(globalExtExecutable, fileExts);
|
|
528
|
+
const cmd = `${executable} ${objFlags.replaceAll('{FILE_NAME}', fileName.toUpperCase().replaceAll('/', '_').replaceAll('.', '_')).replaceAll('{in}', fileName).replaceAll('{out}', obj)}`; // out and input handling
|
|
529
|
+
if (!executable) {
|
|
530
|
+
console.log(fileName + ' skipped due to wrong configuration');
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
console.log(cmd);
|
|
534
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
535
|
+
}
|
|
536
|
+
if (fs.existsSync(obj + '_compile_commands.json'))
|
|
537
|
+
compileCommandsFiles.push(obj + '_compile_commands.json');
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const finalOutName = `${build_dir}/${name}${group.finalExeSuffix ? `.${group.finalExeSuffix}` : ``}`;
|
|
541
|
+
if (group.finalExe.length > 0 && linkNeedsRebuild(finalOutName, objects)) {
|
|
542
|
+
let finalFlags = group.finalFlags
|
|
543
|
+
.sort((a, b) => a.sort - b.sort)
|
|
544
|
+
.map(x => x.flag)
|
|
545
|
+
.join(' ');
|
|
546
|
+
/*if (group.finalFlagsToBeRemoved.length > 0)
|
|
547
|
+
for (const remove of group.finalFlagsToBeRemoved)
|
|
548
|
+
finalFlags = finalFlags.replaceAll(remove, '')*/
|
|
549
|
+
const cmd = `${group.finalExe} ${(group.finalFlagsGenCb ? group.finalFlagsGenCb(group, objects, finalFlags) : finalFlags).replaceAll('{out}', finalOutName).replaceAll('{in}', objects.map(x => group.finalInputPattern.replaceAll('{in}', x)).join(' '))}`;
|
|
550
|
+
console.log(cmd);
|
|
551
|
+
execSync(cmd, {
|
|
552
|
+
stdio: 'inherit'
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (compileCommandsFiles.length > 0) {
|
|
557
|
+
let compileCommands = '[';
|
|
558
|
+
for (const file of compileCommandsFiles)
|
|
559
|
+
compileCommands += fs.readFileSync(file);
|
|
560
|
+
compileCommands += ']';
|
|
561
|
+
fs.writeFileSync(path.join(process.cwd(), build_dir, 'compile_commands.json'), compileCommands);
|
|
562
|
+
}
|
|
563
|
+
// @ts-ignore
|
|
564
|
+
if (global['post_compile'])
|
|
565
|
+
post_compile();
|
|
566
|
+
});
|
|
567
|
+
// #endregion
|