2
2
//
3
3
// Modifications Copyright Kani Contributors
4
4
// See GitHub history for details.
5
- // This file is a lightly modified version of upstream rustc:
5
+ // This file is a heavily modified version of upstream rustc:
6
6
// compiler/rustc_codegen_cranelift/src/archive.rs
7
7
8
- // Along with lifting the deps:
9
- // object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
10
- // ar = "0.8.0"
11
-
12
- // Also: I removed all mentions of 'ranlib' which caused issues on macos.
13
- // We don't actually need these to be passed to a real linker anyway.
14
- // 'ranlib' is about building a global symbol table out of all the object
15
- // files in the archive, and we just don't put object files in our archives.
16
-
17
8
//! Creation of ar archives like for the lib and staticlib crate type
9
+ //! We now call the ArchiveBuilder directly, so we don't bother trying to fit into the rustc's
10
+ //! `ArchiveBuilder`.
11
+ //! Note that once we update to a version newer than 2022-12-04 we should be able to remove the
12
+ //! logic here and use the compiler ArArchiveBuilder introduced here:
13
+ //! <https://github.com/rust-lang/rust/pull/97485>
18
14
15
+ use rustc_session:: Session ;
19
16
use std:: fs:: File ;
20
- use std:: io:: { self , Read , Seek } ;
21
17
use std:: path:: { Path , PathBuf } ;
22
18
23
- use rustc_codegen_ssa:: back:: archive:: { ArchiveBuilder , ArchiveBuilderBuilder } ;
24
- use rustc_session:: Session ;
25
-
26
- use object:: read:: archive:: ArchiveFile ;
27
- use object:: ReadCache ;
28
-
29
- #[ derive( Debug ) ]
30
- enum ArchiveEntry {
31
- FromArchive { archive_index : usize , file_range : ( u64 , u64 ) } ,
32
- File ( PathBuf ) ,
33
- }
34
-
35
- pub ( crate ) struct ArArchiveBuilder < ' a > {
19
+ pub ( crate ) struct ArchiveBuilder < ' a > {
36
20
sess : & ' a Session ,
37
21
use_gnu_style_archive : bool ,
38
22
39
- src_archives : Vec < File > ,
40
23
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
41
24
// the end of an archive for linkers to not get confused.
42
- entries : Vec < ( Vec < u8 > , ArchiveEntry ) > ,
25
+ entries : Vec < ( Vec < u8 > , PathBuf ) > ,
43
26
}
44
27
45
- impl < ' a > ArchiveBuilder < ' a > for ArArchiveBuilder < ' a > {
46
- fn add_file ( & mut self , file : & Path ) {
28
+ impl < ' a > ArchiveBuilder < ' a > {
29
+ pub fn add_file ( & mut self , file : & Path ) {
47
30
self . entries . push ( (
48
31
file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) . into_bytes ( ) ,
49
- ArchiveEntry :: File ( file. to_owned ( ) ) ,
32
+ file. to_owned ( ) ,
50
33
) ) ;
51
34
}
52
35
53
- fn add_archive (
54
- & mut self ,
55
- archive_path : & Path ,
56
- mut skip : Box < dyn FnMut ( & str ) -> bool + ' static > ,
57
- ) -> std:: io:: Result < ( ) > {
58
- let read_cache = ReadCache :: new ( std:: fs:: File :: open ( & archive_path) ?) ;
59
- let archive = ArchiveFile :: parse ( & read_cache) . unwrap ( ) ;
60
- let archive_index = self . src_archives . len ( ) ;
61
-
62
- for entry in archive. members ( ) {
63
- let entry = entry. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
64
- let file_name = String :: from_utf8 ( entry. name ( ) . to_vec ( ) )
65
- . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
66
- if !skip ( & file_name) {
67
- self . entries . push ( (
68
- file_name. into_bytes ( ) ,
69
- ArchiveEntry :: FromArchive { archive_index, file_range : entry. file_range ( ) } ,
70
- ) ) ;
71
- }
72
- }
73
-
74
- self . src_archives . push ( read_cache. into_inner ( ) ) ;
75
- Ok ( ( ) )
76
- }
77
-
78
- fn build ( mut self : Box < Self > , output : & Path ) -> bool {
36
+ pub fn build ( & self , output : & Path ) -> bool {
79
37
enum BuilderKind {
80
38
Bsd ( ar:: Builder < File > ) ,
81
39
Gnu ( ar:: GnuBuilder < File > ) ,
82
40
}
83
41
84
42
let sess = self . sess ;
85
43
86
- let mut entries = Vec :: new ( ) ;
87
-
88
- for ( entry_name, entry) in self . entries {
89
- // FIXME only read the symbol table of the object files to avoid having to keep all
90
- // object files in memory at once, or read them twice.
91
- let data = match entry {
92
- ArchiveEntry :: FromArchive { archive_index, file_range } => {
93
- // FIXME read symbols from symtab
94
- let src_read_cache = & mut self . src_archives [ archive_index] ;
95
-
96
- src_read_cache. seek ( io:: SeekFrom :: Start ( file_range. 0 ) ) . unwrap ( ) ;
97
- let mut data = std:: vec:: from_elem ( 0 , usize:: try_from ( file_range. 1 ) . unwrap ( ) ) ;
98
- src_read_cache. read_exact ( & mut data) . unwrap ( ) ;
99
-
100
- data
101
- }
102
- ArchiveEntry :: File ( file) => std:: fs:: read ( file) . unwrap_or_else ( |err| {
103
- sess. fatal ( & format ! (
104
- "error while reading object file during archive building: {}" ,
105
- err
106
- ) ) ;
107
- } ) ,
108
- } ;
109
-
110
- entries. push ( ( entry_name, data) ) ;
111
- }
112
-
113
44
let mut builder = if self . use_gnu_style_archive {
114
45
BuilderKind :: Gnu ( ar:: GnuBuilder :: new (
115
46
File :: create ( & output) . unwrap_or_else ( |err| {
@@ -118,50 +49,45 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
118
49
err
119
50
) ) ;
120
51
} ) ,
121
- entries. iter ( ) . map ( |( name, _) | name. clone ( ) ) . collect ( ) ,
52
+ self . entries . iter ( ) . map ( |( name, _) | name. clone ( ) ) . collect ( ) ,
122
53
) )
123
54
} else {
124
55
BuilderKind :: Bsd ( ar:: Builder :: new ( File :: create ( & output) . unwrap_or_else ( |err| {
125
56
sess. fatal ( & format ! ( "error opening destination during archive building: {err}" ) ) ;
126
57
} ) ) )
127
58
} ;
128
59
60
+ let entries = self . entries . iter ( ) . map ( |( entry_name, file) | {
61
+ let data = std:: fs:: read ( file) . unwrap_or_else ( |err| {
62
+ sess. fatal ( & format ! (
63
+ "error while reading object file during archive building: {}" ,
64
+ err
65
+ ) ) ;
66
+ } ) ;
67
+ ( entry_name, data)
68
+ } ) ;
69
+
129
70
// Add all files
130
- let any_members = !entries . is_empty ( ) ;
131
- for ( entry_name, data) in entries. into_iter ( ) {
132
- let header = ar:: Header :: new ( entry_name, data. len ( ) as u64 ) ;
71
+ let mut any_members = false ;
72
+ for ( entry_name, data) in entries {
73
+ let header = ar:: Header :: new ( entry_name. clone ( ) , data. len ( ) as u64 ) ;
133
74
match builder {
134
75
BuilderKind :: Bsd ( ref mut builder) => builder. append ( & header, & mut & * data) . unwrap ( ) ,
135
76
BuilderKind :: Gnu ( ref mut builder) => builder. append ( & header, & mut & * data) . unwrap ( ) ,
136
77
}
78
+ any_members = true ;
137
79
}
138
80
139
81
// Finalize archive
140
82
std:: mem:: drop ( builder) ;
141
83
any_members
142
84
}
143
- }
144
85
145
- pub ( crate ) struct ArArchiveBuilderBuilder ;
146
-
147
- impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
148
- fn new_archive_builder < ' a > ( & self , sess : & ' a Session ) -> Box < dyn ArchiveBuilder < ' a > + ' a > {
149
- Box :: new ( ArArchiveBuilder {
86
+ pub fn new ( sess : & ' a Session ) -> Self {
87
+ ArchiveBuilder {
150
88
sess,
151
89
use_gnu_style_archive : sess. target . archive_format == "gnu" ,
152
- src_archives : vec ! [ ] ,
153
90
entries : vec ! [ ] ,
154
- } )
155
- }
156
-
157
- fn create_dll_import_lib (
158
- & self ,
159
- _sess : & Session ,
160
- _lib_name : & str ,
161
- _dll_imports : & [ rustc_session:: cstore:: DllImport ] ,
162
- _tmpdir : & Path ,
163
- _is_direct_dependency : bool ,
164
- ) -> PathBuf {
165
- unimplemented ! ( "injecting dll imports is not supported" ) ;
91
+ }
166
92
}
167
93
}
0 commit comments