1 /* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
2 Copyright (C) 1998 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"
46 #include "dyn-string.h"
51 #ifdef HAVE_SYS_WAIT_H
53 #else /* ! HAVE_SYS_WAIT_H */
54 #if ! defined (_WIN32) || defined (__CYGWIN32__)
56 #define WIFEXITED(w) (((w)&0377) == 0)
59 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
62 #define WTERMSIG(w) ((w) & 0177)
65 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
67 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
69 #define WIFEXITED(w) (((w) & 0xff) == 0)
72 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
75 #define WTERMSIG(w) ((w) & 0x7f)
78 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
80 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
81 #endif /* ! HAVE_SYS_WAIT_H */
83 static char *program_version
= "0.2.4";
84 static char *driver_name
= "gcc";
85 static char *cygwin32_driver_flags
=
86 "-Wl,--dll -nostartfiles";
87 static char *mingw32_driver_flags
= "-mdll";
88 static char *generic_driver_flags
= "-Wl,--dll";
90 static char *entry_point
;
92 static char *dlltool_name
= "dlltool";
94 static char *target
= TARGET
;
103 static target_type which_target
= UNKNOWN_TARGET
;
105 static int dontdeltemps
= 0;
106 static int dry_run
= 0;
108 static char *program_name
;
110 static int verbose
= 0;
112 static char *dll_file_name
;
113 static char *dll_name
;
114 static char *base_file_name
;
115 static char *exp_file_name
;
116 static char *def_file_name
;
117 static int delete_base_file
= 1;
118 static int delete_exp_file
= 1;
119 static int delete_def_file
= 1;
121 static int run
PARAMS ((const char *, char *));
122 static void usage
PARAMS ((FILE *, int));
123 static void delete_temp_files
PARAMS ((void));
124 static void cleanup_and_exit
PARAMS ((int status
));
126 /**********************************************************************/
131 if (delete_base_file
&& base_file_name
)
134 fprintf (stderr
, "%s temporary base file %s\n",
135 dontdeltemps
? "Keeping" : "Deleting",
139 unlink (base_file_name
);
140 free (base_file_name
);
144 if (delete_exp_file
&& exp_file_name
)
147 fprintf (stderr
, "%s temporary exp file %s\n",
148 dontdeltemps
? "Keeping" : "Deleting",
152 unlink (exp_file_name
);
153 free (exp_file_name
);
156 if (delete_def_file
&& def_file_name
)
159 fprintf (stderr
, "%s temporary def file %s\n",
160 dontdeltemps
? "Keeping" : "Deleting",
164 unlink (def_file_name
);
165 free (def_file_name
);
171 cleanup_and_exit (int status
)
173 delete_temp_files ();
183 int pid
, wait_status
, retcode
;
186 char *errmsg_fmt
, *errmsg_arg
;
187 char *temp_base
= choose_temp_base ();
191 if (verbose
|| dry_run
)
192 fprintf (stderr
, "%s %s\n", what
, args
);
196 for (s
= args
; *s
; s
++)
200 argv
= alloca (sizeof (char *) * (i
+ 3));
206 while (*s
== ' ' && *s
!= 0)
210 in_quote
= (*s
== '\'' || *s
== '"');
211 sep
= (in_quote
) ? *s
++ : ' ';
213 while (*s
!= sep
&& *s
!= 0)
226 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
227 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
231 int errno_val
= errno
;
233 fprintf (stderr
, "%s: ", program_name
);
234 fprintf (stderr
, errmsg_fmt
, errmsg_arg
);
235 fprintf (stderr
, ": %s\n", strerror (errno_val
));
240 pid
= pwait (pid
, &wait_status
, 0);
243 fprintf (stderr
, "%s: wait: %s\n", program_name
, strerror (errno
));
246 else if (WIFSIGNALED (wait_status
))
248 fprintf (stderr
, "%s: subprocess got fatal signal %d\n",
249 program_name
, WTERMSIG (wait_status
));
252 else if (WIFEXITED (wait_status
))
254 if (WEXITSTATUS (wait_status
) != 0)
256 fprintf (stderr
, "%s: %s exited with status %d\n",
257 program_name
, what
, WEXITSTATUS (wait_status
));
271 const char *base
= name
;
275 if (*name
== '/' || *name
== '\\')
281 return (char *) base
;
285 strhash (const char *str
)
287 const unsigned char *s
;
294 s
= (const unsigned char *) str
;
295 while ((c
= *s
++) != '\0')
297 hash
+= c
+ (c
<< 17);
301 hash
+= len
+ (len
<< 17);
307 /**********************************************************************/
313 /* This output is intended to follow the GNU standards document. */
314 /* xgettext:c-format */
315 printf ("GNU %s %s\n", name
, program_version
);
316 printf ("Copyright 1998 Free Software Foundation, Inc.\n");
318 This program is free software; you may redistribute it under the terms of\n\
319 the GNU General Public License. This program has absolutely no warranty.\n");
328 fprintf (file
, "Usage %s <options> <object-files>\n", program_name
);
329 fprintf (file
, " Generic options:\n");
330 fprintf (file
, " --quiet, -q Work quietly\n");
331 fprintf (file
, " --verbose, -v Verbose\n");
332 fprintf (file
, " --version Print dllwrap version\n");
333 fprintf (file
, " --implib <outname> Synonym for --output-lib\n");
334 fprintf (file
, " Options for %s:\n", program_name
);
335 fprintf (file
, " --driver-name <driver> Defaults to \"gcc\"\n");
336 fprintf (file
, " --driver-flags <flags> Override default ld flags\n");
337 fprintf (file
, " --dlltool-name <dlltool> Defaults to \"dlltool\"\n");
338 fprintf (file
, " --entry <entry> Specify alternate DLL entry point\n");
339 fprintf (file
, " --image-base <base> Specify image base address\n");
340 fprintf (file
, " --target <machine> i386-cygwin32 or i386-mingw32\n");
341 fprintf (file
, " --dry-run Show what needs to be run\n");
342 fprintf (file
, " Options passed to DLLTOOL:\n");
343 fprintf (file
, " --machine <machine>\n");
344 fprintf (file
, " --output-exp <outname> Generate export file.\n");
345 fprintf (file
, " --output-lib <outname> Generate input library.\n");
346 fprintf (file
, " --add-indirect Add dll indirects to export file.\n");
347 fprintf (file
, " --dllname <name> Name of input dll to put into output lib.\n");
348 fprintf (file
, " --def <deffile> Name input .def file\n");
349 fprintf (file
, " --output-def <deffile> Name output .def file\n");
350 fprintf (file
, " --export-all-symbols Export all symbols to .def\n");
351 fprintf (file
, " --no-export-all-symbols Only export .drectve symbols\n");
352 fprintf (file
, " --exclude-symbols <list> Exclude <list> from .def\n");
353 fprintf (file
, " --no-default-excludes Zap default exclude symbols\n");
354 fprintf (file
, " --base-file <basefile> Read linker generated base file\n");
355 fprintf (file
, " --no-idata4 Don't generate idata$4 section\n");
356 fprintf (file
, " --no-idata5 Don't generate idata$5 section\n");
357 fprintf (file
, " -U Add underscores to .lib\n");
358 fprintf (file
, " -k Kill @<n> from exported names\n");
359 fprintf (file
, " --add-stdcall-alias Add aliases without @<n>\n");
360 fprintf (file
, " --as <name> Use <name> for assembler\n");
361 fprintf (file
, " --nodelete Keep temp files.\n");
362 fprintf (file
, " Rest are passed unmodified to the language driver\n");
363 fprintf (file
, "\n\n");
367 #define OPTION_START 149
369 /* GENERIC options. */
370 #define OPTION_QUIET (OPTION_START + 1)
371 #define OPTION_VERBOSE (OPTION_QUIET + 1)
372 #define OPTION_VERSION (OPTION_VERBOSE + 1)
374 /* DLLWRAP options. */
375 #define OPTION_DRY_RUN (OPTION_VERSION + 1)
376 #define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
377 #define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
378 #define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
379 #define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
380 #define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
381 #define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
383 /* DLLTOOL options. */
384 #define OPTION_NODELETE (OPTION_TARGET + 1)
385 #define OPTION_DLLNAME (OPTION_NODELETE + 1)
386 #define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
387 #define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
388 #define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
389 #define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
390 #define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
391 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
392 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
393 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
394 #define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
395 #define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
396 #define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
397 #define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
398 #define OPTION_HELP (OPTION_KILLAT + 1)
399 #define OPTION_MACHINE (OPTION_HELP + 1)
400 #define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)
401 #define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1)
402 #define OPTION_AS (OPTION_BASE_FILE + 1)
404 static const struct option long_options
[] =
406 /* generic options. */
407 {"quiet", no_argument
, NULL
, 'q'},
408 {"verbose", no_argument
, NULL
, 'v'},
409 {"version", no_argument
, NULL
, OPTION_VERSION
},
410 {"implib", required_argument
, NULL
, OPTION_OUTPUT_LIB
},
412 /* dllwrap options. */
413 {"dry-run", no_argument
, NULL
, OPTION_DRY_RUN
},
414 {"driver-name", required_argument
, NULL
, OPTION_DRIVER_NAME
},
415 {"driver-flags", required_argument
, NULL
, OPTION_DRIVER_FLAGS
},
416 {"dlltool-name", required_argument
, NULL
, OPTION_DLLTOOL_NAME
},
417 {"entry", required_argument
, NULL
, 'e'},
418 {"image-base", required_argument
, NULL
, OPTION_IMAGE_BASE
},
419 {"target", required_argument
, NULL
, OPTION_TARGET
},
421 /* dlltool options. */
422 {"no-delete", no_argument
, NULL
, 'n'},
423 {"dllname", required_argument
, NULL
, OPTION_DLLNAME
},
424 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
425 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
426 {"output-exp", required_argument
, NULL
, OPTION_OUTPUT_EXP
},
427 {"output-def", required_argument
, NULL
, OPTION_OUTPUT_DEF
},
428 {"export-all-symbols", no_argument
, NULL
, OPTION_EXPORT_ALL_SYMS
},
429 {"no-export-all-symbols", no_argument
, NULL
, OPTION_NO_EXPORT_ALL_SYMS
},
430 {"exclude-symbols", required_argument
, NULL
, OPTION_EXCLUDE_SYMS
},
431 {"no-default-excludes", no_argument
, NULL
, OPTION_NO_DEFAULT_EXCLUDES
},
432 {"output-lib", required_argument
, NULL
, OPTION_OUTPUT_LIB
},
433 {"def", required_argument
, NULL
, OPTION_DEF
},
434 {"add-underscore", no_argument
, NULL
, 'U'},
435 {"killat", no_argument
, NULL
, 'k'},
436 {"add-stdcall-alias", no_argument
, NULL
, 'A'},
437 {"help", no_argument
, NULL
, 'h'},
438 {"machine", required_argument
, NULL
, OPTION_MACHINE
},
439 {"add-indirect", no_argument
, NULL
, OPTION_ADD_INDIRECT
},
440 {"base-file", required_argument
, NULL
, OPTION_BASE_FILE
},
441 {"as", required_argument
, NULL
, OPTION_AS
},
453 char **saved_argv
= 0;
458 int *dlltool_arg_indices
;
459 int *driver_arg_indices
;
461 char *driver_flags
= 0;
462 char *output_lib_file_name
= 0;
464 dyn_string_t dlltool_cmdline
;
465 dyn_string_t driver_cmdline
;
467 int def_file_seen
= 0;
469 char *image_base_str
= 0;
471 program_name
= argv
[0];
473 saved_argv
= (char **) xmalloc (argc
* sizeof (char*));
474 dlltool_arg_indices
= (int *) xmalloc (argc
* sizeof (int));
475 driver_arg_indices
= (int *) xmalloc (argc
* sizeof (int));
476 for (i
= 0; i
< argc
; ++i
)
478 size_t len
= strlen (argv
[i
]);
479 char *arg
= (char *) xmalloc (len
+ 1);
480 strcpy (arg
, argv
[i
]);
483 dlltool_arg_indices
[i
] = 0;
484 driver_arg_indices
[i
] = 1;
488 /* We recognize dllwrap and dlltool options, and everything else is
489 passed onto the language driver (eg., to GCC). We collect options
490 to dlltool and driver in dlltool_args and driver_args. */
493 while ((c
= getopt_long_only (argc
, argv
, "nkAqve:Uho:l:L:I:",
494 long_options
, (int *) 0)) != EOF
)
498 int single_word_option_value_pair
;
502 single_word_option_value_pair
= 0;
506 /* We recognize this option, so it has to be either dllwrap or
507 dlltool option. Do not pass to driver unless it's one of the
508 generic options that are passed to all the tools (such as -v)
509 which are dealt with later. */
513 /* deal with generic and dllwrap options first. */
526 print_version (program_name
);
529 entry_point
= optarg
;
531 case OPTION_IMAGE_BASE
:
532 image_base_str
= optarg
;
535 def_file_name
= optarg
;
544 dll_file_name
= optarg
;
557 case OPTION_DRIVER_NAME
:
558 driver_name
= optarg
;
560 case OPTION_DRIVER_FLAGS
:
561 driver_flags
= optarg
;
563 case OPTION_DLLTOOL_NAME
:
564 dlltool_name
= optarg
;
569 case OPTION_BASE_FILE
:
570 base_file_name
= optarg
;
571 delete_base_file
= 0;
573 case OPTION_OUTPUT_EXP
:
574 exp_file_name
= optarg
;
577 case OPTION_EXPORT_ALL_SYMS
:
580 case OPTION_OUTPUT_LIB
:
581 output_lib_file_name
= optarg
;
590 /* Handle passing through --option=value case. */
592 && saved_argv
[optind
-1][0] == '-'
593 && saved_argv
[optind
-1][1] == '-'
594 && strchr (saved_argv
[optind
-1], '='))
595 single_word_option_value_pair
= 1;
599 dlltool_arg_indices
[optind
-1] = 1;
600 if (optarg
&& ! single_word_option_value_pair
)
602 dlltool_arg_indices
[optind
-2] = 1;
608 driver_arg_indices
[optind
-1] = 0;
609 if (optarg
&& ! single_word_option_value_pair
)
611 driver_arg_indices
[optind
-2] = 0;
617 if (! dll_name
&& ! dll_file_name
)
620 "%s: Must provide at least one of -o or --dllname options\n",
626 dll_name
= xstrdup (mybasename (dll_file_name
));
628 else if (! dll_file_name
)
630 dll_file_name
= xstrdup (dll_name
);
635 char *fileprefix
= choose_temp_base ();
636 def_file_name
= (char *) xmalloc (strlen (fileprefix
) + 5);
637 sprintf (def_file_name
, "%s.def",
638 (dontdeltemps
) ? mybasename (fileprefix
) : fileprefix
);
642 fprintf (stderr
, "Warning: no export definition file provided\n");
644 "dllwrap will create one, but may not be what you want\n");
647 /* set the target platform. */
648 if (strstr (target
, "cygwin32"))
649 which_target
= CYGWIN32_TARGET
;
650 else if (strstr (target
, "mingw32"))
651 which_target
= MINGW32_TARGET
;
653 which_target
= UNKNOWN_TARGET
;
655 /* re-create the command lines as a string, taking care to quote stuff. */
656 dlltool_cmdline
= dyn_string_new (cmdline_len
);
659 dyn_string_append (dlltool_cmdline
, " -v");
661 dyn_string_append (dlltool_cmdline
, " --dllname ");
662 dyn_string_append (dlltool_cmdline
, dll_name
);
664 for (i
= 1; i
< argc
; ++i
)
666 if (dlltool_arg_indices
[i
])
668 char *arg
= saved_argv
[i
];
669 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
670 dyn_string_append (dlltool_cmdline
,
671 (quote
) ? " \"" : " ");
672 dyn_string_append (dlltool_cmdline
, arg
);
673 dyn_string_append (dlltool_cmdline
,
674 (quote
) ? "\"" : "");
678 driver_cmdline
= dyn_string_new (cmdline_len
);
679 if (! driver_flags
|| strlen (driver_flags
) == 0)
681 switch (which_target
)
683 case CYGWIN32_TARGET
:
684 driver_flags
= cygwin32_driver_flags
;
688 driver_flags
= mingw32_driver_flags
;
692 driver_flags
= generic_driver_flags
;
696 dyn_string_append (driver_cmdline
, driver_flags
);
697 dyn_string_append (driver_cmdline
, " -o ");
698 dyn_string_append (driver_cmdline
, dll_file_name
);
700 if (! entry_point
|| strlen (entry_point
) == 0)
702 switch (which_target
)
704 case CYGWIN32_TARGET
:
705 entry_point
= "__cygwin32_dll_entry@12";
709 entry_point
= "_DllMainCRTStartup@12";
713 entry_point
= "_DllMain@12";
717 dyn_string_append (driver_cmdline
, " -Wl,-e,");
718 dyn_string_append (driver_cmdline
, entry_point
);
719 dyn_string_append (dlltool_cmdline
, " --exclude-symbol=");
720 dyn_string_append (dlltool_cmdline
,
721 (entry_point
[0] == '_') ? entry_point
+1 : entry_point
);
723 if (! image_base_str
|| strlen (image_base_str
) == 0)
725 char *tmpbuf
= (char *) xmalloc (sizeof ("0x12345678") + 1);
726 unsigned long hash
= strhash (dll_file_name
);
727 sprintf (tmpbuf
, "0x%.8X", 0x60000000|((hash
<<16)&0xFFC0000));
728 image_base_str
= tmpbuf
;
731 dyn_string_append (driver_cmdline
, " -Wl,--image-base,");
732 dyn_string_append (driver_cmdline
, image_base_str
);
736 dyn_string_append (driver_cmdline
, " -v");
739 for (i
= 1; i
< argc
; ++i
)
741 if (driver_arg_indices
[i
])
743 char *arg
= saved_argv
[i
];
744 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
745 dyn_string_append (driver_cmdline
,
746 (quote
) ? " \"" : " ");
747 dyn_string_append (driver_cmdline
, arg
);
748 dyn_string_append (driver_cmdline
,
749 (quote
) ? "\"" : "");
754 * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it
755 * and then pass it on.
761 dyn_string_t step_pre1
;
763 step_pre1
= dyn_string_new (1024);
765 dyn_string_append (step_pre1
, dlltool_cmdline
->s
);
768 dyn_string_append (step_pre1
, " --export-all --exclude-symbol=");
769 dyn_string_append (step_pre1
,
770 "_cygwin32_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
772 dyn_string_append (step_pre1
, " --output-def ");
773 dyn_string_append (step_pre1
, def_file_name
);
775 for (i
= 1; i
< argc
; ++i
)
777 if (driver_arg_indices
[i
])
779 char *arg
= saved_argv
[i
];
780 size_t len
= strlen (arg
);
781 if (len
>= 2 && arg
[len
-2] == '.'
782 && (arg
[len
-1] == 'o' || arg
[len
-1] == 'a'))
784 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
785 dyn_string_append (step_pre1
,
786 (quote
) ? " \"" : " ");
787 dyn_string_append (step_pre1
, arg
);
788 dyn_string_append (step_pre1
,
789 (quote
) ? "\"" : "");
794 if (run (dlltool_name
, step_pre1
->s
))
795 cleanup_and_exit (1);
797 dyn_string_delete (step_pre1
);
800 dyn_string_append (dlltool_cmdline
, " --def ");
801 dyn_string_append (dlltool_cmdline
, def_file_name
);
805 fprintf (stderr
, "DLLTOOL name : %s\n", dlltool_name
);
806 fprintf (stderr
, "DLLTOOL options : %s\n", dlltool_cmdline
->s
);
807 fprintf (stderr
, "DRIVER name : %s\n", driver_name
);
808 fprintf (stderr
, "DRIVER options : %s\n", driver_cmdline
->s
);
812 * Step 1. Call GCC/LD to create base relocation file. If using GCC, the
813 * driver command line will look like the following:
815 * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
817 * If the user does not specify a base name, create temporary one that
818 * is deleted at exit.
822 if (! base_file_name
)
824 char *fileprefix
= choose_temp_base ();
825 base_file_name
= (char *) xmalloc (strlen (fileprefix
) + 6);
826 sprintf (base_file_name
, "%s.base",
827 (dontdeltemps
) ? mybasename (fileprefix
) : fileprefix
);
828 delete_base_file
= 1;
835 dyn_string_t step1
= dyn_string_new (driver_cmdline
->length
836 + strlen (base_file_name
)
838 dyn_string_append (step1
, "-Wl,--base-file,");
839 quote
= (strchr (base_file_name
, ' ')
840 || strchr (base_file_name
, '\t'));
841 dyn_string_append (step1
,
842 (quote
) ? "\"" : "");
843 dyn_string_append (step1
, base_file_name
);
844 dyn_string_append (step1
,
845 (quote
) ? "\"" : "");
846 if (driver_cmdline
->length
)
848 dyn_string_append (step1
, " ");
849 dyn_string_append (step1
, driver_cmdline
->s
);
852 if (run (driver_name
, step1
->s
))
853 cleanup_and_exit (1);
855 dyn_string_delete (step1
);
861 * Step 2. generate the exp file by running dlltool.
862 * dlltool command line will look like the following:
864 * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
866 * If the user does not specify a base name, create temporary one that
867 * is deleted at exit.
873 char *p
= strrchr (dll_name
, '.');
874 size_t prefix_len
= (p
) ? p
- dll_name
: strlen (dll_name
);
875 exp_file_name
= (char *) xmalloc (prefix_len
+ 4 + 1);
876 strncpy (exp_file_name
, dll_name
, prefix_len
);
877 exp_file_name
[prefix_len
] = '\0';
878 strcat (exp_file_name
, ".exp");
884 dyn_string_t step2
= dyn_string_new (dlltool_cmdline
->length
885 + strlen (base_file_name
)
886 + strlen (exp_file_name
)
889 dyn_string_append (step2
, "--base-file ");
890 quote
= (strchr (base_file_name
, ' ')
891 || strchr (base_file_name
, '\t'));
892 dyn_string_append (step2
,
893 (quote
) ? "\"" : "");
894 dyn_string_append (step2
, base_file_name
);
895 dyn_string_append (step2
,
896 (quote
) ? "\" " : " ");
898 dyn_string_append (step2
, "--output-exp ");
899 quote
= (strchr (exp_file_name
, ' ')
900 || strchr (exp_file_name
, '\t'));
901 dyn_string_append (step2
,
902 (quote
) ? "\"" : "");
903 dyn_string_append (step2
, exp_file_name
);
904 dyn_string_append (step2
,
905 (quote
) ? "\"" : "");
907 if (dlltool_cmdline
->length
)
909 dyn_string_append (step2
, " ");
910 dyn_string_append (step2
, dlltool_cmdline
->s
);
913 if (run (dlltool_name
, step2
->s
))
914 cleanup_and_exit (1);
916 dyn_string_delete (step2
);
920 * Step 3. Call GCC/LD to again, adding the exp file this time.
921 * driver command line will look like the following:
923 * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
929 dyn_string_t step3
= dyn_string_new (driver_cmdline
->length
930 + strlen (exp_file_name
)
931 + strlen (base_file_name
)
933 dyn_string_append (step3
, "-Wl,--base-file,");
934 quote
= (strchr (base_file_name
, ' ')
935 || strchr (base_file_name
, '\t'));
936 dyn_string_append (step3
,
937 (quote
) ? "\"" : "");
938 dyn_string_append (step3
, base_file_name
);
939 dyn_string_append (step3
,
940 (quote
) ? "\" " : " ");
942 quote
= (strchr (exp_file_name
, ' ')
943 || strchr (exp_file_name
, '\t'));
944 dyn_string_append (step3
,
945 (quote
) ? "\"" : "");
946 dyn_string_append (step3
, exp_file_name
);
947 dyn_string_append (step3
,
948 (quote
) ? "\"" : "");
950 if (driver_cmdline
->length
)
952 dyn_string_append (step3
, " ");
953 dyn_string_append (step3
, driver_cmdline
->s
);
956 if (run (driver_name
, step3
->s
))
957 cleanup_and_exit (1);
959 dyn_string_delete (step3
);
964 * Step 4. Run DLLTOOL again using the same command line.
969 dyn_string_t step4
= dyn_string_new (dlltool_cmdline
->length
970 + strlen (base_file_name
)
971 + strlen (exp_file_name
)
974 dyn_string_append (step4
, "--base-file ");
975 quote
= (strchr (base_file_name
, ' ')
976 || strchr (base_file_name
, '\t'));
977 dyn_string_append (step4
,
978 (quote
) ? "\"" : "");
979 dyn_string_append (step4
, base_file_name
);
980 dyn_string_append (step4
,
981 (quote
) ? "\" " : " ");
983 dyn_string_append (step4
, "--output-exp ");
984 quote
= (strchr (exp_file_name
, ' ')
985 || strchr (exp_file_name
, '\t'));
986 dyn_string_append (step4
,
987 (quote
) ? "\"" : "");
988 dyn_string_append (step4
, exp_file_name
);
989 dyn_string_append (step4
,
990 (quote
) ? "\"" : "");
992 if (dlltool_cmdline
->length
)
994 dyn_string_append (step4
, " ");
995 dyn_string_append (step4
, dlltool_cmdline
->s
);
998 if (output_lib_file_name
)
1000 dyn_string_append (step4
, " --output-lib ");
1001 dyn_string_append (step4
, output_lib_file_name
);
1004 if (run (dlltool_name
, step4
->s
))
1005 cleanup_and_exit (1);
1007 dyn_string_delete (step4
);
1012 * Step 5. Link it all together and be done with it.
1013 * driver command line will look like the following:
1015 * % gcc -Wl,--dll foo.exp [rest ...]
1022 dyn_string_t step5
= dyn_string_new (driver_cmdline
->length
1023 + strlen (exp_file_name
)
1025 quote
= (strchr (exp_file_name
, ' ')
1026 || strchr (exp_file_name
, '\t'));
1027 dyn_string_append (step5
,
1028 (quote
) ? "\"" : "");
1029 dyn_string_append (step5
, exp_file_name
);
1030 dyn_string_append (step5
,
1031 (quote
) ? "\"" : "");
1033 if (driver_cmdline
->length
)
1035 dyn_string_append (step5
, " ");
1036 dyn_string_append (step5
, driver_cmdline
->s
);
1039 if (run (driver_name
, step5
->s
))
1040 cleanup_and_exit (1);
1042 dyn_string_delete (step5
);
1045 cleanup_and_exit (0);