forked from riscvarchive/riscv-gcc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgcc.c
10335 lines (8736 loc) · 286 KB
/
gcc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Compiler driver program that can handle many languages.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This program is the user interface to the C compiler and possibly to
other compilers. It is used because compilation is a complicated procedure
which involves running several programs and passing temporary files between
them, forwarding the users switches to those programs selectively,
and deleting the temporary files at the end.
CC recognizes how to compile each input file by suffixes in the file names.
Once it knows which kind of compilation to perform, the procedure for
compilation is specified by a string called a "spec". */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "multilib.h" /* before tm.h */
#include "tm.h"
#include "xregex.h"
#include "obstack.h"
#include "intl.h"
#include "prefix.h"
#include "opt-suggestions.h"
#include "gcc.h"
#include "diagnostic.h"
#include "flags.h"
#include "opts.h"
#include "filenames.h"
#include "spellcheck.h"
/* Manage the manipulation of env vars.
We poison "getenv" and "putenv", so that all enviroment-handling is
done through this class. Note that poisoning happens in the
preprocessor at the identifier level, and doesn't distinguish between
env.getenv ();
and
getenv ();
Hence we need to use "get" for the accessor method, not "getenv". */
struct env_manager
{
public:
void init (bool can_restore, bool debug);
const char *get (const char *name);
void xput (const char *string);
void restore ();
private:
bool m_can_restore;
bool m_debug;
struct kv
{
char *m_key;
char *m_value;
};
vec<kv> m_keys;
};
/* The singleton instance of class env_manager. */
static env_manager env;
/* Initializer for class env_manager.
We can't do this as a constructor since we have a statically
allocated instance ("env" above). */
void
env_manager::init (bool can_restore, bool debug)
{
m_can_restore = can_restore;
m_debug = debug;
}
/* Get the value of NAME within the environment. Essentially
a wrapper for ::getenv, but adding logging, and the possibility
of caching results. */
const char *
env_manager::get (const char *name)
{
const char *result = ::getenv (name);
if (m_debug)
fprintf (stderr, "env_manager::getenv (%s) -> %s\n", name, result);
return result;
}
/* Put the given KEY=VALUE entry STRING into the environment.
If the env_manager was initialized with CAN_RESTORE set, then
also record the old value of KEY within the environment, so that it
can be later restored. */
void
env_manager::xput (const char *string)
{
if (m_debug)
fprintf (stderr, "env_manager::xput (%s)\n", string);
if (verbose_flag)
fnotice (stderr, "%s\n", string);
if (m_can_restore)
{
char *equals = strchr (const_cast <char *> (string), '=');
gcc_assert (equals);
struct kv kv;
kv.m_key = xstrndup (string, equals - string);
const char *cur_value = ::getenv (kv.m_key);
if (m_debug)
fprintf (stderr, "saving old value: %s\n",cur_value);
kv.m_value = cur_value ? xstrdup (cur_value) : NULL;
m_keys.safe_push (kv);
}
::putenv (CONST_CAST (char *, string));
}
/* Undo any xputenv changes made since last restore.
Can only be called if the env_manager was initialized with
CAN_RESTORE enabled. */
void
env_manager::restore ()
{
unsigned int i;
struct kv *item;
gcc_assert (m_can_restore);
FOR_EACH_VEC_ELT_REVERSE (m_keys, i, item)
{
if (m_debug)
printf ("restoring saved key: %s value: %s\n", item->m_key, item->m_value);
if (item->m_value)
::setenv (item->m_key, item->m_value, 1);
else
::unsetenv (item->m_key);
free (item->m_key);
free (item->m_value);
}
m_keys.truncate (0);
}
/* Forbid other uses of getenv and putenv. */
#if (GCC_VERSION >= 3000)
#pragma GCC poison getenv putenv
#endif
/* By default there is no special suffix for target executables. */
#ifdef TARGET_EXECUTABLE_SUFFIX
#define HAVE_TARGET_EXECUTABLE_SUFFIX
#else
#define TARGET_EXECUTABLE_SUFFIX ""
#endif
/* By default there is no special suffix for host executables. */
#ifdef HOST_EXECUTABLE_SUFFIX
#define HAVE_HOST_EXECUTABLE_SUFFIX
#else
#define HOST_EXECUTABLE_SUFFIX ""
#endif
/* By default, the suffix for target object files is ".o". */
#ifdef TARGET_OBJECT_SUFFIX
#define HAVE_TARGET_OBJECT_SUFFIX
#else
#define TARGET_OBJECT_SUFFIX ".o"
#endif
static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */
#ifndef LIBRARY_PATH_ENV
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
#endif
/* If a stage of compilation returns an exit status >= 1,
compilation of that file ceases. */
#define MIN_FATAL_STATUS 1
/* Flag set by cppspec.c to 1. */
int is_cpp_driver;
/* Flag set to nonzero if an @file argument has been supplied to gcc. */
static bool at_file_supplied;
/* Definition of string containing the arguments given to configure. */
#include "configargs.h"
/* Flag saying to print the command line options understood by gcc and its
sub-processes. */
static int print_help_list;
/* Flag saying to print the version of gcc and its sub-processes. */
static int print_version;
/* Flag that stores string prefix for which we provide bash completion. */
static const char *completion = NULL;
/* Flag indicating whether we should ONLY print the command and
arguments (like verbose_flag) without executing the command.
Displayed arguments are quoted so that the generated command
line is suitable for execution. This is intended for use in
shell scripts to capture the driver-generated command line. */
static int verbose_only_flag;
/* Flag indicating how to print command line options of sub-processes. */
static int print_subprocess_help;
/* Linker suffix passed to -fuse-ld=... */
static const char *use_ld;
/* Whether we should report subprocess execution times to a file. */
FILE *report_times_to_file = NULL;
/* Nonzero means place this string before uses of /, so that include
and library files can be found in an alternate location. */
#ifdef TARGET_SYSTEM_ROOT
#define DEFAULT_TARGET_SYSTEM_ROOT (TARGET_SYSTEM_ROOT)
#else
#define DEFAULT_TARGET_SYSTEM_ROOT (0)
#endif
static const char *target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
/* Nonzero means pass the updated target_system_root to the compiler. */
static int target_system_root_changed;
/* Nonzero means append this string to target_system_root. */
static const char *target_sysroot_suffix = 0;
/* Nonzero means append this string to target_system_root for headers. */
static const char *target_sysroot_hdrs_suffix = 0;
/* Nonzero means write "temp" files in source directory
and use the source file's name in them, and don't delete them. */
static enum save_temps {
SAVE_TEMPS_NONE, /* no -save-temps */
SAVE_TEMPS_CWD, /* -save-temps in current directory */
SAVE_TEMPS_OBJ /* -save-temps in object directory */
} save_temps_flag;
/* Output file to use to get the object directory for -save-temps=obj */
static char *save_temps_prefix = 0;
static size_t save_temps_length = 0;
/* The compiler version. */
static const char *compiler_version;
/* The target version. */
static const char *const spec_version = DEFAULT_TARGET_VERSION;
/* The target machine. */
static const char *spec_machine = DEFAULT_TARGET_MACHINE;
static const char *spec_host_machine = DEFAULT_REAL_TARGET_MACHINE;
/* List of offload targets. Separated by colon. Empty string for
-foffload=disable. */
static char *offload_targets = NULL;
/* Nonzero if cross-compiling.
When -b is used, the value comes from the `specs' file. */
#ifdef CROSS_DIRECTORY_STRUCTURE
static const char *cross_compile = "1";
#else
static const char *cross_compile = "0";
#endif
/* Greatest exit code of sub-processes that has been encountered up to
now. */
static int greatest_status = 1;
/* This is the obstack which we use to allocate many strings. */
static struct obstack obstack;
/* This is the obstack to build an environment variable to pass to
collect2 that describes all of the relevant switches of what to
pass the compiler in building the list of pointers to constructors
and destructors. */
static struct obstack collect_obstack;
/* Forward declaration for prototypes. */
struct path_prefix;
struct prefix_list;
static void init_spec (void);
static void store_arg (const char *, int, int);
static void insert_wrapper (const char *);
static char *load_specs (const char *);
static void read_specs (const char *, bool, bool);
static void set_spec (const char *, const char *, bool);
static struct compiler *lookup_compiler (const char *, size_t, const char *);
static char *build_search_list (const struct path_prefix *, const char *,
bool, bool);
static void xputenv (const char *);
static void putenv_from_prefixes (const struct path_prefix *, const char *,
bool);
static int access_check (const char *, int);
static char *find_a_file (const struct path_prefix *, const char *, int, bool);
static void add_prefix (struct path_prefix *, const char *, const char *,
int, int, int);
static void add_sysrooted_prefix (struct path_prefix *, const char *,
const char *, int, int, int);
static char *skip_whitespace (char *);
static void delete_if_ordinary (const char *);
static void delete_temp_files (void);
static void delete_failure_queue (void);
static void clear_failure_queue (void);
static int check_live_switch (int, int);
static const char *handle_braces (const char *);
static inline bool input_suffix_matches (const char *, const char *);
static inline bool switch_matches (const char *, const char *, int);
static inline void mark_matching_switches (const char *, const char *, int);
static inline void process_marked_switches (void);
static const char *process_brace_body (const char *, const char *, const char *, int, int);
static const struct spec_function *lookup_spec_function (const char *);
static const char *eval_spec_function (const char *, const char *, const char *);
static const char *handle_spec_function (const char *, bool *, const char *);
static char *save_string (const char *, int);
static void set_collect_gcc_options (void);
static int do_spec_1 (const char *, int, const char *);
static int do_spec_2 (const char *, const char *);
static void do_option_spec (const char *, const char *);
static void do_self_spec (const char *);
static const char *find_file (const char *);
static int is_directory (const char *, bool);
static const char *validate_switches (const char *, bool);
static void validate_all_switches (void);
static inline void validate_switches_from_spec (const char *, bool);
static void give_switch (int, int);
static int default_arg (const char *, int);
static void set_multilib_dir (void);
static void print_multilib_info (void);
static void display_help (void);
static void add_preprocessor_option (const char *, int);
static void add_assembler_option (const char *, int);
static void add_linker_option (const char *, int);
static void process_command (unsigned int, struct cl_decoded_option *);
static int execute (void);
static void alloc_args (void);
static void clear_args (void);
static void fatal_signal (int);
#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
static void init_gcc_specs (struct obstack *, const char *, const char *,
const char *);
#endif
#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
static const char *convert_filename (const char *, int, int);
#endif
static void try_generate_repro (const char **argv);
static const char *getenv_spec_function (int, const char **);
static const char *if_exists_spec_function (int, const char **);
static const char *if_exists_else_spec_function (int, const char **);
static const char *sanitize_spec_function (int, const char **);
static const char *replace_outfile_spec_function (int, const char **);
static const char *remove_outfile_spec_function (int, const char **);
static const char *version_compare_spec_function (int, const char **);
static const char *include_spec_function (int, const char **);
static const char *find_file_spec_function (int, const char **);
static const char *find_plugindir_spec_function (int, const char **);
static const char *print_asm_header_spec_function (int, const char **);
static const char *compare_debug_dump_opt_spec_function (int, const char **);
static const char *compare_debug_self_opt_spec_function (int, const char **);
static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
static const char *pass_through_libs_spec_func (int, const char **);
static const char *replace_extension_spec_func (int, const char **);
static const char *greater_than_spec_func (int, const char **);
static const char *debug_level_greater_than_spec_func (int, const char **);
static const char *find_fortran_preinclude_file (int, const char **);
static char *convert_white_space (char *);
/* The Specs Language
Specs are strings containing lines, each of which (if not blank)
is made up of a program name, and arguments separated by spaces.
The program name must be exact and start from root, since no path
is searched and it is unreliable to depend on the current working directory.
Redirection of input or output is not supported; the subprograms must
accept filenames saying what files to read and write.
In addition, the specs can contain %-sequences to substitute variable text
or for conditional text. Here is a table of all defined %-sequences.
Note that spaces are not generated automatically around the results of
expanding these sequences; therefore, you can concatenate them together
or with constant text in a single argument.
%% substitute one % into the program name or argument.
%i substitute the name of the input file being processed.
%b substitute the basename of the input file being processed.
This is the substring up to (and not including) the last period
and not including the directory unless -save-temps was specified
to put temporaries in a different location.
%B same as %b, but include the file suffix (text after the last period).
%gSUFFIX
substitute a file name that has suffix SUFFIX and is chosen
once per compilation, and mark the argument a la %d. To reduce
exposure to denial-of-service attacks, the file name is now
chosen in a way that is hard to predict even when previously
chosen file names are known. For example, `%g.s ... %g.o ... %g.s'
might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches
the regexp "[.0-9A-Za-z]*%O"; "%O" is treated exactly as if it
had been pre-processed. Previously, %g was simply substituted
with a file name chosen once per compilation, without regard
to any appended suffix (which was therefore treated just like
ordinary text), making such attacks more likely to succeed.
%|SUFFIX
like %g, but if -pipe is in effect, expands simply to "-".
%mSUFFIX
like %g, but if -pipe is in effect, expands to nothing. (We have both
%| and %m to accommodate differences between system assemblers; see
the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
%uSUFFIX
like %g, but generates a new temporary file name even if %uSUFFIX
was already seen.
%USUFFIX
substitutes the last file name generated with %uSUFFIX, generating a
new one if there is no such last file name. In the absence of any
%uSUFFIX, this is just like %gSUFFIX, except they don't share
the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
would involve the generation of two distinct file names, one
for each `%g.s' and another for each `%U.s'. Previously, %U was
simply substituted with a file name chosen for the previous %u,
without regard to any appended suffix.
%jSUFFIX
substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
writable, and if save-temps is off; otherwise, substitute the name
of a temporary file, just like %u. This temporary file is not
meant for communication between processes, but rather as a junk
disposal mechanism.
%.SUFFIX
substitutes .SUFFIX for the suffixes of a matched switch's args when
it is subsequently output with %*. SUFFIX is terminated by the next
space or %.
%d marks the argument containing or following the %d as a
temporary file name, so that file will be deleted if GCC exits
successfully. Unlike %g, this contributes no text to the argument.
%w marks the argument containing or following the %w as the
"output file" of this compilation. This puts the argument
into the sequence of arguments that %o will substitute later.
%V indicates that this compilation produces no "output file".
%W{...}
like %{...} but marks the last argument supplied within as a file
to be deleted on failure.
%@{...}
like %{...} but puts the result into a FILE and substitutes @FILE
if an @file argument has been supplied.
%o substitutes the names of all the output files, with spaces
automatically placed around them. You should write spaces
around the %o as well or the results are undefined.
%o is for use in the specs for running the linker.
Input files whose names have no recognized suffix are not compiled
at all, but they are included among the output files, so they will
be linked.
%O substitutes the suffix for object files. Note that this is
handled specially when it immediately follows %g, %u, or %U
(with or without a suffix argument) because of the need for
those to form complete file names. The handling is such that
%O is treated exactly as if it had already been substituted,
except that %g, %u, and %U do not currently support additional
SUFFIX characters following %O as they would following, for
example, `.o'.
%I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
(made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
and -B options) and -imultilib as necessary.
%s current argument is the name of a library or startup file of some sort.
Search for that file in a standard list of directories
and substitute the full name found.
%eSTR Print STR as an error message. STR is terminated by a newline.
Use this when inconsistent options are detected.
%nSTR Print STR as a notice. STR is terminated by a newline.
%x{OPTION} Accumulate an option for %X.
%X Output the accumulated linker options specified by compilations.
%Y Output the accumulated assembler options specified by compilations.
%Z Output the accumulated preprocessor options specified by compilations.
%a process ASM_SPEC as a spec.
This allows config.h to specify part of the spec for running as.
%A process ASM_FINAL_SPEC as a spec. A capital A is actually
used here. This can be used to run a post-processor after the
assembler has done its job.
%D Dump out a -L option for each directory in startfile_prefixes.
If multilib_dir is set, extra entries are generated with it affixed.
%l process LINK_SPEC as a spec.
%L process LIB_SPEC as a spec.
%M Output multilib_os_dir.
%G process LIBGCC_SPEC as a spec.
%R Output the concatenation of target_system_root and
target_sysroot_suffix.
%S process STARTFILE_SPEC as a spec. A capital S is actually used here.
%E process ENDFILE_SPEC as a spec. A capital E is actually used here.
%C process CPP_SPEC as a spec.
%1 process CC1_SPEC as a spec.
%2 process CC1PLUS_SPEC as a spec.
%* substitute the variable part of a matched option. (See below.)
Note that each comma in the substituted string is replaced by
a single space. A space is appended after the last substition
unless there is more text in current sequence.
%<S remove all occurrences of -S from the command line.
Note - this command is position dependent. % commands in the
spec string before this one will see -S, % commands in the
spec string after this one will not.
%>S Similar to "%<S", but keep it in the GCC command line.
%<S* remove all occurrences of all switches beginning with -S from the
command line.
%:function(args)
Call the named function FUNCTION, passing it ARGS. ARGS is
first processed as a nested spec string, then split into an
argument vector in the usual fashion. The function returns
a string which is processed as if it had appeared literally
as part of the current spec.
%{S} substitutes the -S switch, if that switch was given to GCC.
If that switch was not specified, this substitutes nothing.
Here S is a metasyntactic variable.
%{S*} substitutes all the switches specified to GCC whose names start
with -S. This is used for -o, -I, etc; switches that take
arguments. GCC considers `-o foo' as being one switch whose
name starts with `o'. %{o*} would substitute this text,
including the space; thus, two arguments would be generated.
%{S*&T*} likewise, but preserve order of S and T options (the order
of S and T in the spec is not significant). Can be any number
of ampersand-separated variables; for each the wild card is
optional. Useful for CPP as %{D*&U*&A*}.
%{S:X} substitutes X, if the -S switch was given to GCC.
%{!S:X} substitutes X, if the -S switch was NOT given to GCC.
%{S*:X} substitutes X if one or more switches whose names start
with -S was given to GCC. Normally X is substituted only
once, no matter how many such switches appeared. However,
if %* appears somewhere in X, then X will be substituted
once for each matching switch, with the %* replaced by the
part of that switch that matched the '*'. A space will be
appended after the last substition unless there is more
text in current sequence.
%{.S:X} substitutes X, if processing a file with suffix S.
%{!.S:X} substitutes X, if NOT processing a file with suffix S.
%{,S:X} substitutes X, if processing a file which will use spec S.
%{!,S:X} substitutes X, if NOT processing a file which will use spec S.
%{S|T:X} substitutes X if either -S or -T was given to GCC. This may be
combined with '!', '.', ',', and '*' as above binding stronger
than the OR.
If %* appears in X, all of the alternatives must be starred, and
only the first matching alternative is substituted.
%{%:function(args):X}
Call function named FUNCTION with args ARGS. If the function
returns non-NULL, then X is substituted, if it returns
NULL, it isn't substituted.
%{S:X; if S was given to GCC, substitutes X;
T:Y; else if T was given to GCC, substitutes Y;
:D} else substitutes D. There can be as many clauses as you need.
This may be combined with '.', '!', ',', '|', and '*' as above.
%(Spec) processes a specification defined in a specs file as *Spec:
The switch matching text S in a %{S}, %{S:X}, or similar construct can use
a backslash to ignore the special meaning of the character following it,
thus allowing literal matching of a character that is otherwise specially
treated. For example, %{std=iso9899\:1999:X} substitutes X if the
-std=iso9899:1999 option is given.
The conditional text X in a %{S:X} or similar construct may contain
other nested % constructs or spaces, or even newlines. They are
processed as usual, as described above. Trailing white space in X is
ignored. White space may also appear anywhere on the left side of the
colon in these constructs, except between . or * and the corresponding
word.
The -O, -f, -g, -m, and -W switches are handled specifically in these
constructs. If another value of -O or the negated form of a -f, -m, or
-W switch is found later in the command line, the earlier switch
value is ignored, except with {S*} where S is just one letter; this
passes all matching options.
The character | at the beginning of the predicate text is used to indicate
that a command should be piped to the following command, but only if -pipe
is specified.
Note that it is built into GCC which switches take arguments and which
do not. You might think it would be useful to generalize this to
allow each compiler's spec to say which switches take arguments. But
this cannot be done in a consistent fashion. GCC cannot even decide
which input files have been specified without knowing which switches
take arguments, and it must know which input files to compile in order
to tell which compilers to run.
GCC also knows implicitly that arguments starting in `-l' are to be
treated as compiler output files, and passed to the linker in their
proper position among the other output files. */
/* Define the macros used for specs %a, %l, %L, %S, %C, %1. */
/* config.h can define ASM_SPEC to provide extra args to the assembler
or extra switch-translations. */
#ifndef ASM_SPEC
#define ASM_SPEC ""
#endif
/* config.h can define ASM_FINAL_SPEC to run a post processor after
the assembler has run. */
#ifndef ASM_FINAL_SPEC
#define ASM_FINAL_SPEC \
"%{gsplit-dwarf: \n\
objcopy --extract-dwo \
%{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
%{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo} \n\
objcopy --strip-dwo \
%{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
}"
#endif
/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
or extra switch-translations. */
#ifndef CPP_SPEC
#define CPP_SPEC ""
#endif
/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
or extra switch-translations. */
#ifndef CC1_SPEC
#define CC1_SPEC ""
#endif
/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
or extra switch-translations. */
#ifndef CC1PLUS_SPEC
#define CC1PLUS_SPEC ""
#endif
/* config.h can define LINK_SPEC to provide extra args to the linker
or extra switch-translations. */
#ifndef LINK_SPEC
#define LINK_SPEC ""
#endif
/* config.h can define LIB_SPEC to override the default libraries. */
#ifndef LIB_SPEC
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#endif
/* When using -fsplit-stack we need to wrap pthread_create, in order
to initialize the stack guard. We always use wrapping, rather than
shared library ordering, and we keep the wrapper function in
libgcc. This is not yet a real spec, though it could become one;
it is currently just stuffed into LINK_SPEC. FIXME: This wrapping
only works with GNU ld and gold. */
#ifdef HAVE_GOLD_NON_DEFAULT_SPLIT_STACK
#define STACK_SPLIT_SPEC " %{fsplit-stack: -fuse-ld=gold --wrap=pthread_create}"
#else
#define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
#endif
#ifndef LIBASAN_SPEC
#define STATIC_LIBASAN_LIBS \
" %{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}"
#ifdef LIBASAN_EARLY_SPEC
#define LIBASAN_SPEC STATIC_LIBASAN_LIBS
#elif defined(HAVE_LD_STATIC_DYNAMIC)
#define LIBASAN_SPEC "%{static-libasan:" LD_STATIC_OPTION \
"} -lasan %{static-libasan:" LD_DYNAMIC_OPTION "}" \
STATIC_LIBASAN_LIBS
#else
#define LIBASAN_SPEC "-lasan" STATIC_LIBASAN_LIBS
#endif
#endif
#ifndef LIBASAN_EARLY_SPEC
#define LIBASAN_EARLY_SPEC ""
#endif
#ifndef LIBTSAN_SPEC
#define STATIC_LIBTSAN_LIBS \
" %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}"
#ifdef LIBTSAN_EARLY_SPEC
#define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS
#elif defined(HAVE_LD_STATIC_DYNAMIC)
#define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \
"} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}" \
STATIC_LIBTSAN_LIBS
#else
#define LIBTSAN_SPEC "-ltsan" STATIC_LIBTSAN_LIBS
#endif
#endif
#ifndef LIBTSAN_EARLY_SPEC
#define LIBTSAN_EARLY_SPEC ""
#endif
#ifndef LIBLSAN_SPEC
#define STATIC_LIBLSAN_LIBS \
" %{static-liblsan|static:%:include(libsanitizer.spec)%(link_liblsan)}"
#ifdef LIBLSAN_EARLY_SPEC
#define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS
#elif defined(HAVE_LD_STATIC_DYNAMIC)
#define LIBLSAN_SPEC "%{static-liblsan:" LD_STATIC_OPTION \
"} -llsan %{static-liblsan:" LD_DYNAMIC_OPTION "}" \
STATIC_LIBLSAN_LIBS
#else
#define LIBLSAN_SPEC "-llsan" STATIC_LIBLSAN_LIBS
#endif
#endif
#ifndef LIBLSAN_EARLY_SPEC
#define LIBLSAN_EARLY_SPEC ""
#endif
#ifndef LIBUBSAN_SPEC
#define STATIC_LIBUBSAN_LIBS \
" %{static-libubsan|static:%:include(libsanitizer.spec)%(link_libubsan)}"
#ifdef HAVE_LD_STATIC_DYNAMIC
#define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \
"} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \
STATIC_LIBUBSAN_LIBS
#else
#define LIBUBSAN_SPEC "-lubsan" STATIC_LIBUBSAN_LIBS
#endif
#endif
/* Linker options for compressed debug sections. */
#if HAVE_LD_COMPRESS_DEBUG == 0
/* No linker support. */
#define LINK_COMPRESS_DEBUG_SPEC \
" %{gz*:%e-gz is not supported in this configuration} "
#elif HAVE_LD_COMPRESS_DEBUG == 1
/* GNU style on input, GNU ld options. Reject, not useful. */
#define LINK_COMPRESS_DEBUG_SPEC \
" %{gz*:%e-gz is not supported in this configuration} "
#elif HAVE_LD_COMPRESS_DEBUG == 2
/* GNU style, GNU gold options. */
#define LINK_COMPRESS_DEBUG_SPEC \
" %{gz|gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
" %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \
" %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
#elif HAVE_LD_COMPRESS_DEBUG == 3
/* ELF gABI style. */
#define LINK_COMPRESS_DEBUG_SPEC \
" %{gz|gz=zlib:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
" %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \
" %{gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
#else
#error Unknown value for HAVE_LD_COMPRESS_DEBUG.
#endif
/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
included. */
#ifndef LIBGCC_SPEC
#if defined(REAL_LIBGCC_SPEC)
#define LIBGCC_SPEC REAL_LIBGCC_SPEC
#elif defined(LINK_LIBGCC_SPECIAL_1)
/* Have gcc do the search for libgcc.a. */
#define LIBGCC_SPEC "libgcc.a%s"
#else
#define LIBGCC_SPEC "-lgcc"
#endif
#endif
/* config.h can define STARTFILE_SPEC to override the default crt0 files. */
#ifndef STARTFILE_SPEC
#define STARTFILE_SPEC \
"%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
#endif
/* config.h can define ENDFILE_SPEC to override the default crtn files. */
#ifndef ENDFILE_SPEC
#define ENDFILE_SPEC ""
#endif
#ifndef LINKER_NAME
#define LINKER_NAME "collect2"
#endif
#ifdef HAVE_AS_DEBUG_PREFIX_MAP
#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
#else
#define ASM_MAP ""
#endif
/* Assembler options for compressed debug sections. */
#if HAVE_LD_COMPRESS_DEBUG < 2
/* Reject if the linker cannot write compressed debug sections. */
#define ASM_COMPRESS_DEBUG_SPEC \
" %{gz*:%e-gz is not supported in this configuration} "
#else /* HAVE_LD_COMPRESS_DEBUG >= 2 */
#if HAVE_AS_COMPRESS_DEBUG == 0
/* No assembler support. Ignore silently. */
#define ASM_COMPRESS_DEBUG_SPEC \
" %{gz*:} "
#elif HAVE_AS_COMPRESS_DEBUG == 1
/* GNU style, GNU as options. */
#define ASM_COMPRESS_DEBUG_SPEC \
" %{gz|gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "}" \
" %{gz=none:" AS_NO_COMPRESS_DEBUG_OPTION "}" \
" %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
#elif HAVE_AS_COMPRESS_DEBUG == 2
/* ELF gABI style. */
#define ASM_COMPRESS_DEBUG_SPEC \
" %{gz|gz=zlib:" AS_COMPRESS_DEBUG_OPTION "=zlib}" \
" %{gz=none:" AS_COMPRESS_DEBUG_OPTION "=none}" \
" %{gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
#else
#error Unknown value for HAVE_AS_COMPRESS_DEBUG.
#endif
#endif /* HAVE_LD_COMPRESS_DEBUG >= 2 */
/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
to the assembler. */
#ifndef ASM_DEBUG_SPEC
# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
&& defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
# define ASM_DEBUG_SPEC \
(PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
? "%{%:debug-level-gt(0):" \
"%{gdwarf*:--gdwarf2}%{!gdwarf*:%{g*:--gstabs}}}" ASM_MAP \
: "%{%:debug-level-gt(0):" \
"%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
# else
# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
# define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):--gstabs}}" ASM_MAP
# endif
# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
# define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):--gdwarf2}}" ASM_MAP
# endif
# endif
#endif
#ifndef ASM_DEBUG_SPEC
# define ASM_DEBUG_SPEC ""
#endif
/* Here is the spec for running the linker, after compiling all files. */
/* This is overridable by the target in case they need to specify the
-lgcc and -lc order specially, yet not require them to override all
of LINK_COMMAND_SPEC. */
#ifndef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC "%G %{!nolibc:%L %G}"
#endif
#ifndef LINK_SSP_SPEC
#ifdef TARGET_LIBC_PROVIDES_SSP
#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
"|fstack-protector-strong|fstack-protector-explicit:}"
#else
#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
"|fstack-protector-strong|fstack-protector-explicit" \
":-lssp_nonshared -lssp}"
#endif
#endif
#ifdef ENABLE_DEFAULT_PIE
#define PIE_SPEC "!no-pie"
#define NO_FPIE1_SPEC "fno-pie"
#define FPIE1_SPEC NO_FPIE1_SPEC ":;"
#define NO_FPIE2_SPEC "fno-PIE"
#define FPIE2_SPEC NO_FPIE2_SPEC ":;"
#define NO_FPIE_SPEC NO_FPIE1_SPEC "|" NO_FPIE2_SPEC
#define FPIE_SPEC NO_FPIE_SPEC ":;"
#define NO_FPIC1_SPEC "fno-pic"
#define FPIC1_SPEC NO_FPIC1_SPEC ":;"
#define NO_FPIC2_SPEC "fno-PIC"
#define FPIC2_SPEC NO_FPIC2_SPEC ":;"
#define NO_FPIC_SPEC NO_FPIC1_SPEC "|" NO_FPIC2_SPEC
#define FPIC_SPEC NO_FPIC_SPEC ":;"
#define NO_FPIE1_AND_FPIC1_SPEC NO_FPIE1_SPEC "|" NO_FPIC1_SPEC
#define FPIE1_OR_FPIC1_SPEC NO_FPIE1_AND_FPIC1_SPEC ":;"
#define NO_FPIE2_AND_FPIC2_SPEC NO_FPIE2_SPEC "|" NO_FPIC2_SPEC
#define FPIE2_OR_FPIC2_SPEC NO_FPIE2_AND_FPIC2_SPEC ":;"
#define NO_FPIE_AND_FPIC_SPEC NO_FPIE_SPEC "|" NO_FPIC_SPEC
#define FPIE_OR_FPIC_SPEC NO_FPIE_AND_FPIC_SPEC ":;"
#else
#define PIE_SPEC "pie"
#define FPIE1_SPEC "fpie"
#define NO_FPIE1_SPEC FPIE1_SPEC ":;"
#define FPIE2_SPEC "fPIE"
#define NO_FPIE2_SPEC FPIE2_SPEC ":;"
#define FPIE_SPEC FPIE1_SPEC "|" FPIE2_SPEC
#define NO_FPIE_SPEC FPIE_SPEC ":;"
#define FPIC1_SPEC "fpic"
#define NO_FPIC1_SPEC FPIC1_SPEC ":;"
#define FPIC2_SPEC "fPIC"
#define NO_FPIC2_SPEC FPIC2_SPEC ":;"
#define FPIC_SPEC FPIC1_SPEC "|" FPIC2_SPEC
#define NO_FPIC_SPEC FPIC_SPEC ":;"
#define FPIE1_OR_FPIC1_SPEC FPIE1_SPEC "|" FPIC1_SPEC
#define NO_FPIE1_AND_FPIC1_SPEC FPIE1_OR_FPIC1_SPEC ":;"
#define FPIE2_OR_FPIC2_SPEC FPIE2_SPEC "|" FPIC2_SPEC
#define NO_FPIE2_AND_FPIC2_SPEC FPIE1_OR_FPIC2_SPEC ":;"
#define FPIE_OR_FPIC_SPEC FPIE_SPEC "|" FPIC_SPEC
#define NO_FPIE_AND_FPIC_SPEC FPIE_OR_FPIC_SPEC ":;"
#endif
#ifndef LINK_PIE_SPEC
#ifdef HAVE_LD_PIE
#ifndef LD_PIE_SPEC
#define LD_PIE_SPEC "-pie"
#endif
#else
#define LD_PIE_SPEC ""
#endif
#define LINK_PIE_SPEC "%{static|shared|r:;" PIE_SPEC ":" LD_PIE_SPEC "} "
#endif
#ifndef LINK_BUILDID_SPEC
# if defined(HAVE_LD_BUILDID) && defined(ENABLE_LD_BUILDID)
# define LINK_BUILDID_SPEC "%{!r:--build-id} "
# endif
#endif
/* Conditional to test whether the LTO plugin is used or not.
FIXME: For slim LTO we will need to enable plugin unconditionally. This
still cause problems with PLUGIN_LD != LD and when plugin is built but
not useable. For GCC 4.6 we don't support slim LTO and thus we can enable
plugin only when LTO is enabled. We still honor explicit
-fuse-linker-plugin if the linker used understands -plugin. */
/* The linker has some plugin support. */
#if HAVE_LTO_PLUGIN > 0
/* The linker used has full plugin support, use LTO plugin by default. */
#if HAVE_LTO_PLUGIN == 2
#define PLUGIN_COND "!fno-use-linker-plugin:%{!fno-lto"
#define PLUGIN_COND_CLOSE "}"
#else
/* The linker used has limited plugin support, use LTO plugin with explicit
-fuse-linker-plugin. */
#define PLUGIN_COND "fuse-linker-plugin"
#define PLUGIN_COND_CLOSE ""
#endif
#define LINK_PLUGIN_SPEC \
"%{" PLUGIN_COND": \
-plugin %(linker_plugin_file) \
-plugin-opt=%(lto_wrapper) \
-plugin-opt=-fresolution=%u.res \
%{flinker-output=*:-plugin-opt=-linker-output-known} \
%{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
}" PLUGIN_COND_CLOSE
#else
/* The linker used doesn't support -plugin, reject -fuse-linker-plugin. */
#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
%e-fuse-linker-plugin is not supported in this configuration}"
#endif
/* Linker command line options for -fsanitize= early on the command line. */
#ifndef SANITIZER_EARLY_SPEC
#define SANITIZER_EARLY_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
%{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
%{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}"
#endif
/* Linker command line options for -fsanitize= late on the command line. */
#ifndef SANITIZER_SPEC
#define SANITIZER_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=address}}\
%{%:sanitize(thread):" LIBTSAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=thread}}\
%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
%{%:sanitize(leak):" LIBLSAN_SPEC "}}}}"
#endif
#ifndef POST_LINK_SPEC
#define POST_LINK_SPEC ""