]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | //! Related to out filenames of compilation (e.g. save analysis, binaries). |
f9f354fc | 2 | use crate::config::{CrateType, Input, OutputFilenames, OutputType}; |
f2b60f7d FG |
3 | use crate::errors::{ |
4 | CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, | |
5 | InvalidCharacterInCrateName, | |
6 | }; | |
ba9703b0 | 7 | use crate::Session; |
3dfed10e | 8 | use rustc_ast as ast; |
dfeec247 | 9 | use rustc_span::symbol::sym; |
6522a427 | 10 | use rustc_span::{Span, Symbol}; |
ea8adc8c | 11 | use std::path::{Path, PathBuf}; |
dfeec247 XL |
12 | |
13 | pub fn out_filename( | |
14 | sess: &Session, | |
f9f354fc | 15 | crate_type: CrateType, |
dfeec247 | 16 | outputs: &OutputFilenames, |
6522a427 | 17 | crate_name: Symbol, |
dfeec247 | 18 | ) -> PathBuf { |
ea8adc8c | 19 | let default_filename = filename_for_input(sess, crate_type, crate_name, outputs); |
dfeec247 XL |
20 | let out_filename = outputs |
21 | .outputs | |
22 | .get(&OutputType::Exe) | |
23 | .and_then(|s| s.to_owned()) | |
24 | .or_else(|| outputs.single_output_file.clone()) | |
25 | .unwrap_or(default_filename); | |
ea8adc8c XL |
26 | |
27 | check_file_is_writeable(&out_filename, sess); | |
28 | ||
29 | out_filename | |
30 | } | |
31 | ||
6522a427 | 32 | /// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers |
ba9703b0 | 33 | /// check this already -- however, the Linux linker will happily overwrite a |
6522a427 | 34 | /// read-only file. We should be consistent. |
ea8adc8c XL |
35 | pub fn check_file_is_writeable(file: &Path, sess: &Session) { |
36 | if !is_writeable(file) { | |
f2b60f7d | 37 | sess.emit_fatal(FileIsNotWriteable { file }); |
ea8adc8c XL |
38 | } |
39 | } | |
40 | ||
41 | fn is_writeable(p: &Path) -> bool { | |
42 | match p.metadata() { | |
43 | Err(..) => true, | |
dfeec247 | 44 | Ok(m) => !m.permissions().readonly(), |
ea8adc8c XL |
45 | } |
46 | } | |
47 | ||
6522a427 EL |
48 | pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol { |
49 | let validate = |s: Symbol, span: Option<Span>| { | |
50 | validate_crate_name(sess, s, span); | |
3b2f2976 XL |
51 | s |
52 | }; | |
53 | ||
54 | // Look in attributes 100% of the time to make sure the attribute is marked | |
55 | // as used. After doing this, however, we still prioritize a crate name from | |
56 | // the command line over one found in the #[crate_name] attribute. If we | |
57 | // find both we ensure that they're the same later on as well. | |
dfeec247 | 58 | let attr_crate_name = |
3dfed10e | 59 | sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s))); |
3b2f2976 | 60 | |
3dfed10e | 61 | if let Some(ref s) = sess.opts.crate_name { |
6522a427 | 62 | let s = Symbol::intern(s); |
3dfed10e | 63 | if let Some((attr, name)) = attr_crate_name { |
6522a427 | 64 | if name != s { |
f2b60f7d | 65 | sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name }); |
3b2f2976 | 66 | } |
3b2f2976 | 67 | } |
6522a427 | 68 | return validate(s, None); |
3b2f2976 XL |
69 | } |
70 | ||
71 | if let Some((attr, s)) = attr_crate_name { | |
6522a427 | 72 | return validate(s, Some(attr.span)); |
3b2f2976 | 73 | } |
6522a427 | 74 | if let Input::File(ref path) = sess.io.input { |
3b2f2976 | 75 | if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { |
74b04a01 | 76 | if s.starts_with('-') { |
f2b60f7d | 77 | sess.emit_err(CrateNameInvalid { s }); |
3b2f2976 | 78 | } else { |
6522a427 | 79 | return validate(Symbol::intern(&s.replace('-', "_")), None); |
3b2f2976 XL |
80 | } |
81 | } | |
82 | } | |
83 | ||
6522a427 | 84 | Symbol::intern("rust_out") |
3b2f2976 XL |
85 | } |
86 | ||
6522a427 | 87 | pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) { |
ba9703b0 XL |
88 | let mut err_count = 0; |
89 | { | |
ba9703b0 | 90 | if s.is_empty() { |
f2b60f7d FG |
91 | err_count += 1; |
92 | sess.emit_err(CrateNameEmpty { span: sp }); | |
ba9703b0 | 93 | } |
6522a427 | 94 | for c in s.as_str().chars() { |
ba9703b0 XL |
95 | if c.is_alphanumeric() { |
96 | continue; | |
97 | } | |
98 | if c == '_' { | |
99 | continue; | |
100 | } | |
f2b60f7d FG |
101 | err_count += 1; |
102 | sess.emit_err(InvalidCharacterInCrateName { span: sp, character: c, crate_name: s }); | |
ba9703b0 XL |
103 | } |
104 | } | |
105 | ||
106 | if err_count > 0 { | |
3dfed10e | 107 | sess.abort_if_errors(); |
ba9703b0 XL |
108 | } |
109 | } | |
110 | ||
dfeec247 XL |
111 | pub fn filename_for_metadata( |
112 | sess: &Session, | |
6522a427 | 113 | crate_name: Symbol, |
dfeec247 XL |
114 | outputs: &OutputFilenames, |
115 | ) -> PathBuf { | |
17df50a5 XL |
116 | // If the command-line specified the path, use that directly. |
117 | if let Some(Some(out_filename)) = sess.opts.output_types.get(&OutputType::Metadata) { | |
118 | return out_filename.clone(); | |
119 | } | |
120 | ||
0bf4aa26 XL |
121 | let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); |
122 | ||
dfeec247 XL |
123 | let out_filename = outputs |
124 | .single_output_file | |
125 | .clone() | |
5e7ed085 | 126 | .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{libname}.rmeta"))); |
0bf4aa26 XL |
127 | |
128 | check_file_is_writeable(&out_filename, sess); | |
129 | ||
130 | out_filename | |
131 | } | |
132 | ||
dfeec247 XL |
133 | pub fn filename_for_input( |
134 | sess: &Session, | |
f9f354fc | 135 | crate_type: CrateType, |
6522a427 | 136 | crate_name: Symbol, |
dfeec247 XL |
137 | outputs: &OutputFilenames, |
138 | ) -> PathBuf { | |
3b2f2976 XL |
139 | let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); |
140 | ||
141 | match crate_type { | |
5e7ed085 | 142 | CrateType::Rlib => outputs.out_directory.join(&format!("lib{libname}.rlib")), |
f9f354fc | 143 | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => { |
29967ef6 | 144 | let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix); |
5e7ed085 | 145 | outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")) |
3b2f2976 | 146 | } |
f9f354fc | 147 | CrateType::Staticlib => { |
29967ef6 | 148 | let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix); |
5e7ed085 | 149 | outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")) |
3b2f2976 | 150 | } |
f9f354fc | 151 | CrateType::Executable => { |
29967ef6 | 152 | let suffix = &sess.target.exe_suffix; |
3b2f2976 | 153 | let out_filename = outputs.path(OutputType::Exe); |
dfeec247 | 154 | if suffix.is_empty() { out_filename } else { out_filename.with_extension(&suffix[1..]) } |
3b2f2976 XL |
155 | } |
156 | } | |
157 | } | |
158 | ||
159 | /// Returns default crate type for target | |
160 | /// | |
161 | /// Default crate type is used when crate type isn't provided neither | |
162 | /// through cmd line arguments nor through crate attributes | |
163 | /// | |
b7449926 | 164 | /// It is CrateType::Executable for all platforms but iOS as there is no |
3b2f2976 XL |
165 | /// way to run iOS binaries anyway without jailbreaking and |
166 | /// interaction with Rust code through static library is the only | |
167 | /// option for now | |
f9f354fc | 168 | pub fn default_output_for_target(sess: &Session) -> CrateType { |
29967ef6 | 169 | if !sess.target.executables { CrateType::Staticlib } else { CrateType::Executable } |
3b2f2976 XL |
170 | } |
171 | ||
172 | /// Checks if target supports crate_type as output | |
f9f354fc | 173 | pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool { |
5e7ed085 FG |
174 | if let CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro = crate_type { |
175 | if !sess.target.dynamic_linking { | |
176 | return true; | |
abe05a73 | 177 | } |
5e7ed085 FG |
178 | if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs { |
179 | return true; | |
abe05a73 XL |
180 | } |
181 | } | |
5e7ed085 FG |
182 | if let CrateType::ProcMacro | CrateType::Dylib = crate_type && sess.target.only_cdylib { |
183 | return true; | |
184 | } | |
185 | if let CrateType::Executable = crate_type && !sess.target.executables { | |
29967ef6 | 186 | return true; |
abe05a73 XL |
187 | } |
188 | ||
189 | false | |
3b2f2976 | 190 | } |