6666
6767-define (DEFAULT_OPTIONS , #{
6868 prune => false ,
69+ lib => false ,
6970 start_module => undefined ,
7071 application_module => undefined ,
7172 include_lines => true
8687% %
8788% % where `DefaultOptions' is `#{
8889% % prune => false,
90+ % % lib => false,
8991% % start_module => undefined,
9092% % application_module => undefined,
9193% % include_lines => false
@@ -120,11 +122,12 @@ create(OutputPath, InputPaths) ->
120122create (OutputPath , InputPaths , Options ) ->
121123 #{
122124 prune := Prune ,
125+ lib := Lib ,
123126 start_module := StartModule ,
124127 application_module := ApplicationModule ,
125128 include_lines := IncludeLines
126129 } = maps :merge (? DEFAULT_OPTIONS , Options ),
127- ParsedFiles = parse_files (InputPaths , StartModule , IncludeLines ),
130+ ParsedFiles = parse_files (InputPaths , Lib , StartModule , IncludeLines ),
128131 write_packbeam (
129132 OutputPath ,
130133 case Prune of
@@ -216,7 +219,7 @@ create(OutputPath, InputPaths, ApplicationModule, Prune, StartModule) ->
216219list (InputPath ) ->
217220 case file_type (InputPath ) of
218221 avm ->
219- parse_file (InputPath , undefined , false );
222+ parse_file (InputPath , false , undefined , false );
220223 _ ->
221224 throw (io_lib :format (" Expected AVM file: ~p " , [InputPath ]))
222225 end .
@@ -244,7 +247,7 @@ list(InputPath) ->
244247extract (InputPath , AVMElementNames , OutputDir ) ->
245248 case file_type (InputPath ) of
246249 avm ->
247- ParsedFiles = parse_file (InputPath , undefined , false ),
250+ ParsedFiles = parse_file (InputPath , false , undefined , false ),
248251 write_files (filter_names (AVMElementNames , ParsedFiles ), OutputDir );
249252 _ ->
250253 throw (io_lib :format (" Expected AVM file: ~p " , [InputPath ]))
@@ -271,7 +274,7 @@ extract(InputPath, AVMElementNames, OutputDir) ->
271274delete (OutputPath , InputPath , AVMElementNames ) ->
272275 case file_type (InputPath ) of
273276 avm ->
274- ParsedFiles = parse_file (InputPath , undefined , false ),
277+ ParsedFiles = parse_file (InputPath , false , undefined , false ),
275278 write_packbeam (OutputPath , remove_names (AVMElementNames , ParsedFiles ));
276279 _ ->
277280 throw (io_lib :format (" Expected AVM file: ~p " , [InputPath ]))
@@ -338,10 +341,10 @@ get_flags(AVMElement) ->
338341 proplists :get_value (flags , AVMElement ).
339342
340343% % @private
341- parse_files (InputPaths , StartModule , IncludeLines ) ->
344+ parse_files (InputPaths , Lib , StartModule , IncludeLines ) ->
342345 Files = lists :foldl (
343346 fun (InputPath , Accum ) ->
344- Accum ++ parse_file (InputPath , StartModule , IncludeLines )
347+ Accum ++ parse_file (InputPath , Lib , StartModule , IncludeLines )
345348 end ,
346349 [],
347350 InputPaths
@@ -354,10 +357,14 @@ parse_files(InputPaths, StartModule, IncludeLines) ->
354357 end .
355358
356359% % @private
357- parse_file ({InputPath , ModuleName }, StartModule , IncludeLines ) ->
358- parse_file (file_type (InputPath ), ModuleName , StartModule , load_file (InputPath ), IncludeLines );
359- parse_file (InputPath , StartModule , IncludeLines ) ->
360- parse_file (file_type (InputPath ), InputPath , StartModule , load_file (InputPath ), IncludeLines ).
360+ parse_file ({InputPath , ModuleName }, Lib , StartModule , IncludeLines ) ->
361+ parse_file (
362+ file_type (InputPath ), ModuleName , Lib , StartModule , load_file (InputPath ), IncludeLines
363+ );
364+ parse_file (InputPath , Lib , StartModule , IncludeLines ) ->
365+ parse_file (
366+ file_type (InputPath ), InputPath , Lib , StartModule , load_file (InputPath ), IncludeLines
367+ ).
361368
362369% % @private
363370file_type (InputPath ) ->
@@ -595,7 +602,7 @@ filter_modules(Modules, ParsedFiles) ->
595602 ).
596603
597604% % @private
598- parse_file (beam , _ModuleName , StartModule , Data , IncludeLines ) ->
605+ parse_file (beam , _ModuleName , Lib , StartModule , Data , IncludeLines ) ->
599606 {ok , Module , Chunks } = beam_lib :all_chunks (Data ),
600607 {UncompressedChunks , UncompressedLiterals } = maybe_uncompress_literals (Chunks ),
601608 FilteredChunks = filter_chunks (UncompressedChunks , IncludeLines ),
@@ -606,7 +613,7 @@ parse_file(beam, _ModuleName, StartModule, Data, IncludeLines) ->
606613 if
607614 StartModule =:= Module ->
608615 ? BEAM_CODE_FLAG bor ? BEAM_START_FLAG ;
609- StartModule =:= undefined ->
616+ StartModule =:= undefined andalso Lib =:= false ->
610617 case lists :member ({start , 0 }, Exports ) of
611618 true ->
612619 ? BEAM_CODE_FLAG bor ? BEAM_START_FLAG ;
@@ -626,14 +633,14 @@ parse_file(beam, _ModuleName, StartModule, Data, IncludeLines) ->
626633 {uncompressed_literals , UncompressedLiterals }
627634 ]
628635 ];
629- parse_file (avm , ModuleName , _StartModule , Data , _IncludeLines ) ->
636+ parse_file (avm , ModuleName , Lib , StartModule , Data , _IncludeLines ) ->
630637 case Data of
631638 <<? AVM_HEADER , AVMData /binary >> ->
632- parse_avm_data (AVMData );
639+ parse_avm_data (Lib , StartModule , AVMData );
633640 _ ->
634641 throw (io_lib :format (" Invalid AVM header: ~p " , [ModuleName ]))
635642 end ;
636- parse_file (normal , ModuleName , _StartModule , Data , _IncludeLines ) ->
643+ parse_file (normal , ModuleName , _Lib , _StartModule , Data , _IncludeLines ) ->
637644 DataSize = byte_size (Data ),
638645 Blob = <<DataSize :32 , Data /binary >>,
639646 [[{element_name , ModuleName }, {flags , ? NORMAL_FILE_FLAG }, {data , Blob }]].
@@ -664,21 +671,41 @@ reorder_start_module(StartModule, Files) ->
664671 end .
665672
666673% % @private
667- parse_avm_data (AVMData ) ->
668- parse_avm_data (AVMData , []).
674+ parse_avm_data (Lib , StartModule , AVMData ) ->
675+ parse_avm_data (Lib , StartModule , AVMData , []).
669676
670677% % @private
671- parse_avm_data (<<" " >>, Accum ) ->
678+ parse_avm_data (_Lib , _StartModule , <<" " >>, Accum ) ->
672679 lists :reverse (Accum );
673- parse_avm_data (<<0 :32 /integer , _AVMRest /binary >>, Accum ) ->
680+ parse_avm_data (_Lib , _StartModule , <<0 :32 /integer , _AVMRest /binary >>, Accum ) ->
674681 lists :reverse (Accum );
675- parse_avm_data (<<Size :32 /integer , AVMRest /binary >>, Accum ) ->
682+ parse_avm_data (Lib , StartModule , <<Size :32 /integer , AVMRest /binary >>, Accum ) ->
676683 SizeWithoutSizeField = Size - 4 ,
677684 case SizeWithoutSizeField =< erlang :byte_size (AVMRest ) of
678685 true ->
679686 <<AVMBeamData :SizeWithoutSizeField /binary , AVMNext /binary >> = AVMRest ,
680- Beam = parse_beam (AVMBeamData , [], in_header , 0 , []),
681- parse_avm_data (AVMNext , [Beam | Accum ]);
687+ Beam0 = parse_beam (AVMBeamData , [], in_header , 0 , []),
688+ {flags , BeamFlags0 } = lists :keyfind (flags , 1 , Beam0 ),
689+ BeamModule =
690+ case lists :keyfind (module , 1 , Beam0 ) of
691+ false -> undefined ;
692+ {module , BeamModule0 } -> BeamModule0
693+ end ,
694+ BeamFlags1 =
695+ if
696+ Lib ->
697+ BeamFlags0 band (bnot ? BEAM_START_FLAG );
698+ BeamModule =:= undefined ->
699+ BeamFlags0 ;
700+ StartModule =:= BeamModule ->
701+ BeamFlags0 bor ? BEAM_START_FLAG ;
702+ StartModule =/= undefined ->
703+ BeamFlags0 band (bnot ? BEAM_START_FLAG );
704+ true ->
705+ BeamFlags0
706+ end ,
707+ Beam1 = lists :keystore (flags , 1 , Beam0 , {flags , BeamFlags1 }),
708+ parse_avm_data (Lib , StartModule , AVMNext , [Beam1 | Accum ]);
682709 _ ->
683710 throw (
684711 io_lib :format (" Invalid AVM data size: ~p (AVMRest=~p )" , [
0 commit comments