Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 84 additions & 26 deletions script/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ main() {

if [ -n "$REQUIRED_TOOLS" ]; then
echo "** Checking dependencies in Homebrew ..."
check_deps
if [ -n "$UNIVERSAL_BUILD" ]; then
check_deps_universal
else
check_deps
fi
fi
}

Expand Down Expand Up @@ -60,27 +64,8 @@ check_deps() {
export expected_prefix=/usr/local
fi

# Ensure that we have libgit2's dependencies installed.
installed=$(brew list)

for tool in $REQUIRED_TOOLS; do
# Skip packages that are already installed.
echo "$installed" | grep -q "$tool" && code=$? || code=$?

if [ "$code" -eq "0" ]; then
echo "*** $tool is available 👍"
continue
elif [ "$code" -ne "1" ]; then
exit $code
fi

echo "*** Installing $tool with Homebrew..."
brew install "$tool"
done

install_path="./External"
echo "*** copy "$brew_prefix"/lib/libssh2.a to $install_path"
cp "$brew_prefix"/lib/libssh2.a $install_path
install_tools "$brew_prefix"
stage_deps "$brew_prefix" "./External"

if [ "$brew_prefix" != "$expected_prefix" ]; then
echo "*** Adding soft links into $expected_prefix..."
Expand All @@ -97,12 +82,85 @@ check_deps() {
sudo ln -s "$brew_prefix/$product" "$destination"
done
fi
}

# Builds a universal libcrypto.a/libssh2.a by lipo-ing together the arm64
# Homebrew install at /opt/homebrew with an x86_64 (Rosetta) Homebrew install
# at /usr/local. Both installs, and the tools under each, are expected to
# already exist -- setting them up is the CI workflow's job, not this
# script's, since it means bootstrapping a second Homebrew prefix.
check_deps_universal() {
local arm64_prefix=/opt/homebrew
local x86_64_prefix=/usr/local

for prefix in "$arm64_prefix" "$x86_64_prefix"; do
if [ ! -x "$prefix/bin/brew" ]; then
echo "UNIVERSAL_BUILD requires a Homebrew install at $prefix; none found." >&2
exit 1
fi
done

install_tools "$arm64_prefix"
install_tools "$x86_64_prefix" arch -x86_64

local staging="./External/universal-deps"
rm -rf "$staging"
mkdir -p "$staging/arm64" "$staging/x86_64"

stage_deps "$arm64_prefix" "$staging/arm64"
stage_deps "$x86_64_prefix" "$staging/x86_64"

echo "*** Combining arm64 + x86_64 libssh2.a and libcrypto.a into universal libraries"
for lib in libssh2.a libcrypto.a; do
lipo -create \
"$staging/arm64/$lib" \
"$staging/x86_64/$lib" \
-output "./External/$lib"
done

rm -rf "$staging"
ls -la ./External
}

# install_tools <brew_prefix> [command prefix to run brew under, e.g. `arch -x86_64`]
install_tools() {
local prefix="$1"
shift
local run=("$@" "$prefix/bin/brew")

local installed
installed=$("${run[@]}" list)

for tool in $REQUIRED_TOOLS; do
echo "$installed" | grep -q "$tool" && code=$? || code=$?

if [ "$code" -eq "0" ]; then
echo "*** $tool is available under $prefix 👍"
continue
elif [ "$code" -ne "1" ]; then
exit $code
fi

echo "*** Installing $tool under $prefix with Homebrew..."
"${run[@]}" install "$tool"
done
}

# stage_deps <brew_prefix> <destination dir> - copies that prefix's
# libssh2.a/libcrypto.a into destination, for either direct use (single-arch)
# or as lipo input (universal).
stage_deps() {
local prefix="$1"
local destination="$2"

echo "*** copy $prefix/lib/libssh2.a to $destination"
cp "$prefix/lib/libssh2.a" "$destination"

# openssl@1 is expected
sslSource=$(find $brew_prefix -name libcrypto.a | grep openssl | sort | head -1 | xargs dirname)
echo "Find libcrypto.a and take first $sslSource and copy to $install_path"
cp $sslSource/* $install_path 2>/dev/null | echo "Copy and ignore subdirectory. This makes build work on x86 and arm64"
ls -la $install_path
local sslSource
sslSource=$(find "$prefix" -name libcrypto.a | grep openssl | sort | head -1 | xargs dirname)
echo "Find libcrypto.a and take first $sslSource and copy to $destination"
cp $sslSource/* "$destination" 2>/dev/null | echo "Copy and ignore subdirectory. This makes build work on x86 and arm64"
}

main
112 changes: 80 additions & 32 deletions script/update_libgit2
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,87 @@ set -e

cd "External/libgit2"

if [ -d "build" ]; then
rm -rf "build"
fi
build_arch() {
arch_name="$1"
arch_prefix="$2"
runner="$3" # e.g. `arch -x86_64`, or empty for native

build_dir="build-$arch_name"
rm -rf "$build_dir"
mkdir "$build_dir"
cd "$build_dir"

export PKG_CONFIG_PATH="$arch_prefix/opt/openssl/lib/pkgconfig:$arch_prefix/lib/pkgconfig"

# augment path to help it find cmake installed in /usr/local/bin,
# e.g. via brew. Xcode's Run Script phase doesn't seem to honor
# ~/.MacOSX/environment.plist
PATH="$arch_prefix/bin:$PATH"

$runner cmake --version
$runner cmake -DBUILD_SHARED_LIBS:BOOL=OFF \
-DBUILD_CLAR:BOOL=OFF \
-DTHREADSAFE:BOOL=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_OSX_ARCHITECTURES="$arch_name" \
..
$runner cmake --build .

cd ..
}

if [ -n "$UNIVERSAL_BUILD" ]; then
# Requires a native arm64 Homebrew at /opt/homebrew and an x86_64 (Rosetta)
# Homebrew at /usr/local, each with openssl installed -- see script/bootstrap.
build_arch arm64 /opt/homebrew ""
build_arch x86_64 /usr/local "arch -x86_64"

mkdir build
cd build
product="libgit2.a"
install_path="../../${product}"
rm -rf "$install_path"
lipo -create \
"build-arm64/${product}" \
"build-x86_64/${product}" \
-output "$install_path"

# OpenSSL is keg-only, so add its pkgconfig location manually
if [[ $(uname -m) == 'arm64' ]]; then
echo "Running on a Apple Silicon M1"
export ARCH_PREFIX=/opt/homebrew
rm -rf build-arm64 build-x86_64

echo "Universal libgit2 has been updated."
else
echo "Running on a Apple x86"
export ARCH_PREFIX=/usr/local
if [ -d "build" ]; then
rm -rf "build"
fi

mkdir build
cd build

# OpenSSL is keg-only, so add its pkgconfig location manually
if [[ $(uname -m) == 'arm64' ]]; then
echo "Running on a Apple Silicon M1"
export ARCH_PREFIX=/opt/homebrew
else
echo "Running on a Apple x86"
export ARCH_PREFIX=/usr/local
fi
export PKG_CONFIG_PATH=$ARCH_PREFIX/opt/openssl/lib/pkgconfig:$ARCH_PREFIX/lib/pkgconfig

# augment path to help it find cmake installed in /usr/local/bin,
# e.g. via brew. Xcode's Run Script phase doesn't seem to honor
# ~/.MacOSX/environment.plist
PATH="$ARCH_PREFIX/bin:$PATH"

cmake --version
cmake -DBUILD_SHARED_LIBS:BOOL=OFF \
-DBUILD_CLAR:BOOL=OFF \
-DTHREADSAFE:BOOL=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
..
cmake --build .

product="libgit2.a"
install_path="../../${product}"
rm -rf $install_path
cp -v "${product}" "${install_path}"

echo "libgit2 has been updated."
fi
export PKG_CONFIG_PATH=$ARCH_PREFIX/opt/openssl/lib/pkgconfig:$ARCH_PREFIX/lib/pkgconfig

# augment path to help it find cmake installed in /usr/local/bin,
# e.g. via brew. Xcode's Run Script phase doesn't seem to honor
# ~/.MacOSX/environment.plist
PATH="$ARCH_PREFIX/bin:$PATH"

cmake --version
cmake -DBUILD_SHARED_LIBS:BOOL=OFF \
-DBUILD_CLAR:BOOL=OFF \
-DTHREADSAFE:BOOL=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
..
cmake --build .

product="libgit2.a"
install_path="../../${product}"
rm -rf $install_path
cp -v "${product}" "${install_path}"

echo "libgit2 has been updated."