@@ -12,6 +12,7 @@ use time::OffsetDateTime;
12
12
use xshell:: { Cmd , Shell , cmd} ;
13
13
use zip:: { DateTime , ZipWriter , write:: SimpleFileOptions } ;
14
14
15
+ use crate :: flags:: PgoTrainingCrate ;
15
16
use crate :: {
16
17
date_iso,
17
18
flags:: { self , Malloc } ,
@@ -93,7 +94,7 @@ fn dist_server(
93
94
target : & Target ,
94
95
allocator : Malloc ,
95
96
zig : bool ,
96
- pgo : bool ,
97
+ pgo : Option < PgoTrainingCrate > ,
97
98
) -> anyhow:: Result < ( ) > {
98
99
let _e = sh. push_env ( "CFG_RELEASE" , release) ;
99
100
let _e = sh. push_env ( "CARGO_PROFILE_RELEASE_LTO" , "thin" ) ;
@@ -111,11 +112,12 @@ fn dist_server(
111
112
let features = allocator. to_features ( ) ;
112
113
let command = if linux_target && zig { "zigbuild" } else { "build" } ;
113
114
114
- let pgo_profile = if pgo {
115
+ let pgo_profile = if let Some ( train_crate ) = pgo {
115
116
Some ( gather_pgo_profile (
116
117
sh,
117
118
build_command ( sh, command, & target_name, features) ,
118
119
& target_name,
120
+ train_crate,
119
121
) ?)
120
122
} else {
121
123
None
@@ -155,8 +157,9 @@ fn gather_pgo_profile<'a>(
155
157
sh : & ' a Shell ,
156
158
ra_build_cmd : Cmd < ' a > ,
157
159
target : & str ,
160
+ train_crate : PgoTrainingCrate ,
158
161
) -> anyhow:: Result < PathBuf > {
159
- let pgo_dir = std:: path:: absolute ( "ra-pgo-profiles " ) ?;
162
+ let pgo_dir = std:: path:: absolute ( "rust-analyzer-pgo " ) ?;
160
163
// Clear out any stale profiles
161
164
if pgo_dir. is_dir ( ) {
162
165
std:: fs:: remove_dir_all ( & pgo_dir) ?;
@@ -168,18 +171,25 @@ fn gather_pgo_profile<'a>(
168
171
. read ( )
169
172
. context ( "cannot resolve target-libdir from rustc" ) ?;
170
173
let target_bindir = PathBuf :: from ( target_libdir) . parent ( ) . unwrap ( ) . join ( "bin" ) ;
171
- let llvm_profdata = target_bindir. join ( format ! ( "llvm-profdata{}" , EXE_EXTENSION ) ) ;
174
+ let llvm_profdata = target_bindir. join ( "llvm-profdata" ) . with_extension ( EXE_EXTENSION ) ;
172
175
173
176
// Build RA with PGO instrumentation
174
177
let cmd_gather =
175
178
ra_build_cmd. env ( "RUSTFLAGS" , format ! ( "-Cprofile-generate={}" , pgo_dir. to_str( ) . unwrap( ) ) ) ;
176
179
cmd_gather. run ( ) . context ( "cannot build rust-analyzer with PGO instrumentation" ) ?;
177
180
178
- // Run RA on itself to gather profiles
179
- let train_crate = "." ;
181
+ let ( train_path, label) = match & train_crate {
182
+ PgoTrainingCrate :: RustAnalyzer => ( PathBuf :: from ( "." ) , "itself" ) ,
183
+ PgoTrainingCrate :: GitHub ( url) => {
184
+ ( download_crate_for_training ( sh, & pgo_dir, url) ?, url. as_str ( ) )
185
+ }
186
+ } ;
187
+
188
+ // Run RA either on itself or on a downloaded crate
189
+ eprintln ! ( "Training RA on {label}..." ) ;
180
190
cmd ! (
181
191
sh,
182
- "target/{target}/release/rust-analyzer analysis-stats {train_crate} --run-all-ide-things"
192
+ "target/{target}/release/rust-analyzer analysis-stats -q --run-all-ide-things {train_path} "
183
193
)
184
194
. run ( )
185
195
. context ( "cannot generate PGO profiles" ) ?;
@@ -201,6 +211,17 @@ fn gather_pgo_profile<'a>(
201
211
Ok ( merged_profile)
202
212
}
203
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 , url : & str ) -> anyhow:: Result < PathBuf > {
216
+ let normalized_path = url. replace ( "/" , "-" ) ;
217
+ let target_path = pgo_dir. join ( normalized_path) ;
218
+ cmd ! ( sh, "git clone --depth 1 https://github.com/{url} {target_path}" )
219
+ . run ( )
220
+ . with_context ( || "cannot download PGO training crate from {url}" ) ?;
221
+
222
+ Ok ( target_path)
223
+ }
224
+
204
225
fn gzip ( src_path : & Path , dest_path : & Path ) -> anyhow:: Result < ( ) > {
205
226
let mut encoder = GzEncoder :: new ( File :: create ( dest_path) ?, Compression :: best ( ) ) ;
206
227
let mut input = io:: BufReader :: new ( File :: open ( src_path) ?) ;
0 commit comments