1 /* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3 Contributed by Mumit Khan (khan@xraylith.wisc.edu).
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* AIX requires this to be the first thing in the file. */
45 #include "libiberty.h"
48 #include "dyn-string.h"
53 #ifdef HAVE_SYS_WAIT_H
55 #else /* ! HAVE_SYS_WAIT_H */
56 #if ! defined (_WIN32) || defined (__CYGWIN32__)
58 #define WIFEXITED(w) (((w)&0377) == 0)
61 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
64 #define WTERMSIG(w) ((w) & 0177)
67 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
69 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
71 #define WIFEXITED(w) (((w) & 0xff) == 0)
74 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
77 #define WTERMSIG(w) ((w) & 0x7f)
80 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
82 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
83 #endif /* ! HAVE_SYS_WAIT_H */
85 static char *program_version
= "0.2.4";
86 static char *driver_name
= "gcc";
87 static char *cygwin_driver_flags
=
88 "-Wl,--dll -nostartfiles";
89 static char *mingw32_driver_flags
= "-mdll";
90 static char *generic_driver_flags
= "-Wl,--dll";
92 static char *entry_point
;
94 static char *dlltool_name
= "dlltool";
96 static char *target
= TARGET
;
105 static target_type which_target
= UNKNOWN_TARGET
;
107 static int dontdeltemps
= 0;
108 static int dry_run
= 0;
110 static char *program_name
;
112 static int verbose
= 0;
114 static char *dll_file_name
;
115 static char *dll_name
;
116 static char *base_file_name
;
117 static char *exp_file_name
;
118 static char *def_file_name
;
119 static int delete_base_file
= 1;
120 static int delete_exp_file
= 1;
121 static int delete_def_file
= 1;
123 static int run
PARAMS ((const char *, char *));
124 static void usage
PARAMS ((FILE *, int));
125 static void delete_temp_files
PARAMS ((void));
126 static void cleanup_and_exit
PARAMS ((int status
));
128 /**********************************************************************/
133 if (delete_base_file
&& base_file_name
)
136 fprintf (stderr
, "%s temporary base file %s\n",
137 dontdeltemps
? "Keeping" : "Deleting",
141 unlink (base_file_name
);
142 free (base_file_name
);
146 if (delete_exp_file
&& exp_file_name
)
149 fprintf (stderr
, "%s temporary exp file %s\n",
150 dontdeltemps
? "Keeping" : "Deleting",
154 unlink (exp_file_name
);
155 free (exp_file_name
);
158 if (delete_def_file
&& def_file_name
)
161 fprintf (stderr
, "%s temporary def file %s\n",
162 dontdeltemps
? "Keeping" : "Deleting",
166 unlink (def_file_name
);
167 free (def_file_name
);
173 cleanup_and_exit (int status
)
175 delete_temp_files ();
185 int pid
, wait_status
, retcode
;
188 char *errmsg_fmt
, *errmsg_arg
;
189 char *temp_base
= choose_temp_base ();
193 if (verbose
|| dry_run
)
194 fprintf (stderr
, "%s %s\n", what
, args
);
198 for (s
= args
; *s
; s
++)
202 argv
= alloca (sizeof (char *) * (i
+ 3));
208 while (*s
== ' ' && *s
!= 0)
212 in_quote
= (*s
== '\'' || *s
== '"');
213 sep
= (in_quote
) ? *s
++ : ' ';
215 while (*s
!= sep
&& *s
!= 0)
228 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
229 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
233 int errno_val
= errno
;
235 fprintf (stderr
, "%s: ", program_name
);
236 fprintf (stderr
, errmsg_fmt
, errmsg_arg
);
237 fprintf (stderr
, ": %s\n", strerror (errno_val
));
242 pid
= pwait (pid
, &wait_status
, 0);
245 fprintf (stderr
, "%s: wait: %s\n", program_name
, strerror (errno
));
248 else if (WIFSIGNALED (wait_status
))
250 fprintf (stderr
, "%s: subprocess got fatal signal %d\n",
251 program_name
, WTERMSIG (wait_status
));
254 else if (WIFEXITED (wait_status
))
256 if (WEXITSTATUS (wait_status
) != 0)
258 fprintf (stderr
, "%s: %s exited with status %d\n",
259 program_name
, what
, WEXITSTATUS (wait_status
));
273 const char *base
= name
;
277 if (*name
== '/' || *name
== '\\')
283 return (char *) base
;
287 strhash (const char *str
)
289 const unsigned char *s
;
296 s
= (const unsigned char *) str
;
297 while ((c
= *s
++) != '\0')
299 hash
+= c
+ (c
<< 17);
303 hash
+= len
+ (len
<< 17);
309 /**********************************************************************/
315 /* This output is intended to follow the GNU standards document. */
316 /* xgettext:c-format */
317 printf ("GNU %s %s\n", name
, program_version
);
318 printf ("Copyright 1998 Free Software Foundation, Inc.\n");
320 This program is free software; you may redistribute it under the terms of\n\
321 the GNU General Public License. This program has absolutely no warranty.\n");
330 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
331 fprintf (file
, " Generic options:\n");
332 fprintf (file
, " --quiet, -q Work quietly\n");
333 fprintf (file
, " --verbose, -v Verbose\n");
334 fprintf (file
, " --version Print dllwrap version\n");
335 fprintf (file
, " --implib <outname> Synonym for --output-lib\n");
336 fprintf (file
, " Options for %s:\n", program_name
);
337 fprintf (file
, " --driver-name <driver> Defaults to \"gcc\"\n");
338 fprintf (file
, " --driver-flags <flags> Override default ld flags\n");
339 fprintf (file
, " --dlltool-name <dlltool> Defaults to \"dlltool\"\n");
340 fprintf (file
, " --entry <entry> Specify alternate DLL entry point\n");
341 fprintf (file
, " --image-base <base> Specify image base address\n");
342 fprintf (file
, " --target <machine> i386-cygwin32 or i386-mingw32\n");
343 fprintf (file
, " --dry-run Show what needs to be run\n");
344 fprintf (file
, " Options passed to DLLTOOL:\n");
345 fprintf (file
, " --machine <machine>\n");
346 fprintf (file
, " --output-exp <outname> Generate export file.\n");
347 fprintf (file
, " --output-lib <outname> Generate input library.\n");
348 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
349 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
350 fprintf (file
, " --def <deffile> Name input .def file\n");
351 fprintf (file
, " --output-def <deffile> Name output .def file\n");
352 fprintf (file
, " --export-all-symbols Export all symbols to .def\n");
353 fprintf (file
, " --no-export-all-symbols Only export .drectve symbols\n");
354 fprintf (file
, " --exclude-symbols <list> Exclude <list> from .def\n");
355 fprintf (file
, " --no-default-excludes Zap default exclude symbols\n");
356 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
357 fprintf (file
, " --no-idata4 Don't generate idata$4 section\n");
358 fprintf (file
, " --no-idata5 Don't generate idata$5 section\n");
359 fprintf (file
, " -U Add underscores to .lib\n");
360 fprintf (file
, " -k Kill @<n> from exported names\n");
361 fprintf (file
, " --add-stdcall-alias Add aliases without @<n>\n");
362 fprintf (file
, " --as <name> Use <name> for assembler\n");
363 fprintf (file
, " --nodelete Keep temp files.\n");
364 fprintf (file
, " Rest are passed unmodified to the language driver\n");
365 fprintf (file
, "\n\n");
369 #define OPTION_START 149
371 /* GENERIC options. */
372 #define OPTION_QUIET (OPTION_START + 1)
373 #define OPTION_VERBOSE (OPTION_QUIET + 1)
374 #define OPTION_VERSION (OPTION_VERBOSE + 1)
376 /* DLLWRAP options. */
377 #define OPTION_DRY_RUN (OPTION_VERSION + 1)
378 #define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
379 #define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
380 #define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
381 #define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
382 #define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
383 #define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
385 /* DLLTOOL options. */
386 #define OPTION_NODELETE (OPTION_TARGET + 1)
387 #define OPTION_DLLNAME (OPTION_NODELETE + 1)
388 #define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
389 #define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
390 #define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
391 #define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
392 #define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
393 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
394 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
395 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
396 #define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
397 #define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
398 #define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
399 #define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
400 #define OPTION_HELP (OPTION_KILLAT + 1)
401 #define OPTION_MACHINE (OPTION_HELP + 1)
402 #define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)
403 #define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1)
404 #define OPTION_AS (OPTION_BASE_FILE + 1)
406 static const struct option long_options
[] =
408 /* generic options. */
409 {"quiet", no_argument
, NULL
, 'q'},
410 {"verbose", no_argument
, NULL
, 'v'},
411 {"version", no_argument
, NULL
, OPTION_VERSION
},
412 {"implib", required_argument
, NULL
, OPTION_OUTPUT_LIB
},
414 /* dllwrap options. */
415 {"dry-run", no_argument
, NULL
, OPTION_DRY_RUN
},
416 {"driver-name", required_argument
, NULL
, OPTION_DRIVER_NAME
},
417 {"driver-flags", required_argument
, NULL
, OPTION_DRIVER_FLAGS
},
418 {"dlltool-name", required_argument
, NULL
, OPTION_DLLTOOL_NAME
},
419 {"entry", required_argument
, NULL
, 'e'},
420 {"image-base", required_argument
, NULL
, OPTION_IMAGE_BASE
},
421 {"target", required_argument
, NULL
, OPTION_TARGET
},
423 /* dlltool options. */
424 {"no-delete", no_argument
, NULL
, 'n'},
425 {"dllname", required_argument
, NULL
, OPTION_DLLNAME
},
426 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
427 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
428 {"output-exp", required_argument
, NULL
, OPTION_OUTPUT_EXP
},
429 {"output-def", required_argument
, NULL
, OPTION_OUTPUT_DEF
},
430 {"export-all-symbols", no_argument
, NULL
, OPTION_EXPORT_ALL_SYMS
},
431 {"no-export-all-symbols", no_argument
, NULL
, OPTION_NO_EXPORT_ALL_SYMS
},
432 {"exclude-symbols", required_argument
, NULL
, OPTION_EXCLUDE_SYMS
},
433 {"no-default-excludes", no_argument
, NULL
, OPTION_NO_DEFAULT_EXCLUDES
},
434 {"output-lib", required_argument
, NULL
, OPTION_OUTPUT_LIB
},
435 {"def", required_argument
, NULL
, OPTION_DEF
},
436 {"add-underscore", no_argument
, NULL
, 'U'},
437 {"killat", no_argument
, NULL
, 'k'},
438 {"add-stdcall-alias", no_argument
, NULL
, 'A'},
439 {"help", no_argument
, NULL
, 'h'},
440 {"machine", required_argument
, NULL
, OPTION_MACHINE
},
441 {"add-indirect", no_argument
, NULL
, OPTION_ADD_INDIRECT
},
442 {"base-file", required_argument
, NULL
, OPTION_BASE_FILE
},
443 {"as", required_argument
, NULL
, OPTION_AS
},
455 char **saved_argv
= 0;
460 int *dlltool_arg_indices
;
461 int *driver_arg_indices
;
463 char *driver_flags
= 0;
464 char *output_lib_file_name
= 0;
466 dyn_string_t dlltool_cmdline
;
467 dyn_string_t driver_cmdline
;
469 int def_file_seen
= 0;
471 char *image_base_str
= 0;
473 program_name
= argv
[0];
475 saved_argv
= (char **) xmalloc (argc
* sizeof (char*));
476 dlltool_arg_indices
= (int *) xmalloc (argc
* sizeof (int));
477 driver_arg_indices
= (int *) xmalloc (argc
* sizeof (int));
478 for (i
= 0; i
< argc
; ++i
)
480 size_t len
= strlen (argv
[i
]);
481 char *arg
= (char *) xmalloc (len
+ 1);
482 strcpy (arg
, argv
[i
]);
485 dlltool_arg_indices
[i
] = 0;
486 driver_arg_indices
[i
] = 1;
490 /* We recognize dllwrap and dlltool options, and everything else is
491 passed onto the language driver (eg., to GCC). We collect options
492 to dlltool and driver in dlltool_args and driver_args. */
495 while ((c
= getopt_long_only (argc
, argv
, "nkAqve:Uho:l:L:I:",
496 long_options
, (int *) 0)) != EOF
)
500 int single_word_option_value_pair
;
504 single_word_option_value_pair
= 0;
508 /* We recognize this option, so it has to be either dllwrap or
509 dlltool option. Do not pass to driver unless it's one of the
510 generic options that are passed to all the tools (such as -v)
511 which are dealt with later. */
515 /* deal with generic and dllwrap options first. */
528 print_version (program_name
);
531 entry_point
= optarg
;
533 case OPTION_IMAGE_BASE
:
534 image_base_str
= optarg
;
537 def_file_name
= optarg
;
546 dll_file_name
= optarg
;
559 case OPTION_DRIVER_NAME
:
560 driver_name
= optarg
;
562 case OPTION_DRIVER_FLAGS
:
563 driver_flags
= optarg
;
565 case OPTION_DLLTOOL_NAME
:
566 dlltool_name
= optarg
;
571 case OPTION_BASE_FILE
:
572 base_file_name
= optarg
;
573 delete_base_file
= 0;
575 case OPTION_OUTPUT_EXP
:
576 exp_file_name
= optarg
;
579 case OPTION_EXPORT_ALL_SYMS
:
582 case OPTION_OUTPUT_LIB
:
583 output_lib_file_name
= optarg
;
592 /* Handle passing through --option=value case. */
594 && saved_argv
[optind
-1][0] == '-'
595 && saved_argv
[optind
-1][1] == '-'
596 && strchr (saved_argv
[optind
-1], '='))
597 single_word_option_value_pair
= 1;
601 dlltool_arg_indices
[optind
-1] = 1;
602 if (optarg
&& ! single_word_option_value_pair
)
604 dlltool_arg_indices
[optind
-2] = 1;
610 driver_arg_indices
[optind
-1] = 0;
611 if (optarg
&& ! single_word_option_value_pair
)
613 driver_arg_indices
[optind
-2] = 0;
619 if (! dll_name
&& ! dll_file_name
)
622 "%s: Must provide at least one of -o or --dllname options\n",
628 dll_name
= xstrdup (mybasename (dll_file_name
));
630 else if (! dll_file_name
)
632 dll_file_name
= xstrdup (dll_name
);
637 char *fileprefix
= choose_temp_base ();
638 def_file_name
= (char *) xmalloc (strlen (fileprefix
) + 5);
639 sprintf (def_file_name
, "%s.def",
640 (dontdeltemps
) ? mybasename (fileprefix
) : fileprefix
);
644 fprintf (stderr
, "Warning: no export definition file provided\n");
646 "dllwrap will create one, but may not be what you want\n");
649 /* set the target platform. */
650 if (strstr (target
, "cygwin32"))
651 which_target
= CYGWIN_TARGET
;
652 else if (strstr (target
, "mingw32"))
653 which_target
= MINGW32_TARGET
;
655 which_target
= UNKNOWN_TARGET
;
657 /* re-create the command lines as a string, taking care to quote stuff. */
658 dlltool_cmdline
= dyn_string_new (cmdline_len
);
661 dyn_string_append (dlltool_cmdline
, " -v");
663 dyn_string_append (dlltool_cmdline
, " --dllname ");
664 dyn_string_append (dlltool_cmdline
, dll_name
);
666 for (i
= 1; i
< argc
; ++i
)
668 if (dlltool_arg_indices
[i
])
670 char *arg
= saved_argv
[i
];
671 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
672 dyn_string_append (dlltool_cmdline
,
673 (quote
) ? " \"" : " ");
674 dyn_string_append (dlltool_cmdline
, arg
);
675 dyn_string_append (dlltool_cmdline
,
676 (quote
) ? "\"" : "");
680 driver_cmdline
= dyn_string_new (cmdline_len
);
681 if (! driver_flags
|| strlen (driver_flags
) == 0)
683 switch (which_target
)
686 driver_flags
= cygwin_driver_flags
;
690 driver_flags
= mingw32_driver_flags
;
694 driver_flags
= generic_driver_flags
;
698 dyn_string_append (driver_cmdline
, driver_flags
);
699 dyn_string_append (driver_cmdline
, " -o ");
700 dyn_string_append (driver_cmdline
, dll_file_name
);
702 if (! entry_point
|| strlen (entry_point
) == 0)
704 switch (which_target
)
707 entry_point
= "__cygwin_dll_entry@12";
711 entry_point
= "_DllMainCRTStartup@12";
715 entry_point
= "_DllMain@12";
719 dyn_string_append (driver_cmdline
, " -Wl,-e,");
720 dyn_string_append (driver_cmdline
, entry_point
);
721 dyn_string_append (dlltool_cmdline
, " --exclude-symbol=");
722 dyn_string_append (dlltool_cmdline
,
723 (entry_point
[0] == '_') ? entry_point
+1 : entry_point
);
725 if (! image_base_str
|| strlen (image_base_str
) == 0)
727 char *tmpbuf
= (char *) xmalloc (sizeof ("0x12345678") + 1);
728 unsigned long hash
= strhash (dll_file_name
);
729 sprintf (tmpbuf
, "0x%.8lX", 0x60000000|((hash
<<16)&0xFFC0000));
730 image_base_str
= tmpbuf
;
733 dyn_string_append (driver_cmdline
, " -Wl,--image-base,");
734 dyn_string_append (driver_cmdline
, image_base_str
);
738 dyn_string_append (driver_cmdline
, " -v");
741 for (i
= 1; i
< argc
; ++i
)
743 if (driver_arg_indices
[i
])
745 char *arg
= saved_argv
[i
];
746 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
747 dyn_string_append (driver_cmdline
,
748 (quote
) ? " \"" : " ");
749 dyn_string_append (driver_cmdline
, arg
);
750 dyn_string_append (driver_cmdline
,
751 (quote
) ? "\"" : "");
756 * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it
757 * and then pass it on.
763 dyn_string_t step_pre1
;
765 step_pre1
= dyn_string_new (1024);
767 dyn_string_append (step_pre1
, dlltool_cmdline
->s
);
770 dyn_string_append (step_pre1
, " --export-all --exclude-symbol=");
771 dyn_string_append (step_pre1
,
772 "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
774 dyn_string_append (step_pre1
, " --output-def ");
775 dyn_string_append (step_pre1
, def_file_name
);
777 for (i
= 1; i
< argc
; ++i
)
779 if (driver_arg_indices
[i
])
781 char *arg
= saved_argv
[i
];
782 size_t len
= strlen (arg
);
783 if (len
>= 2 && arg
[len
-2] == '.'
784 && (arg
[len
-1] == 'o' || arg
[len
-1] == 'a'))
786 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
787 dyn_string_append (step_pre1
,
788 (quote
) ? " \"" : " ");
789 dyn_string_append (step_pre1
, arg
);
790 dyn_string_append (step_pre1
,
791 (quote
) ? "\"" : "");
796 if (run (dlltool_name
, step_pre1
->s
))
797 cleanup_and_exit (1);
799 dyn_string_delete (step_pre1
);
802 dyn_string_append (dlltool_cmdline
, " --def ");
803 dyn_string_append (dlltool_cmdline
, def_file_name
);
807 fprintf (stderr
, "DLLTOOL name : %s\n", dlltool_name
);
808 fprintf (stderr
, "DLLTOOL options : %s\n", dlltool_cmdline
->s
);
809 fprintf (stderr
, "DRIVER name : %s\n", driver_name
);
810 fprintf (stderr
, "DRIVER options : %s\n", driver_cmdline
->s
);
814 * Step 1. Call GCC/LD to create base relocation file. If using GCC, the
815 * driver command line will look like the following:
817 * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
819 * If the user does not specify a base name, create temporary one that
820 * is deleted at exit.
824 if (! base_file_name
)
826 char *fileprefix
= choose_temp_base ();
827 base_file_name
= (char *) xmalloc (strlen (fileprefix
) + 6);
828 sprintf (base_file_name
, "%s.base",
829 (dontdeltemps
) ? mybasename (fileprefix
) : fileprefix
);
830 delete_base_file
= 1;
837 dyn_string_t step1
= dyn_string_new (driver_cmdline
->length
838 + strlen (base_file_name
)
840 dyn_string_append (step1
, "-Wl,--base-file,");
841 quote
= (strchr (base_file_name
, ' ')
842 || strchr (base_file_name
, '\t'));
843 dyn_string_append (step1
,
844 (quote
) ? "\"" : "");
845 dyn_string_append (step1
, base_file_name
);
846 dyn_string_append (step1
,
847 (quote
) ? "\"" : "");
848 if (driver_cmdline
->length
)
850 dyn_string_append (step1
, " ");
851 dyn_string_append (step1
, driver_cmdline
->s
);
854 if (run (driver_name
, step1
->s
))
855 cleanup_and_exit (1);
857 dyn_string_delete (step1
);
863 * Step 2. generate the exp file by running dlltool.
864 * dlltool command line will look like the following:
866 * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
868 * If the user does not specify a base name, create temporary one that
869 * is deleted at exit.
875 char *p
= strrchr (dll_name
, '.');
876 size_t prefix_len
= (p
) ? p
- dll_name
: strlen (dll_name
);
877 exp_file_name
= (char *) xmalloc (prefix_len
+ 4 + 1);
878 strncpy (exp_file_name
, dll_name
, prefix_len
);
879 exp_file_name
[prefix_len
] = '\0';
880 strcat (exp_file_name
, ".exp");
886 dyn_string_t step2
= dyn_string_new (dlltool_cmdline
->length
887 + strlen (base_file_name
)
888 + strlen (exp_file_name
)
891 dyn_string_append (step2
, "--base-file ");
892 quote
= (strchr (base_file_name
, ' ')
893 || strchr (base_file_name
, '\t'));
894 dyn_string_append (step2
,
895 (quote
) ? "\"" : "");
896 dyn_string_append (step2
, base_file_name
);
897 dyn_string_append (step2
,
898 (quote
) ? "\" " : " ");
900 dyn_string_append (step2
, "--output-exp ");
901 quote
= (strchr (exp_file_name
, ' ')
902 || strchr (exp_file_name
, '\t'));
903 dyn_string_append (step2
,
904 (quote
) ? "\"" : "");
905 dyn_string_append (step2
, exp_file_name
);
906 dyn_string_append (step2
,
907 (quote
) ? "\"" : "");
909 if (dlltool_cmdline
->length
)
911 dyn_string_append (step2
, " ");
912 dyn_string_append (step2
, dlltool_cmdline
->s
);
915 if (run (dlltool_name
, step2
->s
))
916 cleanup_and_exit (1);
918 dyn_string_delete (step2
);
922 * Step 3. Call GCC/LD to again, adding the exp file this time.
923 * driver command line will look like the following:
925 * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
931 dyn_string_t step3
= dyn_string_new (driver_cmdline
->length
932 + strlen (exp_file_name
)
933 + strlen (base_file_name
)
935 dyn_string_append (step3
, "-Wl,--base-file,");
936 quote
= (strchr (base_file_name
, ' ')
937 || strchr (base_file_name
, '\t'));
938 dyn_string_append (step3
,
939 (quote
) ? "\"" : "");
940 dyn_string_append (step3
, base_file_name
);
941 dyn_string_append (step3
,
942 (quote
) ? "\" " : " ");
944 quote
= (strchr (exp_file_name
, ' ')
945 || strchr (exp_file_name
, '\t'));
946 dyn_string_append (step3
,
947 (quote
) ? "\"" : "");
948 dyn_string_append (step3
, exp_file_name
);
949 dyn_string_append (step3
,
950 (quote
) ? "\"" : "");
952 if (driver_cmdline
->length
)
954 dyn_string_append (step3
, " ");
955 dyn_string_append (step3
, driver_cmdline
->s
);
958 if (run (driver_name
, step3
->s
))
959 cleanup_and_exit (1);
961 dyn_string_delete (step3
);
966 * Step 4. Run DLLTOOL again using the same command line.
971 dyn_string_t step4
= dyn_string_new (dlltool_cmdline
->length
972 + strlen (base_file_name
)
973 + strlen (exp_file_name
)
976 dyn_string_append (step4
, "--base-file ");
977 quote
= (strchr (base_file_name
, ' ')
978 || strchr (base_file_name
, '\t'));
979 dyn_string_append (step4
,
980 (quote
) ? "\"" : "");
981 dyn_string_append (step4
, base_file_name
);
982 dyn_string_append (step4
,
983 (quote
) ? "\" " : " ");
985 dyn_string_append (step4
, "--output-exp ");
986 quote
= (strchr (exp_file_name
, ' ')
987 || strchr (exp_file_name
, '\t'));
988 dyn_string_append (step4
,
989 (quote
) ? "\"" : "");
990 dyn_string_append (step4
, exp_file_name
);
991 dyn_string_append (step4
,
992 (quote
) ? "\"" : "");
994 if (dlltool_cmdline
->length
)
996 dyn_string_append (step4
, " ");
997 dyn_string_append (step4
, dlltool_cmdline
->s
);
1000 if (output_lib_file_name
)
1002 dyn_string_append (step4
, " --output-lib ");
1003 dyn_string_append (step4
, output_lib_file_name
);
1006 if (run (dlltool_name
, step4
->s
))
1007 cleanup_and_exit (1);
1009 dyn_string_delete (step4
);
1014 * Step 5. Link it all together and be done with it.
1015 * driver command line will look like the following:
1017 * % gcc -Wl,--dll foo.exp [rest ...]
1024 dyn_string_t step5
= dyn_string_new (driver_cmdline
->length
1025 + strlen (exp_file_name
)
1027 quote
= (strchr (exp_file_name
, ' ')
1028 || strchr (exp_file_name
, '\t'));
1029 dyn_string_append (step5
,
1030 (quote
) ? "\"" : "");
1031 dyn_string_append (step5
, exp_file_name
);
1032 dyn_string_append (step5
,
1033 (quote
) ? "\"" : "");
1035 if (driver_cmdline
->length
)
1037 dyn_string_append (step5
, " ");
1038 dyn_string_append (step5
, driver_cmdline
->s
);
1041 if (run (driver_name
, step5
->s
))
1042 cleanup_and_exit (1);
1044 dyn_string_delete (step5
);
1047 cleanup_and_exit (0);