@@ -620,6 +620,12 @@ int main(int argc, const char* argv[]) {
620620 std::string outputSourceMapFilename;
621621 std::string outputSourceMapUrl;
622622
623+ // We can write wasm-split manifests that can later be fed to wasm-split to
624+ // split the merged module back up along the lines of the original modules.
625+ // Map functions to their originating modules so we can write this manifest.
626+ std::string manifestFile;
627+ std::unordered_map<Name, Name> functionToModule;
628+
623629 const std::string WasmMergeOption = " wasm-merge options" ;
624630
625631 ToolOptions options (" wasm-merge" ,
@@ -687,6 +693,16 @@ Input source maps can be specified by adding an -ism option right after the modu
687693 [&outputSourceMapUrl](Options* o, const std::string& argument) {
688694 outputSourceMapUrl = argument;
689695 })
696+ .add (" --output-manifest" ,
697+ " " ,
698+ " Write a wasm-split manifest to the specified file. This manifest can "
699+ " be given to wasm-split to split the merged module along the lines of "
700+ " the original modules." ,
701+ WasmMergeOption,
702+ Options::Arguments::One,
703+ [&manifestFile](Options* o, const std::string& argument) {
704+ manifestFile = argument;
705+ })
690706 .add (" --rename-export-conflicts" ,
691707 " -rec" ,
692708 " Rename exports to avoid conflicts (rather than error)" ,
@@ -780,6 +796,15 @@ Input source maps can be specified by adding an -ism option right after the modu
780796 // This is a later module: do a full merge.
781797 mergeInto (*currModule, inputFileName);
782798
799+ // The functions in the module have been renamed and copied rather than
800+ // moved, so we can get their final names directly. (We don't need this
801+ // for the first module because it does not appear in the manifest.)
802+ for (auto & func : currModule->functions ) {
803+ if (!func->imported ()) {
804+ functionToModule[func->name ] = inputFileName;
805+ }
806+ }
807+
783808 // Validate after each merged module, when we are in pass-debug mode
784809 // (this can be quadratic time).
785810 if (PassRunner::getPassDebug ()) {
@@ -822,6 +847,28 @@ Input source maps can be specified by adding an -ism option right after the modu
822847 }
823848
824849 // Output.
850+ if (!manifestFile.empty ()) {
851+ std::ofstream manifest (manifestFile);
852+ // Skip module 0 because it will be the primary module for the split and
853+ // does not need to appear in the manifest.
854+ for (size_t i = 1 ; i < inputFileNames.size (); i++) {
855+ const auto & moduleName = inputFileNames[i];
856+ bool first = true ;
857+ for (auto & func : merged.functions ) {
858+ if (!func->imported () && functionToModule[func->name ] == moduleName) {
859+ if (first) {
860+ manifest << moduleName << " \n " ;
861+ first = false ;
862+ }
863+ manifest << func->name .str << " \n " ;
864+ }
865+ }
866+ if (!first) {
867+ manifest << " \n " ;
868+ }
869+ }
870+ }
871+
825872 if (options.extra .count (" output" ) > 0 ) {
826873 ModuleWriter writer (options.passOptions );
827874 writer.setBinary (emitBinary);
0 commit comments