1
1
#! /bin/sh
2
2
# This file is a part of Julia. License is MIT: https://julialang.org/license
3
3
4
- # Run as: fixup-libgfortran.sh <$private_libdir>
4
+ # Run as: fixup-libgfortran.sh [--verbose] <$private_libdir>
5
+
6
+ # If we're invoked with "--verbose", create a `debug` function that prints stuff out
7
+ if [ " $1 " == " --verbose" ] || [ " $1 " == " -v" ]; then
8
+ shift 1
9
+ debug () { echo " $* " ; }
10
+ else
11
+ debug () { : ; }
12
+ fi
5
13
6
14
if [ -z " $1 " ]; then
7
15
echo " Usage: $0 <private_libdir>"
@@ -14,7 +22,7 @@ if [ "$UNAME" = "Linux" ]; then
14
22
elif [ " $UNAME " = " Darwin" ]; then
15
23
SHLIB_EXT=" dylib"
16
24
else
17
- echo " WARNING: Could not autodetect platform type ('uname -s' == $UNAME ); assuming Linux"
25
+ echo " WARNING: Could not autodetect platform type ('uname -s' == $UNAME ); assuming Linux" >&2
18
26
UNAME=" Linux"
19
27
SHLIB_EXT=" so"
20
28
fi
@@ -26,27 +34,34 @@ if [ ! -f "$private_libdir/libarpack.$SHLIB_EXT" ]; then
26
34
exit 2
27
35
fi
28
36
29
- find_shlib ()
37
+ find_shlib ()
30
38
{
31
- if [ -f " $private_libdir /lib$1 .$SHLIB_EXT " ]; then
39
+ lib_path=" $1 "
40
+ if [ -f " $lib_path " ]; then
32
41
if [ " $UNAME " = " Linux" ]; then
33
- ldd " $private_libdir /lib $1 . $SHLIB_EXT " | grep $2 | cut -d' ' -f3 | xargs
42
+ ldd " $lib_path " | grep $2 | cut -d' ' -f3 | xargs
34
43
else # $UNAME is "Darwin", we only have two options, see above
35
- otool -L " $private_libdir /lib $1 . $SHLIB_EXT " | grep $2 | cut -d' ' -f1 | xargs
44
+ otool -L " $lib_path " | grep $2 | cut -d' ' -f1 | xargs
36
45
fi
37
46
fi
38
47
}
39
48
49
+ private_libname ()
50
+ {
51
+ echo " $private_libdir /lib$1 .$SHLIB_EXT "
52
+ }
53
+
40
54
# First, discover all the places where libgfortran/libgcc is, as well as their true SONAMES
41
55
for lib in arpack openspecfun lapack; do
42
56
if [ -f " $private_libdir /lib$lib .$SHLIB_EXT " ]; then
43
57
# Find the paths to the libraries we're interested in. These are almost
44
58
# always within the same directory, but we like to be general.
45
- LIBGFORTRAN_PATH=$( find_shlib $ lib libgfortran)
46
- LIBGCC_PATH=$( find_shlib $ lib libgcc_s)
47
- LIBQUADMATH_PATH=$( find_shlib $ lib libquadmath)
59
+ LIBGFORTRAN_PATH=$( find_shlib " $( private_libname $ lib) " libgfortran)
60
+ LIBGCC_PATH=$( find_shlib " $( private_libname $ lib) " libgcc_s)
61
+ LIBQUADMATH_PATH=$( find_shlib " $( private_libname $ lib) " libquadmath)
48
62
49
- # Take the directories, add them onto LIBGFORTRAN_DIRS to search for things later
63
+ # Take the directories, add them onto LIBGFORTRAN_DIRS, which we use to
64
+ # search for these libraries in the future.
50
65
LIBGFORTRAN_DIRS=" $LIBGFORTRAN_DIRS $( dirname $LIBGFORTRAN_PATH ) "
51
66
LIBGFORTRAN_DIRS=" $LIBGFORTRAN_DIRS $( dirname $LIBGCC_PATH ) "
52
67
LIBGFORTRAN_DIRS=" $LIBGFORTRAN_DIRS $( dirname $LIBQUADMATH_PATH ) "
@@ -66,6 +81,8 @@ uniquify()
66
81
67
82
LIBGFORTRAN_DIRS=$( uniquify " $LIBGFORTRAN_DIRS " )
68
83
SONAMES=" $( uniquify " $LIBGFORTRAN_SONAMES $LIBGCC_SONAMES $LIBQUADMATH_SONAMES " ) "
84
+ debug " Discovered traces of libgfortran within $LIBGFORTRAN_DIRS "
85
+ debug " Got SONAMES of $SONAMES "
69
86
70
87
# Copy the SONAMEs we identified above into our private_libdir
71
88
for soname in $SONAMES ; do
@@ -78,48 +95,48 @@ for soname in $SONAMES; do
78
95
fi
79
96
fi
80
97
done
81
-
82
- # Add possible internal directories to LIBGFORTRAN_DIRS so that we can find all possible ways
83
- # That any of our libraries or these libraries we just copied in link to themselves later.
84
- if [ -f " $private_libdir /$soname " ]; then
85
- LIBGFORTRAN_DIRS=" $LIBGFORTRAN_DIRS $( dirname $( find_shlib $lib libgfortran) ) "
86
- LIBGFORTRAN_DIRS=" $LIBGFORTRAN_DIRS $( dirname $( find_shlib $lib libgcc_s) ) "
87
- LIBGFORTRAN_DIRS=" $LIBGFORTRAN_DIRS $( dirname $( find_shlib $lib libquadmath) ) "
88
- fi
89
98
done
90
99
91
-
100
+ # On OSX, we need to change the old link (which is usually a full path)
101
+ # to point to `@rpath/${soname}` explicitly, so we use `find_shlib()`
102
+ # to dynamically find the full path we want to change. On Linux, we
103
+ # don't care about full paths, we just set the rpath to `$ORIGIN`.
92
104
change_linkage ()
93
105
{
94
- shlib_path=" $1 "
95
- old_link=" $2 "
96
- new_link=" $3 "
106
+ # This is the path of the library we want to edit
107
+ lib_path=" $1 "
108
+
109
+ # If it doesn't exist, exit quietly
110
+ if [ ! -f " $lib_path " ]; then
111
+ debug " $lib_path doesn't exist, skipping"
112
+ return
113
+ fi
114
+
115
+ # This is the soname of the dependency we want to swap out
116
+ soname=" $2 "
117
+
97
118
if [ " $UNAME " = " Darwin" ]; then
98
- install_name_tool -change " $old_link " " $new_link " " $shlib_path "
119
+ old_link=$( find_shlib " $lib_path " " $soname " )
120
+ echo " $old_link "
121
+ install_name_tool -change " $old_link " " @rpath/$soname " " $lib_path "
99
122
else # $UNAME is "Linux", we only have two options, see above
100
- patchelf --set-rpath \$ ORIGIN " $shlib_path "
123
+ patchelf --set-rpath \$ ORIGIN " $lib_path "
101
124
fi
102
125
}
103
126
104
- LIBGFORTRAN_DIRS=$( uniquify " $LIBGFORTRAN_DIRS " )
105
- echo " Found traces of libgfortran/libgcc in $LIBGFORTRAN_DIRS "
106
-
107
- # For every library that remotely touches libgfortran stuff (so the libraries
108
- # we have copied in ourselves as well as arpack, openspecfun, etc...) we must
127
+ # For every library that remotely touches libgfortran stuff (the libraries we
128
+ # have copied in ourselves as well as arpack, openspecfun, etc...) we must
109
129
# update the linkage to point to @rpath (on OSX) or $ORIGIN (on Linux) so
110
130
# that direct links to the old libgfortran directories are instead directed
111
131
# to the proper location, which is our $private_libdir.
112
- cd $private_libdir
113
-
114
- # Iterate over possible library names
115
- for soname in libopenblas libarpack libcholmod liblapack libopenspecfun $SONAMES ; do
132
+ for lib in libopenblas libarpack libcholmod liblapack libopenspecfun $SONAMES ; do
116
133
# Grab every incarnation of that library that exists within $private_libdir
117
134
# (e.g. "libopenspecfun.so", and "libopenspecfun.so.0", etc...)
118
- for lib in $private_libdir /$soname * . $SHLIB_EXT * ; do
119
- # Look for links to any of the our three musketeers within ANY of the
120
- # potential LIBGFORTRAN_DIRS we've discovered so far
121
- for dir in $LIBGFORTRAN_DIRS ; do
122
- change_linkage " $lib " " $dir / $soname " " @rpath/ $soname "
135
+ for lib_path in $private_libdir /$lib * ; do
136
+ # Iterate over dependency names that need to be changed
137
+ for soname in $SONAMES ; do
138
+ debug " changing linkage of $lib_path to $soname "
139
+ change_linkage " $lib_path " " $soname "
123
140
done
124
141
done
125
142
done
0 commit comments