55
66use std:: env;
77use std:: fs;
8- use std:: path:: { Component , Path , PathBuf } ;
8+ use std:: path:: { Component , PathBuf } ;
99use std:: process:: Command ;
1010
1111use build_helper:: t;
@@ -26,74 +26,63 @@ fn install_sh(
2626) {
2727 builder. info ( & format ! ( "Install {} stage{} ({:?})" , package, stage, host) ) ;
2828
29- let prefix_default = PathBuf :: from ( "/usr/local" ) ;
30- let sysconfdir_default = PathBuf :: from ( "/etc" ) ;
31- let datadir_default = PathBuf :: from ( "share" ) ;
32- let docdir_default = datadir_default. join ( "doc/rust" ) ;
33- let libdir_default = PathBuf :: from ( "lib" ) ;
34- let mandir_default = datadir_default. join ( "man" ) ;
35- let prefix = builder. config . prefix . as_ref ( ) . unwrap_or ( & prefix_default) ;
36- let sysconfdir = builder. config . sysconfdir . as_ref ( ) . unwrap_or ( & sysconfdir_default) ;
37- let datadir = builder. config . datadir . as_ref ( ) . unwrap_or ( & datadir_default) ;
38- let docdir = builder. config . docdir . as_ref ( ) . unwrap_or ( & docdir_default) ;
39- let bindir = & builder. config . bindir ;
40- let libdir = builder. config . libdir . as_ref ( ) . unwrap_or ( & libdir_default) ;
41- let mandir = builder. config . mandir . as_ref ( ) . unwrap_or ( & mandir_default) ;
42-
43- let sysconfdir = prefix. join ( sysconfdir) ;
44- let datadir = prefix. join ( datadir) ;
45- let docdir = prefix. join ( docdir) ;
46- let bindir = prefix. join ( bindir) ;
47- let libdir = prefix. join ( libdir) ;
48- let mandir = prefix. join ( mandir) ;
49-
50- let destdir = env:: var_os ( "DESTDIR" ) . map ( PathBuf :: from) ;
51-
52- let prefix = add_destdir ( & prefix, & destdir) ;
53- let sysconfdir = add_destdir ( & sysconfdir, & destdir) ;
54- let datadir = add_destdir ( & datadir, & destdir) ;
55- let docdir = add_destdir ( & docdir, & destdir) ;
56- let bindir = add_destdir ( & bindir, & destdir) ;
57- let libdir = add_destdir ( & libdir, & destdir) ;
58- let mandir = add_destdir ( & mandir, & destdir) ;
59-
60- let prefix = {
61- fs:: create_dir_all ( & prefix)
62- . unwrap_or_else ( |err| panic ! ( "could not create {}: {}" , prefix. display( ) , err) ) ;
63- fs:: canonicalize ( & prefix)
64- . unwrap_or_else ( |err| panic ! ( "could not canonicalize {}: {}" , prefix. display( ) , err) )
65- } ;
29+ let prefix = default_path ( & builder. config . prefix , "/usr/local" ) ;
30+ let sysconfdir = prefix. join ( default_path ( & builder. config . sysconfdir , "/etc" ) ) ;
31+ let datadir = prefix. join ( default_path ( & builder. config . datadir , "share" ) ) ;
32+ let docdir = prefix. join ( default_path ( & builder. config . docdir , "share/doc" ) ) ;
33+ let mandir = prefix. join ( default_path ( & builder. config . mandir , "share/man" ) ) ;
34+ let libdir = prefix. join ( default_path ( & builder. config . libdir , "lib" ) ) ;
35+ let bindir = prefix. join ( & builder. config . bindir ) ; // Default in config.rs
6636
6737 let empty_dir = builder. out . join ( "tmp/empty_dir" ) ;
68-
6938 t ! ( fs:: create_dir_all( & empty_dir) ) ;
7039
7140 let mut cmd = Command :: new ( "sh" ) ;
7241 cmd. current_dir ( & empty_dir)
7342 . arg ( sanitize_sh ( & tarball. decompressed_output ( ) . join ( "install.sh" ) ) )
74- . arg ( format ! ( "--prefix={}" , sanitize_sh ( & prefix) ) )
75- . arg ( format ! ( "--sysconfdir={}" , sanitize_sh ( & sysconfdir) ) )
76- . arg ( format ! ( "--datadir={}" , sanitize_sh ( & datadir) ) )
77- . arg ( format ! ( "--docdir={}" , sanitize_sh ( & docdir) ) )
78- . arg ( format ! ( "--bindir={}" , sanitize_sh ( & bindir) ) )
79- . arg ( format ! ( "--libdir={}" , sanitize_sh ( & libdir) ) )
80- . arg ( format ! ( "--mandir={}" , sanitize_sh ( & mandir) ) )
43+ . arg ( format ! ( "--prefix={}" , prepare_dir ( prefix) ) )
44+ . arg ( format ! ( "--sysconfdir={}" , prepare_dir ( sysconfdir) ) )
45+ . arg ( format ! ( "--datadir={}" , prepare_dir ( datadir) ) )
46+ . arg ( format ! ( "--docdir={}" , prepare_dir ( docdir) ) )
47+ . arg ( format ! ( "--bindir={}" , prepare_dir ( bindir) ) )
48+ . arg ( format ! ( "--libdir={}" , prepare_dir ( libdir) ) )
49+ . arg ( format ! ( "--mandir={}" , prepare_dir ( mandir) ) )
8150 . arg ( "--disable-ldconfig" ) ;
8251 builder. run ( & mut cmd) ;
8352 t ! ( fs:: remove_dir_all( & empty_dir) ) ;
8453}
8554
86- fn add_destdir ( path : & Path , destdir : & Option < PathBuf > ) -> PathBuf {
87- let mut ret = match * destdir {
88- Some ( ref dest) => dest. clone ( ) ,
89- None => return path. to_path_buf ( ) ,
90- } ;
91- for part in path. components ( ) {
92- if let Component :: Normal ( s) = part {
93- ret. push ( s)
55+ fn default_path ( config : & Option < PathBuf > , default : & str ) -> PathBuf {
56+ PathBuf :: from ( config. as_ref ( ) . cloned ( ) . unwrap_or_else ( || PathBuf :: from ( default) ) )
57+ }
58+
59+ fn prepare_dir ( mut path : PathBuf ) -> String {
60+ // The DESTDIR environment variable is a standard way to install software in a subdirectory
61+ // while keeping the original directory structure, even if the prefix or other directories
62+ // contain absolute paths.
63+ //
64+ // More information on the environment variable is available here:
65+ // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
66+ if let Some ( destdir) = env:: var_os ( "DESTDIR" ) . map ( PathBuf :: from) {
67+ let without_destdir = path. clone ( ) ;
68+ path = destdir;
69+ // Custom .join() which ignores disk roots.
70+ for part in without_destdir. components ( ) {
71+ if let Component :: Normal ( s) = part {
72+ path. push ( s)
73+ }
9474 }
9575 }
96- ret
76+
77+ // The installation command is not executed from the current directory, but from a temporary
78+ // directory. To prevent relative paths from breaking this converts relative paths to absolute
79+ // paths. std::fs::canonicalize is not used as that requires the path to actually be present.
80+ if path. is_relative ( ) {
81+ path = std:: env:: current_dir ( ) . expect ( "failed to get the current directory" ) . join ( path) ;
82+ assert ! ( path. is_absolute( ) , "could not make the path relative" ) ;
83+ }
84+
85+ sanitize_sh ( & path)
9786}
9887
9988macro_rules! install {
0 commit comments