Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | |
| 3 | # |
| 4 | #//===----------------------------------------------------------------------===// |
| 5 | #// |
| 6 | #// The LLVM Compiler Infrastructure |
| 7 | #// |
| 8 | #// This file is dual licensed under the MIT and the University of Illinois Open |
| 9 | #// Source Licenses. See LICENSE.txt for details. |
| 10 | #// |
| 11 | #//===----------------------------------------------------------------------===// |
| 12 | # |
| 13 | |
| 14 | use strict; |
| 15 | use warnings; |
| 16 | |
| 17 | use File::Glob ":glob"; |
| 18 | use Data::Dumper; |
| 19 | |
| 20 | use FindBin; |
| 21 | use lib "$FindBin::Bin/lib"; |
| 22 | |
| 23 | use tools; |
| 24 | use Platform ":vars"; |
| 25 | |
| 26 | our $VERSION = "0.004"; |
| 27 | |
| 28 | # -------------------------------------------------------------------------------------------------- |
| 29 | # Set of objects: # Ref to hash, keys are names of objects. |
| 30 | # object0: # Ref to hash of two elements with keys "defined" and "undefined". |
| 31 | # defined: # Ref to array of symbols defined in object0. |
| 32 | # - symbol0 # Symbol name. |
| 33 | # - ... |
| 34 | # undefined: # Ref to array of symbols referenced in object0. |
| 35 | # - symbol0 |
| 36 | # - ... |
| 37 | # object1: |
| 38 | # ... |
| 39 | # ... |
| 40 | # -------------------------------------------------------------------------------------------------- |
| 41 | |
| 42 | # -------------------------------------------------------------------------------------------------- |
| 43 | # Set of symbols: # Ref to hash, keys are names of symbols. |
| 44 | # symbol0: # Ref to array of object names where the symbol0 is defined. |
| 45 | # - object0 # Object file name. |
| 46 | # - ... |
| 47 | # symbol1: |
| 48 | # ... |
| 49 | # ... |
| 50 | # -------------------------------------------------------------------------------------------------- |
| 51 | |
| 52 | sub dump_objects($$$) { |
| 53 | |
| 54 | my ( $title, $objects, $dump ) = @_; |
| 55 | |
| 56 | if ( $dump > 0 ) { |
| 57 | STDERR->print( $title, "\n" ); |
| 58 | foreach my $object ( sort( keys( %$objects ) ) ) { |
| 59 | STDERR->print( " $object\n" ); |
| 60 | if ( $dump > 1 ) { |
| 61 | STDERR->print( " Defined symbols:\n" ); |
| 62 | foreach my $symbol ( sort( @{ $objects->{ $object }->{ defined } } ) ) { |
| 63 | STDERR->print( " $symbol\n" ); |
| 64 | }; # foreach $symbol |
| 65 | STDERR->print( " Undefined symbols:\n" ); |
| 66 | foreach my $symbol ( sort( @{ $objects->{ $object }->{ undefined } } ) ) { |
| 67 | STDERR->print( " $symbol\n" ); |
| 68 | }; # foreach $symbol |
| 69 | }; # if |
| 70 | }; # foreach $object |
| 71 | }; # if |
| 72 | |
| 73 | }; # sub dump_objects |
| 74 | |
| 75 | sub dump_symbols($$$) { |
| 76 | |
| 77 | my ( $title, $symbols, $dump ) = @_; |
| 78 | |
| 79 | if ( $dump > 0 ) { |
| 80 | STDERR->print( $title, "\n" ); |
| 81 | foreach my $symbol ( sort( keys( %$symbols ) ) ) { |
| 82 | STDERR->print( " $symbol\n" ); |
| 83 | if ( $dump > 1 ) { |
| 84 | foreach my $object ( sort( @{ $symbols->{ $symbol } } ) ) { |
| 85 | STDERR->print( " $object\n" ); |
| 86 | }; # foreach |
| 87 | }; # if |
| 88 | }; # foreach $object |
| 89 | }; # if |
| 90 | |
| 91 | }; # sub dump_symbols |
| 92 | |
| 93 | # -------------------------------------------------------------------------------------------------- |
| 94 | # Name: |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 95 | # load_symbols -- Fulfill objects data structure with symbol names. |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 96 | # Synopsis: |
| 97 | # load_symbols( $objects ); |
| 98 | # Arguments: |
| 99 | # $objects (in/out) -- Set of objects. On enter, it is expected that top-level hash has filled |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 100 | # with object names only. On exit, it is completely fulfilled with lists of symbols |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 101 | # defined or referenced in each object file. |
| 102 | # Returns: |
| 103 | # Nothing. |
| 104 | # Example: |
| 105 | # my $objects = { foo.o => {} }; |
| 106 | # load_symbols( $objects ); |
| 107 | # # Now $objects is { goo.o => { defined => [ ... ], undefined => [ ... ] } }. |
| 108 | # |
| 109 | # -------------------------------------------------------------------------------------------------- |
| 110 | # This version of load_symbols parses output of nm command and works on Linux* OS and OS X*. |
| 111 | # |
| 112 | sub _load_symbols_nm($) { |
| 113 | |
| 114 | my $objects = shift( @_ ); |
| 115 | # It is a ref to hash. Keys are object names, values are empty hashes (for now). |
| 116 | my @bulk; |
| 117 | |
| 118 | if ( %$objects ) { |
| 119 | # Do not run nm if a set of objects is empty -- nm will try to open a.out in this case. |
| 120 | execute( |
| 121 | [ |
| 122 | "nm", |
| 123 | "-g", # Display only external (global) symbols. |
| 124 | "-o", # Precede each symbol by the name of the input file. |
| 125 | keys( %$objects ) |
| 126 | # Running nm once (rather than once per object) improves performance |
| 127 | # drastically. |
| 128 | ], |
| 129 | -stdout => \@bulk |
| 130 | ); |
| 131 | }; # if |
| 132 | |
| 133 | foreach my $line ( @bulk ) { |
| 134 | if ( $line !~ m{^(.*):(?: ?[0-9a-f]*| *) ([A-Za-z]) (.*)$} ) { |
| 135 | die "Cannot parse nm output, line:\n $line\n"; |
| 136 | }; # if |
| 137 | my ( $file, $tag, $symbol ) = ( $1, $2, $3 ); |
| 138 | if ( not exists( $objects->{ $file } ) ) { |
| 139 | die "nm reported unknown object file:\n $line\n"; |
| 140 | }; # if |
| 141 | # AC: exclude some libc symbols from renaming, otherwise we have problems |
| 142 | # in tests for gfortran + static libiomp on Lin_32. |
| 143 | # These symbols came from libtbbmalloc.a |
| 144 | if ( $target_os eq "lin" ) { |
| 145 | if ( $symbol =~ m{__i686} ) { |
| 146 | next; |
| 147 | } |
| 148 | } |
| 149 | # AC: added "w" to tags of undefined symbols, e.g. malloc is weak in libirc v12.1. |
| 150 | if ( $tag eq "U" or $tag eq "w" ) { # Symbol not defined. |
| 151 | push( @{ $objects->{ $file }->{ undefined } }, $symbol ); |
| 152 | } else { # Symbol defined. |
| 153 | push( @{ $objects->{ $file }->{ defined } }, $symbol ); |
| 154 | }; # if |
| 155 | }; # foreach |
| 156 | |
| 157 | return undef; |
| 158 | |
| 159 | }; # sub _load_symbols_nm |
| 160 | |
| 161 | # -------------------------------------------------------------------------------------------------- |
| 162 | # This version of load_symbols parses output of link command and works on Windows* OS. |
| 163 | # |
| 164 | sub _load_symbols_link($) { |
| 165 | |
| 166 | my $objects = shift( @_ ); |
| 167 | # It is a ref to hash. Keys are object names, values are empty hashes (for now). |
| 168 | my @bulk; |
| 169 | |
| 170 | if ( %$objects ) { |
| 171 | # Do not run nm if a set of objects is empty -- nm will try to open a.out in this case. |
| 172 | execute( |
| 173 | [ |
| 174 | "link", |
| 175 | "/dump", |
| 176 | "/symbols", |
| 177 | keys( %$objects ) |
| 178 | # Running nm once (rather than once per object) improves performance |
| 179 | # drastically. |
| 180 | ], |
| 181 | -stdout => \@bulk |
| 182 | ); |
| 183 | }; # if |
| 184 | |
| 185 | my $num_re = qr{[0-9A-F]{3,4}}; |
| 186 | my $addr_re = qr{[0-9A-F]{8}}; |
| 187 | my $tag_re = qr{DEBUG|ABS|UNDEF|SECT[0-9A-F]+}; |
| 188 | my $class_re = qr{Static|External|Filename|Label|BeginFunction|EndFunction|WeakExternal|\.bf or\.ef}; |
| 189 | |
| 190 | my $file; |
| 191 | foreach my $line ( @bulk ) { |
| 192 | if ( $line =~ m{\ADump of file (.*?)\n\z} ) { |
| 193 | $file = $1; |
| 194 | if ( not exists( $objects->{ $file } ) ) { |
| 195 | die "link reported unknown object file:\n $line\n"; |
| 196 | }; # if |
| 197 | } elsif ( $line =~ m{\A$num_re } ) { |
| 198 | if ( not defined( $file ) ) { |
| 199 | die "link reported symbol of unknown object file:\n $line\n"; |
| 200 | }; # if |
| 201 | if ( $line !~ m{\A$num_re $addr_re ($tag_re)\s+notype(?: \(\))?\s+($class_re)\s+\| (.*?)\n\z} ) { |
| 202 | die "Cannot parse link output, line:\n $line\n"; |
| 203 | }; # if |
| 204 | my ( $tag, $class, $symbol ) = ( $1, $2, $3 ); |
| 205 | # link.exe /dump sometimes prints comments for symbols, e. g.: |
| 206 | # ".?0_memcopyA ([Entry] ?0_memcopyA)", or "??_C@_01A@r?$AA@ (`string')". |
| 207 | # Strip these comments. |
| 208 | $symbol =~ s{ \(.*\)\z}{}; |
| 209 | if ( $class eq "External" ) { |
| 210 | if ( $tag eq "UNDEF" ) { # Symbol not defined. |
| 211 | push( @{ $objects->{ $file }->{ undefined } }, $symbol ); |
| 212 | } else { # Symbol defined. |
| 213 | push( @{ $objects->{ $file }->{ defined } }, $symbol ); |
| 214 | }; # if |
| 215 | }; # if |
| 216 | } else { |
| 217 | # Ignore all other lines. |
| 218 | }; # if |
| 219 | }; # foreach |
| 220 | |
| 221 | return undef; |
| 222 | |
| 223 | }; # sub _load_symbols_link |
| 224 | |
| 225 | # -------------------------------------------------------------------------------------------------- |
| 226 | # Name: |
| 227 | # symbols -- Construct set of symbols with specified tag in the specified set of objects. |
| 228 | # Synopsis: |
| 229 | # my $symbols = defined_symbols( $objects, $tag ); |
| 230 | # Arguments: |
| 231 | # $objects (in) -- Set of objects. |
| 232 | # $tag (in) -- A tag, "defined" or "undefined". |
| 233 | # Returns: |
| 234 | # Set of symbols with the specified tag. |
| 235 | # |
| 236 | sub symbols($$) { |
| 237 | |
| 238 | my $objects = shift( @_ ); |
| 239 | my $tag = shift( @_ ); |
| 240 | |
| 241 | my $symbols = {}; |
| 242 | |
| 243 | foreach my $object ( keys( %$objects ) ) { |
| 244 | foreach my $symbol ( @{ $objects->{ $object }->{ $tag } } ) { |
| 245 | push( @{ $symbols->{ $symbol } }, $object ); |
| 246 | }; # foreach $symbol |
| 247 | }; # foreach $object |
| 248 | |
| 249 | return $symbols; |
| 250 | |
| 251 | }; # sub symbols |
| 252 | |
| 253 | sub defined_symbols($) { |
| 254 | |
| 255 | my $objects = shift( @_ ); |
| 256 | my $defined = symbols( $objects, "defined" ); |
| 257 | return $defined; |
| 258 | |
| 259 | }; # sub defined_symbols |
| 260 | |
| 261 | sub undefined_symbols($) { |
| 262 | |
| 263 | my $objects = shift( @_ ); |
| 264 | my $defined = symbols( $objects, "defined" ); |
| 265 | my $undefined = symbols( $objects, "undefined" ); |
| 266 | foreach my $symbol ( keys( %$defined ) ) { |
| 267 | delete( $undefined->{ $symbol } ); |
| 268 | }; # foreach symbol |
| 269 | return $undefined; |
| 270 | |
| 271 | }; # sub undefined_symbols |
| 272 | |
| 273 | # -------------------------------------------------------------------------------------------------- |
| 274 | # Name: |
| 275 | # _required_extra_objects -- Select a subset of extra objects required to resolve undefined |
| 276 | # symbols in a set of objects. It is a helper sub for required_extra_objects(). |
| 277 | # Synopsis: |
| 278 | # my $required = _required_extra_objects( $objects, $extra, $symbols ); |
| 279 | # Arguments: |
| 280 | # $objects (in) -- A set of objects to be searched for undefined symbols. |
| 281 | # $extra (in) -- A set of extra objects to be searched for defined symbols to resolve undefined |
| 282 | # symbols in objects. |
| 283 | # $symbols (in/out) -- Set of symbols defined in the set of external objects. At the first call |
| 284 | # it should consist of all the symbols defined in all the extra objects. Symbols defined in |
| 285 | # the selected subset of extra objects are removed from set of defined symbols, because |
| 286 | # they are out of interest for subsequent calls. |
| 287 | # Returns: |
| 288 | # A subset of extra objects required by the specified set of objects. |
| 289 | # |
| 290 | sub _required_extra_objects($$$$) { |
| 291 | |
| 292 | my $objects = shift( @_ ); |
| 293 | my $extra = shift( @_ ); |
| 294 | my $symbols = shift( @_ ); |
| 295 | my $dump = shift( @_ ); |
| 296 | |
| 297 | my $required = {}; |
| 298 | |
| 299 | if ( $dump > 0 ) { |
| 300 | STDERR->print( "Required extra objects:\n" ); |
| 301 | }; # if |
| 302 | foreach my $object ( keys( %$objects ) ) { |
| 303 | foreach my $symbol ( @{ $objects->{ $object }->{ undefined } } ) { |
| 304 | if ( exists( $symbols->{ $symbol } ) ) { |
| 305 | # Add all objects where the symbol is defined to the required objects. |
| 306 | foreach my $req_obj ( @{ $symbols->{ $symbol } } ) { |
| 307 | if ( $dump > 0 ) { |
| 308 | STDERR->print( " $req_obj\n" ); |
| 309 | if ( $dump > 1 ) { |
| 310 | STDERR->print( " by $object\n" ); |
| 311 | STDERR->print( " due to $symbol\n" ); |
| 312 | }; # if |
| 313 | }; # if |
| 314 | $required->{ $req_obj } = $extra->{ $req_obj }; |
| 315 | }; # foreach $req_obj |
| 316 | # Delete the symbol from list of defined symbols. |
| 317 | delete( $symbols->{ $symbol } ); |
| 318 | }; # if |
| 319 | }; # foreach $symbol |
| 320 | }; # foreach $object |
| 321 | |
| 322 | return $required; |
| 323 | |
| 324 | }; # sub _required_extra_objects |
| 325 | |
| 326 | |
| 327 | # -------------------------------------------------------------------------------------------------- |
| 328 | # Name: |
| 329 | # required_extra_objects -- Select a subset of extra objects required to resolve undefined |
| 330 | # symbols in a set of base objects and selected extra objects. |
| 331 | # Synopsis: |
| 332 | # my $required = required_extra_objects( $base, $extra ); |
| 333 | # Arguments: |
| 334 | # $base (in/out) -- A set of base objects to be searched for undefined symbols. On enter, it is |
| 335 | # expected that top-level hash has filled with object names only. On exit, it is completely |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 336 | # fulfilled with lists of symbols defined and/or referenced in each object file. |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 337 | # $extra (in/out) -- A set of extra objects to be searched for defined symbols required to |
| 338 | # resolve undefined symbols in a set of base objects. Usage is similar to base objects. |
| 339 | # Returns: |
| 340 | # A subset of extra object files. |
| 341 | # |
| 342 | sub required_extra_objects($$$) { |
| 343 | |
| 344 | my $base = shift( @_ ); |
| 345 | my $extra = shift( @_ ); |
| 346 | my $dump = shift( @_ ); |
| 347 | |
| 348 | # Load symbols for each object. |
| 349 | load_symbols( $base ); |
| 350 | load_symbols( $extra ); |
| 351 | if ( $dump ) { |
| 352 | dump_objects( "Base objects:", $base, $dump ); |
| 353 | dump_objects( "Extra objects:", $extra, $dump ); |
| 354 | }; # if |
| 355 | |
| 356 | # Collect symbols defined in extra objects. |
| 357 | my $symbols = defined_symbols( $extra ); |
| 358 | |
| 359 | my $required = {}; |
| 360 | # Select extra objects required by base objects. |
| 361 | my $delta = _required_extra_objects( $base, $extra, $symbols, $dump ); |
| 362 | while ( %$delta ) { |
| 363 | %$required = ( %$required, %$delta ); |
| 364 | # Probably, just selected objects require some more objects. |
| 365 | $delta = _required_extra_objects( $delta, $extra, $symbols, $dump ); |
| 366 | }; # while |
| 367 | |
| 368 | if ( $dump ) { |
| 369 | my $base_undefined = undefined_symbols( $base ); |
| 370 | my $req_undefined = undefined_symbols( $required ); |
| 371 | dump_symbols( "Symbols undefined in base objects:", $base_undefined, $dump ); |
| 372 | dump_symbols( "Symbols undefined in required objects:", $req_undefined, $dump ); |
| 373 | }; # if |
| 374 | |
| 375 | return $required; |
| 376 | |
| 377 | }; # sub required_extra_objects |
| 378 | |
| 379 | |
| 380 | # -------------------------------------------------------------------------------------------------- |
| 381 | # Name: |
| 382 | # copy_objects -- Copy (and optionally edit) object files to specified directory. |
| 383 | # Synopsis: |
| 384 | # copy_objects( $objects, $target, $prefix, @symbols ); |
| 385 | # Arguments: |
| 386 | # $objects (in) -- A set of object files. |
| 387 | # $target (in) -- A name of target directory. Directory must exist. |
| 388 | # $prefix (in) -- A prefix to add to all the symbols listed in @symbols. If prefix is undefined, |
| 389 | # object files are just copied. |
| 390 | # @symbols (in) -- List of symbol names to be renamed. |
| 391 | # Returns: |
| 392 | # None. |
| 393 | # |
| 394 | sub copy_objects($$;$\@) { |
| 395 | |
| 396 | my $objects = shift( @_ ); |
| 397 | my $target = shift( @_ ); |
| 398 | my $prefix = shift( @_ ); |
| 399 | my $symbols = shift( @_ ); |
| 400 | my @redefine; |
| 401 | my @redefine_; |
| 402 | my $syms_file = "__kmp_sym_pairs.log"; |
| 403 | |
| 404 | if ( not -e $target ) { |
| 405 | die "\"$target\" directory does not exist\n"; |
| 406 | }; # if |
| 407 | if ( not -d $target ) { |
| 408 | die "\"$target\" is not a directory\n"; |
| 409 | }; # if |
| 410 | |
| 411 | if ( defined( $prefix ) and @$symbols ) { |
| 412 | my %a = map ( ( "$_ $prefix$_" => 1 ), @$symbols ); |
| 413 | @redefine_ = keys( %a ); |
| 414 | }; # if |
| 415 | foreach my $line ( @redefine_ ) { |
| 416 | $line =~ s{$prefix(\W+)}{$1$prefix}; |
| 417 | push( @redefine, $line ); |
| 418 | } |
| 419 | write_file( $syms_file, \@redefine ); |
| 420 | foreach my $src ( sort( keys( %$objects ) ) ) { |
| 421 | my $dst = cat_file( $target, get_file( $src ) ); |
| 422 | if ( @redefine ) { |
| 423 | execute( [ "objcopy", "--redefine-syms", $syms_file, $src, $dst ] ); |
| 424 | } else { |
| 425 | copy_file( $src, $dst, -overwrite => 1 ); |
| 426 | }; # if |
| 427 | }; # foreach $object |
| 428 | |
| 429 | }; # sub copy_objects |
| 430 | |
| 431 | |
| 432 | # -------------------------------------------------------------------------------------------------- |
| 433 | # Main. |
| 434 | # -------------------------------------------------------------------------------------------------- |
| 435 | |
| 436 | my $base = {}; |
| 437 | my $extra = {}; |
| 438 | my $switcher = $base; |
| 439 | my $dump = 0; |
| 440 | my $print_base; |
| 441 | my $print_extra; |
| 442 | my $copy_base; |
| 443 | my $copy_extra; |
| 444 | my $prefix; |
| 445 | |
| 446 | # Parse command line. |
| 447 | |
| 448 | Getopt::Long::Configure( "permute" ); |
| 449 | get_options( |
| 450 | Platform::target_options(), |
| 451 | "base" => sub { $switcher = $base; }, |
| 452 | "extra" => sub { $switcher = $extra; }, |
| 453 | "print-base" => \$print_base, |
| 454 | "print-extra" => \$print_extra, |
| 455 | "print-all" => sub { $print_base = 1; $print_extra = 1; }, |
| 456 | "copy-base=s" => \$copy_base, |
| 457 | "copy-extra=s" => \$copy_extra, |
| 458 | "copy-all=s" => sub { $copy_base = $_[ 1 ]; $copy_extra = $_[ 1 ]; }, |
| 459 | "dump" => sub { ++ $dump; }, |
| 460 | "prefix=s" => \$prefix, |
| 461 | "<>" => |
| 462 | sub { |
| 463 | my $arg = $_[ 0 ]; |
| 464 | my @args; |
| 465 | if ( $^O eq "MSWin32" ) { |
| 466 | # Windows* OS does not expand wildcards. Do it... |
| 467 | @args = bsd_glob( $arg ); |
| 468 | } else { |
| 469 | @args = ( $arg ); |
| 470 | }; # if |
| 471 | foreach my $object ( @args ) { |
| 472 | if ( exists( $base->{ $object } ) or exists( $extra->{ $object } ) ) { |
| 473 | die "Object \"$object\" has already been specified.\n"; |
| 474 | }; # if |
| 475 | $switcher->{ $object } = { defined => [], undefined => [] }; |
| 476 | }; # foreach |
| 477 | }, |
| 478 | ); |
| 479 | if ( not %$base ) { |
| 480 | cmdline_error( "No base objects specified" ); |
| 481 | }; # if |
| 482 | |
| 483 | if ( $target_os eq "win" ) { |
| 484 | *load_symbols = \&_load_symbols_link; |
| 485 | } elsif ( $target_os eq "lin" or $target_os eq "lrb" ) { |
| 486 | *load_symbols = \&_load_symbols_nm; |
| 487 | } elsif ( $target_os eq "mac" ) { |
| 488 | *load_symbols = \&_load_symbols_nm; |
| 489 | } else { |
| 490 | runtime_error( "OS \"$target_os\" not supported" ); |
| 491 | }; # if |
| 492 | |
| 493 | # Do the work. |
| 494 | |
| 495 | my $required = required_extra_objects( $base, $extra, $dump ); |
| 496 | if ( $print_base ) { |
| 497 | print( map( "$_\n", sort( keys( %$base ) ) ) ); |
| 498 | }; # if |
| 499 | if ( $print_extra ) { |
| 500 | print( map( "$_\n", sort( keys( %$required ) ) ) ); |
| 501 | }; # if |
| 502 | my @symbols; |
| 503 | if ( defined( $prefix ) ) { |
| 504 | foreach my $object ( sort( keys( %$required ) ) ) { |
| 505 | push( @symbols, @{ $required->{ $object }->{ defined } } ); |
| 506 | }; # foreach $objects |
| 507 | }; # if |
| 508 | if ( $copy_base ) { |
| 509 | copy_objects( $base, $copy_base, $prefix, @symbols ); |
| 510 | }; # if |
| 511 | if ( $copy_extra ) { |
| 512 | copy_objects( $required, $copy_extra, $prefix, @symbols ); |
| 513 | }; # if |
| 514 | |
| 515 | exit( 0 ); |
| 516 | |
| 517 | __END__ |
| 518 | |
| 519 | =pod |
| 520 | |
| 521 | =head1 NAME |
| 522 | |
| 523 | B<required-objects.pl> -- Select a required extra object files. |
| 524 | |
| 525 | =head1 SYNOPSIS |
| 526 | |
| 527 | B<required-objects.pl> I<option>... [--base] I<file>... --extra I<file>... |
| 528 | |
| 529 | =head1 DESCRIPTION |
| 530 | |
| 531 | B<required-objects.pl> works with two sets of object files -- a set of I<base> objects |
| 532 | and a set of I<extra> objects, and selects those extra objects which are required for resolving |
| 533 | undefined symbols in base objects I<and> selected extra objects. |
| 534 | |
| 535 | Selected object files may be copied to specified location or their names may be printed to stdout, |
| 536 | a name per line. Additionally, symbols defined in selected extra objects may be renamed. |
| 537 | |
| 538 | Depending on OS, different external tools may be used. For example, B<required-objects.pl> uses |
| 539 | F<link.exe> on "win" and F<nm> on "lin" and "mac" OSes. Normally OS is autodetected, but |
| 540 | detection can be overrided with B<--os> option. It may be helpful in cross-build environments. |
| 541 | |
| 542 | =head1 OPTIONS |
| 543 | |
| 544 | =over |
| 545 | |
| 546 | =item B<--base> |
| 547 | |
| 548 | The list of base objects follows this option. |
| 549 | |
| 550 | =item B<--extra> |
| 551 | |
| 552 | List of extra objects follows this option. |
| 553 | |
| 554 | =item B<--print-all> |
| 555 | |
| 556 | Print list of base objects and list of required extra objects. |
| 557 | |
| 558 | =item B<--print-base> |
| 559 | |
| 560 | Print list of base objects. |
| 561 | |
| 562 | =item B<--print-extra> |
| 563 | |
| 564 | Print list of selected extra objects. |
| 565 | |
| 566 | =item B<--copy-all=>I<dir> |
| 567 | |
| 568 | Copy all base and selected extra objects to specified directory. The directory must exist. Existing |
| 569 | files are overwritten. |
| 570 | |
| 571 | =item B<--copy-base=>I<dir> |
| 572 | |
| 573 | Copy all base objects to specified directory. |
| 574 | |
| 575 | =item B<--copy-extra=>I<dir> |
| 576 | |
| 577 | Copy selected extra objects to specified directory. |
| 578 | |
| 579 | =item B<--prefix=>I<str> |
| 580 | |
| 581 | If prefix is specified, copied object files are edited -- symbols defined in selected extra |
| 582 | object files are renamed (in all the copied object files) by adding this prefix. |
| 583 | |
| 584 | F<objcopy> program should be available for performing this operation. |
| 585 | |
| 586 | =item B<--os=>I<str> |
| 587 | |
| 588 | Specify OS name. By default OS is autodetected. |
| 589 | |
| 590 | Depending on OS, B<required-objects.pl> uses different external tools. |
| 591 | |
| 592 | =item B<--help> |
| 593 | |
| 594 | Print short help message and exit. |
| 595 | |
| 596 | =item B<--doc> |
| 597 | |
| 598 | =item B<--manual> |
| 599 | |
| 600 | Print full documentation and exit. |
| 601 | |
| 602 | =item B<--version> |
| 603 | |
| 604 | Print version and exit. |
| 605 | |
| 606 | =back |
| 607 | |
| 608 | =head1 ARGUMENTS |
| 609 | |
| 610 | =over |
| 611 | |
| 612 | =item I<file> |
| 613 | |
| 614 | A name of object file. |
| 615 | |
| 616 | =back |
| 617 | |
| 618 | =head1 EXAMPLES |
| 619 | |
| 620 | $ required-objects.pl --base obj/*.o --extra ../lib/obj/*.o --print-extra > required.lst |
| 621 | $ ar cr libx.a obj/*.o $(cat required.lst) |
| 622 | |
| 623 | $ required-objects.pl --base internal/*.o --extra external/*.o --prefix=__xyz_ --copy-all=obj |
| 624 | $ ar cr xyz.a obj/*.o |
| 625 | |
| 626 | =cut |
| 627 | |
| 628 | # end of file # |
| 629 | |