14
14
pub use self :: EntryFnType :: * ;
15
15
pub use self :: CrateType :: * ;
16
16
pub use self :: Passes :: * ;
17
- pub use self :: OptLevel :: * ;
18
17
pub use self :: DebugInfoLevel :: * ;
19
18
20
19
use session:: { early_error, early_warn, Session } ;
@@ -71,6 +70,18 @@ pub enum OutputType {
71
70
DepInfo ,
72
71
}
73
72
73
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
74
+ pub enum ErrorOutputType {
75
+ Tty ( ColorConfig ) ,
76
+ Json ,
77
+ }
78
+
79
+ impl Default for ErrorOutputType {
80
+ fn default ( ) -> ErrorOutputType {
81
+ ErrorOutputType :: Tty ( ColorConfig :: Auto )
82
+ }
83
+ }
84
+
74
85
impl OutputType {
75
86
fn is_compatible_with_codegen_units_and_single_output_file ( & self ) -> bool {
76
87
match * self {
@@ -124,14 +135,14 @@ pub struct Options {
124
135
pub test : bool ,
125
136
pub parse_only : bool ,
126
137
pub no_trans : bool ,
138
+ pub output : ErrorOutputType ,
127
139
pub treat_err_as_bug : bool ,
128
140
pub incremental_compilation : bool ,
129
141
pub dump_dep_graph : bool ,
130
142
pub no_analysis : bool ,
131
143
pub debugging_opts : DebuggingOptions ,
132
144
pub prints : Vec < PrintRequest > ,
133
145
pub cg : CodegenOptions ,
134
- pub color : ColorConfig ,
135
146
pub externs : HashMap < String , Vec < String > > ,
136
147
pub crate_name : Option < String > ,
137
148
/// An optional name to use as the crate for std during std injection,
@@ -221,7 +232,7 @@ pub fn basic_options() -> Options {
221
232
Options {
222
233
crate_types : Vec :: new ( ) ,
223
234
gc : false ,
224
- optimize : No ,
235
+ optimize : OptLevel :: No ,
225
236
debuginfo : NoDebugInfo ,
226
237
lint_opts : Vec :: new ( ) ,
227
238
lint_cap : None ,
@@ -241,7 +252,12 @@ pub fn basic_options() -> Options {
241
252
debugging_opts : basic_debugging_options ( ) ,
242
253
prints : Vec :: new ( ) ,
243
254
cg : basic_codegen_options ( ) ,
255
+ <<<<<<< HEAD
244
256
color: ColorConfig :: Auto ,
257
+ =======
258
+ output: ErrorOutputType :: default ( ) ,
259
+ show_span : None ,
260
+ >>>>>>> Add an --output option for specifying an error emitter
245
261
externs: HashMap :: new ( ) ,
246
262
crate_name: None ,
247
263
alt_std_name: None ,
@@ -308,7 +324,7 @@ macro_rules! options {
308
324
$struct_name { $( $opt: $init) , * }
309
325
}
310
326
311
- pub fn $buildfn( matches: & getopts:: Matches , color : ColorConfig ) -> $struct_name
327
+ pub fn $buildfn( matches: & getopts:: Matches , output : ErrorOutputType ) -> $struct_name
312
328
{
313
329
let mut op = $defaultfn( ) ;
314
330
for option in matches. opt_strs( $prefix) {
@@ -322,17 +338,17 @@ macro_rules! options {
322
338
if !setter( & mut op, value) {
323
339
match ( value, opt_type_desc) {
324
340
( Some ( ..) , None ) => {
325
- early_error( color , & format!( "{} option `{}` takes no \
341
+ early_error( output , & format!( "{} option `{}` takes no \
326
342
value", $outputname, key) )
327
343
}
328
344
( None , Some ( type_desc) ) => {
329
- early_error( color , & format!( "{0} option `{1}` requires \
345
+ early_error( output , & format!( "{0} option `{1}` requires \
330
346
{2} ({3} {1}=<value>)",
331
347
$outputname, key,
332
348
type_desc, $prefix) )
333
349
}
334
350
( Some ( value) , Some ( type_desc) ) => {
335
- early_error( color , & format!( "incorrect value `{}` for {} \
351
+ early_error( output , & format!( "incorrect value `{}` for {} \
336
352
option `{}` - {} was expected",
337
353
value, $outputname,
338
354
key, type_desc) )
@@ -344,7 +360,7 @@ macro_rules! options {
344
360
break ;
345
361
}
346
362
if !found {
347
- early_error( color , & format!( "unknown {} option: `{}`" ,
363
+ early_error( output , & format!( "unknown {} option: `{}`" ,
348
364
$outputname, key) ) ;
349
365
}
350
366
}
@@ -863,6 +879,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
863
879
"NAME=PATH" ) ,
864
880
opt:: opt( "" , "sysroot" , "Override the system root" , "PATH" ) ,
865
881
opt:: multi( "Z" , "" , "Set internal debugging options" , "FLAG" ) ,
882
+ opt:: opt_u( "" , "output" , "How errors and other mesasges are produced" , "tty|json" ) ,
866
883
opt:: opt( "" , "color" , "Configure coloring of output:
867
884
auto = colorize, if output goes to a tty (default);
868
885
always = always colorize output;
@@ -905,15 +922,36 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
905
922
None => ColorConfig :: Auto ,
906
923
907
924
Some ( arg) => {
908
- early_error ( ColorConfig :: Auto , & format ! ( "argument for --color must be auto, always \
909
- or never (instead was `{}`)",
910
- arg) )
925
+ early_error( ErrorOutputType :: default ( ) , & format!( "argument for --color must be auto, \
926
+ always or never (instead was `{}`)",
927
+ arg) )
911
928
}
912
929
} ;
913
930
931
+ // We need the opts_present check because the driver will send us Matches
932
+ // with only stable options if no unstable options are used. Since output is
933
+ // unstable, it will not be present. We have to use opts_present not
934
+ // opt_present because the latter will panic.
935
+ let output = if matches. opts_present( & [ "output" . to_owned( ) ] ) {
936
+ match matches. opt_str( "output" ) . as_ref( ) . map( |s| & s[ ..] ) {
937
+ Some ( "tty" ) => ErrorOutputType :: Tty ( color) ,
938
+ Some ( "json" ) => ErrorOutputType :: Json ,
939
+
940
+ None => ErrorOutputType :: default ( ) ,
941
+
942
+ Some ( arg) => {
943
+ early_error( ErrorOutputType :: default ( ) , & format!( "argument for --output must be tty or \
944
+ json (instead was `{}`)",
945
+ arg) )
946
+ }
947
+ }
948
+ } else {
949
+ ErrorOutputType :: default ( )
950
+ } ;
951
+
914
952
let unparsed_crate_types = matches. opt_strs( "crate-type" ) ;
915
953
let crate_types = parse_crate_types_from_list( unparsed_crate_types)
916
- . unwrap_or_else ( |e| early_error ( color , & e[ ..] ) ) ;
954
+ . unwrap_or_else( |e| early_error( output , & e[ ..] ) ) ;
917
955
918
956
let mut lint_opts = vec!( ) ;
919
957
let mut describe_lints = false ;
@@ -930,11 +968,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
930
968
931
969
let lint_cap = matches. opt_str( "cap-lints" ) . map( |cap| {
932
970
lint:: Level :: from_str( & cap) . unwrap_or_else( || {
933
- early_error ( color , & format ! ( "unknown lint level: `{}`" , cap) )
971
+ early_error( output , & format!( "unknown lint level: `{}`" , cap) )
934
972
} )
935
973
} ) ;
936
974
937
- let debugging_opts = build_debugging_options ( matches, color ) ;
975
+ let debugging_opts = build_debugging_options( matches, output ) ;
938
976
939
977
let parse_only = debugging_opts. parse_only;
940
978
let no_trans = debugging_opts. no_trans;
@@ -960,7 +998,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
960
998
"link" => OutputType :: Exe ,
961
999
"dep-info" => OutputType :: DepInfo ,
962
1000
part => {
963
- early_error ( color , & format ! ( "unknown emission type: `{}`" ,
1001
+ early_error( output , & format!( "unknown emission type: `{}`" ,
964
1002
part) )
965
1003
}
966
1004
} ;
@@ -973,7 +1011,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
973
1011
output_types. insert( OutputType :: Exe , None ) ;
974
1012
}
975
1013
976
- let mut cg = build_codegen_options ( matches, color ) ;
1014
+ let mut cg = build_codegen_options( matches, output ) ;
977
1015
978
1016
// Issue #30063: if user requests llvm-related output to one
979
1017
// particular path, disable codegen-units.
@@ -985,11 +1023,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
985
1023
} ) . collect( ) ;
986
1024
if !incompatible. is_empty( ) {
987
1025
for ot in & incompatible {
988
- early_warn ( color , & format ! ( "--emit={} with -o incompatible with \
1026
+ early_warn( output , & format!( "--emit={} with -o incompatible with \
989
1027
-C codegen-units=N for N > 1",
990
1028
ot. shorthand( ) ) ) ;
991
1029
}
992
- early_warn ( color , "resetting to default -C codegen-units=1" ) ;
1030
+ early_warn( output , "resetting to default -C codegen-units=1" ) ;
993
1031
cg. codegen_units = 1 ;
994
1032
}
995
1033
}
@@ -1002,29 +1040,29 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1002
1040
let opt_level = {
1003
1041
if matches. opt_present( "O" ) {
1004
1042
if cg. opt_level. is_some( ) {
1005
- early_error ( color , "-O and -C opt-level both provided" ) ;
1043
+ early_error( output , "-O and -C opt-level both provided" ) ;
1006
1044
}
1007
- Default
1045
+ OptLevel :: Default
1008
1046
} else {
1009
1047
match cg. opt_level {
1010
- None => No ,
1011
- Some ( 0 ) => No ,
1012
- Some ( 1 ) => Less ,
1013
- Some ( 2 ) => Default ,
1014
- Some ( 3 ) => Aggressive ,
1048
+ None => OptLevel :: No ,
1049
+ Some ( 0 ) => OptLevel :: No ,
1050
+ Some ( 1 ) => OptLevel :: Less ,
1051
+ Some ( 2 ) => OptLevel :: Default ,
1052
+ Some ( 3 ) => OptLevel :: Aggressive ,
1015
1053
Some ( arg) => {
1016
- early_error ( color , & format ! ( "optimization level needs to be \
1054
+ early_error( output , & format!( "optimization level needs to be \
1017
1055
between 0-3 (instead was `{}`)",
1018
1056
arg) ) ;
1019
1057
}
1020
1058
}
1021
1059
}
1022
1060
} ;
1023
- let debug_assertions = cg. debug_assertions . unwrap_or ( opt_level == No ) ;
1061
+ let debug_assertions = cg. debug_assertions. unwrap_or( opt_level == OptLevel :: No ) ;
1024
1062
let gc = debugging_opts. gc;
1025
1063
let debuginfo = if matches. opt_present( "g" ) {
1026
1064
if cg. debuginfo. is_some( ) {
1027
- early_error ( color , "-g and -C debuginfo both provided" ) ;
1065
+ early_error( output , "-g and -C debuginfo both provided" ) ;
1028
1066
}
1029
1067
FullDebugInfo
1030
1068
} else {
@@ -1033,7 +1071,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1033
1071
Some ( 1 ) => LimitedDebugInfo ,
1034
1072
Some ( 2 ) => FullDebugInfo ,
1035
1073
Some ( arg) => {
1036
- early_error ( color , & format ! ( "debug info level needs to be between \
1074
+ early_error( output , & format!( "debug info level needs to be between \
1037
1075
0-2 (instead was `{}`)",
1038
1076
arg) ) ;
1039
1077
}
@@ -1042,7 +1080,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1042
1080
1043
1081
let mut search_paths = SearchPaths :: new( ) ;
1044
1082
for s in & matches. opt_strs( "L" ) {
1045
- search_paths. add_path ( & s[ ..] , color ) ;
1083
+ search_paths. add_path( & s[ ..] , output ) ;
1046
1084
}
1047
1085
1048
1086
let libs = matches. opt_strs( "l" ) . into_iter( ) . map( |s| {
@@ -1054,7 +1092,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1054
1092
( Some ( name) , "framework" ) => ( name, cstore:: NativeFramework ) ,
1055
1093
( Some ( name) , "static" ) => ( name, cstore:: NativeStatic ) ,
1056
1094
( _, s) => {
1057
- early_error ( color , & format ! ( "unknown library kind `{}`, expected \
1095
+ early_error( output , & format!( "unknown library kind `{}`, expected \
1058
1096
one of dylib, framework, or static",
1059
1097
s) ) ;
1060
1098
}
@@ -1071,13 +1109,13 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1071
1109
"file-names" => PrintRequest :: FileNames ,
1072
1110
"sysroot" => PrintRequest :: Sysroot ,
1073
1111
req => {
1074
- early_error ( color , & format ! ( "unknown print request `{}`" , req) )
1112
+ early_error( output , & format!( "unknown print request `{}`" , req) )
1075
1113
}
1076
1114
}
1077
1115
} ) . collect:: <Vec <_>>( ) ;
1078
1116
1079
1117
if !cg. remark. is_empty( ) && debuginfo == NoDebugInfo {
1080
- early_warn ( color , "-C remark will not show source locations without \
1118
+ early_warn( output , "-C remark will not show source locations without \
1081
1119
--debuginfo") ;
1082
1120
}
1083
1121
@@ -1086,11 +1124,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1086
1124
let mut parts = arg. splitn( 2 , '=' ) ;
1087
1125
let name = match parts. next( ) {
1088
1126
Some ( s) => s,
1089
- None => early_error ( color , "--extern value must not be empty" ) ,
1127
+ None => early_error( output , "--extern value must not be empty" ) ,
1090
1128
} ;
1091
1129
let location = match parts. next( ) {
1092
1130
Some ( s) => s,
1093
- None => early_error ( color , "--extern value must be of the format `foo=bar`" ) ,
1131
+ None => early_error( output , "--extern value must be of the format `foo=bar`" ) ,
1094
1132
} ;
1095
1133
1096
1134
externs. entry( name. to_string( ) ) . or_insert( vec![ ] ) . push( location. to_string( ) ) ;
@@ -1121,7 +1159,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1121
1159
debugging_opts: debugging_opts,
1122
1160
prints: prints,
1123
1161
cg: cg,
1124
- color : color ,
1162
+ output : output ,
1125
1163
externs: externs,
1126
1164
crate_name: crate_name,
1127
1165
alt_std_name: None ,
0 commit comments