@@ -123,6 +123,18 @@ size_t SeaSerializer::Write(const SeaResource& sea) {
123123 written_total += WriteStringView (content, StringLogMode::kAddressOnly );
124124 }
125125 }
126+
127+ if (static_cast <bool >(sea.flags & SeaFlags::kIncludeExecArgv )) {
128+ Debug (" Write SEA resource exec argv size %zu\n " , sea.exec_argv .size ());
129+ written_total += WriteArithmetic<size_t >(sea.exec_argv .size ());
130+ for (const auto & arg : sea.exec_argv ) {
131+ Debug (" Write SEA resource exec arg %s at %p, size=%zu\n " ,
132+ arg.data (),
133+ arg.data (),
134+ arg.size ());
135+ written_total += WriteStringView (arg, StringLogMode::kAddressAndContent );
136+ }
137+ }
126138 return written_total;
127139}
128140
@@ -185,7 +197,22 @@ SeaResource SeaDeserializer::Read() {
185197 assets.emplace (key, content);
186198 }
187199 }
188- return {flags, code_path, code, code_cache, assets};
200+
201+ std::vector<std::string_view> exec_argv;
202+ if (static_cast <bool >(flags & SeaFlags::kIncludeExecArgv )) {
203+ size_t exec_argv_size = ReadArithmetic<size_t >();
204+ Debug (" Read SEA resource exec args size %zu\n " , exec_argv_size);
205+ exec_argv.reserve (exec_argv_size);
206+ for (size_t i = 0 ; i < exec_argv_size; ++i) {
207+ std::string_view arg = ReadStringView (StringLogMode::kAddressAndContent );
208+ Debug (" Read SEA resource exec arg %s at %p, size=%zu\n " ,
209+ arg.data (),
210+ arg.data (),
211+ arg.size ());
212+ exec_argv.emplace_back (arg);
213+ }
214+ }
215+ return {flags, code_path, code, code_cache, assets, exec_argv};
189216}
190217
191218std::string_view FindSingleExecutableBlob () {
@@ -269,8 +296,27 @@ std::tuple<int, char**> FixupArgsForSEA(int argc, char** argv) {
269296 // entry point file path.
270297 if (IsSingleExecutable ()) {
271298 static std::vector<char *> new_argv;
272- new_argv.reserve (argc + 2 );
299+ static std::vector<std::string> exec_argv_storage;
300+
301+ SeaResource sea_resource = FindSingleExecutableResource ();
302+
303+ new_argv.clear ();
304+ exec_argv_storage.clear ();
305+
306+ // Reserve space for argv[0], exec argv, original argv, and nullptr
307+ new_argv.reserve (argc + sea_resource.exec_argv .size () + 2 );
273308 new_argv.emplace_back (argv[0 ]);
309+
310+ // Insert exec argv from SEA config
311+ if (!sea_resource.exec_argv .empty ()) {
312+ exec_argv_storage.reserve (sea_resource.exec_argv .size ());
313+ for (const auto & arg : sea_resource.exec_argv ) {
314+ exec_argv_storage.emplace_back (arg);
315+ new_argv.emplace_back (exec_argv_storage.back ().data ());
316+ }
317+ }
318+
319+ // Add actual run time arguments.
274320 new_argv.insert (new_argv.end (), argv, argv + argc);
275321 new_argv.emplace_back (nullptr );
276322 argc = new_argv.size () - 1 ;
@@ -287,6 +333,7 @@ struct SeaConfig {
287333 std::string output_path;
288334 SeaFlags flags = SeaFlags::kDefault ;
289335 std::unordered_map<std::string, std::string> assets;
336+ std::vector<std::string> exec_argv;
290337};
291338
292339std::optional<SeaConfig> ParseSingleExecutableConfig (
@@ -405,6 +452,29 @@ std::optional<SeaConfig> ParseSingleExecutableConfig(
405452 if (!result.assets .empty ()) {
406453 result.flags |= SeaFlags::kIncludeAssets ;
407454 }
455+ } else if (key == " execArgv" ) {
456+ simdjson::ondemand::array exec_argv_array;
457+ if (field.value ().get_array ().get (exec_argv_array)) {
458+ FPrintF (stderr,
459+ " \" execArgv\" field of %s is not an array of strings\n " ,
460+ config_path);
461+ return std::nullopt ;
462+ }
463+ std::vector<std::string> exec_argv;
464+ for (auto argv : exec_argv_array) {
465+ std::string_view argv_str;
466+ if (argv.get_string ().get (argv_str)) {
467+ FPrintF (stderr,
468+ " \" execArgv\" field of %s is not an array of strings\n " ,
469+ config_path);
470+ return std::nullopt ;
471+ }
472+ exec_argv.emplace_back (argv_str);
473+ }
474+ if (!exec_argv.empty ()) {
475+ result.flags |= SeaFlags::kIncludeExecArgv ;
476+ result.exec_argv = std::move (exec_argv);
477+ }
408478 }
409479 }
410480
@@ -599,14 +669,19 @@ ExitCode GenerateSingleExecutableBlob(
599669 for (auto const & [key, content] : assets) {
600670 assets_view.emplace (key, content);
601671 }
672+ std::vector<std::string_view> exec_argv_view;
673+ for (const auto & arg : config.exec_argv ) {
674+ exec_argv_view.emplace_back (arg);
675+ }
602676 SeaResource sea{
603677 config.flags ,
604678 config.main_path ,
605679 builds_snapshot_from_main
606680 ? std::string_view{snapshot_blob.data (), snapshot_blob.size ()}
607681 : std::string_view{main_script.data (), main_script.size ()},
608682 optional_sv_code_cache,
609- assets_view};
683+ assets_view,
684+ exec_argv_view};
610685
611686 SeaSerializer serializer;
612687 serializer.Write (sea);
0 commit comments