1
1
use anyhow:: Context ;
2
2
use flate2:: { Compression , write:: GzEncoder } ;
3
- use std:: env:: consts:: EXE_EXTENSION ;
4
- use std:: ffi:: OsStr ;
5
3
use std:: {
6
- env,
7
4
fs:: File ,
8
5
io:: { self , BufWriter } ,
9
6
path:: { Path , PathBuf } ,
@@ -12,11 +9,11 @@ use time::OffsetDateTime;
12
9
use xshell:: { Cmd , Shell , cmd} ;
13
10
use zip:: { DateTime , ZipWriter , write:: SimpleFileOptions } ;
14
11
15
- use crate :: flags:: PgoTrainingCrate ;
16
12
use crate :: {
17
13
date_iso,
18
- flags:: { self , Malloc } ,
14
+ flags:: { self , Malloc , PgoTrainingCrate } ,
19
15
project_root,
16
+ util:: detect_target,
20
17
} ;
21
18
22
19
const VERSION_STABLE : & str = "0.3" ;
@@ -28,7 +25,7 @@ impl flags::Dist {
28
25
let stable = sh. var ( "GITHUB_REF" ) . unwrap_or_default ( ) . as_str ( ) == "refs/heads/release" ;
29
26
30
27
let project_root = project_root ( ) ;
31
- let target = Target :: get ( & project_root) ;
28
+ let target = Target :: get ( & project_root, sh ) ;
32
29
let allocator = self . allocator ( ) ;
33
30
let dist = project_root. join ( "dist" ) ;
34
31
sh. remove_path ( & dist) ?;
@@ -113,9 +110,9 @@ fn dist_server(
113
110
let command = if linux_target && zig { "zigbuild" } else { "build" } ;
114
111
115
112
let pgo_profile = if let Some ( train_crate) = pgo {
116
- Some ( gather_pgo_profile (
113
+ Some ( crate :: pgo :: gather_pgo_profile (
117
114
sh,
118
- build_command ( sh, command, & target_name, features) ,
115
+ crate :: pgo :: build_command ( sh, command, & target_name, features) ,
119
116
& target_name,
120
117
train_crate,
121
118
) ?)
@@ -151,85 +148,6 @@ fn build_command<'a>(
151
148
)
152
149
}
153
150
154
- /// Decorates `ra_build_cmd` to add PGO instrumentation, and then runs the PGO instrumented
155
- /// Rust Analyzer on itself to gather a PGO profile.
156
- fn gather_pgo_profile < ' a > (
157
- sh : & ' a Shell ,
158
- ra_build_cmd : Cmd < ' a > ,
159
- target : & str ,
160
- train_crate : PgoTrainingCrate ,
161
- ) -> anyhow:: Result < PathBuf > {
162
- let pgo_dir = std:: path:: absolute ( "rust-analyzer-pgo" ) ?;
163
- // Clear out any stale profiles
164
- if pgo_dir. is_dir ( ) {
165
- std:: fs:: remove_dir_all ( & pgo_dir) ?;
166
- }
167
- std:: fs:: create_dir_all ( & pgo_dir) ?;
168
-
169
- // Figure out a path to `llvm-profdata`
170
- let target_libdir = cmd ! ( sh, "rustc --print=target-libdir" )
171
- . read ( )
172
- . context ( "cannot resolve target-libdir from rustc" ) ?;
173
- let target_bindir = PathBuf :: from ( target_libdir) . parent ( ) . unwrap ( ) . join ( "bin" ) ;
174
- let llvm_profdata = target_bindir. join ( "llvm-profdata" ) . with_extension ( EXE_EXTENSION ) ;
175
-
176
- // Build RA with PGO instrumentation
177
- let cmd_gather =
178
- ra_build_cmd. env ( "RUSTFLAGS" , format ! ( "-Cprofile-generate={}" , pgo_dir. to_str( ) . unwrap( ) ) ) ;
179
- cmd_gather. run ( ) . context ( "cannot build rust-analyzer with PGO instrumentation" ) ?;
180
-
181
- let ( train_path, label) = match & train_crate {
182
- PgoTrainingCrate :: RustAnalyzer => ( PathBuf :: from ( "." ) , "itself" ) ,
183
- PgoTrainingCrate :: GitHub ( repo) => {
184
- ( download_crate_for_training ( sh, & pgo_dir, repo) ?, repo. as_str ( ) )
185
- }
186
- } ;
187
-
188
- // Run RA either on itself or on a downloaded crate
189
- eprintln ! ( "Training RA on {label}..." ) ;
190
- cmd ! (
191
- sh,
192
- "target/{target}/release/rust-analyzer analysis-stats -q --run-all-ide-things {train_path}"
193
- )
194
- . run ( )
195
- . context ( "cannot generate PGO profiles" ) ?;
196
-
197
- // Merge profiles into a single file
198
- let merged_profile = pgo_dir. join ( "merged.profdata" ) ;
199
- let profile_files = std:: fs:: read_dir ( pgo_dir) ?. filter_map ( |entry| {
200
- let entry = entry. ok ( ) ?;
201
- if entry. path ( ) . extension ( ) == Some ( OsStr :: new ( "profraw" ) ) {
202
- Some ( entry. path ( ) . to_str ( ) . unwrap ( ) . to_owned ( ) )
203
- } else {
204
- None
205
- }
206
- } ) ;
207
- cmd ! ( sh, "{llvm_profdata} merge {profile_files...} -o {merged_profile}" ) . run ( ) . context (
208
- "cannot merge PGO profiles. Do you have the rustup `llvm-tools` component installed?" ,
209
- ) ?;
210
-
211
- Ok ( merged_profile)
212
- }
213
-
214
- /// Downloads a crate from GitHub, stores it into `pgo_dir` and returns a path to it.
215
- fn download_crate_for_training ( sh : & Shell , pgo_dir : & Path , repo : & str ) -> anyhow:: Result < PathBuf > {
216
- let mut it = repo. splitn ( 2 , '@' ) ;
217
- let repo = it. next ( ) . unwrap ( ) ;
218
- let revision = it. next ( ) ;
219
-
220
- // FIXME: switch to `--revision` here around 2035 or so
221
- let revision =
222
- if let Some ( revision) = revision { & [ "--branch" , revision] as & [ & str ] } else { & [ ] } ;
223
-
224
- let normalized_path = repo. replace ( "/" , "-" ) ;
225
- let target_path = pgo_dir. join ( normalized_path) ;
226
- cmd ! ( sh, "git clone --depth 1 https://github.com/{repo} {revision...} {target_path}" )
227
- . run ( )
228
- . with_context ( || "cannot download PGO training crate from {repo}" ) ?;
229
-
230
- Ok ( target_path)
231
- }
232
-
233
151
fn gzip ( src_path : & Path , dest_path : & Path ) -> anyhow:: Result < ( ) > {
234
152
let mut encoder = GzEncoder :: new ( File :: create ( dest_path) ?, Compression :: best ( ) ) ;
235
153
let mut input = io:: BufReader :: new ( File :: open ( src_path) ?) ;
@@ -283,21 +201,8 @@ struct Target {
283
201
}
284
202
285
203
impl Target {
286
- fn get ( project_root : & Path ) -> Self {
287
- let name = match env:: var ( "RA_TARGET" ) {
288
- Ok ( target) => target,
289
- _ => {
290
- if cfg ! ( target_os = "linux" ) {
291
- "x86_64-unknown-linux-gnu" . to_owned ( )
292
- } else if cfg ! ( target_os = "windows" ) {
293
- "x86_64-pc-windows-msvc" . to_owned ( )
294
- } else if cfg ! ( target_os = "macos" ) {
295
- "x86_64-apple-darwin" . to_owned ( )
296
- } else {
297
- panic ! ( "Unsupported OS, maybe try setting RA_TARGET" )
298
- }
299
- }
300
- } ;
204
+ fn get ( project_root : & Path , sh : & Shell ) -> Self {
205
+ let name = detect_target ( sh) ;
301
206
let ( name, libc_suffix) = match name. split_once ( '.' ) {
302
207
Some ( ( l, r) ) => ( l. to_owned ( ) , Some ( r. to_owned ( ) ) ) ,
303
208
None => ( name, None ) ,
0 commit comments