Line data Source code
1 : /* Specific flags and argument handling of the Fortran front-end.
2 : Copyright (C) 1997-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
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
8 : the Free Software Foundation; either version 3, or (at your option)
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
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
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.cc, 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"
49 : #include "coretypes.h"
50 : #include "opt-suggestions.h"
51 : #include "gcc.h"
52 : #include "opts.h"
53 :
54 : #include "tm.h"
55 : #include "intl.h"
56 :
57 : #ifndef MATH_LIBRARY
58 : #define MATH_LIBRARY "m"
59 : #endif
60 :
61 : #ifndef FORTRAN_LIBRARY
62 : #define FORTRAN_LIBRARY "gfortran"
63 : #endif
64 :
65 : /* Name of the spec file. */
66 : #define SPEC_FILE "libgfortran.spec"
67 :
68 : /* The original argument list and related info is copied here. */
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 *);
72 :
73 : /* The new argument list will be built here. */
74 : static unsigned int g77_newargc;
75 : static struct cl_decoded_option *g77_new_decoded_options;
76 :
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;
80 :
81 :
82 : /* Return whether strings S1 and S2 are both NULL or both the same
83 : string. */
84 :
85 : static bool
86 4359845 : strings_same (const char *s1, const char *s2)
87 : {
88 4359845 : return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0);
89 : }
90 :
91 : /* Return whether decoded option structures OPT1 and OPT2 are the
92 : same. */
93 :
94 : static bool
95 747392 : options_same (const struct cl_decoded_option *opt1,
96 : const struct cl_decoded_option *opt2)
97 : {
98 747392 : return (opt1->opt_index == opt2->opt_index
99 747390 : && strings_same (opt1->arg, opt2->arg)
100 722491 : && strings_same (opt1->orig_option_with_args_text,
101 722491 : opt2->orig_option_with_args_text)
102 722491 : && strings_same (opt1->canonical_option[0],
103 722491 : opt2->canonical_option[0])
104 722491 : && strings_same (opt1->canonical_option[1],
105 722491 : opt2->canonical_option[1])
106 722491 : && strings_same (opt1->canonical_option[2],
107 722491 : opt2->canonical_option[2])
108 722491 : && strings_same (opt1->canonical_option[3],
109 722491 : opt2->canonical_option[3])
110 722491 : && (opt1->canonical_option_num_elements
111 722491 : == opt2->canonical_option_num_elements)
112 722491 : && opt1->value == opt2->value
113 1469883 : && opt1->errors == opt2->errors);
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
121 872170 : append_arg (const struct cl_decoded_option *arg)
122 : {
123 872170 : static unsigned int newargsize;
124 :
125 872170 : if (g77_new_decoded_options == g77_x_decoded_options
126 747484 : && g77_newargc < g77_xargc
127 1619562 : && options_same (arg, &g77_x_decoded_options[g77_newargc]))
128 : {
129 722491 : ++g77_newargc;
130 722491 : return; /* Nothing new here. */
131 : }
132 :
133 149679 : if (g77_new_decoded_options == g77_x_decoded_options)
134 : { /* Make new arglist. */
135 24993 : unsigned int i;
136 :
137 24993 : newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
138 24993 : g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
139 :
140 : /* Copy what has been done so far. */
141 558635 : for (i = 0; i < g77_newargc; ++i)
142 533642 : g77_new_decoded_options[i] = g77_x_decoded_options[i];
143 : }
144 :
145 149679 : if (g77_newargc == newargsize)
146 0 : fatal_error (input_location, "overflowed output argument list for %qs",
147 0 : arg->orig_option_with_args_text);
148 :
149 149679 : g77_new_decoded_options[g77_newargc++] = *arg;
150 : }
151 :
152 : /* Append an option described by OPT_INDEX, ARG and VALUE to the list
153 : being built. */
154 : static void
155 99879 : append_option (size_t opt_index, const char *arg, int value)
156 : {
157 99879 : struct cl_decoded_option decoded;
158 :
159 99879 : generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
160 99879 : append_arg (&decoded);
161 99879 : }
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 49894 : add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
168 : {
169 : #ifdef HAVE_LD_STATIC_DYNAMIC
170 49894 : if (force_static)
171 4 : append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
172 : #endif
173 49894 : append_option (OPT_l, FORTRAN_LIBRARY, 1);
174 : #ifdef HAVE_LD_STATIC_DYNAMIC
175 49894 : if (force_static)
176 4 : append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
177 : #endif
178 49894 : }
179 :
180 : void
181 34522 : lang_specific_driver (struct cl_decoded_option **in_decoded_options,
182 : unsigned int *in_decoded_options_count,
183 : int *in_added_libraries ATTRIBUTE_UNUSED)
184 : {
185 34522 : unsigned int argc = *in_decoded_options_count;
186 34522 : struct cl_decoded_option *decoded_options = *in_decoded_options;
187 34522 : unsigned int i;
188 34522 : int verbose = 0;
189 :
190 : /* 0 => -xnone in effect.
191 : 1 => -xfoo in effect. */
192 34522 : 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 34522 : int saw_library = 0;
198 :
199 : /* By default, we throw on the math library if we have one. */
200 34522 : int need_math = (MATH_LIBRARY[0] != '\0');
201 :
202 : /* Whether we should link a static libgfortran. */
203 34522 : int static_lib = 0;
204 :
205 : /* Whether we need to link statically. */
206 34522 : int static_linking = 0;
207 :
208 : /* The number of input and output files in the incoming arg list. */
209 34522 : int n_infiles = 0;
210 34522 : int n_outfiles = 0;
211 :
212 34522 : library = FORTRAN_LIBRARY;
213 :
214 : #if 0
215 : fprintf (stderr, "Incoming:");
216 : for (i = 0; i < argc; i++)
217 : fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text);
218 : fprintf (stderr, "\n");
219 : #endif
220 :
221 34522 : g77_xargc = argc;
222 34522 : g77_x_decoded_options = decoded_options;
223 34522 : g77_newargc = 0;
224 34522 : g77_new_decoded_options = decoded_options;
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
230 : relating to -x). */
231 :
232 772321 : for (i = 1; i < argc; ++i)
233 : {
234 737803 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
235 0 : continue;
236 :
237 737803 : switch (decoded_options[i].opt_index)
238 : {
239 34785 : case OPT_SPECIAL_input_file:
240 34785 : ++n_infiles;
241 34785 : continue;
242 :
243 8401 : case OPT_nostdlib:
244 8401 : case OPT_nodefaultlibs:
245 8401 : case OPT_c:
246 8401 : case OPT_r:
247 8401 : case OPT_S:
248 8401 : case OPT_fsyntax_only:
249 8401 : case OPT_E:
250 : /* These options disable linking entirely or linking of the
251 : standard libraries. */
252 8401 : library = 0;
253 8401 : break;
254 :
255 2 : case OPT_static_libgfortran:
256 : #ifdef HAVE_LD_STATIC_DYNAMIC
257 2 : static_lib = 1;
258 : #endif
259 2 : break;
260 :
261 11 : case OPT_static:
262 : #ifdef HAVE_LD_STATIC_DYNAMIC
263 11 : static_linking = 1;
264 : #endif
265 11 : break;
266 :
267 25466 : case OPT_l:
268 25466 : ++n_infiles;
269 25466 : break;
270 :
271 32768 : case OPT_o:
272 32768 : ++n_outfiles;
273 32768 : break;
274 :
275 190 : case OPT_v:
276 190 : verbose = 1;
277 190 : break;
278 :
279 4 : case OPT__version:
280 4 : printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
281 4 : printf ("Copyright %s 2026 Free Software Foundation, Inc.\n",
282 : _("(C)"));
283 4 : 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);
286 4 : exit (0);
287 : break;
288 :
289 : case OPT__help:
290 : /* Let gcc.cc handle this, as it has a really
291 : cool facility for handling --help and --verbose --help. */
292 : return;
293 :
294 : default:
295 : break;
296 : }
297 : }
298 :
299 34518 : if ((n_outfiles != 0) && (n_infiles == 0))
300 0 : fatal_error (input_location,
301 : "no input files; unwilling to write output files");
302 :
303 : /* If there are no input files, no need for the library. */
304 34518 : if (n_infiles == 0)
305 1212 : library = 0;
306 :
307 : /* Second pass through arglist, transforming arguments as appropriate. */
308 :
309 34518 : append_arg (&decoded_options[0]); /* Start with command name, of course. */
310 :
311 772293 : for (i = 1; i < argc; ++i)
312 : {
313 737775 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
314 : {
315 0 : append_arg (&decoded_options[i]);
316 0 : continue;
317 : }
318 :
319 737775 : if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
320 34785 : && decoded_options[i].arg[0] == '\0')
321 : {
322 : /* Interesting. Just append as is. */
323 0 : append_arg (&decoded_options[i]);
324 0 : continue;
325 : }
326 :
327 737775 : if (decoded_options[i].opt_index != OPT_l
328 712309 : && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
329 34785 : || strcmp (decoded_options[i].arg, "-") == 0))
330 : {
331 : /* Not a filename or library. */
332 :
333 677524 : if (saw_library == 1 && need_math) /* -l<library>. */
334 0 : append_option (OPT_l, MATH_LIBRARY, 1);
335 :
336 677524 : saw_library = 0;
337 :
338 677524 : if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
339 : {
340 0 : append_arg (&decoded_options[i]); /* "-" == Standard input. */
341 0 : continue;
342 : }
343 :
344 677524 : if (decoded_options[i].opt_index == OPT_x)
345 : {
346 : /* Track input language. */
347 932 : const char *lang = decoded_options[i].arg;
348 :
349 932 : saw_speclang = (strcmp (lang, "none") != 0);
350 : }
351 :
352 677524 : append_arg (&decoded_options[i]);
353 :
354 677524 : continue;
355 677524 : }
356 :
357 : /* A filename/library, not an option. */
358 :
359 60251 : if (saw_speclang)
360 : saw_library = 0; /* -xfoo currently active. */
361 : else
362 : { /* -lfoo or filename. */
363 59242 : if (decoded_options[i].opt_index == OPT_l
364 25466 : && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
365 : {
366 24899 : if (saw_library == 1)
367 : saw_library = 2; /* -l<library> -lm. */
368 : else
369 24899 : add_arg_libgfortran (static_lib && !static_linking);
370 : }
371 34343 : else if (decoded_options[i].opt_index == OPT_l
372 567 : && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0)
373 : {
374 2 : saw_library = 1; /* -l<library>. */
375 2 : add_arg_libgfortran (static_lib && !static_linking);
376 2 : continue;
377 : }
378 : else
379 : { /* Other library, or filename. */
380 34341 : if (saw_library == 1 && need_math)
381 2 : append_option (OPT_l, MATH_LIBRARY, 1);
382 : saw_library = 0;
383 : }
384 : }
385 60249 : append_arg (&decoded_options[i]);
386 : }
387 :
388 : /* Append `-lgfortran -lm' as necessary. */
389 :
390 34518 : if (library)
391 : { /* Doing a link and no -nostdlib. */
392 24993 : if (saw_speclang)
393 0 : append_option (OPT_x, "none", 1);
394 :
395 24993 : switch (saw_library)
396 : {
397 24993 : case 0:
398 24993 : add_arg_libgfortran (static_lib && !static_linking);
399 : /* Fall through. */
400 :
401 24993 : case 1:
402 24993 : if (need_math)
403 24993 : append_option (OPT_l, MATH_LIBRARY, 1);
404 : default:
405 : break;
406 : }
407 : }
408 :
409 : #ifdef ENABLE_SHARED_LIBGCC
410 34518 : if (library)
411 : {
412 : unsigned int i;
413 :
414 658248 : for (i = 1; i < g77_newargc; i++)
415 633266 : if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
416 633266 : || g77_new_decoded_options[i].opt_index == OPT_static)
417 : break;
418 :
419 24993 : if (i == g77_newargc)
420 24982 : append_option (OPT_shared_libgcc, NULL, 1);
421 : }
422 :
423 : #endif
424 :
425 34518 : if (verbose && g77_new_decoded_options != g77_x_decoded_options)
426 : {
427 0 : fprintf (stderr, _("Driving:"));
428 0 : for (i = 0; i < g77_newargc; i++)
429 0 : fprintf (stderr, " %s",
430 0 : g77_new_decoded_options[i].orig_option_with_args_text);
431 0 : fprintf (stderr, "\n");
432 : }
433 :
434 34518 : *in_decoded_options_count = g77_newargc;
435 34518 : *in_decoded_options = g77_new_decoded_options;
436 : }
437 :
438 :
439 : /* Called before linking. Returns 0 on success and -1 on failure. */
440 : int
441 30911 : lang_specific_pre_link (void)
442 : {
443 30911 : if (library)
444 24989 : do_spec ("%:include(libgfortran.spec)");
445 :
446 30911 : return 0;
447 : }
448 :
449 : /* Number of extra output files that lang_specific_pre_link may generate. */
450 : int lang_specific_extra_outfiles = 0; /* Not used for F77. */
|