emsdk-env 0.7.0 → 0.9.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/README.md +39 -3
- package/dist/{build-Btgi1orl.js → build-BOZTStIM.js} +505 -19
- package/dist/build-BOZTStIM.js.map +1 -0
- package/dist/{build-CjKDHGn4.cjs → build-CgmcFNSR.cjs} +503 -17
- package/dist/build-CgmcFNSR.cjs.map +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.d.ts +59 -8
- package/dist/index.mjs +3 -3
- package/dist/vite.cjs +7 -5
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.ts +49 -8
- package/dist/vite.mjs +7 -5
- package/dist/vite.mjs.map +1 -1
- package/package.json +7 -7
- package/dist/build-Btgi1orl.js.map +0 -1
- package/dist/build-CjKDHGn4.cjs.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* name: emsdk-env
|
|
3
|
-
* version: 0.
|
|
3
|
+
* version: 0.9.0
|
|
4
4
|
* description: Emscripten environment builder
|
|
5
5
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
6
6
|
* license: MIT
|
|
7
7
|
* repository.url: https://github.com/kekyo/emsdk-env
|
|
8
|
-
* git.commit.hash:
|
|
8
|
+
* git.commit.hash: 73d7e217903f020ef22daa9289362dcd19bddac1
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { mkdir, access, constants, mkdtemp, rename, rm, readFile } from "fs/promises";
|
|
11
|
+
import { mkdir, access, constants, mkdtemp, rename, rm, writeFile, readFile } from "fs/promises";
|
|
12
12
|
import { homedir, tmpdir } from "os";
|
|
13
13
|
import { glob } from "glob";
|
|
14
|
-
import { join, resolve, isAbsolute, dirname,
|
|
14
|
+
import { join, resolve, relative, isAbsolute, dirname, parse } from "path";
|
|
15
15
|
import { spawn } from "child_process";
|
|
16
16
|
const __NOOP_HANDLER = () => {
|
|
17
17
|
};
|
|
@@ -552,6 +552,11 @@ const DEFAULT_IMPORT_LIB_DIR = "lib";
|
|
|
552
552
|
const DEFAULT_WASM_BUILD_DIR = join(tmpdir(), "emsdk-env");
|
|
553
553
|
const DEFAULT_EMSDK_TARGET_VERSION = "latest";
|
|
554
554
|
const DEFAULT_WASM_OPT_ARGS = ["-Oz"];
|
|
555
|
+
const DEFAULT_GENERATED_LOADER_OUT_FILE = join(
|
|
556
|
+
"src",
|
|
557
|
+
"generated",
|
|
558
|
+
"wasm-loader.ts"
|
|
559
|
+
);
|
|
555
560
|
let buildSequence = 0;
|
|
556
561
|
const padNumber = (value, length = 2) => String(value).padStart(length, "0");
|
|
557
562
|
const formatTimestamp = (date) => {
|
|
@@ -578,9 +583,53 @@ const normalizePrepareOptions = (options) => {
|
|
|
578
583
|
...rest
|
|
579
584
|
};
|
|
580
585
|
};
|
|
586
|
+
const parseStringKeyValueInput = (values) => {
|
|
587
|
+
const parsed = {};
|
|
588
|
+
for (const entry of values) {
|
|
589
|
+
const index = entry.indexOf("=");
|
|
590
|
+
if (index === -1) {
|
|
591
|
+
parsed[entry] = void 0;
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
const key = entry.slice(0, index);
|
|
595
|
+
const value = entry.slice(index + 1);
|
|
596
|
+
parsed[key] = value;
|
|
597
|
+
}
|
|
598
|
+
return parsed;
|
|
599
|
+
};
|
|
600
|
+
const isDefineMap = (input) => input instanceof Map;
|
|
601
|
+
const normalizeDefineInput = (input) => {
|
|
602
|
+
if (!input) {
|
|
603
|
+
return {};
|
|
604
|
+
}
|
|
605
|
+
if (Array.isArray(input)) {
|
|
606
|
+
return parseStringKeyValueInput(input);
|
|
607
|
+
}
|
|
608
|
+
if (isDefineMap(input)) {
|
|
609
|
+
return Object.fromEntries(input);
|
|
610
|
+
}
|
|
611
|
+
return { ...input };
|
|
612
|
+
};
|
|
613
|
+
const isLinkDirectiveMap = (input) => input instanceof Map;
|
|
614
|
+
const normalizeLinkDirectiveInput = (input) => {
|
|
615
|
+
if (!input) {
|
|
616
|
+
return {};
|
|
617
|
+
}
|
|
618
|
+
if (Array.isArray(input)) {
|
|
619
|
+
return parseStringKeyValueInput(input);
|
|
620
|
+
}
|
|
621
|
+
if (isLinkDirectiveMap(input)) {
|
|
622
|
+
return Object.fromEntries(input);
|
|
623
|
+
}
|
|
624
|
+
return { ...input };
|
|
625
|
+
};
|
|
581
626
|
const mergeDefines = (common, target) => ({
|
|
582
|
-
...common
|
|
583
|
-
...target
|
|
627
|
+
...normalizeDefineInput(common),
|
|
628
|
+
...normalizeDefineInput(target)
|
|
629
|
+
});
|
|
630
|
+
const mergeLinkDirectives = (common, target) => ({
|
|
631
|
+
...normalizeLinkDirectiveInput(common),
|
|
632
|
+
...normalizeLinkDirectiveInput(target)
|
|
584
633
|
});
|
|
585
634
|
const resolveWasmOptEnabled = (common, target) => {
|
|
586
635
|
var _a, _b;
|
|
@@ -588,10 +637,62 @@ const resolveWasmOptEnabled = (common, target) => {
|
|
|
588
637
|
};
|
|
589
638
|
const resolveWasmOptArgs = (common, target, env) => {
|
|
590
639
|
var _a, _b;
|
|
591
|
-
const commonArgs = (_a = common == null ? void 0 : common.
|
|
592
|
-
const targetArgs = (_b = target == null ? void 0 : target.
|
|
640
|
+
const commonArgs = (_a = common == null ? void 0 : common.options) != null ? _a : DEFAULT_WASM_OPT_ARGS;
|
|
641
|
+
const targetArgs = (_b = target == null ? void 0 : target.options) != null ? _b : [];
|
|
593
642
|
const mergedArgs = [...commonArgs, ...targetArgs];
|
|
594
|
-
return expandArray(mergedArgs, env, "wasmOpt.
|
|
643
|
+
return expandArray(mergedArgs, env, "wasmOpt.options");
|
|
644
|
+
};
|
|
645
|
+
const stripOuterQuotes = (value) => {
|
|
646
|
+
const trimmed = value.trim();
|
|
647
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
648
|
+
return trimmed.slice(1, -1);
|
|
649
|
+
}
|
|
650
|
+
return trimmed;
|
|
651
|
+
};
|
|
652
|
+
const extractWasmBinaryFile = (value) => {
|
|
653
|
+
if (value.startsWith("WASM_BINARY_FILE=")) {
|
|
654
|
+
return value.slice("WASM_BINARY_FILE=".length);
|
|
655
|
+
}
|
|
656
|
+
const match = value.match(/^(?:-s|--settings)(?:=)?WASM_BINARY_FILE=(.+)$/);
|
|
657
|
+
if (match) {
|
|
658
|
+
return match[1];
|
|
659
|
+
}
|
|
660
|
+
return void 0;
|
|
661
|
+
};
|
|
662
|
+
const resolveWasmBinaryFileFromLinkOptions = (linkOptions) => {
|
|
663
|
+
for (let index = 0; index < linkOptions.length; index += 1) {
|
|
664
|
+
const option = linkOptions[index];
|
|
665
|
+
if (!option) {
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
if (option === "-s" || option === "--settings") {
|
|
669
|
+
const next = linkOptions[index + 1];
|
|
670
|
+
if (!next) {
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
const extracted2 = extractWasmBinaryFile(next);
|
|
674
|
+
if (extracted2) {
|
|
675
|
+
return stripOuterQuotes(extracted2);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const extracted = extractWasmBinaryFile(option);
|
|
679
|
+
if (extracted) {
|
|
680
|
+
return stripOuterQuotes(extracted);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return void 0;
|
|
684
|
+
};
|
|
685
|
+
const resolveWasmOptInputFile = (resolvedOutFile, resolvedLinkOptions) => {
|
|
686
|
+
const wasmBinaryFile = resolveWasmBinaryFileFromLinkOptions(resolvedLinkOptions);
|
|
687
|
+
if (wasmBinaryFile) {
|
|
688
|
+
return isAbsolute(wasmBinaryFile) ? wasmBinaryFile : resolve(dirname(resolvedOutFile), wasmBinaryFile);
|
|
689
|
+
}
|
|
690
|
+
const parsed = parse(resolvedOutFile);
|
|
691
|
+
if (parsed.ext.toLowerCase() === ".wasm") {
|
|
692
|
+
return resolvedOutFile;
|
|
693
|
+
}
|
|
694
|
+
const baseName = parsed.name.toLowerCase().endsWith(".wasm") ? parsed.name : `${parsed.name}.wasm`;
|
|
695
|
+
return join(parsed.dir, baseName);
|
|
595
696
|
};
|
|
596
697
|
const resolvePath = (rootDir, value) => isAbsolute(value) ? value : resolve(rootDir, value);
|
|
597
698
|
const expandPlaceholders = (value, env, label) => value.replace(/\{([A-Z0-9_]+)\}/g, (_match, key) => {
|
|
@@ -613,6 +714,28 @@ const resolveDefines = (defines, env) => {
|
|
|
613
714
|
}
|
|
614
715
|
return resolved;
|
|
615
716
|
};
|
|
717
|
+
const resolveLinkDirectiveValue = (value, env, label) => {
|
|
718
|
+
if (typeof value === "string") {
|
|
719
|
+
return expandPlaceholders(value, env, label);
|
|
720
|
+
}
|
|
721
|
+
if (Array.isArray(value)) {
|
|
722
|
+
return value.map(
|
|
723
|
+
(entry, index) => expandPlaceholders(entry, env, `${label}[${index}]`)
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
return value;
|
|
727
|
+
};
|
|
728
|
+
const resolveLinkDirectives = (directives, env) => {
|
|
729
|
+
const resolved = {};
|
|
730
|
+
for (const [key, value] of Object.entries(directives)) {
|
|
731
|
+
resolved[key] = resolveLinkDirectiveValue(
|
|
732
|
+
value,
|
|
733
|
+
env,
|
|
734
|
+
`linkDirectives.${key}`
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
return resolved;
|
|
738
|
+
};
|
|
616
739
|
const resolveIncludeDirs = (includeDirs, env, rootDir) => {
|
|
617
740
|
const expanded = expandArray(includeDirs, env, "includeDirs");
|
|
618
741
|
return expanded.map((value) => resolvePath(rootDir, value));
|
|
@@ -631,7 +754,18 @@ const resolveSourcesFromPatterns = async (patterns, env, srcDir, label) => {
|
|
|
631
754
|
sources.sort();
|
|
632
755
|
return sources;
|
|
633
756
|
};
|
|
634
|
-
const buildDefineFlags = (defines) => Object.entries(defines).
|
|
757
|
+
const buildDefineFlags = (defines) => Object.entries(defines).flatMap(
|
|
758
|
+
([key, value]) => value === null || value === void 0 ? [`-D${key}`] : [`-D${key}=${String(value)}`]
|
|
759
|
+
);
|
|
760
|
+
const serializeLinkDirectiveValue = (value) => Array.isArray(value) ? JSON.stringify(value) : String(value);
|
|
761
|
+
const buildLinkDirectiveFlags = (directives) => {
|
|
762
|
+
if (Object.keys(directives).length === 0) {
|
|
763
|
+
return [];
|
|
764
|
+
}
|
|
765
|
+
return Object.entries(directives).flatMap(
|
|
766
|
+
([key, value]) => value === null || value === void 0 ? ["-s", key] : ["-s", `${key}=${serializeLinkDirectiveValue(value)}`]
|
|
767
|
+
);
|
|
768
|
+
};
|
|
635
769
|
const buildExportFlags = (exports$1) => {
|
|
636
770
|
if (exports$1.length === 0) {
|
|
637
771
|
return [];
|
|
@@ -684,6 +818,248 @@ const dedupeValues = (values) => {
|
|
|
684
818
|
}
|
|
685
819
|
return deduped;
|
|
686
820
|
};
|
|
821
|
+
const isSubPath = (parentDir, targetPath) => {
|
|
822
|
+
const rel = relative(parentDir, targetPath);
|
|
823
|
+
if (rel === "") {
|
|
824
|
+
return true;
|
|
825
|
+
}
|
|
826
|
+
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
827
|
+
};
|
|
828
|
+
const readTextIfExists = async (filePath) => {
|
|
829
|
+
try {
|
|
830
|
+
return await readFile(filePath, "utf8");
|
|
831
|
+
} catch (error) {
|
|
832
|
+
const nodeError = error;
|
|
833
|
+
if (nodeError.code === "ENOENT") {
|
|
834
|
+
return void 0;
|
|
835
|
+
}
|
|
836
|
+
throw error;
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
const writeTextIfChanged = async (filePath, content) => {
|
|
840
|
+
const existing = await readTextIfExists(filePath);
|
|
841
|
+
if (existing === content) {
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
await ensureDirectory(dirname(filePath));
|
|
845
|
+
await writeFile(filePath, content, "utf8");
|
|
846
|
+
return true;
|
|
847
|
+
};
|
|
848
|
+
const toPascalCaseIdentifier = (value) => {
|
|
849
|
+
const tokens = value.split(/[^A-Za-z0-9]+/).map((token) => token.trim()).filter((token) => token.length > 0);
|
|
850
|
+
if (tokens.length === 0) {
|
|
851
|
+
throw new Error(`Cannot derive loader function name from target: ${value}`);
|
|
852
|
+
}
|
|
853
|
+
const pascal = tokens.map((token) => token.charAt(0).toUpperCase() + token.slice(1)).join("");
|
|
854
|
+
return /^[0-9]/.test(pascal) ? `Target${pascal}` : pascal;
|
|
855
|
+
};
|
|
856
|
+
const toRelativeImportSpecifier = (fromFile, toFile) => {
|
|
857
|
+
const rel = relative(dirname(fromFile), toFile).replace(/\\/g, "/");
|
|
858
|
+
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
859
|
+
};
|
|
860
|
+
const buildGeneratedLoaderContent = (generatedLoaderFile, targets) => {
|
|
861
|
+
const targetBlocks = targets.map((target) => {
|
|
862
|
+
const specifier = JSON.stringify(
|
|
863
|
+
toRelativeImportSpecifier(generatedLoaderFile, target.outFile)
|
|
864
|
+
);
|
|
865
|
+
return `export const ${target.functionName} = async <T extends object>(
|
|
866
|
+
options?: TargetWasmLoadOptions
|
|
867
|
+
): Promise<WasmInstance<T>> => {
|
|
868
|
+
const source = options?.url ?? new URL(${specifier}, import.meta.url);
|
|
869
|
+
return await loadWasm<T>(source, {
|
|
870
|
+
imports: options?.imports,
|
|
871
|
+
});
|
|
872
|
+
};`;
|
|
873
|
+
}).join("\n\n");
|
|
874
|
+
return `// Generated by emsdk-env. DO NOT EDIT.
|
|
875
|
+
|
|
876
|
+
export type WasmSource =
|
|
877
|
+
| string
|
|
878
|
+
| URL
|
|
879
|
+
| ArrayBuffer
|
|
880
|
+
| ArrayBufferView
|
|
881
|
+
| Response;
|
|
882
|
+
|
|
883
|
+
export interface WasmLoadOptions {
|
|
884
|
+
readonly imports?: WebAssembly.Imports;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
export interface TargetWasmLoadOptions extends WasmLoadOptions {
|
|
888
|
+
readonly url?: string | URL;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
export interface WasmInstance<T extends object> {
|
|
892
|
+
readonly exports: T;
|
|
893
|
+
readonly memory: WebAssembly.Memory;
|
|
894
|
+
readonly table: WebAssembly.Table | undefined;
|
|
895
|
+
readonly rawExports: WebAssembly.Exports;
|
|
896
|
+
readonly module: WebAssembly.Module;
|
|
897
|
+
readonly instance: WebAssembly.Instance;
|
|
898
|
+
readonly initialize: (() => unknown) | undefined;
|
|
899
|
+
readonly start: (() => unknown) | undefined;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const resolveWasmBytes = async (source: WasmSource): Promise<ArrayBuffer> => {
|
|
903
|
+
if (typeof Response !== 'undefined' && source instanceof Response) {
|
|
904
|
+
return await source.arrayBuffer();
|
|
905
|
+
}
|
|
906
|
+
if (source instanceof URL || typeof source === 'string') {
|
|
907
|
+
const response = await fetch(source);
|
|
908
|
+
if (!response.ok) {
|
|
909
|
+
throw new Error(\`Failed to fetch wasm: \${response.url}\`);
|
|
910
|
+
}
|
|
911
|
+
return await response.arrayBuffer();
|
|
912
|
+
}
|
|
913
|
+
if (ArrayBuffer.isView(source)) {
|
|
914
|
+
const view = new Uint8Array(
|
|
915
|
+
source.buffer,
|
|
916
|
+
source.byteOffset,
|
|
917
|
+
source.byteLength
|
|
918
|
+
);
|
|
919
|
+
return view.slice().buffer;
|
|
920
|
+
}
|
|
921
|
+
return source;
|
|
922
|
+
};
|
|
923
|
+
|
|
924
|
+
const getImportValue = (
|
|
925
|
+
imports: WebAssembly.Imports | undefined,
|
|
926
|
+
moduleName: string,
|
|
927
|
+
name: string
|
|
928
|
+
) => {
|
|
929
|
+
const moduleImports = imports?.[moduleName];
|
|
930
|
+
if (!moduleImports || typeof moduleImports !== 'object') {
|
|
931
|
+
return undefined;
|
|
932
|
+
}
|
|
933
|
+
return (moduleImports as Record<string, unknown>)[name];
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
const resolveMemory = (
|
|
937
|
+
module: WebAssembly.Module,
|
|
938
|
+
instance: WebAssembly.Instance,
|
|
939
|
+
imports: WebAssembly.Imports | undefined
|
|
940
|
+
) => {
|
|
941
|
+
let memory: WebAssembly.Memory | undefined;
|
|
942
|
+
for (const entry of WebAssembly.Module.exports(module)) {
|
|
943
|
+
if (entry.kind !== 'memory') {
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
if (memory) {
|
|
947
|
+
throw new Error('Multiple wasm memories are not supported.');
|
|
948
|
+
}
|
|
949
|
+
const value = instance.exports[entry.name];
|
|
950
|
+
if (!(value instanceof WebAssembly.Memory)) {
|
|
951
|
+
throw new Error(\`Export is not a WebAssembly.Memory: \${entry.name}\`);
|
|
952
|
+
}
|
|
953
|
+
memory = value;
|
|
954
|
+
}
|
|
955
|
+
if (memory) {
|
|
956
|
+
return memory;
|
|
957
|
+
}
|
|
958
|
+
for (const entry of WebAssembly.Module.imports(module)) {
|
|
959
|
+
if (entry.kind !== 'memory') {
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
if (memory) {
|
|
963
|
+
throw new Error('Multiple wasm memories are not supported.');
|
|
964
|
+
}
|
|
965
|
+
const value = getImportValue(imports, entry.module, entry.name);
|
|
966
|
+
if (!(value instanceof WebAssembly.Memory)) {
|
|
967
|
+
throw new Error(
|
|
968
|
+
\`Imported value is not a WebAssembly.Memory: \${entry.module}.\${entry.name}\`
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
memory = value;
|
|
972
|
+
}
|
|
973
|
+
if (!memory) {
|
|
974
|
+
throw new Error('WASM memory export/import was not resolved.');
|
|
975
|
+
}
|
|
976
|
+
return memory;
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
const resolveTable = (
|
|
980
|
+
module: WebAssembly.Module,
|
|
981
|
+
instance: WebAssembly.Instance,
|
|
982
|
+
imports: WebAssembly.Imports | undefined
|
|
983
|
+
) => {
|
|
984
|
+
let table: WebAssembly.Table | undefined;
|
|
985
|
+
for (const entry of WebAssembly.Module.exports(module)) {
|
|
986
|
+
if (entry.kind !== 'table') {
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
if (table) {
|
|
990
|
+
throw new Error('Multiple wasm tables are not supported.');
|
|
991
|
+
}
|
|
992
|
+
const value = instance.exports[entry.name];
|
|
993
|
+
if (!(value instanceof WebAssembly.Table)) {
|
|
994
|
+
throw new Error(\`Export is not a WebAssembly.Table: \${entry.name}\`);
|
|
995
|
+
}
|
|
996
|
+
table = value;
|
|
997
|
+
}
|
|
998
|
+
if (table) {
|
|
999
|
+
return table;
|
|
1000
|
+
}
|
|
1001
|
+
for (const entry of WebAssembly.Module.imports(module)) {
|
|
1002
|
+
if (entry.kind !== 'table') {
|
|
1003
|
+
continue;
|
|
1004
|
+
}
|
|
1005
|
+
if (table) {
|
|
1006
|
+
throw new Error('Multiple wasm tables are not supported.');
|
|
1007
|
+
}
|
|
1008
|
+
const value = getImportValue(imports, entry.module, entry.name);
|
|
1009
|
+
if (!(value instanceof WebAssembly.Table)) {
|
|
1010
|
+
throw new Error(
|
|
1011
|
+
\`Imported value is not a WebAssembly.Table: \${entry.module}.\${entry.name}\`
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
table = value;
|
|
1015
|
+
}
|
|
1016
|
+
return table;
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
export const loadWasm = async <T extends object>(
|
|
1020
|
+
source: WasmSource,
|
|
1021
|
+
options?: WasmLoadOptions
|
|
1022
|
+
): Promise<WasmInstance<T>> => {
|
|
1023
|
+
const bytes = await resolveWasmBytes(source);
|
|
1024
|
+
const module = await WebAssembly.compile(bytes);
|
|
1025
|
+
const instance = await WebAssembly.instantiate(module, options?.imports ?? {});
|
|
1026
|
+
|
|
1027
|
+
const functionExports: Record<string, (...args: unknown[]) => unknown> = {};
|
|
1028
|
+
for (const entry of WebAssembly.Module.exports(module)) {
|
|
1029
|
+
if (entry.kind !== 'function') {
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
const value = instance.exports[entry.name];
|
|
1033
|
+
if (typeof value !== 'function') {
|
|
1034
|
+
throw new Error(\`Export is not a function: \${entry.name}\`);
|
|
1035
|
+
}
|
|
1036
|
+
functionExports[entry.name] = value as (...args: unknown[]) => unknown;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
const initialize =
|
|
1040
|
+
typeof instance.exports._initialize === 'function'
|
|
1041
|
+
? (instance.exports._initialize as () => unknown)
|
|
1042
|
+
: undefined;
|
|
1043
|
+
const start =
|
|
1044
|
+
typeof instance.exports._start === 'function'
|
|
1045
|
+
? (instance.exports._start as () => unknown)
|
|
1046
|
+
: undefined;
|
|
1047
|
+
|
|
1048
|
+
return {
|
|
1049
|
+
exports: functionExports as T,
|
|
1050
|
+
memory: resolveMemory(module, instance, options?.imports),
|
|
1051
|
+
table: resolveTable(module, instance, options?.imports),
|
|
1052
|
+
rawExports: instance.exports,
|
|
1053
|
+
module,
|
|
1054
|
+
instance,
|
|
1055
|
+
initialize,
|
|
1056
|
+
start,
|
|
1057
|
+
};
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
${targetBlocks}
|
|
1061
|
+
`;
|
|
1062
|
+
};
|
|
687
1063
|
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
688
1064
|
const resolvePackageJsonPath = async (startPath, packageName) => {
|
|
689
1065
|
let current = dirname(startPath);
|
|
@@ -784,6 +1160,42 @@ const resolveImportDirectories = async (rootDir, imports) => {
|
|
|
784
1160
|
libDirs: dedupeValues(libDirs)
|
|
785
1161
|
};
|
|
786
1162
|
};
|
|
1163
|
+
const resolveGeneratedLoaderOutFile = (rootDir, env, generatedLoader) => {
|
|
1164
|
+
var _a;
|
|
1165
|
+
if (!(generatedLoader == null ? void 0 : generatedLoader.enable)) {
|
|
1166
|
+
return void 0;
|
|
1167
|
+
}
|
|
1168
|
+
const rawOutFile = expandPlaceholders(
|
|
1169
|
+
(_a = generatedLoader.outFile) != null ? _a : DEFAULT_GENERATED_LOADER_OUT_FILE,
|
|
1170
|
+
env,
|
|
1171
|
+
"generatedLoader.outFile"
|
|
1172
|
+
);
|
|
1173
|
+
return resolvePath(rootDir, rawOutFile);
|
|
1174
|
+
};
|
|
1175
|
+
const resolveGeneratedLoaderWatchDirs = (rootDir, srcDir, commonIncludeDirs, env, targetEntries, importIncludeDirs) => {
|
|
1176
|
+
const dirs = [srcDir, ...resolveIncludeDirs(commonIncludeDirs, env, rootDir)];
|
|
1177
|
+
for (const [targetName, target] of targetEntries) {
|
|
1178
|
+
if (!target.includeDirs || target.includeDirs.length === 0) {
|
|
1179
|
+
continue;
|
|
1180
|
+
}
|
|
1181
|
+
const targetEnv = {
|
|
1182
|
+
...env,
|
|
1183
|
+
TARGET_NAME: targetName
|
|
1184
|
+
};
|
|
1185
|
+
dirs.push(...resolveIncludeDirs(target.includeDirs, targetEnv, rootDir));
|
|
1186
|
+
}
|
|
1187
|
+
dirs.push(...importIncludeDirs);
|
|
1188
|
+
return dedupeValues(dirs);
|
|
1189
|
+
};
|
|
1190
|
+
const validateGeneratedLoaderOutFile = (generatedLoaderFile, watchDirs) => {
|
|
1191
|
+
for (const dir of watchDirs) {
|
|
1192
|
+
if (isSubPath(dir, generatedLoaderFile)) {
|
|
1193
|
+
throw new Error(
|
|
1194
|
+
`generatedLoader.outFile must not be placed under watched directory: ${generatedLoaderFile}`
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
787
1199
|
const buildCompileArgs = (options, includeDirs, defines, env, rootDir) => {
|
|
788
1200
|
const resolvedOptions = expandArray(options, env, "options");
|
|
789
1201
|
const includeArgs = resolveIncludeDirs(includeDirs, env, rootDir).map(
|
|
@@ -866,6 +1278,22 @@ const buildWasm = async (options) => {
|
|
|
866
1278
|
const importIncludeDirs = importDirectories.includeDirs;
|
|
867
1279
|
const importLibDirs = importDirectories.libDirs;
|
|
868
1280
|
const linkLibDirs = dedupeValues([libDir, ...importLibDirs]);
|
|
1281
|
+
const generatedLoaderFile = resolveGeneratedLoaderOutFile(
|
|
1282
|
+
rootDir,
|
|
1283
|
+
envWithDirs,
|
|
1284
|
+
options.generatedLoader
|
|
1285
|
+
);
|
|
1286
|
+
if (generatedLoaderFile) {
|
|
1287
|
+
const watchDirs = resolveGeneratedLoaderWatchDirs(
|
|
1288
|
+
rootDir,
|
|
1289
|
+
srcDir,
|
|
1290
|
+
commonIncludeDirs,
|
|
1291
|
+
envWithDirs,
|
|
1292
|
+
targetEntries,
|
|
1293
|
+
importIncludeDirs
|
|
1294
|
+
);
|
|
1295
|
+
validateGeneratedLoaderOutFile(generatedLoaderFile, watchDirs);
|
|
1296
|
+
}
|
|
869
1297
|
logger.debug(`Detected rootDir: '${rootDir}'`);
|
|
870
1298
|
logger.debug(`Detected srcDir: '${srcDir}'`);
|
|
871
1299
|
logger.debug(`Detected outDir: '${outDir}'`);
|
|
@@ -882,6 +1310,9 @@ const buildWasm = async (options) => {
|
|
|
882
1310
|
logger.debug(
|
|
883
1311
|
`Detected importLibDirs: [${importLibDirs.map((p) => `'${p}'`).join(",")}]`
|
|
884
1312
|
);
|
|
1313
|
+
if (generatedLoaderFile) {
|
|
1314
|
+
logger.debug(`Detected generatedLoaderFile: '${generatedLoaderFile}'`);
|
|
1315
|
+
}
|
|
885
1316
|
await ensureDirectory(outDir);
|
|
886
1317
|
await ensureDirectory(libDir);
|
|
887
1318
|
await ensureDirectory(buildDir);
|
|
@@ -904,6 +1335,7 @@ const buildWasm = async (options) => {
|
|
|
904
1335
|
return wasmOptCommand;
|
|
905
1336
|
};
|
|
906
1337
|
const outFiles = {};
|
|
1338
|
+
let resultGeneratedLoaderFile;
|
|
907
1339
|
const buildTargets = async (expectedType) => {
|
|
908
1340
|
var _a2;
|
|
909
1341
|
for (const [targetName, target] of targetEntries) {
|
|
@@ -917,6 +1349,11 @@ const buildWasm = async (options) => {
|
|
|
917
1349
|
`linkOptions is not supported for archive target: ${targetName}`
|
|
918
1350
|
);
|
|
919
1351
|
}
|
|
1352
|
+
if (target.linkDirectives !== void 0) {
|
|
1353
|
+
throw new Error(
|
|
1354
|
+
`linkDirectives is not supported for archive target: ${targetName}`
|
|
1355
|
+
);
|
|
1356
|
+
}
|
|
920
1357
|
if (target.exports !== void 0) {
|
|
921
1358
|
throw new Error(
|
|
922
1359
|
`exports is not supported for archive target: ${targetName}`
|
|
@@ -932,6 +1369,7 @@ const buildWasm = async (options) => {
|
|
|
932
1369
|
...ensureArray(common.linkOptions),
|
|
933
1370
|
...ensureArray(target.linkOptions)
|
|
934
1371
|
];
|
|
1372
|
+
const mergedLinkDirectives = targetType === "archive" ? {} : mergeLinkDirectives(common.linkDirectives, target.linkDirectives);
|
|
935
1373
|
const mergedExports = targetType === "archive" ? [] : [...ensureArray(common.exports), ...ensureArray(target.exports)];
|
|
936
1374
|
const wasmOptEnabled = targetType === "archive" ? false : resolveWasmOptEnabled(common.wasmOpt, target.wasmOpt);
|
|
937
1375
|
const baseCompileOptions = [
|
|
@@ -991,7 +1429,12 @@ const buildWasm = async (options) => {
|
|
|
991
1429
|
const targetBuildDir = resolve(buildRunDir, targetName);
|
|
992
1430
|
await rm(targetBuildDir, { recursive: true, force: true });
|
|
993
1431
|
await ensureDirectory(targetBuildDir);
|
|
994
|
-
const
|
|
1432
|
+
const resolvedLinkDirectives = targetType === "archive" ? {} : resolveLinkDirectives(mergedLinkDirectives, targetEnv);
|
|
1433
|
+
const linkDirectiveArgs = buildLinkDirectiveFlags(resolvedLinkDirectives);
|
|
1434
|
+
const resolvedLinkOptions = targetType === "archive" ? [] : [
|
|
1435
|
+
...linkDirectiveArgs,
|
|
1436
|
+
...expandArray(mergedLinkOptions, targetEnv, "linkOptions")
|
|
1437
|
+
];
|
|
995
1438
|
const resolvedExports = targetType === "archive" ? [] : expandArray(mergedExports, targetEnv, "exports");
|
|
996
1439
|
const exportArgs = buildExportFlags(resolvedExports);
|
|
997
1440
|
const resolvedWasmOptArgs = wasmOptEnabled ? resolveWasmOptArgs(common.wasmOpt, target.wasmOpt, targetEnv) : [];
|
|
@@ -1003,7 +1446,6 @@ const buildWasm = async (options) => {
|
|
|
1003
1446
|
rootDir
|
|
1004
1447
|
);
|
|
1005
1448
|
const groupCompileArgs = sourceGroups.map((group) => {
|
|
1006
|
-
var _a3;
|
|
1007
1449
|
const groupOptions = [
|
|
1008
1450
|
...baseCompileOptions,
|
|
1009
1451
|
...ensureArray(group == null ? void 0 : group.options)
|
|
@@ -1012,7 +1454,7 @@ const buildWasm = async (options) => {
|
|
|
1012
1454
|
...baseIncludeDirs,
|
|
1013
1455
|
...ensureArray(group == null ? void 0 : group.includeDirs)
|
|
1014
1456
|
];
|
|
1015
|
-
const groupDefines = mergeDefines(baseDefines,
|
|
1457
|
+
const groupDefines = mergeDefines(baseDefines, group == null ? void 0 : group.defines);
|
|
1016
1458
|
return buildCompileArgs(
|
|
1017
1459
|
groupOptions,
|
|
1018
1460
|
groupIncludeDirs,
|
|
@@ -1129,9 +1571,18 @@ const buildWasm = async (options) => {
|
|
|
1129
1571
|
emsdkOptions.signal
|
|
1130
1572
|
);
|
|
1131
1573
|
if (wasmOptEnabled) {
|
|
1132
|
-
const
|
|
1133
|
-
const wasmOptArgs = [
|
|
1574
|
+
const wasmOptInput = resolveWasmOptInputFile(
|
|
1134
1575
|
resolvedOutFile,
|
|
1576
|
+
resolvedLinkOptions
|
|
1577
|
+
);
|
|
1578
|
+
if (!await pathExists(wasmOptInput)) {
|
|
1579
|
+
throw new Error(
|
|
1580
|
+
`wasm-opt enabled but wasm binary not found: ${wasmOptInput}`
|
|
1581
|
+
);
|
|
1582
|
+
}
|
|
1583
|
+
const tempOutFile = `${wasmOptInput}.opt`;
|
|
1584
|
+
const wasmOptArgs = [
|
|
1585
|
+
wasmOptInput,
|
|
1135
1586
|
"-o",
|
|
1136
1587
|
tempOutFile,
|
|
1137
1588
|
...resolvedWasmOptArgs
|
|
@@ -1146,8 +1597,8 @@ const buildWasm = async (options) => {
|
|
|
1146
1597
|
buildEnv,
|
|
1147
1598
|
emsdkOptions.signal
|
|
1148
1599
|
);
|
|
1149
|
-
await rm(
|
|
1150
|
-
await rename(tempOutFile,
|
|
1600
|
+
await rm(wasmOptInput, { force: true });
|
|
1601
|
+
await rename(tempOutFile, wasmOptInput);
|
|
1151
1602
|
}
|
|
1152
1603
|
}
|
|
1153
1604
|
outFiles[targetName] = resolvedOutFile;
|
|
@@ -1156,6 +1607,40 @@ const buildWasm = async (options) => {
|
|
|
1156
1607
|
try {
|
|
1157
1608
|
await buildTargets("archive");
|
|
1158
1609
|
await buildTargets("wasm");
|
|
1610
|
+
if (generatedLoaderFile) {
|
|
1611
|
+
const generatedTargets = [];
|
|
1612
|
+
const functionNames = /* @__PURE__ */ new Set();
|
|
1613
|
+
for (const [targetName, target] of targetEntries) {
|
|
1614
|
+
if (resolveTargetType(target.type) !== "wasm") {
|
|
1615
|
+
continue;
|
|
1616
|
+
}
|
|
1617
|
+
const outFile = outFiles[targetName];
|
|
1618
|
+
if (!outFile) {
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
const functionName = `load${toPascalCaseIdentifier(targetName)}Wasm`;
|
|
1622
|
+
if (functionNames.has(functionName)) {
|
|
1623
|
+
throw new Error(
|
|
1624
|
+
`Generated loader function name collision: ${functionName}`
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
functionNames.add(functionName);
|
|
1628
|
+
generatedTargets.push({
|
|
1629
|
+
targetName,
|
|
1630
|
+
functionName,
|
|
1631
|
+
outFile
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
const content = buildGeneratedLoaderContent(
|
|
1635
|
+
generatedLoaderFile,
|
|
1636
|
+
generatedTargets
|
|
1637
|
+
);
|
|
1638
|
+
const didWrite = await writeTextIfChanged(generatedLoaderFile, content);
|
|
1639
|
+
logger.info(
|
|
1640
|
+
didWrite ? `Generated loader: ${relative(rootDir, generatedLoaderFile)}` : `Generated loader unchanged: ${relative(rootDir, generatedLoaderFile)}`
|
|
1641
|
+
);
|
|
1642
|
+
resultGeneratedLoaderFile = generatedLoaderFile;
|
|
1643
|
+
}
|
|
1159
1644
|
} finally {
|
|
1160
1645
|
if (cleanupBuildDir) {
|
|
1161
1646
|
await rm(buildRunDir, { recursive: true, force: true });
|
|
@@ -1163,7 +1648,8 @@ const buildWasm = async (options) => {
|
|
|
1163
1648
|
}
|
|
1164
1649
|
return {
|
|
1165
1650
|
emsdkRoot,
|
|
1166
|
-
outFiles
|
|
1651
|
+
outFiles,
|
|
1652
|
+
...resultGeneratedLoaderFile ? { generatedLoaderFile: resultGeneratedLoaderFile } : {}
|
|
1167
1653
|
};
|
|
1168
1654
|
};
|
|
1169
1655
|
export {
|
|
@@ -1171,4 +1657,4 @@ export {
|
|
|
1171
1657
|
createConsoleLogger as c,
|
|
1172
1658
|
prepareEmsdk as p
|
|
1173
1659
|
};
|
|
1174
|
-
//# sourceMappingURL=build-
|
|
1660
|
+
//# sourceMappingURL=build-BOZTStIM.js.map
|