1- //! Creation of ar archives like for the lib and staticlib crate type
2-
3- use std:: collections:: BTreeMap ;
4- use std:: fs:: File ;
5- use std:: io:: { self , Read , Seek } ;
61use std:: path:: { Path , PathBuf } ;
72
8- use rustc_codegen_ssa:: back:: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
3+ use rustc_codegen_ssa:: back:: archive:: {
4+ get_native_object_symbols, ArArchiveBuilder , ArchiveBuilder , ArchiveBuilderBuilder ,
5+ } ;
96use rustc_session:: Session ;
107
11- use object:: read:: archive:: ArchiveFile ;
12- use object:: { Object , ObjectSymbol , ReadCache } ;
13-
14- #[ derive( Debug ) ]
15- enum ArchiveEntry {
16- FromArchive { archive_index : usize , file_range : ( u64 , u64 ) } ,
17- File ( PathBuf ) ,
18- }
19-
208pub ( crate ) struct ArArchiveBuilderBuilder ;
219
2210impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
2311 fn new_archive_builder < ' a > ( & self , sess : & ' a Session ) -> Box < dyn ArchiveBuilder < ' a > + ' a > {
24- Box :: new ( ArArchiveBuilder {
25- sess,
26- use_gnu_style_archive : sess. target . archive_format == "gnu" ,
27- // FIXME fix builtin ranlib on macOS
28- no_builtin_ranlib : sess. target . is_like_osx ,
29-
30- src_archives : vec ! [ ] ,
31- entries : vec ! [ ] ,
32- } )
12+ Box :: new ( ArArchiveBuilder :: new ( sess, get_native_object_symbols) )
3313 }
3414
3515 fn create_dll_import_lib (
@@ -40,200 +20,6 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
4020 _tmpdir : & Path ,
4121 _is_direct_dependency : bool ,
4222 ) -> PathBuf {
43- bug ! ( "creating dll imports is not supported" ) ;
44- }
45- }
46-
47- pub ( crate ) struct ArArchiveBuilder < ' a > {
48- sess : & ' a Session ,
49- use_gnu_style_archive : bool ,
50- no_builtin_ranlib : bool ,
51-
52- src_archives : Vec < File > ,
53- // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
54- // the end of an archive for linkers to not get confused.
55- entries : Vec < ( Vec < u8 > , ArchiveEntry ) > ,
56- }
57-
58- impl < ' a > ArchiveBuilder < ' a > for ArArchiveBuilder < ' a > {
59- fn add_file ( & mut self , file : & Path ) {
60- self . entries . push ( (
61- file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) . into_bytes ( ) ,
62- ArchiveEntry :: File ( file. to_owned ( ) ) ,
63- ) ) ;
64- }
65-
66- fn add_archive (
67- & mut self ,
68- archive_path : & Path ,
69- mut skip : Box < dyn FnMut ( & str ) -> bool + ' static > ,
70- ) -> std:: io:: Result < ( ) > {
71- let read_cache = ReadCache :: new ( std:: fs:: File :: open ( & archive_path) ?) ;
72- let archive = ArchiveFile :: parse ( & read_cache) . unwrap ( ) ;
73- let archive_index = self . src_archives . len ( ) ;
74-
75- for entry in archive. members ( ) {
76- let entry = entry. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
77- let file_name = String :: from_utf8 ( entry. name ( ) . to_vec ( ) )
78- . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
79- if !skip ( & file_name) {
80- self . entries . push ( (
81- file_name. into_bytes ( ) ,
82- ArchiveEntry :: FromArchive { archive_index, file_range : entry. file_range ( ) } ,
83- ) ) ;
84- }
85- }
86-
87- self . src_archives . push ( read_cache. into_inner ( ) ) ;
88- Ok ( ( ) )
89- }
90-
91- fn build ( mut self : Box < Self > , output : & Path ) -> bool {
92- enum BuilderKind {
93- Bsd ( ar:: Builder < File > ) ,
94- Gnu ( ar:: GnuBuilder < File > ) ,
95- }
96-
97- let sess = self . sess ;
98-
99- let mut symbol_table = BTreeMap :: new ( ) ;
100-
101- let mut entries = Vec :: new ( ) ;
102-
103- for ( mut entry_name, entry) in self . entries {
104- // FIXME only read the symbol table of the object files to avoid having to keep all
105- // object files in memory at once, or read them twice.
106- let data = match entry {
107- ArchiveEntry :: FromArchive { archive_index, file_range } => {
108- // FIXME read symbols from symtab
109- let src_read_cache = & mut self . src_archives [ archive_index] ;
110-
111- src_read_cache. seek ( io:: SeekFrom :: Start ( file_range. 0 ) ) . unwrap ( ) ;
112- let mut data = std:: vec:: from_elem ( 0 , usize:: try_from ( file_range. 1 ) . unwrap ( ) ) ;
113- src_read_cache. read_exact ( & mut data) . unwrap ( ) ;
114-
115- data
116- }
117- ArchiveEntry :: File ( file) => std:: fs:: read ( file) . unwrap_or_else ( |err| {
118- sess. fatal ( & format ! (
119- "error while reading object file during archive building: {}" ,
120- err
121- ) ) ;
122- } ) ,
123- } ;
124-
125- if !self . no_builtin_ranlib {
126- if symbol_table. contains_key ( & entry_name) {
127- // The ar crate can't handle creating a symbol table in case of multiple archive
128- // members with the same name. Work around this by prepending a number until we
129- // get a unique name.
130- for i in 1 .. {
131- let new_name = format ! ( "{}_" , i)
132- . into_bytes ( )
133- . into_iter ( )
134- . chain ( entry_name. iter ( ) . copied ( ) )
135- . collect :: < Vec < _ > > ( ) ;
136- if !symbol_table. contains_key ( & new_name) {
137- entry_name = new_name;
138- break ;
139- }
140- }
141- }
142-
143- match object:: File :: parse ( & * data) {
144- Ok ( object) => {
145- symbol_table. insert (
146- entry_name. to_vec ( ) ,
147- object
148- . symbols ( )
149- . filter_map ( |symbol| {
150- if symbol. is_undefined ( ) || symbol. is_local ( ) {
151- None
152- } else {
153- symbol. name ( ) . map ( |name| name. as_bytes ( ) . to_vec ( ) ) . ok ( )
154- }
155- } )
156- . collect :: < Vec < _ > > ( ) ,
157- ) ;
158- }
159- Err ( err) => {
160- let err = err. to_string ( ) ;
161- if err == "Unknown file magic" {
162- // Not an object file; skip it.
163- } else if object:: read:: archive:: ArchiveFile :: parse ( & * data) . is_ok ( ) {
164- // Nested archive file; skip it.
165- } else {
166- sess. fatal ( & format ! (
167- "error parsing `{}` during archive creation: {}" ,
168- String :: from_utf8_lossy( & entry_name) ,
169- err
170- ) ) ;
171- }
172- }
173- }
174- }
175-
176- entries. push ( ( entry_name, data) ) ;
177- }
178-
179- let mut builder = if self . use_gnu_style_archive {
180- BuilderKind :: Gnu (
181- ar:: GnuBuilder :: new (
182- File :: create ( output) . unwrap_or_else ( |err| {
183- sess. fatal ( & format ! (
184- "error opening destination during archive building: {}" ,
185- err
186- ) ) ;
187- } ) ,
188- entries. iter ( ) . map ( |( name, _) | name. clone ( ) ) . collect ( ) ,
189- ar:: GnuSymbolTableFormat :: Size32 ,
190- symbol_table,
191- )
192- . unwrap ( ) ,
193- )
194- } else {
195- BuilderKind :: Bsd (
196- ar:: Builder :: new (
197- File :: create ( output) . unwrap_or_else ( |err| {
198- sess. fatal ( & format ! (
199- "error opening destination during archive building: {}" ,
200- err
201- ) ) ;
202- } ) ,
203- symbol_table,
204- )
205- . unwrap ( ) ,
206- )
207- } ;
208-
209- let any_members = !entries. is_empty ( ) ;
210-
211- // Add all files
212- for ( entry_name, data) in entries. into_iter ( ) {
213- let header = ar:: Header :: new ( entry_name, data. len ( ) as u64 ) ;
214- match builder {
215- BuilderKind :: Bsd ( ref mut builder) => builder. append ( & header, & mut & * data) . unwrap ( ) ,
216- BuilderKind :: Gnu ( ref mut builder) => builder. append ( & header, & mut & * data) . unwrap ( ) ,
217- }
218- }
219-
220- // Finalize archive
221- std:: mem:: drop ( builder) ;
222-
223- if self . no_builtin_ranlib {
224- let ranlib = crate :: toolchain:: get_toolchain_binary ( self . sess , "ranlib" ) ;
225-
226- // Run ranlib to be able to link the archive
227- let status = std:: process:: Command :: new ( ranlib)
228- . arg ( output)
229- . status ( )
230- . expect ( "Couldn't run ranlib" ) ;
231-
232- if !status. success ( ) {
233- self . sess . fatal ( & format ! ( "Ranlib exited with code {:?}" , status. code( ) ) ) ;
234- }
235- }
236-
237- any_members
23+ unimplemented ! ( "creating dll imports is not yet supported" ) ;
23824 }
23925}
0 commit comments