diff --git a/.github/workflows/BuildPR.yml b/.github/workflows/BuildPR.yml index 784d8b00..3be5d9f2 100644 --- a/.github/workflows/BuildPR.yml +++ b/.github/workflows/BuildPR.yml @@ -48,6 +48,6 @@ jobs: run: | brew unlink openssl@3 # - name: Test project -# run: xcodebuild -workspace ObjectiveGitFramework.xcworkspace -scheme "ObjectiveGit Mac" test ARCHS="${{ matrix.arch }}" +# run: xcodebuild -workspace ObjectiveGitFramework.xcworkspace -scheme "ObjectiveGit Mac" test ARCHS="${{ matrix.abi }}" - name: Archive project - run: xcodebuild -workspace ObjectiveGitFramework.xcworkspace -scheme "ObjectiveGit Mac" archive ARCHS="${{ matrix.arch }}" + run: xcodebuild -workspace ObjectiveGitFramework.xcworkspace -scheme "ObjectiveGit Mac" archive ARCHS="${{ matrix.abi }}" diff --git a/.gitignore b/.gitignore index 8d65cfa6..8b4b6d7f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ objective-git.bridgesupport ObjectiveGitFramework/build/* ObjectiveGit-iOS.framework/* External/*.a +External/*.stamp External/*.dylib *.pbxuser diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index bdfc1d91..ae48de7c 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -1386,6 +1386,7 @@ }; D0A330F116027F2300A616FA /* libgit2 */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -1393,6 +1394,7 @@ ); name = libgit2; outputPaths = ( + "$(SRCROOT)/External/libgit2.a", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/script/update_libgit2 b/script/update_libgit2 index c4c736c2..0495f0e2 100755 --- a/script/update_libgit2 +++ b/script/update_libgit2 @@ -2,7 +2,45 @@ set -e -cd "External/libgit2" +# Resolve the repository root so the script behaves identically whether CI runs +# it from the root or Xcode runs it from $SRCROOT. +script_dir=$(cd "$(dirname "$0")" && pwd) +script_path="$script_dir/$(basename "$0")" +root=$(cd "$script_dir/.." && pwd) +cd "$root" + +submodule="$root/External/libgit2" +archive="$root/External/libgit2.a" +stamp="$root/External/libgit2.a.stamp" + +# A key identifying the archive we would produce. It covers the submodule +# revision, so switching revisions invalidates the archive even when the new +# revision only deletes or renames sources; the submodule working tree, so +# local edits and deletions invalidate it; the host architecture, since the +# archive is built for the host only; and this script, so changing the cmake +# flags invalidates it. If any part of the key cannot be computed we rebuild +# rather than trust an archive we cannot account for. +build_key() { + git -C "$submodule" rev-parse HEAD || return 1 + git -C "$submodule" status --porcelain --untracked-files=all \ + -- . ':(exclude)build' || return 1 + uname -m || return 1 + git hash-object "$script_path" || return 1 +} + +key=$(build_key) || key='' + +if [ -n "$key" ] && [ -f "$archive" ] && [ -f "$stamp" ] && + [ "$key" = "$(cat "$stamp")" ]; then + echo "libgit2 is up to date." + exit 0 +fi + +# Drop the stamp before building: if the build fails or is interrupted, the +# archive left behind must not look up to date on the next run. +rm -f "$stamp" + +cd "$submodule" if [ -d "build" ]; then rm -rf "build" @@ -12,7 +50,7 @@ mkdir build cd build # OpenSSL is keg-only, so add its pkgconfig location manually -if [[ $(uname -m) == 'arm64' ]]; then +if [ "$(uname -m)" = 'arm64' ]; then echo "Running on a Apple Silicon M1" export ARCH_PREFIX=/opt/homebrew else @@ -34,9 +72,13 @@ cmake -DBUILD_SHARED_LIBS:BOOL=OFF \ .. cmake --build . -product="libgit2.a" -install_path="../../${product}" -rm -rf $install_path -cp -v "${product}" "${install_path}" +rm -f "$archive" +cp -v "libgit2.a" "$archive" + +if [ -n "$key" ]; then + printf '%s\n' "$key" > "$stamp" +else + echo "Could not record a libgit2 build stamp; libgit2 will be rebuilt next time." >&2 +fi echo "libgit2 has been updated."