emsdk-env 0.3.0 → 0.4.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 CHANGED
@@ -9,14 +9,13 @@ A Vite plugin that automatically builds WASM C/C++ source code using the Emscrip
9
9
 
10
10
  ---
11
11
 
12
- WIP:
13
-
14
12
  ## What is this?
15
13
 
16
- This is a Vite plugin that automatically downloads and manages the Emscripten SDK, and makes it possible to automatically build WASM C/C++ code in your project.
14
+ This is a Vite plugin that automatically downloads and manages the [Emscripten SDK](https://github.com/emscripten-core/emsdk),
15
+ and makes it possible to automatically build WASM C/C++ code in your project.
17
16
  With this plugin, you can easily set up a WASM C/C++ development environment in your Vite project.
18
17
 
19
- Usage is simple. Just add this Vite plugin package to your project and initialize the plugin in `vite.config.ts` like this:
18
+ Usage is simple. Just add this Vite plugin package to your project and initialize the plugin in `vite.config` like this:
20
19
 
21
20
  ```typescript
22
21
  // `vite.config.ts`
@@ -57,6 +56,8 @@ You can focus on writing C/C++ code just like you would TypeScript/JavaScript co
57
56
  - Simplified specification of export symbols
58
57
  - Ability to generate multiple target WASM binaries
59
58
  - Customizable directory paths, compile options, and linker options
59
+ - Archive libraries (`*.a`) can be built and referenced
60
+ - WASM libraries can be distributed and referenced via NPM packages
60
61
 
61
62
  ---
62
63
 
@@ -70,6 +71,9 @@ Add to `devDependencies` (emsdk-env itself does not require runtime code):
70
71
  $ npm install -D emsdk-env
71
72
  ```
72
73
 
74
+ - emsdk-env automatically downloads and caches the Emscripten SDK (located under `~/.cache/emsdk-env/`).
75
+ Therefore, you do not need to manually set up the Emscripten SDK.
76
+
73
77
  ### C/C++ Source Code and Binary Placement
74
78
 
75
79
  By default, C/C++ source code is placed in the `wasm/` directory under your project,
@@ -88,6 +92,19 @@ project/
88
92
  └── add.c
89
93
  ```
90
94
 
95
+ - In addition to the above, a temporary build directory is created under the OS temp directory.
96
+ The default location is `${TMPDIR}/emsdk-env` (typically `/tmp/emsdk-env` on Unix).
97
+ This directory is used during the build process and is typically deleted after the build completes.
98
+ If you override `buildDir` to point inside the project, add it to `.gitignore`.
99
+
100
+ Of course, you can change these. Specify them in the Vite plugin options.
101
+
102
+ You might find it odd that the built binary is placed in `src/wasm/`, but this is because the Vite server defaults to a path where it can easily access WASM binaries.
103
+
104
+ If you plan to operate with the default settings, there is essentially no configuration work required.
105
+
106
+ Other topics include features such as explicitly specifying source files, applying multiple compile options separately, handling multiple target outputs, generating and referencing archive library files, and compilation and referencing NPM packages.
107
+
91
108
  ### Documents
92
109
 
93
110
  For more information, please visit repository and refer README: [emsdk-env](https://github.com/kekyo/emsdk-env)
@@ -0,0 +1,15 @@
1
+ /*!
2
+ * name: emsdk-env
3
+ * version: 0.4.0
4
+ * description: Emscripten environment builder
5
+ * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
+ * license: MIT
7
+ * repository.url: https://github.com/kekyo/emsdk-env
8
+ * git.commit.hash: cd0d8e53bf52b98940dd50343a9d3a39200306bd
9
+ */
10
+
11
+ const __viteBrowserExternal = {};
12
+ export {
13
+ __viteBrowserExternal as default
14
+ };
15
+ //# sourceMappingURL=__vite-browser-external-2Ng8QIWW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__vite-browser-external-2Ng8QIWW.js","sources":["../__vite-browser-external"],"sourcesContent":["export default {}"],"names":[],"mappings":";;;;;;;;;;AAAA,MAAA,wBAAe,CAAA;"}
@@ -0,0 +1,15 @@
1
+ /*!
2
+ * name: emsdk-env
3
+ * version: 0.4.0
4
+ * description: Emscripten environment builder
5
+ * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
+ * license: MIT
7
+ * repository.url: https://github.com/kekyo/emsdk-env
8
+ * git.commit.hash: cd0d8e53bf52b98940dd50343a9d3a39200306bd
9
+ */
10
+
11
+ "use strict";
12
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
13
+ const __viteBrowserExternal = {};
14
+ exports.default = __viteBrowserExternal;
15
+ //# sourceMappingURL=__vite-browser-external-DES75WN9.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__vite-browser-external-DES75WN9.cjs","sources":["../__vite-browser-external"],"sourcesContent":["export default {}"],"names":[],"mappings":";;;;;;;;;;;;AAAA,MAAA,wBAAe,CAAA;;"}
@@ -1,11 +1,11 @@
1
1
  /*!
2
2
  * name: emsdk-env
3
- * version: 0.3.0
3
+ * version: 0.4.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: 4a03739b8c88111950fa216a7c10c7bfd65ea239
8
+ * git.commit.hash: cd0d8e53bf52b98940dd50343a9d3a39200306bd
9
9
  */
10
10
 
11
11
  "use strict";
@@ -502,6 +502,22 @@ const resolveEmccCommand = async (env, emsdkRoot) => {
502
502
  }
503
503
  return "emcc";
504
504
  };
505
+ const resolveEmarCommand = async (env, emsdkRoot) => {
506
+ if (env.EMAR) {
507
+ return env.EMAR;
508
+ }
509
+ if (env.EMSCRIPTEN) {
510
+ const candidate = path.join(env.EMSCRIPTEN, "emar");
511
+ if (await pathExists(candidate)) {
512
+ return candidate;
513
+ }
514
+ }
515
+ const fallback = path.join(emsdkRoot, "upstream", "emscripten", "emar");
516
+ if (await pathExists(fallback)) {
517
+ return fallback;
518
+ }
519
+ return "emar";
520
+ };
505
521
  const createConsoleLogger = (prefix) => {
506
522
  return {
507
523
  debug: (msg) => console.debug(`[${prefix}]: ${msg}`),
@@ -511,7 +527,11 @@ const createConsoleLogger = (prefix) => {
511
527
  };
512
528
  };
513
529
  const DEFAULT_WASM_SRC_DIR = "wasm";
530
+ const DEFAULT_WASM_INCLUDE_DIR = "include";
514
531
  const DEFAULT_WASM_OUT_DIR = path.join("src", "wasm");
532
+ const DEFAULT_WASM_LIB_DIR = "lib";
533
+ const DEFAULT_IMPORT_INCLUDE_DIR = "include";
534
+ const DEFAULT_IMPORT_LIB_DIR = "lib";
515
535
  const DEFAULT_WASM_BUILD_DIR = path.join(os.tmpdir(), "emsdk-env");
516
536
  const DEFAULT_EMSDK_TARGET_VERSION = "latest";
517
537
  let buildSequence = 0;
@@ -532,6 +552,7 @@ const createBuildId = () => {
532
552
  return `${timestamp}_${seq}_${process.pid}`;
533
553
  };
534
554
  const ensureArray = (value) => value != null ? value : [];
555
+ const resolveTargetType = (value) => value != null ? value : "wasm";
535
556
  const normalizePrepareOptions = (options) => {
536
557
  const { targetVersion, ...rest } = options != null ? options : {};
537
558
  return {
@@ -593,11 +614,11 @@ const createEnvForBuild = (baseEnv, overrides) => ({
593
614
  ...baseEnv,
594
615
  ...overrides
595
616
  });
596
- const resolveTargetOutFile = (targetName, targetOutFile, env, outDir) => {
617
+ const resolveTargetOutFile = (targetName, targetOutFile, env, baseDir, extension) => {
597
618
  if (targetOutFile) {
598
- return resolveOutFile(targetOutFile, env, outDir);
619
+ return resolveOutFile(targetOutFile, env, baseDir);
599
620
  }
600
- return path.resolve(outDir, `${targetName}.wasm`);
621
+ return path.resolve(baseDir, `${targetName}.${extension}`);
601
622
  };
602
623
  const resolveTargetSources = async (targetSources, env, srcDir) => {
603
624
  const patterns = targetSources && targetSources.length > 0 ? targetSources : [path.join(srcDir, "**", "*.c"), path.join(srcDir, "**", "*.cpp")];
@@ -622,6 +643,118 @@ const dedupeSources = (sources) => {
622
643
  }
623
644
  return deduped;
624
645
  };
646
+ const dedupeValues = (values) => {
647
+ const seen = /* @__PURE__ */ new Set();
648
+ const deduped = [];
649
+ for (const value of values) {
650
+ if (seen.has(value)) {
651
+ continue;
652
+ }
653
+ seen.add(value);
654
+ deduped.push(value);
655
+ }
656
+ return deduped;
657
+ };
658
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
659
+ const resolvePackageJsonPath = async (startPath, packageName) => {
660
+ let current = path.dirname(startPath);
661
+ for (; ; ) {
662
+ const candidate = path.join(current, "package.json");
663
+ if (await pathExists(candidate)) {
664
+ return candidate;
665
+ }
666
+ const parent = path.dirname(current);
667
+ if (parent === current) {
668
+ throw new Error(`package.json not found for import: ${packageName}`);
669
+ }
670
+ current = parent;
671
+ }
672
+ };
673
+ const loadPackageJson = async (packageJsonPath, packageName) => {
674
+ try {
675
+ const raw = await promises.readFile(packageJsonPath, "utf8");
676
+ const parsed = JSON.parse(raw);
677
+ if (!isRecord(parsed)) {
678
+ throw new Error("package.json must be an object.");
679
+ }
680
+ return parsed;
681
+ } catch (error) {
682
+ const message = error instanceof Error ? error.message : String(error);
683
+ throw new Error(
684
+ `Failed to read package.json for import ${packageName}: ${message}`
685
+ );
686
+ }
687
+ };
688
+ const resolveImportPaths = async (resolver, packageName) => {
689
+ let resolvedEntry;
690
+ try {
691
+ resolvedEntry = resolver.resolve(packageName);
692
+ } catch (error) {
693
+ const message = error instanceof Error ? error.message : String(error);
694
+ throw new Error(`Failed to resolve import ${packageName}: ${message}`);
695
+ }
696
+ const packageJsonPath = await resolvePackageJsonPath(
697
+ resolvedEntry,
698
+ packageName
699
+ );
700
+ const packageRoot = path.dirname(packageJsonPath);
701
+ const packageJson = await loadPackageJson(packageJsonPath, packageName);
702
+ const emsdkConfigRaw = packageJson["emsdk-env"];
703
+ if (emsdkConfigRaw !== void 0 && !isRecord(emsdkConfigRaw)) {
704
+ throw new Error(
705
+ `Invalid emsdk-env config for import ${packageName}: expected an object.`
706
+ );
707
+ }
708
+ const includeRaw = isRecord(emsdkConfigRaw) ? emsdkConfigRaw.include : void 0;
709
+ if (includeRaw !== void 0 && typeof includeRaw !== "string") {
710
+ throw new Error(
711
+ `Invalid emsdk-env include for import ${packageName}: expected a string.`
712
+ );
713
+ }
714
+ const libRaw = isRecord(emsdkConfigRaw) ? emsdkConfigRaw.lib : void 0;
715
+ if (libRaw !== void 0 && typeof libRaw !== "string") {
716
+ throw new Error(
717
+ `Invalid emsdk-env lib for import ${packageName}: expected a string.`
718
+ );
719
+ }
720
+ const includeRel = includeRaw != null ? includeRaw : DEFAULT_IMPORT_INCLUDE_DIR;
721
+ const libRel = libRaw != null ? libRaw : DEFAULT_IMPORT_LIB_DIR;
722
+ const includeDir = path.resolve(packageRoot, includeRel);
723
+ const libDir = path.resolve(packageRoot, libRel);
724
+ const includeExists = await pathExists(includeDir);
725
+ const libExists = await pathExists(libDir);
726
+ if (!includeExists && !libExists) {
727
+ throw new Error(
728
+ `Import ${packageName} does not provide include or lib directories.`
729
+ );
730
+ }
731
+ return {
732
+ includeDir: includeExists ? includeDir : void 0,
733
+ libDir: libExists ? libDir : void 0
734
+ };
735
+ };
736
+ const resolveImportDirectories = async (rootDir, imports) => {
737
+ if (imports.length === 0) {
738
+ return { includeDirs: [], libDirs: [] };
739
+ }
740
+ const moduleApi = await Promise.resolve().then(() => require("./__vite-browser-external-DES75WN9.cjs"));
741
+ const resolver = moduleApi.createRequire(path.resolve(rootDir, "package.json"));
742
+ const includeDirs = [];
743
+ const libDirs = [];
744
+ for (const packageName of imports) {
745
+ const resolved = await resolveImportPaths(resolver, packageName);
746
+ if (resolved.includeDir) {
747
+ includeDirs.push(resolved.includeDir);
748
+ }
749
+ if (resolved.libDir) {
750
+ libDirs.push(resolved.libDir);
751
+ }
752
+ }
753
+ return {
754
+ includeDirs: dedupeValues(includeDirs),
755
+ libDirs: dedupeValues(libDirs)
756
+ };
757
+ };
625
758
  const buildCompileArgs = (options, includeDirs, defines, env, rootDir) => {
626
759
  const resolvedOptions = expandArray(options, env, "options");
627
760
  const includeArgs = resolveIncludeDirs(includeDirs, env, rootDir).map(
@@ -631,15 +764,15 @@ const buildCompileArgs = (options, includeDirs, defines, env, rootDir) => {
631
764
  return { resolvedOptions, includeArgs, defineArgs };
632
765
  };
633
766
  const buildWasm = async (options) => {
634
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
767
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
635
768
  if (!options) {
636
769
  throw new TypeError("options must be provided.");
637
770
  }
638
771
  if (!options.rule || !options.rule.targets) {
639
772
  throw new TypeError("rule targets must be provided.");
640
773
  }
641
- const targets = Object.entries(options.rule.targets);
642
- if (targets.length === 0) {
774
+ const targetEntries = Object.entries(options.rule.targets);
775
+ if (targetEntries.length === 0) {
643
776
  throw new TypeError("rule targets must not be empty.");
644
777
  }
645
778
  const logger = (_a = options.logger) != null ? _a : createConsoleLogger("emsdk-env");
@@ -656,57 +789,118 @@ const buildWasm = async (options) => {
656
789
  baseEnv,
657
790
  "srcDir"
658
791
  );
792
+ const rawIncludeDir = expandPlaceholders(
793
+ (_d = options.includeDir) != null ? _d : DEFAULT_WASM_INCLUDE_DIR,
794
+ baseEnv,
795
+ "includeDir"
796
+ );
659
797
  const rawOutDir = expandPlaceholders(
660
- (_d = options.outDir) != null ? _d : DEFAULT_WASM_OUT_DIR,
798
+ (_e = options.outDir) != null ? _e : DEFAULT_WASM_OUT_DIR,
661
799
  baseEnv,
662
800
  "outDir"
663
801
  );
802
+ const rawLibDir = expandPlaceholders(
803
+ (_f = options.libDir) != null ? _f : DEFAULT_WASM_LIB_DIR,
804
+ baseEnv,
805
+ "libDir"
806
+ );
664
807
  const rawBuildDir = expandPlaceholders(
665
- (_e = options.buildDir) != null ? _e : DEFAULT_WASM_BUILD_DIR,
808
+ (_g = options.buildDir) != null ? _g : DEFAULT_WASM_BUILD_DIR,
666
809
  baseEnv,
667
810
  "buildDir"
668
811
  );
669
812
  const srcDir = resolvePath(rootDir, rawSrcDir);
813
+ const includeDir = resolvePath(rootDir, rawIncludeDir);
670
814
  const outDir = resolvePath(rootDir, rawOutDir);
815
+ const libDir = resolvePath(rootDir, rawLibDir);
671
816
  const buildDir = resolvePath(rootDir, rawBuildDir);
672
817
  const buildId = createBuildId();
673
818
  const buildRunDir = path.resolve(buildDir, buildId);
674
- const cleanupBuildDir = (_f = options.cleanupBuildDir) != null ? _f : true;
675
- const parallel = (_g = options.parallel) != null ? _g : true;
819
+ const cleanupBuildDir = (_h = options.cleanupBuildDir) != null ? _h : true;
820
+ const parallel = (_i = options.parallel) != null ? _i : true;
676
821
  const envWithDirs = {
677
822
  ...emsdkEnv,
678
823
  ROOT: rootDir,
679
824
  SRC_DIR: srcDir,
825
+ INCLUDE_DIR: includeDir,
680
826
  OUT_DIR: outDir,
827
+ LIB_DIR: libDir,
681
828
  BUILD_DIR: buildDir
682
829
  };
683
830
  const emccCommand = await resolveEmccCommand(envWithDirs, emsdkRoot);
684
- const common = (_h = options.rule.common) != null ? _h : {};
831
+ const common = (_j = options.rule.common) != null ? _j : {};
832
+ const commonIncludeDirs = common.includeDirs === void 0 ? [includeDir] : common.includeDirs;
833
+ const importDirectories = await resolveImportDirectories(
834
+ rootDir,
835
+ ensureArray(options.imports)
836
+ );
837
+ const importIncludeDirs = importDirectories.includeDirs;
838
+ const importLibDirs = importDirectories.libDirs;
839
+ const linkLibDirs = dedupeValues([libDir, ...importLibDirs]);
840
+ logger.debug(`Detected rootDir: '${rootDir}'`);
841
+ logger.debug(`Detected srcDir: '${srcDir}'`);
842
+ logger.debug(`Detected outDir: '${outDir}'`);
843
+ logger.debug(`Detected libDir: '${libDir}'`);
844
+ logger.debug(`Detected buildDir: '${buildDir}'`);
845
+ logger.debug(`Detected buildId: '${buildId}'`);
846
+ logger.debug(`Detected buildRunDir: '${buildRunDir}'`);
847
+ logger.debug(`Detected cleanupBuildDir: ${cleanupBuildDir}`);
848
+ logger.debug(`Detected parallel: ${parallel}`);
849
+ logger.debug(`Detected emccCommand: '${emccCommand}'`);
850
+ logger.debug(
851
+ `Detected importIncludeDirs: [${importIncludeDirs.map((p) => `'${p}'`).join(",")}]`
852
+ );
853
+ logger.debug(
854
+ `Detected importLibDirs: [${importLibDirs.map((p) => `'${p}'`).join(",")}]`
855
+ );
685
856
  await ensureDirectory(outDir);
857
+ await ensureDirectory(libDir);
686
858
  await ensureDirectory(buildDir);
687
859
  await promises.rm(buildRunDir, { recursive: true, force: true });
688
860
  await ensureDirectory(buildRunDir);
861
+ const hasArchiveTargets = targetEntries.some(
862
+ ([, target]) => resolveTargetType(target.type) === "archive"
863
+ );
864
+ const emarCommand = hasArchiveTargets ? await resolveEmarCommand(envWithDirs, emsdkRoot) : void 0;
865
+ if (emarCommand) {
866
+ logger.debug(`Detected emarCommand: '${emarCommand}'`);
867
+ }
689
868
  const outFiles = {};
690
- try {
691
- for (const [targetName, target] of targets) {
692
- const mergedLinkOptions = [
869
+ const buildTargets = async (expectedType) => {
870
+ var _a2;
871
+ for (const [targetName, target] of targetEntries) {
872
+ const targetType = resolveTargetType(target.type);
873
+ if (targetType !== expectedType) {
874
+ continue;
875
+ }
876
+ if (targetType === "archive") {
877
+ if (target.linkOptions !== void 0) {
878
+ throw new Error(
879
+ `linkOptions is not supported for archive target: ${targetName}`
880
+ );
881
+ }
882
+ if (target.exports !== void 0) {
883
+ throw new Error(
884
+ `exports is not supported for archive target: ${targetName}`
885
+ );
886
+ }
887
+ }
888
+ const mergedLinkOptions = targetType === "archive" ? [] : [
693
889
  ...ensureArray(common.linkOptions),
694
890
  ...ensureArray(target.linkOptions)
695
891
  ];
696
- const mergedExports = [
697
- ...ensureArray(common.exports),
698
- ...ensureArray(target.exports)
699
- ];
892
+ const mergedExports = targetType === "archive" ? [] : [...ensureArray(common.exports), ...ensureArray(target.exports)];
700
893
  const baseCompileOptions = [
701
894
  ...ensureArray(common.options),
702
895
  ...ensureArray(target.options)
703
896
  ];
704
897
  const baseIncludeDirs = [
705
- ...ensureArray(common.includeDirs),
706
- ...ensureArray(target.includeDirs)
898
+ ...ensureArray(commonIncludeDirs),
899
+ ...ensureArray(target.includeDirs),
900
+ ...importIncludeDirs
707
901
  ];
708
902
  const baseDefines = mergeDefines(common.defines, target.defines);
709
- const sourceGroups = (_i = target.sourceGroups) != null ? _i : [];
903
+ const sourceGroups = (_a2 = target.sourceGroups) != null ? _a2 : [];
710
904
  const targetEnv = {
711
905
  ...envWithDirs,
712
906
  TARGET_NAME: targetName
@@ -716,7 +910,8 @@ const buildWasm = async (options) => {
716
910
  targetName,
717
911
  target.outFile,
718
912
  targetEnv,
719
- outDir
913
+ targetType === "archive" ? libDir : outDir,
914
+ targetType === "archive" ? "a" : "wasm"
720
915
  );
721
916
  const sources = await resolveTargetSources(
722
917
  target.sources,
@@ -752,12 +947,8 @@ const buildWasm = async (options) => {
752
947
  const targetBuildDir = path.resolve(buildRunDir, targetName);
753
948
  await promises.rm(targetBuildDir, { recursive: true, force: true });
754
949
  await ensureDirectory(targetBuildDir);
755
- const resolvedLinkOptions = expandArray(
756
- mergedLinkOptions,
757
- targetEnv,
758
- "linkOptions"
759
- );
760
- const resolvedExports = expandArray(mergedExports, targetEnv, "exports");
950
+ const resolvedLinkOptions = targetType === "archive" ? [] : expandArray(mergedLinkOptions, targetEnv, "linkOptions");
951
+ const resolvedExports = targetType === "archive" ? [] : expandArray(mergedExports, targetEnv, "exports");
761
952
  const exportArgs = buildExportFlags(resolvedExports);
762
953
  const baseCompileArgs = buildCompileArgs(
763
954
  baseCompileOptions,
@@ -767,7 +958,7 @@ const buildWasm = async (options) => {
767
958
  rootDir
768
959
  );
769
960
  const groupCompileArgs = sourceGroups.map((group) => {
770
- var _a2;
961
+ var _a3;
771
962
  const groupOptions = [
772
963
  ...baseCompileOptions,
773
964
  ...ensureArray(group == null ? void 0 : group.options)
@@ -776,7 +967,7 @@ const buildWasm = async (options) => {
776
967
  ...baseIncludeDirs,
777
968
  ...ensureArray(group == null ? void 0 : group.includeDirs)
778
969
  ];
779
- const groupDefines = mergeDefines(baseDefines, (_a2 = group == null ? void 0 : group.defines) != null ? _a2 : {});
970
+ const groupDefines = mergeDefines(baseDefines, (_a3 = group == null ? void 0 : group.defines) != null ? _a3 : {});
780
971
  return buildCompileArgs(
781
972
  groupOptions,
782
973
  groupIncludeDirs,
@@ -785,7 +976,6 @@ const buildWasm = async (options) => {
785
976
  rootDir
786
977
  );
787
978
  });
788
- logger.info(`Compiling target: ${targetName}`);
789
979
  const compileSource = async (source, args, groupIndex) => {
790
980
  const objectName = toSafeObjectName(rootDir, source, groupIndex);
791
981
  const outputObject = path.resolve(targetBuildDir, `${objectName}.o`);
@@ -798,6 +988,8 @@ const buildWasm = async (options) => {
798
988
  ...args.includeArgs,
799
989
  ...args.defineArgs
800
990
  ];
991
+ const sourcePath = path.relative(rootDir, source);
992
+ logger.info(`Compiling source: ${sourcePath} --> $tmp/${objectName}.o`);
801
993
  logger.debug(`emcc ${compileArgs.join(" ")}`);
802
994
  await runCommandWithEnv(
803
995
  emccCommand,
@@ -838,6 +1030,9 @@ const buildWasm = async (options) => {
838
1030
  groupIndex: void 0
839
1031
  });
840
1032
  }
1033
+ logger.info(
1034
+ parallel ? `Building target: '${targetName}' [${compileJobs.length} files, in parallel]` : `Building target: '${targetName}' [${compileJobs.length} files]`
1035
+ );
841
1036
  for (let index = 0; index < groupSources.length; index += 1) {
842
1037
  const sourcesInGroup = groupSources[index];
843
1038
  if (!sourcesInGroup) {
@@ -856,24 +1051,45 @@ const buildWasm = async (options) => {
856
1051
  (job) => compileSource(job.source, job.args, job.groupIndex)
857
1052
  )
858
1053
  ) : await buildObjectsSequential();
859
- logger.info(`Linking target: ${targetName}`);
860
- const linkArgs = [
861
- ...objectFiles,
862
- "-o",
863
- resolvedOutFile,
864
- ...resolvedLinkOptions,
865
- ...exportArgs
866
- ];
867
- logger.debug(`emcc ${linkArgs.join(" ")}`);
868
- await runCommandWithEnv(
869
- emccCommand,
870
- linkArgs,
871
- rootDir,
872
- buildEnv,
873
- emsdkOptions.signal
874
- );
1054
+ if (targetType === "archive") {
1055
+ if (!emarCommand) {
1056
+ throw new Error("emar command is required for archive targets.");
1057
+ }
1058
+ logger.info(`Archiving target: ${targetName}.a`);
1059
+ const archiveArgs = ["rcs", resolvedOutFile, ...objectFiles];
1060
+ logger.debug(`emar ${archiveArgs.join(" ")}`);
1061
+ await runCommandWithEnv(
1062
+ emarCommand,
1063
+ archiveArgs,
1064
+ rootDir,
1065
+ buildEnv,
1066
+ emsdkOptions.signal
1067
+ );
1068
+ } else {
1069
+ logger.info(`Linking target: ${targetName}.wasm`);
1070
+ const linkArgs = [
1071
+ ...objectFiles,
1072
+ "-o",
1073
+ resolvedOutFile,
1074
+ ...linkLibDirs.map((dir) => `-L${dir}`),
1075
+ ...resolvedLinkOptions,
1076
+ ...exportArgs
1077
+ ];
1078
+ logger.debug(`emcc ${linkArgs.join(" ")}`);
1079
+ await runCommandWithEnv(
1080
+ emccCommand,
1081
+ linkArgs,
1082
+ rootDir,
1083
+ buildEnv,
1084
+ emsdkOptions.signal
1085
+ );
1086
+ }
875
1087
  outFiles[targetName] = resolvedOutFile;
876
1088
  }
1089
+ };
1090
+ try {
1091
+ await buildTargets("archive");
1092
+ await buildTargets("wasm");
877
1093
  } finally {
878
1094
  if (cleanupBuildDir) {
879
1095
  await promises.rm(buildRunDir, { recursive: true, force: true });
@@ -886,4 +1102,4 @@ const buildWasm = async (options) => {
886
1102
  };
887
1103
  exports.buildWasm = buildWasm;
888
1104
  exports.prepareEmsdk = prepareEmsdk;
889
- //# sourceMappingURL=build-DdEthYh8.cjs.map
1105
+ //# sourceMappingURL=build-DwIdyC2W.cjs.map