File: find_common_syms

package info (click to toggle)
openmpi 5.0.8-4
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 201,684 kB
  • sloc: ansic: 613,078; makefile: 42,353; sh: 11,194; javascript: 9,244; f90: 7,052; java: 6,404; perl: 5,179; python: 1,859; lex: 740; fortran: 61; cpp: 20; tcl: 12
file content (144 lines) | stat: -rwxr-xr-x 4,115 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env perl
# Copyright (c) 2006-2016 Cisco Systems, Inc.  All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#

# Common symbols cause linking issues on some platforms, including OS X.  See
# this issue for more background:
#   https://github.com/open-mpi/ompi/issues/375

use strict;
use warnings;

use Getopt::Long;
use File::Basename qw(basename);

sub is_whitelisted;

my $MAX_BRIEF = 10;

my @orig_argv = @ARGV;
my @sym_whitelist = ();

sub usage {
    print STDERR <<EOT;
Usage: $0 --top_builddir=BUILDDIR --top_srcdir=SRCDIR [--objext=OBJEXT] [--brief] [--full-path]

Searches for all ".OBJEXT" files in BUILDDIR and checks for the existence of
common symbols.  Common symbols are problematic for some platforms, including
OS X.

OBJEXT defaults to 'o' if not specified.
EOT
    exit 1;
}

my $all = 0;
my $brief = 0;
my $objext = 'o';
my $top_builddir = '';
my $top_srcdir = '';
my $print_full_obj_path = 0;
GetOptions(
    "all!" => \$all,
    "brief!" => \$brief,
    "full-path!" => \$print_full_obj_path,
    "objext=s" => \$objext,
    "top_builddir=s" => \$top_builddir,
    "top_srcdir=s" => \$top_srcdir,
) || usage();

if (!$top_builddir or !$top_srcdir) {
    usage();
}

if (0 != system("command -v nm >/dev/null 2>&1")) {
    print STDERR "NOTE: nm not found, skipping common symbol check\n";
    # Makefile usage should prefix this command with "-" to ignore this exit status
    exit 1;
}

# load the common symbol whitelist from files scattered around the codebase
#
# It would be better to load these into some sort of tree and then have those
# whitelists only apply to objects that are found in the same directory or
# subdirectories.  That way a whitelisted symbol in one component doesn't
# "shadow" a symbol that should not be whitelisted in another component.  If we
# find this is actually a problem in practice then we can write a v2 update.
my @wl_files = `find '${top_srcdir}' -name 'common_sym_whitelist.txt'`;
foreach my $wl_file (@wl_files) {
    chomp $wl_file;
    my @lines = `cat $wl_file`;
    foreach my $line (@lines) {
        chomp $line;
        next if ($line =~ /^\s*#/); # skip comments
        next if ($line =~ /^\s*$/); # skip blank lines
        push @sym_whitelist, $line;
    }
}

my $n = 0;
open(FIND, '-|', "find ${top_builddir} -name '*.${objext}'");
OBJECT: while (my $obj_line = <FIND>) {
    my $obj = $obj_line;
    chomp $obj;

    # This pattern may not be 100% robust for all implementations of nm.  If
    # that turns out to be the case, we can try switching to "nm -P", which is
    # supposed to activate the "portable" (yet ugly) format.  It's also unclear
    # at this point how common support for "nm -P" is.
    open(NM, '-|', "nm '${obj}' 2>/dev/null | egrep '\\s[cC]\\s'");
    SYMBOL: while (my $sym_line = <NM>) {
        if (!$all and is_whitelisted($sym_line)) {
            next SYMBOL;
        }

        if ($n == 0) {
            print STDERR "WARNING!  Common symbols found:\n";
        }
        if ($brief and $n == $MAX_BRIEF) {
            print STDERR "[...]\n";
            print STDERR "skipping remaining symbols. To see all symbols, run:\n";
            print STDERR "  " . join(" ", ($0, grep {!/--brief/} @orig_argv)) . "\n";
            last OBJECT;
        }
        if ($print_full_obj_path) {
            print STDERR "$obj: $sym_line";
        } else {
            my $obj_basename = basename($obj);
            printf STDERR "%25s: %s", $obj_basename, $sym_line;
        }
        ++$n;
    }
    close(NM);
}
close(FIND);

if ($n > 0) {
    exit 1;
} else {
    exit 0;
}

sub is_whitelisted {
    my $line = shift;

    foreach my $wl_sym (@sym_whitelist) {
        if ($line =~ m/\b_?\Q$wl_sym\E\b/) {
            return 1;
        }
    }

    # Look for symbol names ending in one or more underscores and assume they
    # are "Fortran-shaped".  This won't match the hex output from most nm's and
    # shouldn't match the single characters that indicate symbol type.
    if ($line =~ m/\b_?[A-Za-z_]+[A-Za-z0-9_]*_+\b/) {
        return 1;
    }

    return 0;
}