]>
Commit | Line | Data |
---|---|---|
4ee9c684 | 1 | /* Specific flags and argument handling of the Fortran front-end. |
fbd26352 | 2 | Copyright (C) 1997-2019 Free Software Foundation, Inc. |
4ee9c684 | 3 | |
ffac9d61 | 4 | This file is part of GCC. |
4ee9c684 | 5 | |
6 | GNU CC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
bdabe786 | 8 | the Free Software Foundation; either version 3, or (at your option) |
4ee9c684 | 9 | any later version. |
10 | ||
11 | GNU CC is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
bdabe786 | 17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
d56f2727 | 19 | |
4ee9c684 | 20 | /* This file is copied more or less verbatim from g77. */ |
21 | /* This file contains a filter for the main `gcc' driver, which is | |
22 | replicated for the `gfortran' driver by adding this filter. The purpose | |
23 | of this filter is to be basically identical to gcc (in that | |
24 | it faithfully passes all of the original arguments to gcc) but, | |
25 | unless explicitly overridden by the user in certain ways, ensure | |
26 | that the needs of the language supported by this wrapper are met. | |
27 | ||
28 | For GNU Fortran 95(gfortran), we do the following to the argument list | |
29 | before passing it to `gcc': | |
30 | ||
31 | 1. Make sure `-lgfortran -lm' is at the end of the list. | |
32 | ||
33 | 2. Make sure each time `-lgfortran' or `-lm' is seen, it forms | |
34 | part of the series `-lgfortran -lm'. | |
35 | ||
36 | #1 and #2 are not done if `-nostdlib' or any option that disables | |
37 | the linking phase is present, or if `-xfoo' is in effect. Note that | |
38 | a lack of source files or -l options disables linking. | |
39 | ||
40 | This program was originally made out of gcc/cp/g++spec.c, but the | |
41 | way it builds the new argument list was rewritten so it is much | |
42 | easier to maintain, improve the way it decides to add or not add | |
43 | extra arguments, etc. And several improvements were made in the | |
44 | handling of arguments, primarily to make it more consistent with | |
45 | `gcc' itself. */ | |
46 | ||
47 | #include "config.h" | |
48 | #include "system.h" | |
cb22f930 | 49 | #include "coretypes.h" |
2abdff38 | 50 | #include "opt-suggestions.h" |
4ee9c684 | 51 | #include "gcc.h" |
cb22f930 | 52 | #include "opts.h" |
4ee9c684 | 53 | |
4ee9c684 | 54 | #include "tm.h" |
41481754 | 55 | #include "intl.h" |
4ee9c684 | 56 | |
57 | #ifndef MATH_LIBRARY | |
cb22f930 | 58 | #define MATH_LIBRARY "m" |
4ee9c684 | 59 | #endif |
60 | ||
4ee9c684 | 61 | #ifndef FORTRAN_LIBRARY |
cb22f930 | 62 | #define FORTRAN_LIBRARY "gfortran" |
9a61fba1 | 63 | #endif |
64 | ||
87969c8c | 65 | /* Name of the spec file. */ |
66 | #define SPEC_FILE "libgfortran.spec" | |
67 | ||
4ee9c684 | 68 | /* The original argument list and related info is copied here. */ |
cb22f930 | 69 | static unsigned int g77_xargc; |
70 | static const struct cl_decoded_option *g77_x_decoded_options; | |
71 | static void append_arg (const struct cl_decoded_option *); | |
4ee9c684 | 72 | |
73 | /* The new argument list will be built here. */ | |
cb22f930 | 74 | static unsigned int g77_newargc; |
75 | static struct cl_decoded_option *g77_new_decoded_options; | |
4ee9c684 | 76 | |
56331357 | 77 | /* This will be NULL if we encounter a situation where we should not |
78 | link in the fortran libraries. */ | |
79 | static const char *library = NULL; | |
5073b85e | 80 | |
87969c8c | 81 | |
cb22f930 | 82 | /* Return whether strings S1 and S2 are both NULL or both the same |
83 | string. */ | |
4ee9c684 | 84 | |
cb22f930 | 85 | static bool |
86 | strings_same (const char *s1, const char *s2) | |
4ee9c684 | 87 | { |
cb22f930 | 88 | return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0); |
89 | } | |
4ee9c684 | 90 | |
cb22f930 | 91 | /* Return whether decoded option structures OPT1 and OPT2 are the |
92 | same. */ | |
93 | ||
94 | static bool | |
95 | options_same (const struct cl_decoded_option *opt1, | |
96 | const struct cl_decoded_option *opt2) | |
97 | { | |
98 | return (opt1->opt_index == opt2->opt_index | |
99 | && strings_same (opt1->arg, opt2->arg) | |
100 | && strings_same (opt1->orig_option_with_args_text, | |
101 | opt2->orig_option_with_args_text) | |
102 | && strings_same (opt1->canonical_option[0], | |
103 | opt2->canonical_option[0]) | |
104 | && strings_same (opt1->canonical_option[1], | |
105 | opt2->canonical_option[1]) | |
106 | && strings_same (opt1->canonical_option[2], | |
107 | opt2->canonical_option[2]) | |
108 | && strings_same (opt1->canonical_option[3], | |
109 | opt2->canonical_option[3]) | |
110 | && (opt1->canonical_option_num_elements | |
111 | == opt2->canonical_option_num_elements) | |
112 | && opt1->value == opt2->value | |
113 | && opt1->errors == opt2->errors); | |
4ee9c684 | 114 | } |
115 | ||
116 | /* Append another argument to the list being built. As long as it is | |
117 | identical to the corresponding arg in the original list, just increment | |
118 | the new arg count. Otherwise allocate a new list, etc. */ | |
119 | ||
120 | static void | |
cb22f930 | 121 | append_arg (const struct cl_decoded_option *arg) |
4ee9c684 | 122 | { |
cb22f930 | 123 | static unsigned int newargsize; |
4ee9c684 | 124 | |
cb22f930 | 125 | if (g77_new_decoded_options == g77_x_decoded_options |
4ee9c684 | 126 | && g77_newargc < g77_xargc |
cb22f930 | 127 | && options_same (arg, &g77_x_decoded_options[g77_newargc])) |
4ee9c684 | 128 | { |
129 | ++g77_newargc; | |
b14e2757 | 130 | return; /* Nothing new here. */ |
4ee9c684 | 131 | } |
132 | ||
cb22f930 | 133 | if (g77_new_decoded_options == g77_x_decoded_options) |
b14e2757 | 134 | { /* Make new arglist. */ |
cb22f930 | 135 | unsigned int i; |
4ee9c684 | 136 | |
b14e2757 | 137 | newargsize = (g77_xargc << 2) + 20; /* This should handle all. */ |
cb22f930 | 138 | g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize); |
4ee9c684 | 139 | |
140 | /* Copy what has been done so far. */ | |
141 | for (i = 0; i < g77_newargc; ++i) | |
cb22f930 | 142 | g77_new_decoded_options[i] = g77_x_decoded_options[i]; |
4ee9c684 | 143 | } |
144 | ||
145 | if (g77_newargc == newargsize) | |
85b9be9b | 146 | fatal_error (input_location, "overflowed output argument list for %qs", |
cb22f930 | 147 | arg->orig_option_with_args_text); |
148 | ||
149 | g77_new_decoded_options[g77_newargc++] = *arg; | |
150 | } | |
4ee9c684 | 151 | |
cb22f930 | 152 | /* Append an option described by OPT_INDEX, ARG and VALUE to the list |
153 | being built. */ | |
154 | static void | |
155 | append_option (size_t opt_index, const char *arg, int value) | |
156 | { | |
157 | struct cl_decoded_option decoded; | |
158 | ||
159 | generate_option (opt_index, arg, value, CL_DRIVER, &decoded); | |
160 | append_arg (&decoded); | |
161 | } | |
162 | ||
163 | /* Append a libgfortran argument to the list being built. If | |
164 | FORCE_STATIC, ensure the library is linked statically. */ | |
165 | ||
166 | static void | |
167 | add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED) | |
168 | { | |
169 | #ifdef HAVE_LD_STATIC_DYNAMIC | |
170 | if (force_static) | |
e6937b3a | 171 | append_option (OPT_Wl_, LD_STATIC_OPTION, 1); |
cb22f930 | 172 | #endif |
173 | append_option (OPT_l, FORTRAN_LIBRARY, 1); | |
174 | #ifdef HAVE_LD_STATIC_DYNAMIC | |
175 | if (force_static) | |
e6937b3a | 176 | append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1); |
cb22f930 | 177 | #endif |
4ee9c684 | 178 | } |
179 | ||
180 | void | |
cb22f930 | 181 | lang_specific_driver (struct cl_decoded_option **in_decoded_options, |
182 | unsigned int *in_decoded_options_count, | |
4ee9c684 | 183 | int *in_added_libraries ATTRIBUTE_UNUSED) |
184 | { | |
cb22f930 | 185 | unsigned int argc = *in_decoded_options_count; |
186 | struct cl_decoded_option *decoded_options = *in_decoded_options; | |
187 | unsigned int i; | |
4ee9c684 | 188 | int verbose = 0; |
4ee9c684 | 189 | |
4ee9c684 | 190 | /* 0 => -xnone in effect. |
191 | 1 => -xfoo in effect. */ | |
192 | int saw_speclang = 0; | |
193 | ||
194 | /* 0 => initial/reset state | |
195 | 1 => last arg was -l<library> | |
196 | 2 => last two args were -l<library> -lm. */ | |
197 | int saw_library = 0; | |
198 | ||
4ee9c684 | 199 | /* By default, we throw on the math library if we have one. */ |
200 | int need_math = (MATH_LIBRARY[0] != '\0'); | |
201 | ||
293d72e0 | 202 | /* Whether we should link a static libgfortran. */ |
5fe33912 | 203 | int static_lib = 0; |
9a61fba1 | 204 | |
205 | /* Whether we need to link statically. */ | |
206 | int static_linking = 0; | |
207 | ||
4ee9c684 | 208 | /* The number of input and output files in the incoming arg list. */ |
209 | int n_infiles = 0; | |
210 | int n_outfiles = 0; | |
211 | ||
56331357 | 212 | library = FORTRAN_LIBRARY; |
213 | ||
4ee9c684 | 214 | #if 0 |
215 | fprintf (stderr, "Incoming:"); | |
216 | for (i = 0; i < argc; i++) | |
cb22f930 | 217 | fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text); |
4ee9c684 | 218 | fprintf (stderr, "\n"); |
219 | #endif | |
220 | ||
221 | g77_xargc = argc; | |
cb22f930 | 222 | g77_x_decoded_options = decoded_options; |
4ee9c684 | 223 | g77_newargc = 0; |
cb22f930 | 224 | g77_new_decoded_options = decoded_options; |
4ee9c684 | 225 | |
226 | /* First pass through arglist. | |
227 | ||
228 | If -nostdlib or a "turn-off-linking" option is anywhere in the | |
229 | command line, don't do any library-option processing (except | |
cb22f930 | 230 | relating to -x). */ |
4ee9c684 | 231 | |
232 | for (i = 1; i < argc; ++i) | |
233 | { | |
3289fb1d | 234 | if (decoded_options[i].errors & CL_ERR_MISSING_ARG) |
235 | continue; | |
236 | ||
cb22f930 | 237 | switch (decoded_options[i].opt_index) |
4ee9c684 | 238 | { |
cb22f930 | 239 | case OPT_SPECIAL_input_file: |
4ee9c684 | 240 | ++n_infiles; |
241 | continue; | |
4ee9c684 | 242 | |
cb22f930 | 243 | case OPT_nostdlib: |
244 | case OPT_nodefaultlibs: | |
245 | case OPT_c: | |
32398841 | 246 | case OPT_r: |
cb22f930 | 247 | case OPT_S: |
248 | case OPT_fsyntax_only: | |
249 | case OPT_E: | |
4ee9c684 | 250 | /* These options disable linking entirely or linking of the |
251 | standard libraries. */ | |
252 | library = 0; | |
253 | break; | |
254 | ||
cb22f930 | 255 | case OPT_static_libgfortran: |
5fe33912 | 256 | #ifdef HAVE_LD_STATIC_DYNAMIC |
9a61fba1 | 257 | static_lib = 1; |
5fe33912 | 258 | #endif |
9a61fba1 | 259 | break; |
260 | ||
cb22f930 | 261 | case OPT_static: |
5fe33912 | 262 | #ifdef HAVE_LD_STATIC_DYNAMIC |
9a61fba1 | 263 | static_linking = 1; |
5fe33912 | 264 | #endif |
ae66030b | 265 | break; |
9a61fba1 | 266 | |
cb22f930 | 267 | case OPT_l: |
4ee9c684 | 268 | ++n_infiles; |
269 | break; | |
270 | ||
cb22f930 | 271 | case OPT_o: |
4ee9c684 | 272 | ++n_outfiles; |
273 | break; | |
274 | ||
cb22f930 | 275 | case OPT_v: |
4ee9c684 | 276 | verbose = 1; |
277 | break; | |
278 | ||
5789e05b | 279 | case OPT__version: |
d25dc80e | 280 | printf ("GNU Fortran %s%s\n", pkgversion_string, version_string); |
3d8932fd | 281 | printf ("Copyright %s 2019 Free Software Foundation, Inc.\n", |
d56f2727 | 282 | _("(C)")); |
d961899a | 283 | fputs (_("This is free software; see the source for copying conditions. There is NO\n\ |
284 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), | |
285 | stdout); | |
4ee9c684 | 286 | exit (0); |
287 | break; | |
288 | ||
5789e05b | 289 | case OPT__help: |
4ee9c684 | 290 | /* Let gcc.c handle this, as it has a really |
291 | cool facility for handling --help and --verbose --help. */ | |
292 | return; | |
293 | ||
294 | default: | |
295 | break; | |
296 | } | |
4ee9c684 | 297 | } |
298 | ||
299 | if ((n_outfiles != 0) && (n_infiles == 0)) | |
c05be867 | 300 | fatal_error (input_location, |
301 | "no input files; unwilling to write output files"); | |
4ee9c684 | 302 | |
303 | /* If there are no input files, no need for the library. */ | |
304 | if (n_infiles == 0) | |
305 | library = 0; | |
306 | ||
307 | /* Second pass through arglist, transforming arguments as appropriate. */ | |
308 | ||
cb22f930 | 309 | append_arg (&decoded_options[0]); /* Start with command name, of course. */ |
4ee9c684 | 310 | |
311 | for (i = 1; i < argc; ++i) | |
312 | { | |
cb22f930 | 313 | if (decoded_options[i].errors & CL_ERR_MISSING_ARG) |
314 | { | |
315 | append_arg (&decoded_options[i]); | |
316 | continue; | |
317 | } | |
318 | ||
319 | if (decoded_options[i].opt_index == OPT_SPECIAL_input_file | |
320 | && decoded_options[i].arg[0] == '\0') | |
4ee9c684 | 321 | { |
cb22f930 | 322 | /* Interesting. Just append as is. */ |
323 | append_arg (&decoded_options[i]); | |
4ee9c684 | 324 | continue; |
325 | } | |
326 | ||
cb22f930 | 327 | if (decoded_options[i].opt_index != OPT_l |
328 | && (decoded_options[i].opt_index != OPT_SPECIAL_input_file | |
329 | || strcmp (decoded_options[i].arg, "-") == 0)) | |
4ee9c684 | 330 | { |
b14e2757 | 331 | /* Not a filename or library. */ |
4ee9c684 | 332 | |
b14e2757 | 333 | if (saw_library == 1 && need_math) /* -l<library>. */ |
cb22f930 | 334 | append_option (OPT_l, MATH_LIBRARY, 1); |
4ee9c684 | 335 | |
336 | saw_library = 0; | |
337 | ||
cb22f930 | 338 | if (decoded_options[i].opt_index == OPT_SPECIAL_input_file) |
4ee9c684 | 339 | { |
cb22f930 | 340 | append_arg (&decoded_options[i]); /* "-" == Standard input. */ |
4ee9c684 | 341 | continue; |
342 | } | |
343 | ||
cb22f930 | 344 | if (decoded_options[i].opt_index == OPT_x) |
4ee9c684 | 345 | { |
b14e2757 | 346 | /* Track input language. */ |
cb22f930 | 347 | const char *lang = decoded_options[i].arg; |
4ee9c684 | 348 | |
349 | saw_speclang = (strcmp (lang, "none") != 0); | |
350 | } | |
351 | ||
cb22f930 | 352 | append_arg (&decoded_options[i]); |
4ee9c684 | 353 | |
354 | continue; | |
355 | } | |
356 | ||
b14e2757 | 357 | /* A filename/library, not an option. */ |
4ee9c684 | 358 | |
359 | if (saw_speclang) | |
b14e2757 | 360 | saw_library = 0; /* -xfoo currently active. */ |
4ee9c684 | 361 | else |
b14e2757 | 362 | { /* -lfoo or filename. */ |
cb22f930 | 363 | if (decoded_options[i].opt_index == OPT_l |
364 | && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0) | |
4ee9c684 | 365 | { |
366 | if (saw_library == 1) | |
b14e2757 | 367 | saw_library = 2; /* -l<library> -lm. */ |
4ee9c684 | 368 | else |
cb22f930 | 369 | add_arg_libgfortran (static_lib && !static_linking); |
4ee9c684 | 370 | } |
cb22f930 | 371 | else if (decoded_options[i].opt_index == OPT_l |
372 | && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0) | |
9a61fba1 | 373 | { |
374 | saw_library = 1; /* -l<library>. */ | |
cb22f930 | 375 | add_arg_libgfortran (static_lib && !static_linking); |
9a61fba1 | 376 | continue; |
377 | } | |
4ee9c684 | 378 | else |
b14e2757 | 379 | { /* Other library, or filename. */ |
4ee9c684 | 380 | if (saw_library == 1 && need_math) |
cb22f930 | 381 | append_option (OPT_l, MATH_LIBRARY, 1); |
4ee9c684 | 382 | saw_library = 0; |
383 | } | |
384 | } | |
cb22f930 | 385 | append_arg (&decoded_options[i]); |
4ee9c684 | 386 | } |
387 | ||
b4a5e31d | 388 | /* Append `-lgfortran -lm' as necessary. */ |
4ee9c684 | 389 | |
390 | if (library) | |
b14e2757 | 391 | { /* Doing a link and no -nostdlib. */ |
4ee9c684 | 392 | if (saw_speclang) |
cb22f930 | 393 | append_option (OPT_x, "none", 1); |
4ee9c684 | 394 | |
395 | switch (saw_library) | |
396 | { | |
397 | case 0: | |
cb22f930 | 398 | add_arg_libgfortran (static_lib && !static_linking); |
9a61fba1 | 399 | /* Fall through. */ |
400 | ||
4ee9c684 | 401 | case 1: |
402 | if (need_math) | |
cb22f930 | 403 | append_option (OPT_l, MATH_LIBRARY, 1); |
4ee9c684 | 404 | default: |
405 | break; | |
406 | } | |
407 | } | |
408 | ||
409 | #ifdef ENABLE_SHARED_LIBGCC | |
410 | if (library) | |
411 | { | |
cb22f930 | 412 | unsigned int i; |
4ee9c684 | 413 | |
414 | for (i = 1; i < g77_newargc; i++) | |
cb22f930 | 415 | if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc |
416 | || g77_new_decoded_options[i].opt_index == OPT_static) | |
417 | break; | |
4ee9c684 | 418 | |
419 | if (i == g77_newargc) | |
cb22f930 | 420 | append_option (OPT_shared_libgcc, NULL, 1); |
4ee9c684 | 421 | } |
422 | ||
423 | #endif | |
424 | ||
cb22f930 | 425 | if (verbose && g77_new_decoded_options != g77_x_decoded_options) |
4ee9c684 | 426 | { |
41481754 | 427 | fprintf (stderr, _("Driving:")); |
4ee9c684 | 428 | for (i = 0; i < g77_newargc; i++) |
cb22f930 | 429 | fprintf (stderr, " %s", |
430 | g77_new_decoded_options[i].orig_option_with_args_text); | |
4ee9c684 | 431 | fprintf (stderr, "\n"); |
432 | } | |
433 | ||
cb22f930 | 434 | *in_decoded_options_count = g77_newargc; |
435 | *in_decoded_options = g77_new_decoded_options; | |
4ee9c684 | 436 | } |
437 | ||
d56f2727 | 438 | |
b14e2757 | 439 | /* Called before linking. Returns 0 on success and -1 on failure. */ |
4ee9c684 | 440 | int |
5073b85e | 441 | lang_specific_pre_link (void) |
4ee9c684 | 442 | { |
667a8869 | 443 | if (library) |
5073b85e | 444 | do_spec ("%:include(libgfortran.spec)"); |
445 | ||
4ee9c684 | 446 | return 0; |
447 | } | |
448 | ||
b14e2757 | 449 | /* Number of extra output files that lang_specific_pre_link may generate. */ |
450 | int lang_specific_extra_outfiles = 0; /* Not used for F77. */ |