aboutsummaryrefslogtreecommitdiff
path: root/binutils/ar.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/ar.c')
-rw-r--r--binutils/ar.c86
1 files changed, 80 insertions, 6 deletions
diff --git a/binutils/ar.c b/binutils/ar.c
index 85b342a..56c758c 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -138,6 +138,11 @@ static bfd_boolean full_pathname = FALSE;
/* Whether to create a "thin" archive (symbol index only -- no files). */
static bfd_boolean make_thin_archive = FALSE;
+#define LIBDEPS "__.LIBDEP"
+/* Text to store in the __.LIBDEP archive element for the linker to use. */
+static char * libdeps = NULL;
+static bfd * libdeps_bfd = NULL;
+
static int show_version = 0;
static int show_help = 0;
@@ -166,6 +171,7 @@ static struct option long_options[] =
{"target", required_argument, NULL, OPTION_TARGET},
{"version", no_argument, &show_version, 1},
{"output", required_argument, NULL, OPTION_OUTPUT},
+ {"record-libdeps", required_argument, NULL, 'l'},
{NULL, no_argument, NULL, 0}
};
@@ -329,6 +335,7 @@ usage (int help)
fprintf (s, _(" generic modifiers:\n"));
fprintf (s, _(" [c] - do not warn if the library had to be created\n"));
fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n"));
+ fprintf (s, _(" [l <text> ] - specify the dependencies of this library\n"));
fprintf (s, _(" [S] - do not build a symbol table\n"));
fprintf (s, _(" [T] - make a thin archive\n"));
fprintf (s, _(" [v] - be verbose\n"));
@@ -336,6 +343,7 @@ usage (int help)
fprintf (s, _(" @<file> - read options from <file>\n"));
fprintf (s, _(" --target=BFDNAME - specify the target object format as BFDNAME\n"));
fprintf (s, _(" --output=DIRNAME - specify the output directory for extraction operations\n"));
+ fprintf (s, _(" --record-libdeps=<text> - specify the dependencies of this library\n"));
#if BFD_SUPPORTS_PLUGINS
fprintf (s, _(" optional:\n"));
fprintf (s, _(" --plugin <p> - load the specified plugin\n"));
@@ -487,7 +495,7 @@ decode_options (int argc, char **argv)
argv = new_argv;
}
- while ((c = getopt_long (argc, argv, "hdmpqrtxlcoOVsSuvabiMNfPTDU",
+ while ((c = getopt_long (argc, argv, "hdmpqrtxl:coOVsSuvabiMNfPTDU",
long_options, NULL)) != EOF)
{
switch (c)
@@ -535,6 +543,9 @@ decode_options (int argc, char **argv)
operation = extract;
break;
case 'l':
+ if (libdeps != NULL)
+ fatal (_("libdeps specified more than once"));
+ libdeps = optarg;
break;
case 'c':
silent_create = 1;
@@ -847,6 +858,49 @@ main (int argc, char **argv)
if (operation == extract && bfd_is_thin_archive (arch))
fatal (_("`x' cannot be used on thin archives."));
+ if (libdeps != NULL)
+ {
+ char **new_files;
+ bfd_size_type reclen = strlen (libdeps) + 1;
+
+ /* Create a bfd to contain the dependencies.
+ It inherits its type from arch, but we must set the type to
+ "binary" otherwise bfd_bwrite() will fail. After writing, we
+ must set the type back to "plugin" otherwise adding it to the
+ archive will fail. */
+ libdeps_bfd = bfd_create (LIBDEPS, arch);
+ if (libdeps_bfd == NULL)
+ fatal (_("Cannot create libdeps record."));
+
+ if (bfd_find_target ("binary", libdeps_bfd) == NULL)
+ fatal (_("Cannot set libdeps record type to binary."));
+
+ if (! bfd_set_format (libdeps_bfd, bfd_object))
+ fatal (_("Cannot set libdeps object format."));
+
+ if (! bfd_make_writable (libdeps_bfd))
+ fatal (_("Cannot make libdeps object writable."));
+
+ if (bfd_bwrite (libdeps, reclen, libdeps_bfd) != reclen)
+ fatal (_("Cannot write libdeps record."));
+
+ if (! bfd_make_readable (libdeps_bfd))
+ fatal (_("Cannot make libdeps object readable."));
+
+ if (bfd_find_target ("plugin", libdeps_bfd) == NULL)
+ fatal (_("Cannot reset libdeps record type."));
+
+ /* Append our libdeps record to the list of files
+ being operated on. */
+ new_files = xmalloc ((file_count + 2) * sizeof (char *));
+ for (i = 0; i < file_count; i++)
+ new_files[i] = files[i];
+ new_files[i++] = LIBDEPS;
+ file_count = i;
+ files = new_files;
+ files[i] = NULL;
+ }
+
switch (operation)
{
case print_table:
@@ -1432,6 +1486,7 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
normalize (bfd_get_filename (current), arch)) == 0
&& current->arelt_data != NULL)
{
+ bfd_boolean replaced;
if (newer_only)
{
struct stat fsbuf, asbuf;
@@ -1453,8 +1508,19 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
bfd_get_filename (current));
- if (ar_emul_replace (after_bfd, *files_to_move,
- target, verbose))
+ if (libdeps_bfd != NULL
+ && FILENAME_CMP (normalize (*files_to_move, arch),
+ LIBDEPS) == 0)
+ {
+ replaced = ar_emul_replace_bfd (after_bfd, libdeps_bfd,
+ verbose);
+ }
+ else
+ {
+ replaced = ar_emul_replace (after_bfd, *files_to_move,
+ target, verbose);
+ }
+ if (replaced)
{
/* Snip out this entry from the chain. */
*current_ptr = (*current_ptr)->archive_next;
@@ -1470,9 +1536,17 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
/* Add to the end of the archive. */
after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
- if (ar_emul_append (after_bfd, *files_to_move, target,
- verbose, make_thin_archive))
- changed = TRUE;
+ if (libdeps_bfd != NULL
+ && FILENAME_CMP (normalize (*files_to_move, arch), LIBDEPS) == 0)
+ {
+ changed |= ar_emul_append_bfd (after_bfd, libdeps_bfd,
+ verbose, make_thin_archive);
+ }
+ else
+ {
+ changed |= ar_emul_append (after_bfd, *files_to_move, target,
+ verbose, make_thin_archive);
+ }
next_file:;