Branch data Line data Source code
1 : : /* Specific flags and argument handling of the Fortran front-end.
2 : : Copyright (C) 1997-2024 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 : 4004125 : strings_same (const char *s1, const char *s2)
87 : : {
88 : 4004125 : 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 : 687727 : options_same (const struct cl_decoded_option *opt1,
96 : : const struct cl_decoded_option *opt2)
97 : : {
98 : 687727 : return (opt1->opt_index == opt2->opt_index
99 : 687725 : && strings_same (opt1->arg, opt2->arg)
100 : 663280 : && strings_same (opt1->orig_option_with_args_text,
101 : 663280 : opt2->orig_option_with_args_text)
102 : 663280 : && strings_same (opt1->canonical_option[0],
103 : 663280 : opt2->canonical_option[0])
104 : 663280 : && strings_same (opt1->canonical_option[1],
105 : 663280 : opt2->canonical_option[1])
106 : 663280 : && strings_same (opt1->canonical_option[2],
107 : 663280 : opt2->canonical_option[2])
108 : 663280 : && strings_same (opt1->canonical_option[3],
109 : 663280 : opt2->canonical_option[3])
110 : 663280 : && (opt1->canonical_option_num_elements
111 : 663280 : == opt2->canonical_option_num_elements)
112 : 663280 : && opt1->value == opt2->value
113 : 1351007 : && 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 : 810238 : append_arg (const struct cl_decoded_option *arg)
122 : : {
123 : 810238 : static unsigned int newargsize;
124 : :
125 : 810238 : if (g77_new_decoded_options == g77_x_decoded_options
126 : 687820 : && g77_newargc < g77_xargc
127 : 1497965 : && options_same (arg, &g77_x_decoded_options[g77_newargc]))
128 : : {
129 : 663280 : ++g77_newargc;
130 : 663280 : return; /* Nothing new here. */
131 : : }
132 : :
133 : 146958 : if (g77_new_decoded_options == g77_x_decoded_options)
134 : : { /* Make new arglist. */
135 : 24540 : unsigned int i;
136 : :
137 : 24540 : newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
138 : 24540 : g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
139 : :
140 : : /* Copy what has been done so far. */
141 : 506234 : for (i = 0; i < g77_newargc; ++i)
142 : 481694 : g77_new_decoded_options[i] = g77_x_decoded_options[i];
143 : : }
144 : :
145 : 146958 : 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 : 146958 : 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 : 98066 : append_option (size_t opt_index, const char *arg, int value)
156 : : {
157 : 98066 : struct cl_decoded_option decoded;
158 : :
159 : 98066 : generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
160 : 98066 : append_arg (&decoded);
161 : 98066 : }
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 : 48987 : add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
168 : : {
169 : : #ifdef HAVE_LD_STATIC_DYNAMIC
170 : 48987 : if (force_static)
171 : 4 : append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
172 : : #endif
173 : 48987 : append_option (OPT_l, FORTRAN_LIBRARY, 1);
174 : : #ifdef HAVE_LD_STATIC_DYNAMIC
175 : 48987 : if (force_static)
176 : 4 : append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
177 : : #endif
178 : 48987 : }
179 : :
180 : : void
181 : 33912 : 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 : 33912 : unsigned int argc = *in_decoded_options_count;
186 : 33912 : struct cl_decoded_option *decoded_options = *in_decoded_options;
187 : 33912 : unsigned int i;
188 : 33912 : int verbose = 0;
189 : :
190 : : /* 0 => -xnone in effect.
191 : : 1 => -xfoo in effect. */
192 : 33912 : 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 : 33912 : int saw_library = 0;
198 : :
199 : : /* By default, we throw on the math library if we have one. */
200 : 33912 : int need_math = (MATH_LIBRARY[0] != '\0');
201 : :
202 : : /* Whether we should link a static libgfortran. */
203 : 33912 : int static_lib = 0;
204 : :
205 : : /* Whether we need to link statically. */
206 : 33912 : int static_linking = 0;
207 : :
208 : : /* The number of input and output files in the incoming arg list. */
209 : 33912 : int n_infiles = 0;
210 : 33912 : int n_outfiles = 0;
211 : :
212 : 33912 : 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 : 33912 : g77_xargc = argc;
222 : 33912 : g77_x_decoded_options = decoded_options;
223 : 33912 : g77_newargc = 0;
224 : 33912 : 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 : 712202 : for (i = 1; i < argc; ++i)
233 : : {
234 : 678294 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
235 : 0 : continue;
236 : :
237 : 678294 : switch (decoded_options[i].opt_index)
238 : : {
239 : 34294 : case OPT_SPECIAL_input_file:
240 : 34294 : ++n_infiles;
241 : 34294 : continue;
242 : :
243 : 8356 : case OPT_nostdlib:
244 : 8356 : case OPT_nodefaultlibs:
245 : 8356 : case OPT_c:
246 : 8356 : case OPT_r:
247 : 8356 : case OPT_S:
248 : 8356 : case OPT_fsyntax_only:
249 : 8356 : case OPT_E:
250 : : /* These options disable linking entirely or linking of the
251 : : standard libraries. */
252 : 8356 : library = 0;
253 : 8356 : 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 : 24825 : case OPT_l:
268 : 24825 : ++n_infiles;
269 : 24825 : break;
270 : :
271 : 32128 : case OPT_o:
272 : 32128 : ++n_outfiles;
273 : 32128 : break;
274 : :
275 : 98 : case OPT_v:
276 : 98 : verbose = 1;
277 : 98 : break;
278 : :
279 : 4 : case OPT__version:
280 : 4 : printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
281 : 4 : printf ("Copyright %s 2024 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 : 33908 : 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 : 33908 : if (n_infiles == 0)
305 : 1100 : library = 0;
306 : :
307 : : /* Second pass through arglist, transforming arguments as appropriate. */
308 : :
309 : 33908 : append_arg (&decoded_options[0]); /* Start with command name, of course. */
310 : :
311 : 712174 : for (i = 1; i < argc; ++i)
312 : : {
313 : 678266 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
314 : : {
315 : 0 : append_arg (&decoded_options[i]);
316 : 0 : continue;
317 : : }
318 : :
319 : 678266 : if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
320 : 34294 : && 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 : 678266 : if (decoded_options[i].opt_index != OPT_l
328 : 653441 : && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
329 : 34294 : || strcmp (decoded_options[i].arg, "-") == 0))
330 : : {
331 : : /* Not a filename or library. */
332 : :
333 : 619147 : if (saw_library == 1 && need_math) /* -l<library>. */
334 : 0 : append_option (OPT_l, MATH_LIBRARY, 1);
335 : :
336 : 619147 : saw_library = 0;
337 : :
338 : 619147 : 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 : 619147 : if (decoded_options[i].opt_index == OPT_x)
345 : : {
346 : : /* Track input language. */
347 : 1216 : const char *lang = decoded_options[i].arg;
348 : :
349 : 1216 : saw_speclang = (strcmp (lang, "none") != 0);
350 : : }
351 : :
352 : 619147 : append_arg (&decoded_options[i]);
353 : :
354 : 619147 : continue;
355 : 619147 : }
356 : :
357 : : /* A filename/library, not an option. */
358 : :
359 : 59119 : if (saw_speclang)
360 : : saw_library = 0; /* -xfoo currently active. */
361 : : else
362 : : { /* -lfoo or filename. */
363 : 57826 : if (decoded_options[i].opt_index == OPT_l
364 : 24825 : && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
365 : : {
366 : 24445 : if (saw_library == 1)
367 : : saw_library = 2; /* -l<library> -lm. */
368 : : else
369 : 24445 : add_arg_libgfortran (static_lib && !static_linking);
370 : : }
371 : 33381 : else if (decoded_options[i].opt_index == OPT_l
372 : 380 : && 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 : 33379 : if (saw_library == 1 && need_math)
381 : 2 : append_option (OPT_l, MATH_LIBRARY, 1);
382 : : saw_library = 0;
383 : : }
384 : : }
385 : 59117 : append_arg (&decoded_options[i]);
386 : : }
387 : :
388 : : /* Append `-lgfortran -lm' as necessary. */
389 : :
390 : 33908 : if (library)
391 : : { /* Doing a link and no -nostdlib. */
392 : 24540 : if (saw_speclang)
393 : 0 : append_option (OPT_x, "none", 1);
394 : :
395 : 24540 : switch (saw_library)
396 : : {
397 : 24540 : case 0:
398 : 24540 : add_arg_libgfortran (static_lib && !static_linking);
399 : : /* Fall through. */
400 : :
401 : 24540 : case 1:
402 : 24540 : if (need_math)
403 : 24540 : append_option (OPT_l, MATH_LIBRARY, 1);
404 : : default:
405 : : break;
406 : : }
407 : : }
408 : :
409 : : #ifdef ENABLE_SHARED_LIBGCC
410 : 33908 : if (library)
411 : : {
412 : : unsigned int i;
413 : :
414 : 604032 : for (i = 1; i < g77_newargc; i++)
415 : 579503 : if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
416 : 579503 : || g77_new_decoded_options[i].opt_index == OPT_static)
417 : : break;
418 : :
419 : 24540 : if (i == g77_newargc)
420 : 24529 : append_option (OPT_shared_libgcc, NULL, 1);
421 : : }
422 : :
423 : : #endif
424 : :
425 : 33908 : 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 : 33908 : *in_decoded_options_count = g77_newargc;
435 : 33908 : *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 : 30550 : lang_specific_pre_link (void)
442 : : {
443 : 30550 : if (library)
444 : 24538 : do_spec ("%:include(libgfortran.spec)");
445 : :
446 : 30550 : 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. */
|