Home | History | Annotate | Line # | Download | only in d
d-spec.cc revision 1.1.1.1
      1 /* d-spec.c -- Specific flags and argument handling of the D front end.
      2    Copyright (C) 2006-2019 Free Software Foundation, Inc.
      3 
      4 GCC is free software; you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation; either version 3, or (at your option)
      7 any later version.
      8 
      9 GCC is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with GCC; see the file COPYING3.  If not see
     16 <http://www.gnu.org/licenses/>.  */
     17 
     18 #include "config.h"
     19 #include "system.h"
     20 #include "coretypes.h"
     21 #include "opt-suggestions.h"
     22 #include "gcc.h"
     23 #include "tm.h"
     24 #include "opts.h"
     25 
     26 /* This bit is set if the arguments is a D source file.  */
     27 #define DSOURCE		(1<<1)
     28 /* This bit is set if they did `-lstdc++'.  */
     29 #define WITHLIBCXX	(1<<2)
     30 /* Skip this option.  */
     31 #define SKIPOPT		(1<<3)
     32 
     33 #ifndef LIBSTDCXX
     34 #define LIBSTDCXX "stdc++"
     35 #endif
     36 #ifndef LIBSTDCXX_PROFILE
     37 #define LIBSTDCXX_PROFILE LIBSTDCXX
     38 #endif
     39 
     40 #ifndef LIBPHOBOS
     41 #define LIBPHOBOS "gphobos"
     42 #endif
     43 #ifndef LIBPHOBOS_PROFILE
     44 #define LIBPHOBOS_PROFILE LIBPHOBOS
     45 #endif
     46 
     47 #ifndef LIBDRUNTIME
     48 #define LIBDRUNTIME "gdruntime"
     49 #endif
     50 #ifndef LIBDRUNTIME_PROFILE
     51 #define LIBDRUNTIME_PROFILE LIBDRUNTIME
     52 #endif
     53 
     54 /* What do with libgphobos.  */
     55 enum phobos_action
     56 {
     57   /* libgphobos should not be linked in.  */
     58   PHOBOS_NOLINK = -1,
     59   /* libgphobos should be linked in if it is needed.  */
     60   PHOBOS_DEFAULT = 0,
     61   /* libgphobos is needed and should be linked in.  */
     62   PHOBOS_LINK,
     63   /* libgphobos is needed and should be linked statically.  */
     64   PHOBOS_STATIC,
     65   /* libgphobos is needed and should be linked dynamically.  */
     66   PHOBOS_DYNAMIC,
     67 };
     68 
     69 static phobos_action phobos_library = PHOBOS_DEFAULT;
     70 
     71 /* If true, use the standard D runtime library when linking with
     72    standard libraries.  */
     73 static bool need_phobos = true;
     74 
     75 /* If true, do load libgphobos.spec even if not needed otherwise.  */
     76 static bool need_spec = false;
     77 
     78 void
     79 lang_specific_driver (cl_decoded_option **in_decoded_options,
     80 		      unsigned int *in_decoded_options_count,
     81 		      int *in_added_libraries)
     82 {
     83   unsigned int i, j;
     84 
     85   /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
     86   int saw_profile_flag = 0;
     87 
     88   /* If true, the user gave `-g'.  Used by -debuglib.  */
     89   bool saw_debug_flag = false;
     90 
     91   /* The new argument list will be contained in this.  */
     92   cl_decoded_option *new_decoded_options;
     93 
     94   /* "-lstdc++" if it appears on the command line.  */
     95   const cl_decoded_option *saw_libcxx = 0;
     96 
     97   /* Whether we need the C++ STD library.  */
     98   bool need_stdcxx = false;
     99 
    100   /* True if we saw -static.  */
    101   bool static_link = false;
    102 
    103   /* True if we should add -shared-libgcc to the command-line.  */
    104   bool shared_libgcc = true;
    105 
    106   /* What default library to use instead of phobos.  */
    107   const char *defaultlib = NULL;
    108 
    109   /* What debug library to use instead of phobos.  */
    110   const char *debuglib = NULL;
    111 
    112   /* The total number of arguments with the new stuff.  */
    113   unsigned int num_args = 1;
    114 
    115   /* "-fonly" if it appears on the command line.  */
    116   const char *only_source_option = 0;
    117 
    118   /* Whether the -o option was used.  */
    119   bool saw_opt_o = false;
    120 
    121   /* Whether the -c option was used.  Also used for -E, -fsyntax-only,
    122      in general anything which implies only compilation and not linking.  */
    123   bool saw_opt_c = false;
    124 
    125   /* Whether the -S option was used.  */
    126   bool saw_opt_S = false;
    127 
    128   /* The first input file with an extension of .d.  */
    129   const char *first_d_file = NULL;
    130 
    131   /* The total number of arguments with the new stuff.  */
    132   unsigned int argc = *in_decoded_options_count;
    133 
    134   /* The argument list.  */
    135   cl_decoded_option *decoded_options = *in_decoded_options;
    136 
    137   /* The number of libraries added in.  */
    138   int added_libraries = *in_added_libraries;
    139 
    140   /* An array used to flag each argument that needs a bit set for
    141      DSOURCE, MATHLIB, WITHTHREAD, WITHLIBC or WITHLIBCXX.  */
    142   int *args = XCNEWVEC (int, argc);
    143 
    144   for (i = 1; i < argc; i++)
    145     {
    146       const char *arg = decoded_options[i].arg;
    147       const int value = decoded_options[i].value;
    148 
    149       switch (decoded_options[i].opt_index)
    150 	{
    151 	case OPT_dstartfiles:
    152 	  need_spec = true;
    153 	  break;
    154 
    155 	case OPT_nostdlib:
    156 	case OPT_nodefaultlibs:
    157 	  phobos_library = PHOBOS_NOLINK;
    158 	  break;
    159 
    160 	case OPT_nophoboslib:
    161 	  need_phobos = false;
    162 	  args[i] |= SKIPOPT;
    163 	  break;
    164 
    165 	case OPT_fdruntime:
    166 	  if (!value)
    167 	    need_phobos = false;
    168 	  break;
    169 
    170 	case OPT_defaultlib_:
    171 	  if (defaultlib != NULL)
    172 	    free (CONST_CAST (char *, defaultlib));
    173 	  if (arg != NULL)
    174 	    {
    175 	      need_phobos = false;
    176 	      args[i] |= SKIPOPT;
    177 	      defaultlib = XNEWVEC (char, strlen (arg));
    178 	      strcpy (CONST_CAST (char *, defaultlib), arg);
    179 	    }
    180 	  break;
    181 
    182 	case OPT_debuglib_:
    183 	  if (debuglib != NULL)
    184 	    free (CONST_CAST (char *, debuglib));
    185 	  if (arg != NULL)
    186 	    {
    187 	      need_phobos = false;
    188 	      args[i] |= SKIPOPT;
    189 	      debuglib = XNEWVEC (char, strlen (arg));
    190 	      strcpy (CONST_CAST (char *, debuglib), arg);
    191 	    }
    192 	  break;
    193 
    194 	case OPT_l:
    195 	  if ((strcmp (arg, LIBSTDCXX) == 0)
    196 	      || (strcmp (arg, LIBSTDCXX_PROFILE) == 0))
    197 	    {
    198 	      args[i] |= WITHLIBCXX;
    199 	      need_stdcxx = false;
    200 	    }
    201 	  /* Unrecognized libraries (e.g. -ltango) may require libphobos.  */
    202 	  else if (phobos_library == PHOBOS_DEFAULT)
    203 	    phobos_library = PHOBOS_LINK;
    204 	  break;
    205 
    206 	case OPT_pg:
    207 	case OPT_p:
    208 	  saw_profile_flag++;
    209 	  break;
    210 
    211 	case OPT_g:
    212 	  saw_debug_flag = true;
    213 	  break;
    214 
    215 	case OPT_v:
    216 	  /* If they only gave us `-v', don't try to link in libphobos.  */
    217 	  if (argc == 2)
    218 	    phobos_library = PHOBOS_NOLINK;
    219 	  break;
    220 
    221 	case OPT_x:
    222 	  if (phobos_library == PHOBOS_DEFAULT && (strcmp (arg, "d") == 0))
    223 	    phobos_library = PHOBOS_LINK;
    224 	  break;
    225 
    226 	case OPT_Xlinker:
    227 	case OPT_Wl_:
    228 	  /* Arguments that go directly to the linker might be .o files
    229 	     or something, and so might cause libphobos to be needed.  */
    230 	  if (phobos_library == PHOBOS_DEFAULT)
    231 	    phobos_library = PHOBOS_LINK;
    232 	  break;
    233 
    234 	case OPT_c:
    235 	case OPT_E:
    236 	case OPT_M:
    237 	case OPT_MM:
    238 	case OPT_fsyntax_only:
    239 	  /* Don't specify libaries if we won't link, since that would
    240 	     cause a warning.  */
    241 	  saw_opt_c = true;
    242 	  phobos_library = PHOBOS_NOLINK;
    243 	  break;
    244 
    245 	case OPT_S:
    246 	  saw_opt_S = true;
    247 	  phobos_library = PHOBOS_NOLINK;
    248 	  break;
    249 
    250 	case OPT_o:
    251 	  saw_opt_o = true;
    252 	  break;
    253 
    254 	case OPT_static:
    255 	  static_link = true;
    256 	  break;
    257 
    258 	case OPT_static_libgcc:
    259 	  shared_libgcc = false;
    260 	  break;
    261 
    262 	case OPT_static_libphobos:
    263 	  if (phobos_library != PHOBOS_NOLINK)
    264 	    phobos_library = PHOBOS_STATIC;
    265 	  args[i] |= SKIPOPT;
    266 	  break;
    267 
    268 	case OPT_shared_libphobos:
    269 	  if (phobos_library != PHOBOS_NOLINK)
    270 	    phobos_library = PHOBOS_DYNAMIC;
    271 	  args[i] |= SKIPOPT;
    272 	  break;
    273 
    274 	case OPT_fonly_:
    275 	  args[i] |= SKIPOPT;
    276 	  only_source_option = decoded_options[i].orig_option_with_args_text;
    277 
    278 	  if (arg != NULL)
    279 	    {
    280 	      const char *suffix = strrchr (only_source_option, '.');
    281 	      if (suffix == NULL || strcmp (suffix, ".d") != 0)
    282 		only_source_option = concat (only_source_option, ".d", NULL);
    283 	    }
    284 	  break;
    285 
    286 	case OPT_SPECIAL_input_file:
    287 	  {
    288 	    if (arg[0] == '\0' || arg[1] == '\0')
    289 	      continue;
    290 
    291 	    if (phobos_library == PHOBOS_DEFAULT)
    292 	      phobos_library = PHOBOS_LINK;
    293 
    294 	    /* Record that this is a D source file.  */
    295 	    const char *suffix = strrchr (arg, '.');
    296 	    if (suffix != NULL && strcmp (suffix, ".d") == 0)
    297 	      {
    298 		if (first_d_file == NULL)
    299 		  first_d_file = arg;
    300 
    301 		args[i] |= DSOURCE;
    302 	      }
    303 
    304 	    /* If this is a C++ source file, we'll need to link
    305 	       against libstdc++ library.  */
    306 	    if (suffix != NULL
    307 		&& (strcmp (suffix, ".cc") == 0
    308 		    || (strcmp (suffix, ".cpp") == 0)
    309 		    || (strcmp (suffix, ".c++") == 0)))
    310 	      need_stdcxx = true;
    311 
    312 	    break;
    313 	  }
    314 	}
    315     }
    316 
    317   /* There's no point adding -shared-libgcc if we don't have a shared
    318      libgcc.  */
    319 #ifndef ENABLE_SHARED_LIBGCC
    320   shared_libgcc = false;
    321 #endif
    322 
    323   /* Make sure to have room for the trailing NULL argument.
    324      - needstdcxx might add `-lstdcxx'
    325      - libphobos adds `-Bstatic -lphobos -ldruntime -Bdynamic'
    326      - only_source adds 1 more arg, also maybe add `-o'.  */
    327   num_args = argc + need_stdcxx + shared_libgcc + need_phobos * 4 + 2;
    328   new_decoded_options = XNEWVEC (cl_decoded_option, num_args);
    329 
    330   i = 0;
    331   j = 0;
    332 
    333   /* Copy the 0th argument, i.e., the name of the program itself.  */
    334   new_decoded_options[j++] = decoded_options[i++];
    335 
    336   /* NOTE: We start at 1 now, not 0.  */
    337   while (i < argc)
    338     {
    339       if (args[i] & SKIPOPT)
    340 	{
    341 	  ++i;
    342 	  continue;
    343 	}
    344 
    345       new_decoded_options[j] = decoded_options[i];
    346 
    347       if (!saw_libcxx && (args[i] & WITHLIBCXX))
    348 	{
    349 	  --j;
    350 	  saw_libcxx = &decoded_options[i];
    351 	}
    352 
    353       if (args[i] & DSOURCE)
    354 	{
    355 	  if (only_source_option)
    356 	    --j;
    357 	}
    358 
    359       i++;
    360       j++;
    361     }
    362 
    363   if (only_source_option)
    364     {
    365       const char *only_source_arg = only_source_option + 7;
    366       generate_option (OPT_fonly_, only_source_arg, 1, CL_DRIVER,
    367 		       &new_decoded_options[j]);
    368       j++;
    369 
    370       generate_option_input_file (only_source_arg,
    371 				  &new_decoded_options[j++]);
    372     }
    373 
    374   /* If no reason to link against libphobos library, then don't add it.  */
    375   if (phobos_library == PHOBOS_DEFAULT)
    376     phobos_library = PHOBOS_NOLINK;
    377 
    378   /* If we didn't see a -o option, add one.  This is because we need the
    379      driver to pass all .d files to the D compiler.  Without a -o option
    380      the driver will invoke the compiler separately for each input file.  */
    381   if (first_d_file != NULL && !saw_opt_o)
    382     {
    383       if (saw_opt_c || saw_opt_S)
    384 	{
    385 	  const char *base = lbasename (first_d_file);
    386 	  int baselen = strlen (base) - 2;
    387 	  char *out = XNEWVEC (char, baselen + 3);
    388 
    389 	  memcpy (out, base, baselen);
    390 	  /* The driver will convert .o to some other suffix if appropriate.  */
    391 	  out[baselen] = '.';
    392 	  if (saw_opt_S)
    393 	    out[baselen + 1] = 's';
    394 	  else
    395 	    out[baselen + 1] = 'o';
    396 	  out[baselen + 2] = '\0';
    397 	  generate_option (OPT_o, out, 1, CL_DRIVER,
    398 			   &new_decoded_options[j]);
    399 	}
    400       else
    401 	{
    402 	  /* Wouldn't be necessary if the driver converted .out also.  */
    403 	  const char *out = NULL;
    404 
    405 #ifdef TARGET_EXECUTABLE_SUFFIX
    406 	  if (TARGET_EXECUTABLE_SUFFIX[0] != 0)
    407 	    out = "a" TARGET_EXECUTABLE_SUFFIX;
    408 #endif
    409 	  if (out == NULL)
    410 	    out = "a.out";
    411 
    412 	  generate_option (OPT_o, out, 1, CL_DRIVER,
    413 			   &new_decoded_options[j]);
    414 	}
    415       j++;
    416     }
    417 
    418   /* Add `-lgphobos' if we haven't already done so.  */
    419   if (phobos_library != PHOBOS_NOLINK && need_phobos)
    420     {
    421       /* Default to static linking.  */
    422       if (phobos_library != PHOBOS_DYNAMIC)
    423 	phobos_library = PHOBOS_STATIC;
    424 
    425 #ifdef HAVE_LD_STATIC_DYNAMIC
    426       if (phobos_library == PHOBOS_DYNAMIC && static_link)
    427 	{
    428 	  generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
    429 			   &new_decoded_options[j]);
    430 	  j++;
    431 	}
    432       else if (phobos_library == PHOBOS_STATIC && !static_link)
    433 	{
    434 	  generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
    435 			   &new_decoded_options[j]);
    436 	  j++;
    437 	}
    438 #endif
    439 
    440       generate_option (OPT_l,
    441 		       saw_profile_flag ? LIBPHOBOS_PROFILE : LIBPHOBOS, 1,
    442 		       CL_DRIVER, &new_decoded_options[j]);
    443       added_libraries++;
    444       j++;
    445       generate_option (OPT_l,
    446 		       saw_profile_flag ? LIBDRUNTIME_PROFILE : LIBDRUNTIME, 1,
    447 		       CL_DRIVER, &new_decoded_options[j]);
    448       added_libraries++;
    449       j++;
    450 
    451 #ifdef HAVE_LD_STATIC_DYNAMIC
    452       if (phobos_library == PHOBOS_DYNAMIC && static_link)
    453 	{
    454 	  generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
    455 			   &new_decoded_options[j]);
    456 	  j++;
    457 	}
    458       else if (phobos_library == PHOBOS_STATIC && !static_link)
    459 	{
    460 	  generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
    461 			   &new_decoded_options[j]);
    462 	  j++;
    463 	}
    464 #endif
    465     }
    466   else if (saw_debug_flag && debuglib)
    467     {
    468       generate_option (OPT_l, debuglib, 1, CL_DRIVER,
    469 		       &new_decoded_options[j++]);
    470       added_libraries++;
    471     }
    472   else if (defaultlib)
    473     {
    474       generate_option (OPT_l, defaultlib, 1, CL_DRIVER,
    475 		       &new_decoded_options[j++]);
    476       added_libraries++;
    477     }
    478 
    479   if (saw_libcxx)
    480     new_decoded_options[j++] = *saw_libcxx;
    481   else if (need_stdcxx)
    482     {
    483       generate_option (OPT_l,
    484 		       (saw_profile_flag
    485 			? LIBSTDCXX_PROFILE
    486 			: LIBSTDCXX),
    487 		       1, CL_DRIVER, &new_decoded_options[j++]);
    488       added_libraries++;
    489     }
    490 
    491   if (shared_libgcc && !static_link)
    492     {
    493       generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
    494 		       &new_decoded_options[j++]);
    495     }
    496 
    497   *in_decoded_options_count = j;
    498   *in_decoded_options = new_decoded_options;
    499   *in_added_libraries = added_libraries;
    500 }
    501 
    502 /* Called before linking.  Returns 0 on success and -1 on failure.  */
    503 
    504 int
    505 lang_specific_pre_link (void)
    506 {
    507   if ((phobos_library != PHOBOS_NOLINK && need_phobos) || need_spec)
    508     do_spec ("%:include(libgphobos.spec)");
    509 
    510   return 0;
    511 }
    512 
    513 /* Number of extra output files that lang_specific_pre_link may generate.  */
    514 
    515 int lang_specific_extra_outfiles = 0;  /* Not used for D.  */
    516 
    517