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