Home | History | Annotate | Line # | Download | only in fortran
gfortranspec.cc revision 1.1.1.1
      1 /* Specific flags and argument handling of the Fortran front-end.
      2    Copyright (C) 1997-2022 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 strings_same (const char *s1, const char *s2)
     87 {
     88   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 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);
    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 append_arg (const struct cl_decoded_option *arg)
    122 {
    123   static unsigned int newargsize;
    124 
    125   if (g77_new_decoded_options == g77_x_decoded_options
    126       && g77_newargc < g77_xargc
    127       && options_same (arg, &g77_x_decoded_options[g77_newargc]))
    128     {
    129       ++g77_newargc;
    130       return;			/* Nothing new here.  */
    131     }
    132 
    133   if (g77_new_decoded_options == g77_x_decoded_options)
    134     {				/* Make new arglist.  */
    135       unsigned int i;
    136 
    137       newargsize = (g77_xargc << 2) + 20;	/* This should handle all.  */
    138       g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
    139 
    140       /* Copy what has been done so far.  */
    141       for (i = 0; i < g77_newargc; ++i)
    142 	g77_new_decoded_options[i] = g77_x_decoded_options[i];
    143     }
    144 
    145   if (g77_newargc == newargsize)
    146     fatal_error (input_location, "overflowed output argument list for %qs",
    147 		 arg->orig_option_with_args_text);
    148 
    149   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 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)
    171     append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
    172 #endif
    173   append_option (OPT_l, FORTRAN_LIBRARY, 1);
    174 #ifdef HAVE_LD_STATIC_DYNAMIC
    175   if (force_static)
    176     append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
    177 #endif
    178 }
    179 
    180 void
    181 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   unsigned int argc = *in_decoded_options_count;
    186   struct cl_decoded_option *decoded_options = *in_decoded_options;
    187   unsigned int i;
    188   int verbose = 0;
    189 
    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 
    199   /* By default, we throw on the math library if we have one.  */
    200   int need_math = (MATH_LIBRARY[0] != '\0');
    201 
    202   /* Whether we should link a static libgfortran.  */
    203   int static_lib = 0;
    204 
    205   /* Whether we need to link statically.  */
    206   int static_linking = 0;
    207 
    208   /* The number of input and output files in the incoming arg list.  */
    209   int n_infiles = 0;
    210   int n_outfiles = 0;
    211 
    212   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   g77_xargc = argc;
    222   g77_x_decoded_options = decoded_options;
    223   g77_newargc = 0;
    224   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   for (i = 1; i < argc; ++i)
    233     {
    234       if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
    235 	continue;
    236 
    237       switch (decoded_options[i].opt_index)
    238 	{
    239 	case OPT_SPECIAL_input_file:
    240 	  ++n_infiles;
    241 	  continue;
    242 
    243 	case OPT_nostdlib:
    244 	case OPT_nodefaultlibs:
    245 	case OPT_c:
    246 	case OPT_r:
    247 	case OPT_S:
    248 	case OPT_fsyntax_only:
    249 	case OPT_E:
    250 	  /* These options disable linking entirely or linking of the
    251 	     standard libraries.  */
    252 	  library = 0;
    253 	  break;
    254 
    255 	case OPT_static_libgfortran:
    256 #ifdef HAVE_LD_STATIC_DYNAMIC
    257 	  static_lib = 1;
    258 #endif
    259 	  break;
    260 
    261 	case OPT_static:
    262 #ifdef HAVE_LD_STATIC_DYNAMIC
    263 	  static_linking = 1;
    264 #endif
    265 	  break;
    266 
    267 	case OPT_l:
    268 	  ++n_infiles;
    269 	  break;
    270 
    271 	case OPT_o:
    272 	  ++n_outfiles;
    273 	  break;
    274 
    275 	case OPT_v:
    276 	  verbose = 1;
    277 	  break;
    278 
    279 	case OPT__version:
    280 	  printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
    281 	  printf ("Copyright %s 2022 Free Software Foundation, Inc.\n",
    282 		  _("(C)"));
    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);
    286 	  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   if ((n_outfiles != 0) && (n_infiles == 0))
    300     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   if (n_infiles == 0)
    305     library = 0;
    306 
    307   /* Second pass through arglist, transforming arguments as appropriate.  */
    308 
    309   append_arg (&decoded_options[0]); /* Start with command name, of course.  */
    310 
    311   for (i = 1; i < argc; ++i)
    312     {
    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')
    321 	{
    322 	  /* Interesting.  Just append as is.  */
    323 	  append_arg (&decoded_options[i]);
    324 	  continue;
    325 	}
    326 
    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))
    330 	{
    331 	  /* Not a filename or library.  */
    332 
    333 	  if (saw_library == 1 && need_math)	/* -l<library>.  */
    334 	    append_option (OPT_l, MATH_LIBRARY, 1);
    335 
    336 	  saw_library = 0;
    337 
    338 	  if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
    339 	    {
    340 	      append_arg (&decoded_options[i]);	/* "-" == Standard input.  */
    341 	      continue;
    342 	    }
    343 
    344 	  if (decoded_options[i].opt_index == OPT_x)
    345 	    {
    346 	      /* Track input language.  */
    347 	      const char *lang = decoded_options[i].arg;
    348 
    349 	      saw_speclang = (strcmp (lang, "none") != 0);
    350 	    }
    351 
    352 	  append_arg (&decoded_options[i]);
    353 
    354 	  continue;
    355 	}
    356 
    357       /* A filename/library, not an option.  */
    358 
    359       if (saw_speclang)
    360 	saw_library = 0;	/* -xfoo currently active.  */
    361       else
    362 	{			/* -lfoo or filename.  */
    363 	  if (decoded_options[i].opt_index == OPT_l
    364 	      && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
    365 	    {
    366 	      if (saw_library == 1)
    367 		saw_library = 2;	/* -l<library> -lm.  */
    368 	      else
    369 		add_arg_libgfortran (static_lib && !static_linking);
    370 	    }
    371 	  else if (decoded_options[i].opt_index == OPT_l
    372 	      && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0)
    373 	    {
    374 	      saw_library = 1;	/* -l<library>.  */
    375 	      add_arg_libgfortran (static_lib && !static_linking);
    376 	      continue;
    377 	    }
    378 	  else
    379 	    {			/* Other library, or filename.  */
    380 	      if (saw_library == 1 && need_math)
    381 		append_option (OPT_l, MATH_LIBRARY, 1);
    382 	      saw_library = 0;
    383 	    }
    384 	}
    385       append_arg (&decoded_options[i]);
    386     }
    387 
    388   /* Append `-lgfortran -lm' as necessary.  */
    389 
    390   if (library)
    391     {				/* Doing a link and no -nostdlib.  */
    392       if (saw_speclang)
    393 	append_option (OPT_x, "none", 1);
    394 
    395       switch (saw_library)
    396 	{
    397 	case 0:
    398 	  add_arg_libgfortran (static_lib && !static_linking);
    399 	  /* Fall through.  */
    400 
    401 	case 1:
    402 	  if (need_math)
    403 	    append_option (OPT_l, MATH_LIBRARY, 1);
    404 	default:
    405 	  break;
    406 	}
    407     }
    408 
    409 #ifdef ENABLE_SHARED_LIBGCC
    410   if (library)
    411     {
    412       unsigned int i;
    413 
    414       for (i = 1; i < g77_newargc; i++)
    415 	if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
    416 	    || g77_new_decoded_options[i].opt_index == OPT_static)
    417 	  break;
    418 
    419       if (i == g77_newargc)
    420 	append_option (OPT_shared_libgcc, NULL, 1);
    421     }
    422 
    423 #endif
    424 
    425   if (verbose && g77_new_decoded_options != g77_x_decoded_options)
    426     {
    427       fprintf (stderr, _("Driving:"));
    428       for (i = 0; i < g77_newargc; i++)
    429 	fprintf (stderr, " %s",
    430 		 g77_new_decoded_options[i].orig_option_with_args_text);
    431       fprintf (stderr, "\n");
    432     }
    433 
    434   *in_decoded_options_count = g77_newargc;
    435   *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 lang_specific_pre_link (void)
    442 {
    443   if (library)
    444     do_spec ("%:include(libgfortran.spec)");
    445 
    446   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.  */
    451