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,11 +1,11 @@
|
|
|
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
11
|
"use strict";
|
|
@@ -575,6 +575,11 @@ const DEFAULT_IMPORT_LIB_DIR = "lib";
|
|
|
575
575
|
const DEFAULT_WASM_BUILD_DIR = path.join(os.tmpdir(), "emsdk-env");
|
|
576
576
|
const DEFAULT_EMSDK_TARGET_VERSION = "latest";
|
|
577
577
|
const DEFAULT_WASM_OPT_ARGS = ["-Oz"];
|
|
578
|
+
const DEFAULT_GENERATED_LOADER_OUT_FILE = path.join(
|
|
579
|
+
"src",
|
|
580
|
+
"generated",
|
|
581
|
+
"wasm-loader.ts"
|
|
582
|
+
);
|
|
578
583
|
let buildSequence = 0;
|
|
579
584
|
const padNumber = (value, length = 2) => String(value).padStart(length, "0");
|
|
580
585
|
const formatTimestamp = (date) => {
|
|
@@ -601,9 +606,53 @@ const normalizePrepareOptions = (options) => {
|
|
|
601
606
|
...rest
|
|
602
607
|
};
|
|
603
608
|
};
|
|
609
|
+
const parseStringKeyValueInput = (values) => {
|
|
610
|
+
const parsed = {};
|
|
611
|
+
for (const entry of values) {
|
|
612
|
+
const index = entry.indexOf("=");
|
|
613
|
+
if (index === -1) {
|
|
614
|
+
parsed[entry] = void 0;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
const key = entry.slice(0, index);
|
|
618
|
+
const value = entry.slice(index + 1);
|
|
619
|
+
parsed[key] = value;
|
|
620
|
+
}
|
|
621
|
+
return parsed;
|
|
622
|
+
};
|
|
623
|
+
const isDefineMap = (input) => input instanceof Map;
|
|
624
|
+
const normalizeDefineInput = (input) => {
|
|
625
|
+
if (!input) {
|
|
626
|
+
return {};
|
|
627
|
+
}
|
|
628
|
+
if (Array.isArray(input)) {
|
|
629
|
+
return parseStringKeyValueInput(input);
|
|
630
|
+
}
|
|
631
|
+
if (isDefineMap(input)) {
|
|
632
|
+
return Object.fromEntries(input);
|
|
633
|
+
}
|
|
634
|
+
return { ...input };
|
|
635
|
+
};
|
|
636
|
+
const isLinkDirectiveMap = (input) => input instanceof Map;
|
|
637
|
+
const normalizeLinkDirectiveInput = (input) => {
|
|
638
|
+
if (!input) {
|
|
639
|
+
return {};
|
|
640
|
+
}
|
|
641
|
+
if (Array.isArray(input)) {
|
|
642
|
+
return parseStringKeyValueInput(input);
|
|
643
|
+
}
|
|
644
|
+
if (isLinkDirectiveMap(input)) {
|
|
645
|
+
return Object.fromEntries(input);
|
|
646
|
+
}
|
|
647
|
+
return { ...input };
|
|
648
|
+
};
|
|
604
649
|
const mergeDefines = (common, target) => ({
|
|
605
|
-
...common
|
|
606
|
-
...target
|
|
650
|
+
...normalizeDefineInput(common),
|
|
651
|
+
...normalizeDefineInput(target)
|
|
652
|
+
});
|
|
653
|
+
const mergeLinkDirectives = (common, target) => ({
|
|
654
|
+
...normalizeLinkDirectiveInput(common),
|
|
655
|
+
...normalizeLinkDirectiveInput(target)
|
|
607
656
|
});
|
|
608
657
|
const resolveWasmOptEnabled = (common, target) => {
|
|
609
658
|
var _a, _b;
|
|
@@ -611,10 +660,62 @@ const resolveWasmOptEnabled = (common, target) => {
|
|
|
611
660
|
};
|
|
612
661
|
const resolveWasmOptArgs = (common, target, env) => {
|
|
613
662
|
var _a, _b;
|
|
614
|
-
const commonArgs = (_a = common == null ? void 0 : common.
|
|
615
|
-
const targetArgs = (_b = target == null ? void 0 : target.
|
|
663
|
+
const commonArgs = (_a = common == null ? void 0 : common.options) != null ? _a : DEFAULT_WASM_OPT_ARGS;
|
|
664
|
+
const targetArgs = (_b = target == null ? void 0 : target.options) != null ? _b : [];
|
|
616
665
|
const mergedArgs = [...commonArgs, ...targetArgs];
|
|
617
|
-
return expandArray(mergedArgs, env, "wasmOpt.
|
|
666
|
+
return expandArray(mergedArgs, env, "wasmOpt.options");
|
|
667
|
+
};
|
|
668
|
+
const stripOuterQuotes = (value) => {
|
|
669
|
+
const trimmed = value.trim();
|
|
670
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
671
|
+
return trimmed.slice(1, -1);
|
|
672
|
+
}
|
|
673
|
+
return trimmed;
|
|
674
|
+
};
|
|
675
|
+
const extractWasmBinaryFile = (value) => {
|
|
676
|
+
if (value.startsWith("WASM_BINARY_FILE=")) {
|
|
677
|
+
return value.slice("WASM_BINARY_FILE=".length);
|
|
678
|
+
}
|
|
679
|
+
const match = value.match(/^(?:-s|--settings)(?:=)?WASM_BINARY_FILE=(.+)$/);
|
|
680
|
+
if (match) {
|
|
681
|
+
return match[1];
|
|
682
|
+
}
|
|
683
|
+
return void 0;
|
|
684
|
+
};
|
|
685
|
+
const resolveWasmBinaryFileFromLinkOptions = (linkOptions) => {
|
|
686
|
+
for (let index = 0; index < linkOptions.length; index += 1) {
|
|
687
|
+
const option = linkOptions[index];
|
|
688
|
+
if (!option) {
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
if (option === "-s" || option === "--settings") {
|
|
692
|
+
const next = linkOptions[index + 1];
|
|
693
|
+
if (!next) {
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
const extracted2 = extractWasmBinaryFile(next);
|
|
697
|
+
if (extracted2) {
|
|
698
|
+
return stripOuterQuotes(extracted2);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
const extracted = extractWasmBinaryFile(option);
|
|
702
|
+
if (extracted) {
|
|
703
|
+
return stripOuterQuotes(extracted);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
return void 0;
|
|
707
|
+
};
|
|
708
|
+
const resolveWasmOptInputFile = (resolvedOutFile, resolvedLinkOptions) => {
|
|
709
|
+
const wasmBinaryFile = resolveWasmBinaryFileFromLinkOptions(resolvedLinkOptions);
|
|
710
|
+
if (wasmBinaryFile) {
|
|
711
|
+
return path.isAbsolute(wasmBinaryFile) ? wasmBinaryFile : path.resolve(path.dirname(resolvedOutFile), wasmBinaryFile);
|
|
712
|
+
}
|
|
713
|
+
const parsed = path.parse(resolvedOutFile);
|
|
714
|
+
if (parsed.ext.toLowerCase() === ".wasm") {
|
|
715
|
+
return resolvedOutFile;
|
|
716
|
+
}
|
|
717
|
+
const baseName = parsed.name.toLowerCase().endsWith(".wasm") ? parsed.name : `${parsed.name}.wasm`;
|
|
718
|
+
return path.join(parsed.dir, baseName);
|
|
618
719
|
};
|
|
619
720
|
const resolvePath = (rootDir, value) => path.isAbsolute(value) ? value : path.resolve(rootDir, value);
|
|
620
721
|
const expandPlaceholders = (value, env, label) => value.replace(/\{([A-Z0-9_]+)\}/g, (_match, key) => {
|
|
@@ -636,6 +737,28 @@ const resolveDefines = (defines, env) => {
|
|
|
636
737
|
}
|
|
637
738
|
return resolved;
|
|
638
739
|
};
|
|
740
|
+
const resolveLinkDirectiveValue = (value, env, label) => {
|
|
741
|
+
if (typeof value === "string") {
|
|
742
|
+
return expandPlaceholders(value, env, label);
|
|
743
|
+
}
|
|
744
|
+
if (Array.isArray(value)) {
|
|
745
|
+
return value.map(
|
|
746
|
+
(entry, index) => expandPlaceholders(entry, env, `${label}[${index}]`)
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
return value;
|
|
750
|
+
};
|
|
751
|
+
const resolveLinkDirectives = (directives, env) => {
|
|
752
|
+
const resolved = {};
|
|
753
|
+
for (const [key, value] of Object.entries(directives)) {
|
|
754
|
+
resolved[key] = resolveLinkDirectiveValue(
|
|
755
|
+
value,
|
|
756
|
+
env,
|
|
757
|
+
`linkDirectives.${key}`
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
return resolved;
|
|
761
|
+
};
|
|
639
762
|
const resolveIncludeDirs = (includeDirs, env, rootDir) => {
|
|
640
763
|
const expanded = expandArray(includeDirs, env, "includeDirs");
|
|
641
764
|
return expanded.map((value) => resolvePath(rootDir, value));
|
|
@@ -654,7 +777,18 @@ const resolveSourcesFromPatterns = async (patterns, env, srcDir, label) => {
|
|
|
654
777
|
sources.sort();
|
|
655
778
|
return sources;
|
|
656
779
|
};
|
|
657
|
-
const buildDefineFlags = (defines) => Object.entries(defines).
|
|
780
|
+
const buildDefineFlags = (defines) => Object.entries(defines).flatMap(
|
|
781
|
+
([key, value]) => value === null || value === void 0 ? [`-D${key}`] : [`-D${key}=${String(value)}`]
|
|
782
|
+
);
|
|
783
|
+
const serializeLinkDirectiveValue = (value) => Array.isArray(value) ? JSON.stringify(value) : String(value);
|
|
784
|
+
const buildLinkDirectiveFlags = (directives) => {
|
|
785
|
+
if (Object.keys(directives).length === 0) {
|
|
786
|
+
return [];
|
|
787
|
+
}
|
|
788
|
+
return Object.entries(directives).flatMap(
|
|
789
|
+
([key, value]) => value === null || value === void 0 ? ["-s", key] : ["-s", `${key}=${serializeLinkDirectiveValue(value)}`]
|
|
790
|
+
);
|
|
791
|
+
};
|
|
658
792
|
const buildExportFlags = (exports$1) => {
|
|
659
793
|
if (exports$1.length === 0) {
|
|
660
794
|
return [];
|
|
@@ -707,6 +841,248 @@ const dedupeValues = (values) => {
|
|
|
707
841
|
}
|
|
708
842
|
return deduped;
|
|
709
843
|
};
|
|
844
|
+
const isSubPath = (parentDir, targetPath) => {
|
|
845
|
+
const rel = path.relative(parentDir, targetPath);
|
|
846
|
+
if (rel === "") {
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
return !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
850
|
+
};
|
|
851
|
+
const readTextIfExists = async (filePath) => {
|
|
852
|
+
try {
|
|
853
|
+
return await promises.readFile(filePath, "utf8");
|
|
854
|
+
} catch (error) {
|
|
855
|
+
const nodeError = error;
|
|
856
|
+
if (nodeError.code === "ENOENT") {
|
|
857
|
+
return void 0;
|
|
858
|
+
}
|
|
859
|
+
throw error;
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
const writeTextIfChanged = async (filePath, content) => {
|
|
863
|
+
const existing = await readTextIfExists(filePath);
|
|
864
|
+
if (existing === content) {
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
await ensureDirectory(path.dirname(filePath));
|
|
868
|
+
await promises.writeFile(filePath, content, "utf8");
|
|
869
|
+
return true;
|
|
870
|
+
};
|
|
871
|
+
const toPascalCaseIdentifier = (value) => {
|
|
872
|
+
const tokens = value.split(/[^A-Za-z0-9]+/).map((token) => token.trim()).filter((token) => token.length > 0);
|
|
873
|
+
if (tokens.length === 0) {
|
|
874
|
+
throw new Error(`Cannot derive loader function name from target: ${value}`);
|
|
875
|
+
}
|
|
876
|
+
const pascal = tokens.map((token) => token.charAt(0).toUpperCase() + token.slice(1)).join("");
|
|
877
|
+
return /^[0-9]/.test(pascal) ? `Target${pascal}` : pascal;
|
|
878
|
+
};
|
|
879
|
+
const toRelativeImportSpecifier = (fromFile, toFile) => {
|
|
880
|
+
const rel = path.relative(path.dirname(fromFile), toFile).replace(/\\/g, "/");
|
|
881
|
+
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
882
|
+
};
|
|
883
|
+
const buildGeneratedLoaderContent = (generatedLoaderFile, targets) => {
|
|
884
|
+
const targetBlocks = targets.map((target) => {
|
|
885
|
+
const specifier = JSON.stringify(
|
|
886
|
+
toRelativeImportSpecifier(generatedLoaderFile, target.outFile)
|
|
887
|
+
);
|
|
888
|
+
return `export const ${target.functionName} = async <T extends object>(
|
|
889
|
+
options?: TargetWasmLoadOptions
|
|
890
|
+
): Promise<WasmInstance<T>> => {
|
|
891
|
+
const source = options?.url ?? new URL(${specifier}, import.meta.url);
|
|
892
|
+
return await loadWasm<T>(source, {
|
|
893
|
+
imports: options?.imports,
|
|
894
|
+
});
|
|
895
|
+
};`;
|
|
896
|
+
}).join("\n\n");
|
|
897
|
+
return `// Generated by emsdk-env. DO NOT EDIT.
|
|
898
|
+
|
|
899
|
+
export type WasmSource =
|
|
900
|
+
| string
|
|
901
|
+
| URL
|
|
902
|
+
| ArrayBuffer
|
|
903
|
+
| ArrayBufferView
|
|
904
|
+
| Response;
|
|
905
|
+
|
|
906
|
+
export interface WasmLoadOptions {
|
|
907
|
+
readonly imports?: WebAssembly.Imports;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
export interface TargetWasmLoadOptions extends WasmLoadOptions {
|
|
911
|
+
readonly url?: string | URL;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
export interface WasmInstance<T extends object> {
|
|
915
|
+
readonly exports: T;
|
|
916
|
+
readonly memory: WebAssembly.Memory;
|
|
917
|
+
readonly table: WebAssembly.Table | undefined;
|
|
918
|
+
readonly rawExports: WebAssembly.Exports;
|
|
919
|
+
readonly module: WebAssembly.Module;
|
|
920
|
+
readonly instance: WebAssembly.Instance;
|
|
921
|
+
readonly initialize: (() => unknown) | undefined;
|
|
922
|
+
readonly start: (() => unknown) | undefined;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
const resolveWasmBytes = async (source: WasmSource): Promise<ArrayBuffer> => {
|
|
926
|
+
if (typeof Response !== 'undefined' && source instanceof Response) {
|
|
927
|
+
return await source.arrayBuffer();
|
|
928
|
+
}
|
|
929
|
+
if (source instanceof URL || typeof source === 'string') {
|
|
930
|
+
const response = await fetch(source);
|
|
931
|
+
if (!response.ok) {
|
|
932
|
+
throw new Error(\`Failed to fetch wasm: \${response.url}\`);
|
|
933
|
+
}
|
|
934
|
+
return await response.arrayBuffer();
|
|
935
|
+
}
|
|
936
|
+
if (ArrayBuffer.isView(source)) {
|
|
937
|
+
const view = new Uint8Array(
|
|
938
|
+
source.buffer,
|
|
939
|
+
source.byteOffset,
|
|
940
|
+
source.byteLength
|
|
941
|
+
);
|
|
942
|
+
return view.slice().buffer;
|
|
943
|
+
}
|
|
944
|
+
return source;
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
const getImportValue = (
|
|
948
|
+
imports: WebAssembly.Imports | undefined,
|
|
949
|
+
moduleName: string,
|
|
950
|
+
name: string
|
|
951
|
+
) => {
|
|
952
|
+
const moduleImports = imports?.[moduleName];
|
|
953
|
+
if (!moduleImports || typeof moduleImports !== 'object') {
|
|
954
|
+
return undefined;
|
|
955
|
+
}
|
|
956
|
+
return (moduleImports as Record<string, unknown>)[name];
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
const resolveMemory = (
|
|
960
|
+
module: WebAssembly.Module,
|
|
961
|
+
instance: WebAssembly.Instance,
|
|
962
|
+
imports: WebAssembly.Imports | undefined
|
|
963
|
+
) => {
|
|
964
|
+
let memory: WebAssembly.Memory | undefined;
|
|
965
|
+
for (const entry of WebAssembly.Module.exports(module)) {
|
|
966
|
+
if (entry.kind !== 'memory') {
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if (memory) {
|
|
970
|
+
throw new Error('Multiple wasm memories are not supported.');
|
|
971
|
+
}
|
|
972
|
+
const value = instance.exports[entry.name];
|
|
973
|
+
if (!(value instanceof WebAssembly.Memory)) {
|
|
974
|
+
throw new Error(\`Export is not a WebAssembly.Memory: \${entry.name}\`);
|
|
975
|
+
}
|
|
976
|
+
memory = value;
|
|
977
|
+
}
|
|
978
|
+
if (memory) {
|
|
979
|
+
return memory;
|
|
980
|
+
}
|
|
981
|
+
for (const entry of WebAssembly.Module.imports(module)) {
|
|
982
|
+
if (entry.kind !== 'memory') {
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
if (memory) {
|
|
986
|
+
throw new Error('Multiple wasm memories are not supported.');
|
|
987
|
+
}
|
|
988
|
+
const value = getImportValue(imports, entry.module, entry.name);
|
|
989
|
+
if (!(value instanceof WebAssembly.Memory)) {
|
|
990
|
+
throw new Error(
|
|
991
|
+
\`Imported value is not a WebAssembly.Memory: \${entry.module}.\${entry.name}\`
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
memory = value;
|
|
995
|
+
}
|
|
996
|
+
if (!memory) {
|
|
997
|
+
throw new Error('WASM memory export/import was not resolved.');
|
|
998
|
+
}
|
|
999
|
+
return memory;
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
const resolveTable = (
|
|
1003
|
+
module: WebAssembly.Module,
|
|
1004
|
+
instance: WebAssembly.Instance,
|
|
1005
|
+
imports: WebAssembly.Imports | undefined
|
|
1006
|
+
) => {
|
|
1007
|
+
let table: WebAssembly.Table | undefined;
|
|
1008
|
+
for (const entry of WebAssembly.Module.exports(module)) {
|
|
1009
|
+
if (entry.kind !== 'table') {
|
|
1010
|
+
continue;
|
|
1011
|
+
}
|
|
1012
|
+
if (table) {
|
|
1013
|
+
throw new Error('Multiple wasm tables are not supported.');
|
|
1014
|
+
}
|
|
1015
|
+
const value = instance.exports[entry.name];
|
|
1016
|
+
if (!(value instanceof WebAssembly.Table)) {
|
|
1017
|
+
throw new Error(\`Export is not a WebAssembly.Table: \${entry.name}\`);
|
|
1018
|
+
}
|
|
1019
|
+
table = value;
|
|
1020
|
+
}
|
|
1021
|
+
if (table) {
|
|
1022
|
+
return table;
|
|
1023
|
+
}
|
|
1024
|
+
for (const entry of WebAssembly.Module.imports(module)) {
|
|
1025
|
+
if (entry.kind !== 'table') {
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
if (table) {
|
|
1029
|
+
throw new Error('Multiple wasm tables are not supported.');
|
|
1030
|
+
}
|
|
1031
|
+
const value = getImportValue(imports, entry.module, entry.name);
|
|
1032
|
+
if (!(value instanceof WebAssembly.Table)) {
|
|
1033
|
+
throw new Error(
|
|
1034
|
+
\`Imported value is not a WebAssembly.Table: \${entry.module}.\${entry.name}\`
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
table = value;
|
|
1038
|
+
}
|
|
1039
|
+
return table;
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
export const loadWasm = async <T extends object>(
|
|
1043
|
+
source: WasmSource,
|
|
1044
|
+
options?: WasmLoadOptions
|
|
1045
|
+
): Promise<WasmInstance<T>> => {
|
|
1046
|
+
const bytes = await resolveWasmBytes(source);
|
|
1047
|
+
const module = await WebAssembly.compile(bytes);
|
|
1048
|
+
const instance = await WebAssembly.instantiate(module, options?.imports ?? {});
|
|
1049
|
+
|
|
1050
|
+
const functionExports: Record<string, (...args: unknown[]) => unknown> = {};
|
|
1051
|
+
for (const entry of WebAssembly.Module.exports(module)) {
|
|
1052
|
+
if (entry.kind !== 'function') {
|
|
1053
|
+
continue;
|
|
1054
|
+
}
|
|
1055
|
+
const value = instance.exports[entry.name];
|
|
1056
|
+
if (typeof value !== 'function') {
|
|
1057
|
+
throw new Error(\`Export is not a function: \${entry.name}\`);
|
|
1058
|
+
}
|
|
1059
|
+
functionExports[entry.name] = value as (...args: unknown[]) => unknown;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const initialize =
|
|
1063
|
+
typeof instance.exports._initialize === 'function'
|
|
1064
|
+
? (instance.exports._initialize as () => unknown)
|
|
1065
|
+
: undefined;
|
|
1066
|
+
const start =
|
|
1067
|
+
typeof instance.exports._start === 'function'
|
|
1068
|
+
? (instance.exports._start as () => unknown)
|
|
1069
|
+
: undefined;
|
|
1070
|
+
|
|
1071
|
+
return {
|
|
1072
|
+
exports: functionExports as T,
|
|
1073
|
+
memory: resolveMemory(module, instance, options?.imports),
|
|
1074
|
+
table: resolveTable(module, instance, options?.imports),
|
|
1075
|
+
rawExports: instance.exports,
|
|
1076
|
+
module,
|
|
1077
|
+
instance,
|
|
1078
|
+
initialize,
|
|
1079
|
+
start,
|
|
1080
|
+
};
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
${targetBlocks}
|
|
1084
|
+
`;
|
|
1085
|
+
};
|
|
710
1086
|
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
711
1087
|
const resolvePackageJsonPath = async (startPath, packageName) => {
|
|
712
1088
|
let current = path.dirname(startPath);
|
|
@@ -807,6 +1183,42 @@ const resolveImportDirectories = async (rootDir, imports) => {
|
|
|
807
1183
|
libDirs: dedupeValues(libDirs)
|
|
808
1184
|
};
|
|
809
1185
|
};
|
|
1186
|
+
const resolveGeneratedLoaderOutFile = (rootDir, env, generatedLoader) => {
|
|
1187
|
+
var _a;
|
|
1188
|
+
if (!(generatedLoader == null ? void 0 : generatedLoader.enable)) {
|
|
1189
|
+
return void 0;
|
|
1190
|
+
}
|
|
1191
|
+
const rawOutFile = expandPlaceholders(
|
|
1192
|
+
(_a = generatedLoader.outFile) != null ? _a : DEFAULT_GENERATED_LOADER_OUT_FILE,
|
|
1193
|
+
env,
|
|
1194
|
+
"generatedLoader.outFile"
|
|
1195
|
+
);
|
|
1196
|
+
return resolvePath(rootDir, rawOutFile);
|
|
1197
|
+
};
|
|
1198
|
+
const resolveGeneratedLoaderWatchDirs = (rootDir, srcDir, commonIncludeDirs, env, targetEntries, importIncludeDirs) => {
|
|
1199
|
+
const dirs = [srcDir, ...resolveIncludeDirs(commonIncludeDirs, env, rootDir)];
|
|
1200
|
+
for (const [targetName, target] of targetEntries) {
|
|
1201
|
+
if (!target.includeDirs || target.includeDirs.length === 0) {
|
|
1202
|
+
continue;
|
|
1203
|
+
}
|
|
1204
|
+
const targetEnv = {
|
|
1205
|
+
...env,
|
|
1206
|
+
TARGET_NAME: targetName
|
|
1207
|
+
};
|
|
1208
|
+
dirs.push(...resolveIncludeDirs(target.includeDirs, targetEnv, rootDir));
|
|
1209
|
+
}
|
|
1210
|
+
dirs.push(...importIncludeDirs);
|
|
1211
|
+
return dedupeValues(dirs);
|
|
1212
|
+
};
|
|
1213
|
+
const validateGeneratedLoaderOutFile = (generatedLoaderFile, watchDirs) => {
|
|
1214
|
+
for (const dir of watchDirs) {
|
|
1215
|
+
if (isSubPath(dir, generatedLoaderFile)) {
|
|
1216
|
+
throw new Error(
|
|
1217
|
+
`generatedLoader.outFile must not be placed under watched directory: ${generatedLoaderFile}`
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
810
1222
|
const buildCompileArgs = (options, includeDirs, defines, env, rootDir) => {
|
|
811
1223
|
const resolvedOptions = expandArray(options, env, "options");
|
|
812
1224
|
const includeArgs = resolveIncludeDirs(includeDirs, env, rootDir).map(
|
|
@@ -889,6 +1301,22 @@ const buildWasm = async (options) => {
|
|
|
889
1301
|
const importIncludeDirs = importDirectories.includeDirs;
|
|
890
1302
|
const importLibDirs = importDirectories.libDirs;
|
|
891
1303
|
const linkLibDirs = dedupeValues([libDir, ...importLibDirs]);
|
|
1304
|
+
const generatedLoaderFile = resolveGeneratedLoaderOutFile(
|
|
1305
|
+
rootDir,
|
|
1306
|
+
envWithDirs,
|
|
1307
|
+
options.generatedLoader
|
|
1308
|
+
);
|
|
1309
|
+
if (generatedLoaderFile) {
|
|
1310
|
+
const watchDirs = resolveGeneratedLoaderWatchDirs(
|
|
1311
|
+
rootDir,
|
|
1312
|
+
srcDir,
|
|
1313
|
+
commonIncludeDirs,
|
|
1314
|
+
envWithDirs,
|
|
1315
|
+
targetEntries,
|
|
1316
|
+
importIncludeDirs
|
|
1317
|
+
);
|
|
1318
|
+
validateGeneratedLoaderOutFile(generatedLoaderFile, watchDirs);
|
|
1319
|
+
}
|
|
892
1320
|
logger.debug(`Detected rootDir: '${rootDir}'`);
|
|
893
1321
|
logger.debug(`Detected srcDir: '${srcDir}'`);
|
|
894
1322
|
logger.debug(`Detected outDir: '${outDir}'`);
|
|
@@ -905,6 +1333,9 @@ const buildWasm = async (options) => {
|
|
|
905
1333
|
logger.debug(
|
|
906
1334
|
`Detected importLibDirs: [${importLibDirs.map((p) => `'${p}'`).join(",")}]`
|
|
907
1335
|
);
|
|
1336
|
+
if (generatedLoaderFile) {
|
|
1337
|
+
logger.debug(`Detected generatedLoaderFile: '${generatedLoaderFile}'`);
|
|
1338
|
+
}
|
|
908
1339
|
await ensureDirectory(outDir);
|
|
909
1340
|
await ensureDirectory(libDir);
|
|
910
1341
|
await ensureDirectory(buildDir);
|
|
@@ -927,6 +1358,7 @@ const buildWasm = async (options) => {
|
|
|
927
1358
|
return wasmOptCommand;
|
|
928
1359
|
};
|
|
929
1360
|
const outFiles = {};
|
|
1361
|
+
let resultGeneratedLoaderFile;
|
|
930
1362
|
const buildTargets = async (expectedType) => {
|
|
931
1363
|
var _a2;
|
|
932
1364
|
for (const [targetName, target] of targetEntries) {
|
|
@@ -940,6 +1372,11 @@ const buildWasm = async (options) => {
|
|
|
940
1372
|
`linkOptions is not supported for archive target: ${targetName}`
|
|
941
1373
|
);
|
|
942
1374
|
}
|
|
1375
|
+
if (target.linkDirectives !== void 0) {
|
|
1376
|
+
throw new Error(
|
|
1377
|
+
`linkDirectives is not supported for archive target: ${targetName}`
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
943
1380
|
if (target.exports !== void 0) {
|
|
944
1381
|
throw new Error(
|
|
945
1382
|
`exports is not supported for archive target: ${targetName}`
|
|
@@ -955,6 +1392,7 @@ const buildWasm = async (options) => {
|
|
|
955
1392
|
...ensureArray(common.linkOptions),
|
|
956
1393
|
...ensureArray(target.linkOptions)
|
|
957
1394
|
];
|
|
1395
|
+
const mergedLinkDirectives = targetType === "archive" ? {} : mergeLinkDirectives(common.linkDirectives, target.linkDirectives);
|
|
958
1396
|
const mergedExports = targetType === "archive" ? [] : [...ensureArray(common.exports), ...ensureArray(target.exports)];
|
|
959
1397
|
const wasmOptEnabled = targetType === "archive" ? false : resolveWasmOptEnabled(common.wasmOpt, target.wasmOpt);
|
|
960
1398
|
const baseCompileOptions = [
|
|
@@ -1014,7 +1452,12 @@ const buildWasm = async (options) => {
|
|
|
1014
1452
|
const targetBuildDir = path.resolve(buildRunDir, targetName);
|
|
1015
1453
|
await promises.rm(targetBuildDir, { recursive: true, force: true });
|
|
1016
1454
|
await ensureDirectory(targetBuildDir);
|
|
1017
|
-
const
|
|
1455
|
+
const resolvedLinkDirectives = targetType === "archive" ? {} : resolveLinkDirectives(mergedLinkDirectives, targetEnv);
|
|
1456
|
+
const linkDirectiveArgs = buildLinkDirectiveFlags(resolvedLinkDirectives);
|
|
1457
|
+
const resolvedLinkOptions = targetType === "archive" ? [] : [
|
|
1458
|
+
...linkDirectiveArgs,
|
|
1459
|
+
...expandArray(mergedLinkOptions, targetEnv, "linkOptions")
|
|
1460
|
+
];
|
|
1018
1461
|
const resolvedExports = targetType === "archive" ? [] : expandArray(mergedExports, targetEnv, "exports");
|
|
1019
1462
|
const exportArgs = buildExportFlags(resolvedExports);
|
|
1020
1463
|
const resolvedWasmOptArgs = wasmOptEnabled ? resolveWasmOptArgs(common.wasmOpt, target.wasmOpt, targetEnv) : [];
|
|
@@ -1026,7 +1469,6 @@ const buildWasm = async (options) => {
|
|
|
1026
1469
|
rootDir
|
|
1027
1470
|
);
|
|
1028
1471
|
const groupCompileArgs = sourceGroups.map((group) => {
|
|
1029
|
-
var _a3;
|
|
1030
1472
|
const groupOptions = [
|
|
1031
1473
|
...baseCompileOptions,
|
|
1032
1474
|
...ensureArray(group == null ? void 0 : group.options)
|
|
@@ -1035,7 +1477,7 @@ const buildWasm = async (options) => {
|
|
|
1035
1477
|
...baseIncludeDirs,
|
|
1036
1478
|
...ensureArray(group == null ? void 0 : group.includeDirs)
|
|
1037
1479
|
];
|
|
1038
|
-
const groupDefines = mergeDefines(baseDefines,
|
|
1480
|
+
const groupDefines = mergeDefines(baseDefines, group == null ? void 0 : group.defines);
|
|
1039
1481
|
return buildCompileArgs(
|
|
1040
1482
|
groupOptions,
|
|
1041
1483
|
groupIncludeDirs,
|
|
@@ -1152,9 +1594,18 @@ const buildWasm = async (options) => {
|
|
|
1152
1594
|
emsdkOptions.signal
|
|
1153
1595
|
);
|
|
1154
1596
|
if (wasmOptEnabled) {
|
|
1155
|
-
const
|
|
1156
|
-
const wasmOptArgs = [
|
|
1597
|
+
const wasmOptInput = resolveWasmOptInputFile(
|
|
1157
1598
|
resolvedOutFile,
|
|
1599
|
+
resolvedLinkOptions
|
|
1600
|
+
);
|
|
1601
|
+
if (!await pathExists(wasmOptInput)) {
|
|
1602
|
+
throw new Error(
|
|
1603
|
+
`wasm-opt enabled but wasm binary not found: ${wasmOptInput}`
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
const tempOutFile = `${wasmOptInput}.opt`;
|
|
1607
|
+
const wasmOptArgs = [
|
|
1608
|
+
wasmOptInput,
|
|
1158
1609
|
"-o",
|
|
1159
1610
|
tempOutFile,
|
|
1160
1611
|
...resolvedWasmOptArgs
|
|
@@ -1169,8 +1620,8 @@ const buildWasm = async (options) => {
|
|
|
1169
1620
|
buildEnv,
|
|
1170
1621
|
emsdkOptions.signal
|
|
1171
1622
|
);
|
|
1172
|
-
await promises.rm(
|
|
1173
|
-
await promises.rename(tempOutFile,
|
|
1623
|
+
await promises.rm(wasmOptInput, { force: true });
|
|
1624
|
+
await promises.rename(tempOutFile, wasmOptInput);
|
|
1174
1625
|
}
|
|
1175
1626
|
}
|
|
1176
1627
|
outFiles[targetName] = resolvedOutFile;
|
|
@@ -1179,6 +1630,40 @@ const buildWasm = async (options) => {
|
|
|
1179
1630
|
try {
|
|
1180
1631
|
await buildTargets("archive");
|
|
1181
1632
|
await buildTargets("wasm");
|
|
1633
|
+
if (generatedLoaderFile) {
|
|
1634
|
+
const generatedTargets = [];
|
|
1635
|
+
const functionNames = /* @__PURE__ */ new Set();
|
|
1636
|
+
for (const [targetName, target] of targetEntries) {
|
|
1637
|
+
if (resolveTargetType(target.type) !== "wasm") {
|
|
1638
|
+
continue;
|
|
1639
|
+
}
|
|
1640
|
+
const outFile = outFiles[targetName];
|
|
1641
|
+
if (!outFile) {
|
|
1642
|
+
continue;
|
|
1643
|
+
}
|
|
1644
|
+
const functionName = `load${toPascalCaseIdentifier(targetName)}Wasm`;
|
|
1645
|
+
if (functionNames.has(functionName)) {
|
|
1646
|
+
throw new Error(
|
|
1647
|
+
`Generated loader function name collision: ${functionName}`
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
functionNames.add(functionName);
|
|
1651
|
+
generatedTargets.push({
|
|
1652
|
+
targetName,
|
|
1653
|
+
functionName,
|
|
1654
|
+
outFile
|
|
1655
|
+
});
|
|
1656
|
+
}
|
|
1657
|
+
const content = buildGeneratedLoaderContent(
|
|
1658
|
+
generatedLoaderFile,
|
|
1659
|
+
generatedTargets
|
|
1660
|
+
);
|
|
1661
|
+
const didWrite = await writeTextIfChanged(generatedLoaderFile, content);
|
|
1662
|
+
logger.info(
|
|
1663
|
+
didWrite ? `Generated loader: ${path.relative(rootDir, generatedLoaderFile)}` : `Generated loader unchanged: ${path.relative(rootDir, generatedLoaderFile)}`
|
|
1664
|
+
);
|
|
1665
|
+
resultGeneratedLoaderFile = generatedLoaderFile;
|
|
1666
|
+
}
|
|
1182
1667
|
} finally {
|
|
1183
1668
|
if (cleanupBuildDir) {
|
|
1184
1669
|
await promises.rm(buildRunDir, { recursive: true, force: true });
|
|
@@ -1186,10 +1671,11 @@ const buildWasm = async (options) => {
|
|
|
1186
1671
|
}
|
|
1187
1672
|
return {
|
|
1188
1673
|
emsdkRoot,
|
|
1189
|
-
outFiles
|
|
1674
|
+
outFiles,
|
|
1675
|
+
...resultGeneratedLoaderFile ? { generatedLoaderFile: resultGeneratedLoaderFile } : {}
|
|
1190
1676
|
};
|
|
1191
1677
|
};
|
|
1192
1678
|
exports.buildWasm = buildWasm;
|
|
1193
1679
|
exports.createConsoleLogger = createConsoleLogger;
|
|
1194
1680
|
exports.prepareEmsdk = prepareEmsdk;
|
|
1195
|
-
//# sourceMappingURL=build-
|
|
1681
|
+
//# sourceMappingURL=build-CgmcFNSR.cjs.map
|