@@ -849,29 +849,68 @@ fn wait(
849849#[ doc( inline) ]
850850pub use crate :: cargo_bin;
851851
852- /// Look up the path to a cargo-built binary within an integration test.
852+ /// Look up the path to a cargo-built binary within an integration test
853853///
854- /// **NOTE:** Prefer [`cargo_bin!`] as this makes assumptions about cargo
854+ /// Cargo support:
855+ /// - `>1.94`: works
856+ /// - `>=1.91,<=1.93`: works with default `build-dir`
857+ /// - `<=1.92`: works
858+ ///
859+ /// # Panic
860+ ///
861+ /// Panics if no binary is found
855862pub fn cargo_bin ( name : & str ) -> std:: path:: PathBuf {
856- let env_var = format ! ( "CARGO_BIN_EXE_{name}" ) ;
863+ let env_var = format ! ( "{ CARGO_BIN_EXE_} {name}" ) ;
857864 std:: env:: var_os ( env_var)
858865 . map ( |p| p. into ( ) )
859- . unwrap_or_else ( || target_dir ( ) . join ( format ! ( "{}{}" , name, std:: env:: consts:: EXE_SUFFIX ) ) )
866+ . or_else ( || legacy_cargo_bin ( name) )
867+ . unwrap_or_else ( || missing_cargo_bin ( name) )
868+ }
869+
870+ const CARGO_BIN_EXE_ : & str = "CARGO_BIN_EXE_" ;
871+
872+ fn missing_cargo_bin ( name : & str ) -> ! {
873+ let possible_names: Vec < _ > = std:: env:: vars_os ( )
874+ . filter_map ( |( k, _) | k. into_string ( ) . ok ( ) )
875+ . filter_map ( |k| k. strip_prefix ( CARGO_BIN_EXE_ ) . map ( |s| s. to_owned ( ) ) )
876+ . collect ( ) ;
877+ if possible_names. is_empty ( ) {
878+ panic ! ( "`CARGO_BIN_EXE_{name}` is unset
879+ help: if this is running within a unit test, move it to an integration test to gain access to `CARGO_BIN_EXE_{name}`" )
880+ } else {
881+ let mut names = String :: new ( ) ;
882+ for ( i, name) in possible_names. iter ( ) . enumerate ( ) {
883+ use std:: fmt:: Write as _;
884+ if i != 0 {
885+ let _ = write ! ( & mut names, ", " ) ;
886+ }
887+ let _ = write ! ( & mut names, "\" {name}\" " ) ;
888+ }
889+ panic ! (
890+ "`CARGO_BIN_EXE_{name}` is unset
891+ help: available binary names are {names}"
892+ )
893+ }
894+ }
895+
896+ fn legacy_cargo_bin ( name : & str ) -> Option < std:: path:: PathBuf > {
897+ let target_dir = target_dir ( ) ?;
898+ let bin_path = target_dir. join ( format ! ( "{}{}" , name, std:: env:: consts:: EXE_SUFFIX ) ) ;
899+ if !bin_path. exists ( ) {
900+ return None ;
901+ }
902+ Some ( bin_path)
860903}
861904
862905// Adapted from
863906// https://github.com/rust-lang/cargo/blob/485670b3983b52289a2f353d589c57fae2f60f82/tests/testsuite/support/mod.rs#L507
864- fn target_dir ( ) -> std:: path:: PathBuf {
865- std:: env:: current_exe ( )
866- . ok ( )
867- . map ( |mut path| {
868- path. pop ( ) ;
869- if path. ends_with ( "deps" ) {
870- path. pop ( ) ;
871- }
872- path
873- } )
874- . unwrap ( )
907+ fn target_dir ( ) -> Option < std:: path:: PathBuf > {
908+ let mut path = std:: env:: current_exe ( ) . ok ( ) ?;
909+ let _test_bin_name = path. pop ( ) ;
910+ if path. ends_with ( "deps" ) {
911+ let _deps = path. pop ( ) ;
912+ }
913+ Some ( path)
875914}
876915
877916#[ cfg( feature = "examples" ) ]
@@ -1009,3 +1048,10 @@ pub(crate) mod examples {
10091048 target. crate_types == [ "bin" ] && target. kind == [ "example" ]
10101049 }
10111050}
1051+
1052+ #[ test]
1053+ #[ should_panic = "`CARGO_BIN_EXE_non-existent` is unset
1054+ help: if this is running within a unit test, move it to an integration test to gain access to `CARGO_BIN_EXE_non-existent`" ]
1055+ fn cargo_bin_in_unit_test ( ) {
1056+ cargo_bin ( "non-existent" ) ;
1057+ }
0 commit comments