xref: /trunk/main/solenv/bin/modules/macosxotoolhelper.pm (revision 91144cd0085a7583d2099b982122deb2184ab956)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22
23
24package macosxotoolhelper;
25require Exporter;
26our @ISA = Exporter;
27our @EXPORT = otoolD;
28
29use File::Basename;
30$::CC_PATH=(fileparse( $ENV{"CC"}))[1];
31
32sub otoolD($) {
33    my ($file) = @_;
34    my $call = "otool -D $file";
35    open(IN, "-|", $call) or die "cannot $call";
36    my @lines = <IN>;
37    close(IN);
38
39    # A fat/universal binary (e.g. a Homebrew-installed library bundling
40    # x86_64 and arm64 slices) makes otool -D print one
41    # "<path> (architecture <arch>):" stanza per slice instead of the
42    # single "<path>:" header a thin binary gets. Every slice of the same
43    # library reports the same install name, so take it from the first
44    # stanza and ignore the rest.
45    #
46    # A slice with no install name (e.g. a loadable module/bundle, such as
47    # a PKCS#11 provider that is only ever dlopen()ed) prints its header
48    # with nothing after it -- callers rely on getting undef back for that
49    # case, same as otool -D on a thin file with no install name.
50    my $header_re = qr/^\Q$file\E(?: \(architecture [^)]+\))?:\n$/;
51    my @names;
52    my $i = 0;
53    while ($i < @lines) {
54        $lines[$i] =~ $header_re or
55            die "unexpected otool -D output (\"$lines[$i]\", expecting \"$file:\")";
56        ++$i;
57        if ($i < @lines && $lines[$i] !~ $header_re) {
58            push @names, $lines[$i];
59            ++$i;
60        }
61    }
62    return undef unless @names;
63    grep($_ ne $names[0], @names) and
64        die "otool -D reported differing install names across architectures for $file";
65    return $names[0];
66}
67