47
47
use serialize:: json:: { Json , ToJson } ;
48
48
use std:: collections:: BTreeMap ;
49
49
use std:: default:: Default ;
50
+ use std:: { fmt, io} ;
51
+ use std:: path:: { Path , PathBuf } ;
50
52
use syntax:: abi:: { Abi , lookup as lookup_abi} ;
51
53
52
54
use { LinkerFlavor , PanicStrategy , RelroLevel } ;
@@ -824,11 +826,10 @@ impl Target {
824
826
///
825
827
/// The error string could come from any of the APIs called, including
826
828
/// filesystem access and JSON decoding.
827
- pub fn search ( target : & str ) -> Result < Target , String > {
829
+ pub fn search ( target_triple : & TargetTriple ) -> Result < Target , String > {
828
830
use std:: env;
829
831
use std:: ffi:: OsString ;
830
832
use std:: fs;
831
- use std:: path:: { Path , PathBuf } ;
832
833
use serialize:: json;
833
834
834
835
fn load_file ( path : & Path ) -> Result < Target , String > {
@@ -838,35 +839,40 @@ impl Target {
838
839
Target :: from_json ( obj)
839
840
}
840
841
841
- if let Ok ( t) = load_specific ( target) {
842
- return Ok ( t)
843
- }
844
-
845
- let path = Path :: new ( target) ;
846
-
847
- if path. is_file ( ) {
848
- return load_file ( & path) ;
849
- }
842
+ match target_triple {
843
+ & TargetTriple :: TargetTriple ( ref target_triple) => {
844
+ // check if triple is in list of supported targets
845
+ if let Ok ( t) = load_specific ( target_triple) {
846
+ return Ok ( t)
847
+ }
850
848
851
- let path = {
852
- let mut target = target. to_string ( ) ;
853
- target. push_str ( ".json" ) ;
854
- PathBuf :: from ( target)
855
- } ;
849
+ // search for a file named `target_triple`.json in RUST_TARGET_PATH
850
+ let path = {
851
+ let mut target = target_triple. to_string ( ) ;
852
+ target. push_str ( ".json" ) ;
853
+ PathBuf :: from ( target)
854
+ } ;
856
855
857
- let target_path = env:: var_os ( "RUST_TARGET_PATH" )
858
- . unwrap_or ( OsString :: new ( ) ) ;
856
+ let target_path = env:: var_os ( "RUST_TARGET_PATH" )
857
+ . unwrap_or ( OsString :: new ( ) ) ;
859
858
860
- // FIXME 16351: add a sane default search path?
859
+ // FIXME 16351: add a sane default search path?
861
860
862
- for dir in env:: split_paths ( & target_path) {
863
- let p = dir. join ( & path) ;
864
- if p. is_file ( ) {
865
- return load_file ( & p) ;
861
+ for dir in env:: split_paths ( & target_path) {
862
+ let p = dir. join ( & path) ;
863
+ if p. is_file ( ) {
864
+ return load_file ( & p) ;
865
+ }
866
+ }
867
+ Err ( format ! ( "Could not find specification for target {:?}" , target_triple) )
868
+ }
869
+ & TargetTriple :: TargetPath ( ref target_path) => {
870
+ if target_path. is_file ( ) {
871
+ return load_file ( & target_path) ;
872
+ }
873
+ Err ( format ! ( "Target path {:?} is not a valid file" , target_path) )
866
874
}
867
875
}
868
-
869
- Err ( format ! ( "Could not find specification for target {:?}" , target) )
870
876
}
871
877
}
872
878
@@ -1014,3 +1020,61 @@ fn maybe_jemalloc() -> Option<String> {
1014
1020
None
1015
1021
}
1016
1022
}
1023
+
1024
+ /// Either a target triple string or a path to a JSON file.
1025
+ #[ derive( PartialEq , Clone , Debug , Hash , RustcEncodable , RustcDecodable ) ]
1026
+ pub enum TargetTriple {
1027
+ TargetTriple ( String ) ,
1028
+ TargetPath ( PathBuf ) ,
1029
+ }
1030
+
1031
+ impl TargetTriple {
1032
+ /// Creates a target triple from the passed target triple string.
1033
+ pub fn from_triple ( triple : & str ) -> Self {
1034
+ TargetTriple :: TargetTriple ( triple. to_string ( ) )
1035
+ }
1036
+
1037
+ /// Creates a target triple from the passed target path.
1038
+ pub fn from_path ( path : & Path ) -> Result < Self , io:: Error > {
1039
+ let canonicalized_path = path. canonicalize ( ) ?;
1040
+ Ok ( TargetTriple :: TargetPath ( canonicalized_path) )
1041
+ }
1042
+
1043
+ /// Returns a string triple for this target.
1044
+ ///
1045
+ /// If this target is a path, the file name (without extension) is returned.
1046
+ pub fn triple ( & self ) -> & str {
1047
+ match self {
1048
+ & TargetTriple :: TargetTriple ( ref triple) => triple,
1049
+ & TargetTriple :: TargetPath ( ref path) => {
1050
+ path. file_stem ( ) . expect ( "target path must not be empty" ) . to_str ( )
1051
+ . expect ( "target path must be valid unicode" )
1052
+ }
1053
+ }
1054
+ }
1055
+
1056
+ /// Returns an extended string triple for this target.
1057
+ ///
1058
+ /// If this target is a path, a hash of the path is appended to the triple returned
1059
+ /// by `triple()`.
1060
+ pub fn debug_triple ( & self ) -> String {
1061
+ use std:: hash:: { Hash , Hasher } ;
1062
+ use std:: collections:: hash_map:: DefaultHasher ;
1063
+
1064
+ let triple = self . triple ( ) ;
1065
+ if let & TargetTriple :: TargetPath ( ref path) = self {
1066
+ let mut hasher = DefaultHasher :: new ( ) ;
1067
+ path. hash ( & mut hasher) ;
1068
+ let hash = hasher. finish ( ) ;
1069
+ format ! ( "{}-{}" , triple, hash)
1070
+ } else {
1071
+ triple. to_owned ( )
1072
+ }
1073
+ }
1074
+ }
1075
+
1076
+ impl fmt:: Display for TargetTriple {
1077
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1078
+ write ! ( f, "{}" , self . debug_triple( ) )
1079
+ }
1080
+ }
0 commit comments