{"thread":{"id":"65595","subject":"[PATCH] Makefile: link osxkeychain helper against Rust","startedAt":"2026-05-05T17:26:19Z","lastAt":"2026-07-08T20:16:05Z","messageCount":46,"participants":["Shardul Natu via GitGitGadget","Kristoffer Haugsbakk","Shnatu","Junio C Hamano","Koji Nakamaru","Patrick Steinhardt","Shardul Natu","Ben Knoble"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"542764","messageId":"pull.2288.git.git.1778001976709.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":null,"subject":"[PATCH] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-05-05T17:26:16Z","receivedAt":"2026-05-05T17:26:19Z","isPatch":true,"body":"From: Shnatu <snatu@google.com>\n\nWhen Rust is enabled, ensure that the git-credential-osxkeychain\nhelper is linked with the necessary Rust libraries.\n\nIntroduce the RUST_LIBS variable inside ifndef NO_RUST block\nto hold the Rust library dependency, and use it in the helper's\nbuild target. This cleanly handles cases where Rust is disabled,\nmaking it a no-op and avoiding any build failures on systems\nwithout Cargo.\n\nThis addresses reviewer feedback from internal CL 910223487\nby simplifying the variables and avoiding confusing \"LINK\"\nterminology.\n\nSigned-off-by: Shnatu <snatu@google.com>\n---\n    Makefile: link osxkeychain helper against Rust\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v1\nPull-Request: https://github.com/git/git/pull/2288\n\n Makefile | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex f86173f93a..a17dca22b1 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1593,6 +1593,7 @@ ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n ifndef NO_RUST\n BASIC_CFLAGS += -DWITH_RUST\n GITLIBS += $(RUST_LIB)\n+RUST_LIBS = $(RUST_LIB)\n ifeq ($(uname_S),Windows)\n EXTLIBS += -luserenv\n endif\n@@ -4082,9 +4083,9 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIBS) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n-\t\t$(filter %.o,$^) $(LIB_FILE) $(EXTLIBS) -framework Security -framework CoreFoundation\n+\t\t$(filter %.o,$^) $(LIB_FILE) $(RUST_LIBS) $(EXTLIBS) -framework Security -framework CoreFoundation\n \n contrib/credential/osxkeychain/git-credential-osxkeychain.o: contrib/credential/osxkeychain/git-credential-osxkeychain.c GIT-CFLAGS\n \t$(QUIET_LINK)$(CC) -o $@ -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<\n\nbase-commit: 4f69b47b940100b02630f745a52f9d9850f122b2\n-- \ngitgitgadget\n"},{"id":"542766","messageId":"a9e71e67-a853-4cfb-beb8-69b98ead720e@app.fastmail.com","threadId":"65595","inReplyTo":"pull.2288.git.git.1778001976709.gitgitgadget@gmail.com","subject":"Re: [PATCH] Makefile: link osxkeychain helper against Rust","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-05-05T19:08:12Z","receivedAt":"2026-05-05T19:08:35Z","isPatch":true,"body":"On Tue, May 5, 2026, at 19:26, Shardul Natu via GitGitGadget wrote:\n> From: Shnatu <snatu@google.com>\n>\n> When Rust is enabled, ensure that the git-credential-osxkeychain\n> helper is linked with the necessary Rust libraries.\n>\n> Introduce the RUST_LIBS variable inside ifndef NO_RUST block\n> to hold the Rust library dependency, and use it in the helper's\n> build target. This cleanly handles cases where Rust is disabled,\n> making it a no-op and avoiding any build failures on systems\n> without Cargo.\n>\n> This addresses reviewer feedback from internal CL 910223487\n> by simplifying the variables and avoiding confusing \"LINK\"\n> terminology.\n\nThis pararagraph is meaningless to those outside internal.\n\n>\n> Signed-off-by: Shnatu <snatu@google.com>\n> ---\n>[snip]\n"},{"id":"542829","messageId":"20260507003927.2739334-1-snatu@google.com","threadId":"65595","inReplyTo":"a9e71e67-a853-4cfb-beb8-69b98ead720e@app.fastmail.com","subject":"Re: [PATCH] Makefile: link osxkeychain helper against Rust","fromName":"Shnatu","fromEmail":"snatu@google.com","sentAt":"2026-05-07T00:39:27Z","receivedAt":"2026-05-07T00:39:29Z","isPatch":true,"body":"I have remove the Google specific paragraph, in addition to updating the description\n"},{"id":"542884","messageId":"xmqqlddufw5d.fsf@gitster.g","threadId":"65595","inReplyTo":"pull.2288.git.git.1778001976709.gitgitgadget@gmail.com","subject":"Re: [PATCH] Makefile: link osxkeychain helper against Rust","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-08T02:54:54Z","receivedAt":"2026-05-08T02:54:56Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Shnatu <snatu@google.com>\n\nIf your name is \"Shardul Natu\", we'd prefer (not 'require', but\n'prefer') that the patches authored by you also identify with that\nname, both on \"From:\" and \"Signed-off-by:\"..\n\n> When Rust is enabled, ensure that the git-credential-osxkeychain\n> helper is linked with the necessary Rust libraries.\n>\n> Introduce the RUST_LIBS variable inside ifndef NO_RUST block\n> to hold the Rust library dependency, and use it in the helper's\n> build target. This cleanly handles cases where Rust is disabled,\n> making it a no-op and avoiding any build failures on systems\n> without Cargo.\n>\n> This addresses reviewer feedback from internal CL 910223487\n> by simplifying the variables and avoiding confusing \"LINK\"\n> terminology.\n>\n> Signed-off-by: Shnatu <snatu@google.com>\n> ---\n>     Makefile: link osxkeychain helper against Rust\n\nThanks.  I've added to CC: a few folks who may be more clueful in\nthe affected area than I am.  It somehow feels strange that we have\nto have RUST_LIB and RUST_LIBS separately, and apparently with the\nnew definition the latter is expected to be a superset of the\nformer, and it is unclear what are the things that should be added\nto the latter without getting added to the former.\n\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v1\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v1\n> Pull-Request: https://github.com/git/git/pull/2288\n>\n>  Makefile | 5 +++--\n>  1 file changed, 3 insertions(+), 2 deletions(-)\n>\n> diff --git a/Makefile b/Makefile\n> index f86173f93a..a17dca22b1 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -1593,6 +1593,7 @@ ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n>  ifndef NO_RUST\n>  BASIC_CFLAGS += -DWITH_RUST\n>  GITLIBS += $(RUST_LIB)\n> +RUST_LIBS = $(RUST_LIB)\n>  ifeq ($(uname_S),Windows)\n>  EXTLIBS += -luserenv\n>  endif\n> @@ -4082,9 +4083,9 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n>  contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n>  \t$(AR) $(ARFLAGS) $@ $^\n>  \n> -contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n> +contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIBS) GIT-LDFLAGS\n>  \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n> -\t\t$(filter %.o,$^) $(LIB_FILE) $(EXTLIBS) -framework Security -framework CoreFoundation\n> +\t\t$(filter %.o,$^) $(LIB_FILE) $(RUST_LIBS) $(EXTLIBS) -framework Security -framework CoreFoundation\n>  \n>  contrib/credential/osxkeychain/git-credential-osxkeychain.o: contrib/credential/osxkeychain/git-credential-osxkeychain.c GIT-CFLAGS\n>  \t$(QUIET_LINK)$(CC) -o $@ -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<\n>\n> base-commit: 4f69b47b940100b02630f745a52f9d9850f122b2\n"},{"id":"542902","messageId":"CAOTNsDyygMEz4dgfkWKb=wWP0g9MhNFgDHzPPEODbMGmDQLTOQ@mail.gmail.com","threadId":"65595","inReplyTo":"xmqqlddufw5d.fsf@gitster.g","subject":"Re: [PATCH] Makefile: link osxkeychain helper against Rust","fromName":"Koji Nakamaru","fromEmail":"koji.nakamaru@gree.net","sentAt":"2026-05-08T09:33:04Z","receivedAt":"2026-05-08T09:33:17Z","isPatch":true,"body":"On Fri, May 8, 2026 at 11:54 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > From: Shnatu <snatu@google.com>\n>\n> If your name is \"Shardul Natu\", we'd prefer (not 'require', but\n> 'prefer') that the patches authored by you also identify with that\n> name, both on \"From:\" and \"Signed-off-by:\"..\n>\n> > When Rust is enabled, ensure that the git-credential-osxkeychain\n> > helper is linked with the necessary Rust libraries.\n> >\n> > Introduce the RUST_LIBS variable inside ifndef NO_RUST block\n> > to hold the Rust library dependency, and use it in the helper's\n> > build target. This cleanly handles cases where Rust is disabled,\n> > making it a no-op and avoiding any build failures on systems\n> > without Cargo.\n> >\n> > This addresses reviewer feedback from internal CL 910223487\n> > by simplifying the variables and avoiding confusing \"LINK\"\n> > terminology.\n> >\n> > Signed-off-by: Shnatu <snatu@google.com>\n> > ---\n> >     Makefile: link osxkeychain helper against Rust\n>\n> Thanks.  I've added to CC: a few folks who may be more clueful in\n> the affected area than I am.  It somehow feels strange that we have\n> to have RUST_LIB and RUST_LIBS separately, and apparently with the\n> new definition the latter is expected to be a superset of the\n> former, and it is unclear what are the things that should be added\n> to the latter without getting added to the former.\n>\n> > Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v1\n> > Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v1\n> > Pull-Request: https://github.com/git/git/pull/2288\n> >\n> >  Makefile | 5 +++--\n> >  1 file changed, 3 insertions(+), 2 deletions(-)\n> >\n> > diff --git a/Makefile b/Makefile\n> > index f86173f93a..a17dca22b1 100644\n> > --- a/Makefile\n> > +++ b/Makefile\n> > @@ -1593,6 +1593,7 @@ ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n> >  ifndef NO_RUST\n> >  BASIC_CFLAGS += -DWITH_RUST\n> >  GITLIBS += $(RUST_LIB)\n> > +RUST_LIBS = $(RUST_LIB)\n> >  ifeq ($(uname_S),Windows)\n> >  EXTLIBS += -luserenv\n> >  endif\n> > @@ -4082,9 +4083,9 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n> >  contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n> >       $(AR) $(ARFLAGS) $@ $^\n> >\n> > -contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n> > +contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIBS) GIT-LDFLAGS\n> >       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n> > -             $(filter %.o,$^) $(LIB_FILE) $(EXTLIBS) -framework Security -framework CoreFoundation\n> > +             $(filter %.o,$^) $(LIB_FILE) $(RUST_LIBS) $(EXTLIBS) -framework Security -framework CoreFoundation\n> >\n> >  contrib/credential/osxkeychain/git-credential-osxkeychain.o: contrib/credential/osxkeychain/git-credential-osxkeychain.c GIT-CFLAGS\n> >       $(QUIET_LINK)$(CC) -o $@ -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<\n> >\n> > base-commit: 4f69b47b940100b02630f745a52f9d9850f122b2\n\nHow about simply wrapping the RUST_LIB-related sections in ifndef\nNO_RUST, as shown below? This way, we can avoid defining\nRUST_LIBS.\n\ndiff --git a/Makefile b/Makefile\nindex f86173f93a..daa1691950 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -947,11 +947,13 @@ else\n RUST_TARGET_DIR = target/release\n endif\n\n+ifndef NO_RUST\n ifeq ($(uname_S),Windows)\n RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n\n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3027,11 +3029,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n        $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n\n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n        $(QUIET_CARGO)cargo build $(CARGO_ARGS)\n\n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n\n export DEFAULT_EDITOR DEFAULT_PAGER\n\n@@ -4082,9 +4086,9 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n        $(AR) $(ARFLAGS) $@ $^\n\n-contrib/credential/osxkeychain/git-credential-osxkeychain:\ncontrib/credential/osxkeychain/git-credential-osxkeychain.o\n$(LIB_FILE) GIT-LDFLAGS\n+contrib/credential/osxkeychain/git-credential-osxkeychain:\ncontrib/credential/osxkeychain/git-credential-osxkeychain.o\n$(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n-               $(filter %.o,$^) $(LIB_FILE) $(EXTLIBS) -framework\nSecurity -framework CoreFoundation\n+               $(filter %.o,$^) $(LIB_FILE) $(RUST_LIB) $(EXTLIBS)\n-framework Security -framework CoreFoundation\n\n contrib/credential/osxkeychain/git-credential-osxkeychain.o:\ncontrib/credential/osxkeychain/git-credential-osxkeychain.c GIT-CFLAGS\n        $(QUIET_LINK)$(CC) -o $@ -c $(dep_args) $(compdb_args)\n$(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<\n"},{"id":"542928","messageId":"20260508174451.606855-1-snatu@google.com","threadId":"65595","inReplyTo":"CAOTNsDyygMEz4dgfkWKb=wWP0g9MhNFgDHzPPEODbMGmDQLTOQ@mail.gmail.com","subject":"Re: [PATCH] Makefile: link osxkeychain helper against Rust","fromName":"Shnatu","fromEmail":"snatu@google.com","sentAt":"2026-05-08T17:44:51Z","receivedAt":"2026-05-08T17:44:53Z","isPatch":true,"body":"Thank you for the suggestion! This is indeed a much cleaner approach.\n\nBy wrapping `RUST_LIB` and the rust targets in `ifndef NO_RUST`, we can link `git-credential-osxkeychain` directly against `$(RUST_LIB)` without needing to introduce an intermediate `RUST_LIBS` variable. When `NO_RUST` is defined, `$(RUST_LIB)` evaluates to empty, and Make naturally links it as a pure C binary without any Rust dependencies.\n\nTo integrate this with the universal build support (`RUST_TARGETS`/`lipo`) introduced in this PR, I have updated the changes to:\n\n- Wrap the `RUST_LIB` definition block (which resolves target-specific paths for universal builds) in ifndef `NO_RUST`.\n- Wrap the entire universal compilation and lipo combining block in ifndef `NO_RUST`.\n- Remove the `RUST_LIBS` helper variable and use `$(RUST_LIB)` directly in `git-credential-osxkeychain`.\n"},{"id":"546945","messageId":"pull.2288.v2.git.git.1782943303219.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.git.git.1778001976709.gitgitgadget@gmail.com","subject":"[PATCH v2] Makefile: link osxkeychain & support universal Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-01T22:01:43Z","receivedAt":"2026-07-01T22:01:49Z","isPatch":true,"body":"From: Shnatu <snatu@google.com>\n\nWhen Rust is enabled, ensure that the git-credential-osxkeychain\nhelper is linked with the necessary Rust libraries.\n\nAlso, introduce native support for macOS Universal Binaries\n(multi-architecture builds) in the Git build system by allowing\nthe user to specify a list of target triples in the RUST_TARGETS\nenvironment variable.\n\nTo implement this cleanly without complex shell scripting in recipes:\n  1. We introduce a declarative Make pattern rule (target/%/...) to\n     compile each target-specific library slice (e.g.,\n     target/aarch64-apple-darwin/...).\n  2. We update the $(RUST_LIB) recipe to depend on the list of\n     compiled target-specific member libraries ($(RUST_MEMBER_LIBS)).\n  3. On macOS, if multiple targets are specified, we use lipo to\n     combine them into a single Universal static library at\n     target/release/libgitcore.a.\n  4. If only one target is specified, we copy it to the standard\n     path.\n  5. We enforce that building for multiple targets requires macOS\n     (as lipo is only available there), raising a clear make error\n     on other platforms.\n\nThis is a highly elegant and native Makefile solution that avoids\ncomplex shell scripting in recipes and fully supports macOS Universal\nBinaries.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n    Makefile: link osxkeychain helper against Rust\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v2\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v1:\n\n 1:  57046d2f78 ! 1:  6a11aff909 Makefile: link osxkeychain helper against Rust\n     @@ Metadata\n      Author: Shnatu <snatu@google.com>\n      \n       ## Commit message ##\n     -    Makefile: link osxkeychain helper against Rust\n     +    Makefile: link osxkeychain & support universal Rust\n      \n          When Rust is enabled, ensure that the git-credential-osxkeychain\n          helper is linked with the necessary Rust libraries.\n      \n     -    Introduce the RUST_LIBS variable inside ifndef NO_RUST block\n     -    to hold the Rust library dependency, and use it in the helper's\n     -    build target. This cleanly handles cases where Rust is disabled,\n     -    making it a no-op and avoiding any build failures on systems\n     -    without Cargo.\n     +    Also, introduce native support for macOS Universal Binaries\n     +    (multi-architecture builds) in the Git build system by allowing\n     +    the user to specify a list of target triples in the RUST_TARGETS\n     +    environment variable.\n      \n     -    This addresses reviewer feedback from internal CL 910223487\n     -    by simplifying the variables and avoiding confusing \"LINK\"\n     -    terminology.\n     +    To implement this cleanly without complex shell scripting in recipes:\n     +      1. We introduce a declarative Make pattern rule (target/%/...) to\n     +         compile each target-specific library slice (e.g.,\n     +         target/aarch64-apple-darwin/...).\n     +      2. We update the $(RUST_LIB) recipe to depend on the list of\n     +         compiled target-specific member libraries ($(RUST_MEMBER_LIBS)).\n     +      3. On macOS, if multiple targets are specified, we use lipo to\n     +         combine them into a single Universal static library at\n     +         target/release/libgitcore.a.\n     +      4. If only one target is specified, we copy it to the standard\n     +         path.\n     +      5. We enforce that building for multiple targets requires macOS\n     +         (as lipo is only available there), raising a clear make error\n     +         on other platforms.\n      \n     -    Signed-off-by: Shnatu <snatu@google.com>\n     +    This is a highly elegant and native Makefile solution that avoids\n     +    complex shell scripting in recipes and fully supports macOS Universal\n     +    Binaries.\n     +\n     +    Signed-off-by: Shardul Natu <snatu@google.com>\n      \n       ## Makefile ##\n     -@@ Makefile: ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n     - ifndef NO_RUST\n     - BASIC_CFLAGS += -DWITH_RUST\n     - GITLIBS += $(RUST_LIB)\n     -+RUST_LIBS = $(RUST_LIB)\n     +@@ Makefile: include shared.mak\n     + #\n     + # Building Rust code requires Cargo.\n     + #\n     ++# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n     ++# the default rust target on the system.\n     ++#\n     ++# On macOS, this supports specifying multiple targets, separated by a space.\n     ++# This will produce a Universal static library using `lipo`.\n     ++#\n     ++# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n     ++#\n     + # == SHA-1 and SHA-256 defines ==\n     + #\n     + # === SHA-1 backend ===\n     +@@ Makefile: TEST_SHELL_PATH = $(SHELL_PATH)\n     + \n     + LIB_FILE = libgit.a\n     + \n     ++ifndef NO_RUST\n     + ifdef DEBUG\n     +-RUST_TARGET_DIR = target/debug\n     ++RUST_BUILD_CONFIG = debug\n     + else\n     +-RUST_TARGET_DIR = target/release\n     ++RUST_BUILD_CONFIG = release\n     + endif\n     + \n       ifeq ($(uname_S),Windows)\n     - EXTLIBS += -luserenv\n     +-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n     ++RUST_LIB_NAME = gitcore.lib\n     + else\n     +-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n     ++RUST_LIB_NAME = libgitcore.a\n     ++endif\n     ++RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n       endif\n     + \n     + GITLIBS = common-main.o $(LIB_FILE)\n     +@@ Makefile: scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n     + $(LIB_FILE): $(LIB_OBJS)\n     + \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n     + \n     ++ifndef NO_RUST\n     ++ifeq ($(RUST_TARGETS),)\n     + $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n     + \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n     ++else\n     ++ifneq ($(words $(RUST_TARGETS)),1)\n     ++ifneq ($(uname_S),Darwin)\n     ++$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n     ++endif\n     ++endif\n     ++\n     ++RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n     ++$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n     ++\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n     ++\n     ++$(RUST_LIB): $(RUST_MEMBER_LIBS)\n     ++\t$(QUIET_GEN)\\\n     ++\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n     ++\t\tlipo -create $^ -output $@; \\\n     ++\telse \\\n     ++\t\tcp $< $@; \\\n     ++\tfi\n     ++endif\n     + \n     + .PHONY: rust\n     + rust: $(RUST_LIB)\n     ++endif\n     + \n     + export DEFAULT_EDITOR DEFAULT_PAGER\n     + \n      @@ Makefile: $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n       contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n       \t$(AR) $(ARFLAGS) $@ $^\n       \n      -contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n     -+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIBS) GIT-LDFLAGS\n     ++# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n     ++contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n       \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n     --\t\t$(filter %.o,$^) $(LIB_FILE) $(EXTLIBS) -framework Security -framework CoreFoundation\n     -+\t\t$(filter %.o,$^) $(LIB_FILE) $(RUST_LIBS) $(EXTLIBS) -framework Security -framework CoreFoundation\n     + \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n       \n     - contrib/credential/osxkeychain/git-credential-osxkeychain.o: contrib/credential/osxkeychain/git-credential-osxkeychain.c GIT-CFLAGS\n     - \t$(QUIET_LINK)$(CC) -o $@ -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<\n\n\n Makefile | 44 +++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 39 insertions(+), 5 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..8d49ecc897 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -939,16 +947,19 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n+endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3019,11 +3030,33 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t$(QUIET_GEN)\\\n+\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4107,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n\nbase-commit: 43192e7977f5f05138abcdb3212a3f87ab513bef\n-- \ngitgitgadget\n"},{"id":"546951","messageId":"xmqqpl16kwb3.fsf@gitster.g","threadId":"65595","inReplyTo":"pull.2288.v2.git.git.1782943303219.gitgitgadget@gmail.com","subject":"Re: [PATCH v2] Makefile: link osxkeychain & support universal Rust","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-02T01:35:44Z","receivedAt":"2026-07-02T01:35:47Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Shnatu <snatu@google.com>\n> Signed-off-by: Shardul Natu <snatu@google.com>\n\nYou'd want to make sure these two match.\n\n> To implement this cleanly without complex shell scripting in recipes:\n>   1. We introduce a declarative Make pattern rule (target/%/...) to\n>      compile each target-specific library slice (e.g.,\n>      target/aarch64-apple-darwin/...).\n>   2. We update the $(RUST_LIB) recipe to depend on the list of\n>      compiled target-specific member libraries ($(RUST_MEMBER_LIBS)).\n>   3. On macOS, if multiple targets are specified, we use lipo to\n>      combine them into a single Universal static library at\n>      target/release/libgitcore.a.\n>   4. If only one target is specified, we copy it to the standard\n>      path.\n>   5. We enforce that building for multiple targets requires macOS\n>      (as lipo is only available there), raising a clear make error\n>      on other platforms.\n>\n> This is a highly elegant and native Makefile solution that avoids\n> complex shell scripting in recipes and fully supports macOS Universal\n> Binaries.\n\nYou're the second person on this list I saw who calls their own\ncreation \"elegant\" ;-).\n\n> +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n> +\t$(QUIET_GEN)\\\n> +\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n> +\t\tlipo -create $^ -output $@; \\\n> +\telse \\\n> +\t\tcp $< $@; \\\n> +\tfi\n> +endif\n\nDo we know that leading directories to $(RUST_LIB) target has\nalready been created at this point?  If not, we may want to have\n\n    $(RUST_LIB): $(RUST_MEMBER_LIBS)\n   +        $(call mkdir_p_parent_template)\n            $(QUIET_GEN)\\\n            if [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n                    lipo -create $^ -output $@; \\\n\non top.\n\nThanks for making the build procedure better.\n"},{"id":"546977","messageId":"akZQmDYe9MtTdGM2@pks.im","threadId":"65595","inReplyTo":"pull.2288.v2.git.git.1782943303219.gitgitgadget@gmail.com","subject":"Re: [PATCH v2] Makefile: link osxkeychain & support universal Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-02T11:50:48Z","receivedAt":"2026-07-02T11:50:55Z","isPatch":true,"body":"On Wed, Jul 01, 2026 at 10:01:43PM +0000, Shardul Natu via GitGitGadget wrote:\n> From: Shnatu <snatu@google.com>\n> \n> When Rust is enabled, ensure that the git-credential-osxkeychain\n> helper is linked with the necessary Rust libraries.\n> \n> Also, introduce native support for macOS Universal Binaries\n> (multi-architecture builds) in the Git build system by allowing\n> the user to specify a list of target triples in the RUST_TARGETS\n> environment variable.\n\nThese are fundamentally unrelated things, aren't they? So I'd argue they\nshould be split up into two commits.\n\nI think we could also use an explanation here what the universal binary\nbuys us for those who are not deeply familiar with the macOS platform.\nWhat are they, and why do we want/need to support them?\n\n> To implement this cleanly without complex shell scripting in recipes:\n>   1. We introduce a declarative Make pattern rule (target/%/...) to\n>      compile each target-specific library slice (e.g.,\n>      target/aarch64-apple-darwin/...).\n>   2. We update the $(RUST_LIB) recipe to depend on the list of\n>      compiled target-specific member libraries ($(RUST_MEMBER_LIBS)).\n>   3. On macOS, if multiple targets are specified, we use lipo to\n>      combine them into a single Universal static library at\n>      target/release/libgitcore.a.\n>   4. If only one target is specified, we copy it to the standard\n>      path.\n>   5. We enforce that building for multiple targets requires macOS\n>      (as lipo is only available there), raising a clear make error\n>      on other platforms.\n> \n> This is a highly elegant and native Makefile solution that avoids\n> complex shell scripting in recipes and fully supports macOS Universal\n> Binaries.\n\nAs Junio already pointed out this self-praise reads quite weird. I'm\njust going to assume that this is AI-generated fluff.\n\n> diff --git a/Makefile b/Makefile\n> index 1f3f099f5c..8d49ecc897 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -3019,11 +3030,33 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n>  $(LIB_FILE): $(LIB_OBJS)\n>  \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>  \n> +ifndef NO_RUST\n> +ifeq ($(RUST_TARGETS),)\n>  $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n>  \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n> +else\n> +ifneq ($(words $(RUST_TARGETS)),1)\n> +ifneq ($(uname_S),Darwin)\n> +$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n> +endif\n> +endif\n> +\n> +RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n> +$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n> \n> +\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n> +\n> +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n> +\t$(QUIET_GEN)\\\n> +\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n> +\t\tlipo -create $^ -output $@; \\\n\nCan we assume lipo to be generally available on macOS? Also, is it\nsufficient to just do this for the library? I would have expected that\nbinaries would also need some treatment there.\n\nIn other words: what does it help us to have the Rust treated this way\nif the rest isn't?\n\nThanks!\n\nPatrick\n"},{"id":"547015","messageId":"pull.2288.v3.git.git.1783030971.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v2.git.git.1782943303219.gitgitgadget@gmail.com","subject":"[PATCH v3 0/2] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-02T22:22:49Z","receivedAt":"2026-07-02T22:22:54Z","isPatch":true,"body":"Shardul Natu (2):\n  Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n  Makefile: support universal macOS builds via RUST_TARGETS\n\n Makefile | 45 ++++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 40 insertions(+), 5 deletions(-)\n\n\nbase-commit: 602f6c329a7d99df269d382df353b4e1bbbbd8aa\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v3\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v2:\n\n -:  ---------- > 1:  41de7d391a Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n 1:  6a11aff909 ! 2:  257f5ef42f Makefile: link osxkeychain & support universal Rust\n     @@\n       ## Metadata ##\n     -Author: Shnatu <snatu@google.com>\n     +Author: Shardul Natu <snatu@google.com>\n      \n       ## Commit message ##\n     -    Makefile: link osxkeychain & support universal Rust\n     +    Makefile: support universal macOS builds via RUST_TARGETS\n      \n     -    When Rust is enabled, ensure that the git-credential-osxkeychain\n     -    helper is linked with the necessary Rust libraries.\n     +    On macOS, Universal Binaries contain native executable code for\n     +    multiple architectures (such as Intel x86_64 and Apple Silicon arm64)\n     +    bundled into a single file. This is standard practice for macOS\n     +    distribution and CI packaging (such as internal distribution packages\n     +    or tooling like Burrito/Homebrew), allowing a single build artifact\n     +    to run natively across all Macs without Rosetta emulation or\n     +    maintaining separate packages.\n      \n     -    Also, introduce native support for macOS Universal Binaries\n     -    (multi-architecture builds) in the Git build system by allowing\n     -    the user to specify a list of target triples in the RUST_TARGETS\n     -    environment variable.\n     +    When building Git C code for multiple architectures on macOS, the\n     +    Apple toolchain (clang) natively supports universal builds via\n     +    CFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\n     +    automatically compiles and links universal binaries for all C object\n     +    files and executables out of the box.\n      \n     -    To implement this cleanly without complex shell scripting in recipes:\n     -      1. We introduce a declarative Make pattern rule (target/%/...) to\n     -         compile each target-specific library slice (e.g.,\n     -         target/aarch64-apple-darwin/...).\n     -      2. We update the $(RUST_LIB) recipe to depend on the list of\n     -         compiled target-specific member libraries ($(RUST_MEMBER_LIBS)).\n     -      3. On macOS, if multiple targets are specified, we use lipo to\n     -         combine them into a single Universal static library at\n     -         target/release/libgitcore.a.\n     -      4. If only one target is specified, we copy it to the standard\n     -         path.\n     -      5. We enforce that building for multiple targets requires macOS\n     -         (as lipo is only available there), raising a clear make error\n     -         on other platforms.\n     +    Cargo and rustc, however, do not support multiple \"-arch\" flags or\n     +    emitting universal binaries in a single invocation. Instead, Cargo\n     +    requires invoking each target triple independently (e.g., passing\n     +    \"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n      \n     -    This is a highly elegant and native Makefile solution that avoids\n     -    complex shell scripting in recipes and fully supports macOS Universal\n     -    Binaries.\n     +    To bridge this gap when Rust is enabled:\n     +      1. Allow specifying space-separated target triples in RUST_TARGETS.\n     +      2. Introduce declarative pattern rules (target/%/...) to compile\n     +         each target-specific library slice via Cargo.\n     +      3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     +         the mandatory Xcode Command Line Tools) to combine the resulting\n     +         static libraries into target/release/libgitcore.a.\n     +      4. Ensure target directory creation before invoking lipo via\n     +         mkdir_p_parent_template.\n     +\n     +    Once $(RUST_LIB) is compiled into a universal static archive, the\n     +    standard C linker seamlessly links it with the C object files to\n     +    produce universal Git executables.\n      \n          Signed-off-by: Shardul Natu <snatu@google.com>\n      \n     @@ Makefile: include shared.mak\n       # == SHA-1 and SHA-256 defines ==\n       #\n       # === SHA-1 backend ===\n     -@@ Makefile: TEST_SHELL_PATH = $(SHELL_PATH)\n     - \n     - LIB_FILE = libgit.a\n     +@@ Makefile: LIB_FILE = libgit.a\n       \n     -+ifndef NO_RUST\n     + ifndef NO_RUST\n       ifdef DEBUG\n      -RUST_TARGET_DIR = target/debug\n      +RUST_BUILD_CONFIG = debug\n     @@ Makefile: TEST_SHELL_PATH = $(SHELL_PATH)\n       else\n      -RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n      +RUST_LIB_NAME = libgitcore.a\n     -+endif\n     + endif\n      +RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n       endif\n       \n       GITLIBS = common-main.o $(LIB_FILE)\n     -@@ Makefile: scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n     - $(LIB_FILE): $(LIB_OBJS)\n     +@@ Makefile: $(LIB_FILE): $(LIB_OBJS)\n       \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n       \n     -+ifndef NO_RUST\n     + ifndef NO_RUST\n      +ifeq ($(RUST_TARGETS),)\n       $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n       \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n     @@ Makefile: scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n      +\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n      +\n      +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n     ++\t@$(call mkdir_p_parent_template)\n      +\t$(QUIET_GEN)\\\n      +\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n      +\t\tlipo -create $^ -output $@; \\\n     @@ Makefile: scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n       \n       .PHONY: rust\n       rust: $(RUST_LIB)\n     -+endif\n     - \n     - export DEFAULT_EDITOR DEFAULT_PAGER\n     - \n     -@@ Makefile: $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n     - contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n     - \t$(AR) $(ARFLAGS) $@ $^\n     - \n     --contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n     -+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n     -+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n     - \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n     - \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n     - \n\n-- \ngitgitgadget\n"},{"id":"547016","messageId":"41de7d391ac00c70bfa981d20ed9df22dbdf7ace.1783030971.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v3.git.git.1783030971.gitgitgadget@gmail.com","subject":"[PATCH v3 1/2] Makefile: add $(RUST_LIB) prerequisite to osxkeychain","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-02T22:22:50Z","receivedAt":"2026-07-02T22:22:56Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen Rust is enabled, the git-credential-osxkeychain helper depends on\nRust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n(\"osxkeychain: fix build with Rust\") updated the linker command line to\nuse $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\nWithout this prerequisite, running a parallel build (\"make -j\") from a\nclean working tree can fail because Make does not know to invoke Cargo\nto build libgitcore.a before linking git-credential-osxkeychain.\n\nAdd $(RUST_LIB) as a prerequisite dependency to the\ngit-credential-osxkeychain target.\n\nAdditionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\ntarget in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\nspecified, $(RUST_LIB) evaluates to empty, making the Rust dependency a\nclean no-op without needing intermediate variables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..7db38ecce9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -939,6 +939,7 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n RUST_TARGET_DIR = target/debug\n else\n@@ -950,6 +951,7 @@ RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3019,11 +3021,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n-- \ngitgitgadget\n\n"},{"id":"547017","messageId":"257f5ef42fbb2841036591657e740872635df49b.1783030971.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v3.git.git.1783030971.gitgitgadget@gmail.com","subject":"[PATCH v3 2/2] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-02T22:22:51Z","receivedAt":"2026-07-02T22:22:58Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nOn macOS, Universal Binaries contain native executable code for\nmultiple architectures (such as Intel x86_64 and Apple Silicon arm64)\nbundled into a single file. This is standard practice for macOS\ndistribution and CI packaging (such as internal distribution packages\nor tooling like Burrito/Homebrew), allowing a single build artifact\nto run natively across all Macs without Rosetta emulation or\nmaintaining separate packages.\n\nWhen building Git C code for multiple architectures on macOS, the\nApple toolchain (clang) natively supports universal builds via\nCFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n\nCargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo\nrequires invoking each target triple independently (e.g., passing\n\"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nTo bridge this gap when Rust is enabled:\n  1. Allow specifying space-separated target triples in RUST_TARGETS.\n  2. Introduce declarative pattern rules (target/%/...) to compile\n     each target-specific library slice via Cargo.\n  3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     the mandatory Xcode Command Line Tools) to combine the resulting\n     static libraries into target/release/libgitcore.a.\n  4. Ensure target directory creation before invoking lipo via\n     mkdir_p_parent_template.\n\nOnce $(RUST_LIB) is compiled into a universal static archive, the\nstandard C linker seamlessly links it with the C object files to\nproduce universal Git executables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 38 ++++++++++++++++++++++++++++++++++----\n 1 file changed, 34 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7db38ecce9..e01f989cd0 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -941,16 +949,17 @@ LIB_FILE = libgit.a\n \n ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3022,8 +3031,29 @@ $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t@$(call mkdir_p_parent_template)\n+\t$(QUIET_GEN)\\\n+\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n-- \ngitgitgadget\n"},{"id":"547018","messageId":"CABw8Y3H7P3JKwaSrUGjifcDh7rMR2nCFgqPjw8q6vfZnLc730w@mail.gmail.com","threadId":"65595","inReplyTo":"akZQmDYe9MtTdGM2@pks.im","subject":"Re: [PATCH v2] Makefile: link osxkeychain & support universal Rust","fromName":"Shardul Natu","fromEmail":"shardul.27591@gmail.com","sentAt":"2026-07-02T22:30:15Z","receivedAt":"2026-07-02T22:30:30Z","isPatch":true,"body":"> \"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > From: Shnatu <snatu@google.com>\n> > Signed-off-by: Shardul Natu <snatu@google.com>\n>\n> You'd want to make sure these two match.\n\nGood catch. Done!\n\n> > This is a highly elegant and native Makefile solution that avoids\n> > complex shell scripting in recipes and fully supports macOS Universal\n> > Binaries.\n>\n> You're the second person on this list I saw who calls their own\n> creation \"elegant\" ;-).\n\nRemoved! It was AI generated description\n\n> Do we know that leading directories to $(RUST_LIB) target has\n> already been created at this point? If not, we may want to have\n>\n> $(RUST_LIB): $(RUST_MEMBER_LIBS)\n> + $(call mkdir_p_parent_template)\n> $(QUIET_GEN)\\\n> if [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n> lipo -create $^ -output $@; \\\n>\n> on top.\n\nAdded $(call mkdir_p_parent_template).\n\n> > When Rust is enabled, ensure that the git-credential-osxkeychain\n> > helper is linked with the necessary Rust libraries.\n> >\n> > Also, introduce native support for macOS Universal Binaries\n> > (multi-architecture builds) in the Git build system by allowing\n> > the user to specify a list of target triples in the RUST_TARGETS\n> > environment variable.\n>\n> These are fundamentally unrelated things, aren't they? So I'd argue they\n> should be split up into two commits.\n\nYou're right; these address two fundamentally different\nproblems. In v3, I have split this into a two commits:\n1. Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n2. Makefile: support universal macOS builds via RUST_TARGETS\n\n\n> I think we could also use an explanation here what the universal binary\n> buys us for those who are not deeply familiar with the macOS platform.\n> What are they, and why do we want/need to support them?\n\nI have added this background to the relevant commit.\n\n\n> Can we assume lipo to be generally available on macOS? Also, is it\n> sufficient to just do this for the library? I would have expected that\n> binaries would also need some treatment there.\n>\n> In other words: what does it help us to have the Rust treated this way\n> if the rest isn't?\n\nYes, \"lipo\" is part of the Apple Xcode CLT, which\nis already a hard prerequisite for invoking clang or make on macOS.\nThe reason only Rust needs special treatment in the Makefile is due to\nhow the respective toolchains handle multi-architecture builds:\n1. Apple's C toolchain (clang) natively supports universal builds via\nCFLAGS and LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n2. Cargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo must\nbe invoked separately for each target triple (\"--target x86_64-apple-darwin\"\nand \"--target aarch64-apple-darwin\").\n\nBy using \"lipo\" to combine those target-specific Rust static libraries\ninto a single universal archive at \"target/release/libgitcore.a\", we\nbridge this gap. Once $(RUST_LIB) is a universal archive, the standard C\nlinker seamlessly links it with the C object files to produce the final\nuniversal Git executables.\n\n\nOn Thu, Jul 2, 2026 at 4:57 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> On Wed, Jul 01, 2026 at 10:01:43PM +0000, Shardul Natu via GitGitGadget wrote:\n> > From: Shnatu <snatu@google.com>\n> >\n> > When Rust is enabled, ensure that the git-credential-osxkeychain\n> > helper is linked with the necessary Rust libraries.\n> >\n> > Also, introduce native support for macOS Universal Binaries\n> > (multi-architecture builds) in the Git build system by allowing\n> > the user to specify a list of target triples in the RUST_TARGETS\n> > environment variable.\n>\n> These are fundamentally unrelated things, aren't they? So I'd argue they\n> should be split up into two commits.\n>\n> I think we could also use an explanation here what the universal binary\n> buys us for those who are not deeply familiar with the macOS platform.\n> What are they, and why do we want/need to support them?\n>\n> > To implement this cleanly without complex shell scripting in recipes:\n> >   1. We introduce a declarative Make pattern rule (target/%/...) to\n> >      compile each target-specific library slice (e.g.,\n> >      target/aarch64-apple-darwin/...).\n> >   2. We update the $(RUST_LIB) recipe to depend on the list of\n> >      compiled target-specific member libraries ($(RUST_MEMBER_LIBS)).\n> >   3. On macOS, if multiple targets are specified, we use lipo to\n> >      combine them into a single Universal static library at\n> >      target/release/libgitcore.a.\n> >   4. If only one target is specified, we copy it to the standard\n> >      path.\n> >   5. We enforce that building for multiple targets requires macOS\n> >      (as lipo is only available there), raising a clear make error\n> >      on other platforms.\n> >\n> > This is a highly elegant and native Makefile solution that avoids\n> > complex shell scripting in recipes and fully supports macOS Universal\n> > Binaries.\n>\n> As Junio already pointed out this self-praise reads quite weird. I'm\n> just going to assume that this is AI-generated fluff.\n>\n> > diff --git a/Makefile b/Makefile\n> > index 1f3f099f5c..8d49ecc897 100644\n> > --- a/Makefile\n> > +++ b/Makefile\n> > @@ -3019,11 +3030,33 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n> >  $(LIB_FILE): $(LIB_OBJS)\n> >       $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n> >\n> > +ifndef NO_RUST\n> > +ifeq ($(RUST_TARGETS),)\n> >  $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n> >       $(QUIET_CARGO)cargo build $(CARGO_ARGS)\n> > +else\n> > +ifneq ($(words $(RUST_TARGETS)),1)\n> > +ifneq ($(uname_S),Darwin)\n> > +$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n> > +endif\n> > +endif\n> > +\n> > +RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n> > +$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n> >\n> > +     $(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n> > +\n> > +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n> > +     $(QUIET_GEN)\\\n> > +     if [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n> > +             lipo -create $^ -output $@; \\\n>\n> Can we assume lipo to be generally available on macOS? Also, is it\n> sufficient to just do this for the library? I would have expected that\n> binaries would also need some treatment there.\n>\n> In other words: what does it help us to have the Rust treated this way\n> if the rest isn't?\n>\n> Thanks!\n>\n> Patrick\n>\n"},{"id":"547033","messageId":"akdFarZgYhhFehGo@pks.im","threadId":"65595","inReplyTo":"CABw8Y3H7P3JKwaSrUGjifcDh7rMR2nCFgqPjw8q6vfZnLc730w@mail.gmail.com","subject":"Re: [PATCH v2] Makefile: link osxkeychain & support universal Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-03T05:15:22Z","receivedAt":"2026-07-03T05:15:32Z","isPatch":true,"body":"On Thu, Jul 02, 2026 at 03:30:15PM -0700, Shardul Natu wrote:\n> > Can we assume lipo to be generally available on macOS? Also, is it\n> > sufficient to just do this for the library? I would have expected that\n> > binaries would also need some treatment there.\n> >\n> > In other words: what does it help us to have the Rust treated this way\n> > if the rest isn't?\n> \n> Yes, \"lipo\" is part of the Apple Xcode CLT, which\n> is already a hard prerequisite for invoking clang or make on macOS.\n> The reason only Rust needs special treatment in the Makefile is due to\n> how the respective toolchains handle multi-architecture builds:\n> 1. Apple's C toolchain (clang) natively supports universal builds via\n> CFLAGS and LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\n> automatically compiles and links universal binaries for all C object\n> files and executables out of the box.\n> 2. Cargo and rustc, however, do not support multiple \"-arch\" flags or\n> emitting universal binaries in a single invocation. Instead, Cargo must\n> be invoked separately for each target triple (\"--target x86_64-apple-darwin\"\n> and \"--target aarch64-apple-darwin\").\n> \n> By using \"lipo\" to combine those target-specific Rust static libraries\n> into a single universal archive at \"target/release/libgitcore.a\", we\n> bridge this gap. Once $(RUST_LIB) is a universal archive, the standard C\n> linker seamlessly links it with the C object files to produce the final\n> universal Git executables.\n\nOkay, that makes sense. This information should definitely be part of\nthe commit message to give reviewers a bit more context.\n\nThanks!\n\nPatrick\n"},{"id":"547035","messageId":"xmqqldbsk51t.fsf@gitster.g","threadId":"65595","inReplyTo":"257f5ef42fbb2841036591657e740872635df49b.1783030971.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 2/2] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-03T05:36:46Z","receivedAt":"2026-07-03T05:36:49Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Shardul Natu <snatu@google.com>\n>\n> On macOS, Universal Binaries contain native executable code for\n> multiple architectures (such as Intel x86_64 and Apple Silicon arm64)\n> bundled into a single file. This is standard practice for macOS\n> distribution and CI packaging (such as internal distribution packages\n> or tooling like Burrito/Homebrew), allowing a single build artifact\n> to run natively across all Macs without Rosetta emulation or\n> maintaining separate packages.\n>\n> When building Git C code for multiple architectures on macOS, the\n> Apple toolchain (clang) natively supports universal builds via\n> CFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\n> automatically compiles and links universal binaries for all C object\n> files and executables out of the box.\n>\n> Cargo and rustc, however, do not support multiple \"-arch\" flags or\n> emitting universal binaries in a single invocation. Instead, Cargo\n> requires invoking each target triple independently (e.g., passing\n> \"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nThis is much easier to understand for those of us unfamiliar with\nthe macOS ecosystem.  Very much appreciated.\n\n> +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n> +\t@$(call mkdir_p_parent_template)\n\nThe leading @ is a bit curious because among ~20 existing use of\nthis pattern, nobody adds it to squelch \"mkdir -p\".  In fact, the\nmacro uses the standard pattern to define $(QUIET_MKDIR_P_PARENT)\nthat does the squelching when $(V) is unset.\n\n> +\t$(QUIET_GEN)\\\n> +\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n\nRecipe parts in our Makefile that are written in bourne shell, the\nCodingGuidelines apply.\n\n    $ git grep -n -e 'if \\[' ':(glob)**/Makefile'\n\ngives empty.  Probably,\n\n\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n\tthen \\\n\nwould fit better.\n\n> +\t\tlipo -create $^ -output $@; \\\n> +\telse \\\n> +\t\tcp $< $@; \\\n> +\tfi\n> +endif\n>  \n>  .PHONY: rust\n>  rust: $(RUST_LIB)\n\nOther than that, looking good.\n\nThanks.\n"},{"id":"547073","messageId":"539E5E6E-ADEB-415B-B126-18FC0BDABC99@gmail.com","threadId":"65595","inReplyTo":"akZQmDYe9MtTdGM2@pks.im","subject":"lipo availability [was: [PATCH v2] Makefile: link osxkeychain & support universal Rust]","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-07-03T12:02:44Z","receivedAt":"2026-07-03T12:02:57Z","isPatch":true,"body":"\n> Le 2 juil. 2026 à 07:57, Patrick Steinhardt <ps@pks.im> a écrit :\n> \n> ﻿On Wed, Jul 01, 2026 at 10:01:43PM +0000, Shardul Natu via GitGitGadget wrote:\n>> From: Shnatu <snatu@google.com>\n>> \n>> Also, introduce native support for macOS Universal Binaries\n>> (multi-architecture builds) in the Git build system by allowing\n>> the user to specify a list of target triples in the RUST_TARGETS\n>> environment variable.\n> \n>>  3. On macOS, if multiple targets are specified, we use lipo to\n>>     combine them into a single Universal static library at\n>>     target/release/libgitcore.a.\n>> \n> \n>> diff --git a/Makefile b/Makefile\n>> index 1f3f099f5c..8d49ecc897 100644\n>> --- a/Makefile\n>> +++ b/Makefile\n>> @@ -3019,11 +3030,33 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n>> $(LIB_FILE): $(LIB_OBJS)\n>>    $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>> \n>> +ifndef NO_RUST\n>> +ifeq ($(RUST_TARGETS),)\n>> $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n>>    $(QUIET_CARGO)cargo build $(CARGO_ARGS)\n>> +else\n>> +ifneq ($(words $(RUST_TARGETS)),1)\n>> +ifneq ($(uname_S),Darwin)\n>> +$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n>> +endif\n>> +endif\n>> +\n>> +RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n>> +$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n>> \n>> +    $(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n>> +\n>> +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n>> +    $(QUIET_GEN)\\\n>> +    if [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n>> +        lipo -create $^ -output $@; \\\n> \n> Can we assume lipo to be generally available on macOS?\n\nFrom my digging, universal binaries to support the PowerPC transition to Intel have been available since Xcode 2.1 from 2005 (whose release notes, if they ever existed, have been impossible for me to find). Of course for modern (Universal Binary 2) formats, you will need newer Xcode: the format was announced in 2020, so I suspect Xcode 12 is a minimum but not necessarily sufficient version. I have not been able to find a release note specific to UB2, though in 12.2 there is mention of both universal binaries and the arm architecture. Apple’s announcement [1] supports the argument for v12.\n\n[1]: https://www.apple.com/au/newsroom/2020/06/apple-announces-mac-transition-to-apple-silicon/"},{"id":"547111","messageId":"CABaQWZey-7FKd7FDTKZ5v7jjuRdTXm5cqJUpL8JKAL+Pom1iWw@mail.gmail.com","threadId":"65595","inReplyTo":"xmqqldbsk51t.fsf@gitster.g","subject":"Re: [PATCH v3 2/2] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu","fromEmail":"snatu@google.com","sentAt":"2026-07-03T17:37:05Z","receivedAt":"2026-07-03T17:37:18Z","isPatch":true,"body":"> > +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n> > + @$(call mkdir_p_parent_template)\n>\n> The leading @ is a bit curious because among ~20 existing use of\n> this pattern, nobody adds it to squelch \"mkdir -p\". In fact, the\n> macro uses the standard pattern to define $(QUIET_MKDIR_P_PARENT)\n> that does the squelching when $(V) is unset.\n\nDone!\n\n> Recipe parts in our Makefile that are written in bourne shell, the\n> CodingGuidelines apply.\n>\n> $ git grep -n -e 'if \\[' ':(glob)**/Makefile'\n>\n> gives empty. Probably,\n>\n> if test $(words $(RUST_TARGETS)) -gt 1; \\\n> then \\\n>\n> would fit better.\n\nThank you for pointing out the CodingGuidelines rule for Bourne shell\nsnippets in Makefiles. I have updated the condition from \"if [\" to \"if\ntest\".\n\nThanks,\nShardul\n\n\nOn Thu, Jul 2, 2026 at 10:36 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > From: Shardul Natu <snatu@google.com>\n> >\n> > On macOS, Universal Binaries contain native executable code for\n> > multiple architectures (such as Intel x86_64 and Apple Silicon arm64)\n> > bundled into a single file. This is standard practice for macOS\n> > distribution and CI packaging (such as internal distribution packages\n> > or tooling like Burrito/Homebrew), allowing a single build artifact\n> > to run natively across all Macs without Rosetta emulation or\n> > maintaining separate packages.\n> >\n> > When building Git C code for multiple architectures on macOS, the\n> > Apple toolchain (clang) natively supports universal builds via\n> > CFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\n> > automatically compiles and links universal binaries for all C object\n> > files and executables out of the box.\n> >\n> > Cargo and rustc, however, do not support multiple \"-arch\" flags or\n> > emitting universal binaries in a single invocation. Instead, Cargo\n> > requires invoking each target triple independently (e.g., passing\n> > \"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n>\n> This is much easier to understand for those of us unfamiliar with\n> the macOS ecosystem.  Very much appreciated.\n>\n> > +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n> > +     @$(call mkdir_p_parent_template)\n>\n> The leading @ is a bit curious because among ~20 existing use of\n> this pattern, nobody adds it to squelch \"mkdir -p\".  In fact, the\n> macro uses the standard pattern to define $(QUIET_MKDIR_P_PARENT)\n> that does the squelching when $(V) is unset.\n>\n> > +     $(QUIET_GEN)\\\n> > +     if [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n>\n> Recipe parts in our Makefile that are written in bourne shell, the\n> CodingGuidelines apply.\n>\n>     $ git grep -n -e 'if \\[' ':(glob)**/Makefile'\n>\n> gives empty.  Probably,\n>\n>         if test $(words $(RUST_TARGETS)) -gt 1; \\\n>         then \\\n>\n> would fit better.\n>\n> > +             lipo -create $^ -output $@; \\\n> > +     else \\\n> > +             cp $< $@; \\\n> > +     fi\n> > +endif\n> >\n> >  .PHONY: rust\n> >  rust: $(RUST_LIB)\n>\n> Other than that, looking good.\n>\n> Thanks.\n"},{"id":"547137","messageId":"pull.2288.v4.git.git.1783188355.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v3.git.git.1783030971.gitgitgadget@gmail.com","subject":"[PATCH v4 0/2] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-04T18:05:53Z","receivedAt":"2026-07-04T18:05:57Z","isPatch":true,"body":"This series improves macOS build reliability and distribution support when\nRust is enabled in the Git build system. It addresses two distinct\nchallenges: a parallel build race condition in git-credential-osxkeychain\nand support for macOS Universal Binaries (multi-architecture distribution).\n\n\nWhy This Series is Needed\n=========================\n\n 1. Parallel Build Race Condition (\"make -j\"): While commit 522ea8ef7d\n    (\"osxkeychain: fix build with Rust\") updated the link command for\n    git-credential-osxkeychain to pass $(LIBS), it omitted $(RUST_LIB) from\n    the target prerequisite list. When running a parallel build (\"make -j\")\n    from a clean working tree, Make can attempt to link\n    git-credential-osxkeychain before Cargo has finished compiling\n    libgitcore.a, causing linker failures.\n\n 2. macOS Universal Binary (lipo) Support: On macOS, Universal Binaries\n    bundle native executable code for multiple architectures (Intel x86_64\n    and Apple Silicon arm64) into a single file. This is standard practice\n    for macOS distribution and CI packaging (such as Burrito, Homebrew, and\n    Git's macOS CI runners), allowing a single artifact to run natively\n    across all Macs without Rosetta translation.\n\nWhile Apple's C compiler (clang) natively supports universal builds by\npassing \"-arch x86_64 -arch arm64\" in CFLAGS and LDFLAGS, Cargo and rustc do\nnot support multiple \"-arch\" flags in a single invocation. Instead, Cargo\nmust be invoked separately for each target triple (\"--target\nx86_64-apple-darwin\" and \"--target aarch64-apple-darwin\"). This series\nbridges that gap.\n\n\nOverview of Patches\n===================\n\n * Patch 1: Makefile: add $(RUST_LIB) prerequisite to osxkeychain Adds\n   $(RUST_LIB) as a prerequisite dependency to the osxkeychain target,\n   eliminating the parallel build race condition. Additionally, wraps the\n   definitions of $(RUST_LIB) and the \"rust\" build target in \"ifndef\n   NO_RUST\" so that disabling Rust cleanly makes the dependency a no-op.\n\n * Patch 2: Makefile: support universal macOS builds via RUST_TARGETS Allows\n   users to specify space-separated target triples in RUST_TARGETS.\n   Introduces declarative pattern rules (target/%/...) to compile each\n   target slice via Cargo, and uses \"lipo\" (part of the mandatory Xcode\n   Command Line Tools) to combine the resulting static archives into a\n   universal library at target/release/libgitcore.a. Uses\n   mkdir_p_parent_template to guarantee directory creation before lipo.\n\nChanges since v2:\n\n * Split the original combined commit into a two-patch series to separate\n   prerequisite bug fixes from Universal Binary features.\n * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n   that parent target directories exist.\n * \n\nShardul Natu (2):\n  Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n  Makefile: support universal macOS builds via RUST_TARGETS\n\n Makefile | 46 +++++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 41 insertions(+), 5 deletions(-)\n\n\nbase-commit: 602f6c329a7d99df269d382df353b4e1bbbbd8aa\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v4\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v3:\n\n 1:  41de7d391a = 1:  41de7d391a Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n 2:  257f5ef42f ! 2:  88fc2e0bd8 Makefile: support universal macOS builds via RUST_TARGETS\n     @@ Makefile: $(LIB_FILE): $(LIB_OBJS)\n      +\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n      +\n      +$(RUST_LIB): $(RUST_MEMBER_LIBS)\n     -+\t@$(call mkdir_p_parent_template)\n     ++\t$(call mkdir_p_parent_template)\n      +\t$(QUIET_GEN)\\\n     -+\tif [ $(words $(RUST_TARGETS)) -gt 1 ]; then \\\n     ++\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n     ++\tthen \\\n      +\t\tlipo -create $^ -output $@; \\\n      +\telse \\\n      +\t\tcp $< $@; \\\n\n-- \ngitgitgadget\n"},{"id":"547138","messageId":"41de7d391ac00c70bfa981d20ed9df22dbdf7ace.1783188355.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v4.git.git.1783188355.gitgitgadget@gmail.com","subject":"[PATCH v4 1/2] Makefile: add $(RUST_LIB) prerequisite to osxkeychain","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-04T18:05:54Z","receivedAt":"2026-07-04T18:05:59Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen Rust is enabled, the git-credential-osxkeychain helper depends on\nRust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n(\"osxkeychain: fix build with Rust\") updated the linker command line to\nuse $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\nWithout this prerequisite, running a parallel build (\"make -j\") from a\nclean working tree can fail because Make does not know to invoke Cargo\nto build libgitcore.a before linking git-credential-osxkeychain.\n\nAdd $(RUST_LIB) as a prerequisite dependency to the\ngit-credential-osxkeychain target.\n\nAdditionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\ntarget in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\nspecified, $(RUST_LIB) evaluates to empty, making the Rust dependency a\nclean no-op without needing intermediate variables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..7db38ecce9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -939,6 +939,7 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n RUST_TARGET_DIR = target/debug\n else\n@@ -950,6 +951,7 @@ RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3019,11 +3021,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n-- \ngitgitgadget\n\n"},{"id":"547139","messageId":"88fc2e0bd88756a07467bdaf75f6a344d2e58b41.1783188355.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v4.git.git.1783188355.gitgitgadget@gmail.com","subject":"[PATCH v4 2/2] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-04T18:05:55Z","receivedAt":"2026-07-04T18:06:01Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nOn macOS, Universal Binaries contain native executable code for\nmultiple architectures (such as Intel x86_64 and Apple Silicon arm64)\nbundled into a single file. This is standard practice for macOS\ndistribution and CI packaging (such as internal distribution packages\nor tooling like Burrito/Homebrew), allowing a single build artifact\nto run natively across all Macs without Rosetta emulation or\nmaintaining separate packages.\n\nWhen building Git C code for multiple architectures on macOS, the\nApple toolchain (clang) natively supports universal builds via\nCFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n\nCargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo\nrequires invoking each target triple independently (e.g., passing\n\"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nTo bridge this gap when Rust is enabled:\n  1. Allow specifying space-separated target triples in RUST_TARGETS.\n  2. Introduce declarative pattern rules (target/%/...) to compile\n     each target-specific library slice via Cargo.\n  3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     the mandatory Xcode Command Line Tools) to combine the resulting\n     static libraries into target/release/libgitcore.a.\n  4. Ensure target directory creation before invoking lipo via\n     mkdir_p_parent_template.\n\nOnce $(RUST_LIB) is compiled into a universal static archive, the\nstandard C linker seamlessly links it with the C object files to\nproduce universal Git executables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 39 +++++++++++++++++++++++++++++++++++----\n 1 file changed, 35 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7db38ecce9..ecada0acb4 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -941,16 +949,17 @@ LIB_FILE = libgit.a\n \n ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t$(call mkdir_p_parent_template)\n+\t$(QUIET_GEN)\\\n+\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n+\tthen \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n-- \ngitgitgadget\n"},{"id":"547146","messageId":"xmqqpl12dqot.fsf@gitster.g","threadId":"65595","inReplyTo":"pull.2288.v4.git.git.1783188355.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 0/2] Makefile: link osxkeychain helper against Rust","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-05T04:08:02Z","receivedAt":"2026-07-05T04:08:04Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> Changes since v2:\n>\n>  * Split the original combined commit into a two-patch series to separate\n>    prerequisite bug fixes from Universal Binary features.\n\nThis was addressing Patrick's comment, which was already done in v3;\nhopefully that is now settled?\n\n>  * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n>    that parent target directories exist.\n\nObviously correct ;-).\n\n>  * \n>\n\nIt is a mystery what the third bullet point was ;-)\n\nThe changes relative to v3 (which I looked at) look good now.\n\nThanks.\n"},{"id":"547166","messageId":"CABaQWZe7vO7iWuQAosGP4masmTg4_RKA+bWCJsAfSiq+MsHDrw@mail.gmail.com","threadId":"65595","inReplyTo":"xmqqpl12dqot.fsf@gitster.g","subject":"Re: [PATCH v4 0/2] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu","fromEmail":"snatu@google.com","sentAt":"2026-07-05T17:38:54Z","receivedAt":"2026-07-05T17:39:07Z","isPatch":true,"body":"> This was addressing Patrick's comment, which was already done in v3;\n> hopefully that is now settled?\n\nSorry, updated the description of the PR!\n\n> It is a mystery what the third bullet point was ;-)\n\nRemnant of thoughts! Removed!!\n\nThank you,\n  Shardul\n\nOn Sat, Jul 4, 2026 at 9:08 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > Changes since v2:\n> >\n> >  * Split the original combined commit into a two-patch series to separate\n> >    prerequisite bug fixes from Universal Binary features.\n>\n> This was addressing Patrick's comment, which was already done in v3;\n> hopefully that is now settled?\n>\n> >  * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n> >    that parent target directories exist.\n>\n> Obviously correct ;-).\n>\n> >  *\n> >\n>\n> It is a mystery what the third bullet point was ;-)\n>\n> The changes relative to v3 (which I looked at) look good now.\n>\n> Thanks.\n"},{"id":"547210","messageId":"akuIO-uOy3KhqIAE@pks.im","threadId":"65595","inReplyTo":"41de7d391ac00c70bfa981d20ed9df22dbdf7ace.1783188355.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 1/2] Makefile: add $(RUST_LIB) prerequisite to osxkeychain","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-06T10:49:31Z","receivedAt":"2026-07-06T10:49:38Z","isPatch":true,"body":"On Sat, Jul 04, 2026 at 06:05:54PM +0000, Shardul Natu via GitGitGadget wrote:\n> From: Shardul Natu <snatu@google.com>\n> diff --git a/Makefile b/Makefile\n> index 1f3f099f5c..7db38ecce9 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n>  contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n>  \t$(AR) $(ARFLAGS) $@ $^\n>  \n> -contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n> +# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n> +contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n>  \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n>  \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n\nI was wondering why no other target declares an explicit dependency on\nRUST_LIB. As it turns out, all the other targets that link \"$(LIBS)\" all\nalready depend on \"$(GITLIBS)\", which includes both \"$(LIB_FILE)\" and\n\"$(RUST_LIB)\". So shouldn't we also depend depend on \"$(GITLIBS)\" here\ninstead of on either of the other two variables?\n\nPatrick\n"},{"id":"547211","messageId":"akuIQADP_aRb5pY6@pks.im","threadId":"65595","inReplyTo":"88fc2e0bd88756a07467bdaf75f6a344d2e58b41.1783188355.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 2/2] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-06T10:49:36Z","receivedAt":"2026-07-06T10:49:48Z","isPatch":true,"body":"On Sat, Jul 04, 2026 at 06:05:55PM +0000, Shardul Natu via GitGitGadget wrote:\n> From: Shardul Natu <snatu@google.com>\n> \n> On macOS, Universal Binaries contain native executable code for\n> multiple architectures (such as Intel x86_64 and Apple Silicon arm64)\n> bundled into a single file. This is standard practice for macOS\n> distribution and CI packaging (such as internal distribution packages\n> or tooling like Burrito/Homebrew), allowing a single build artifact\n> to run natively across all Macs without Rosetta emulation or\n> maintaining separate packages.\n> \n> When building Git C code for multiple architectures on macOS, the\n> Apple toolchain (clang) natively supports universal builds via\n> CFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\n> automatically compiles and links universal binaries for all C object\n> files and executables out of the box.\n> \n> Cargo and rustc, however, do not support multiple \"-arch\" flags or\n> emitting universal binaries in a single invocation. Instead, Cargo\n> requires invoking each target triple independently (e.g., passing\n> \"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n> \n> To bridge this gap when Rust is enabled:\n>   1. Allow specifying space-separated target triples in RUST_TARGETS.\n>   2. Introduce declarative pattern rules (target/%/...) to compile\n>      each target-specific library slice via Cargo.\n>   3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n>      the mandatory Xcode Command Line Tools) to combine the resulting\n>      static libraries into target/release/libgitcore.a.\n>   4. Ensure target directory creation before invoking lipo via\n>      mkdir_p_parent_template.\n\nNit: The last item really is quite uninteresting in the bigger scheme of\nthings.\n\n> Once $(RUST_LIB) is compiled into a universal static archive, the\n> standard C linker seamlessly links it with the C object files to\n> produce universal Git executables.\n\nOkay, this overall reads a lot better now.\n\n> diff --git a/Makefile b/Makefile\n> index 7db38ecce9..ecada0acb4 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -500,6 +500,14 @@ include shared.mak\n>  #\n>  # Building Rust code requires Cargo.\n>  #\n> +# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n> +# the default rust target on the system.\n\ns/rust/Rust/\n\n> @@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)\n>  \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>  \n>  ifndef NO_RUST\n> +ifeq ($(RUST_TARGETS),)\n>  $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n>  \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n> +else\n> +ifneq ($(words $(RUST_TARGETS)),1)\n> +ifneq ($(uname_S),Darwin)\n> +$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n> +endif\n> +endif\n> +\n> +RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n> +$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n> +\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n\nWith this we now have both:\n\n    - target/$ARCH/$BUILD_CONFIG/\n\n    - target/$BUILD_CONFIG/\n\nIs there any reason why we have to have those two different layouts\ninstead of swapping the order in the first item so that all artifacts\nare in \"target/$BUILD_CONFIG/\"? Essentially, what I'm proposing instead\nis:\n\n    - \"target/$BUILD_CONFIG/\" for the final universal executable.\n\n    - \"target/$BUILD_CONFIG/$ARCH\" for the per-arch artifacts.\n\nPatrick\n"},{"id":"547250","messageId":"pull.2288.v5.git.git.1783358097.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v4.git.git.1783188355.gitgitgadget@gmail.com","subject":"[PATCH v5 0/2] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T17:14:55Z","receivedAt":"2026-07-06T17:15:00Z","isPatch":true,"body":"This series improves macOS build reliability and distribution support when\nRust is enabled in the Git build system. It addresses two distinct\nchallenges: a parallel build race condition in git-credential-osxkeychain\nand support for macOS Universal Binaries (multi-architecture distribution).\n\n\nWhy This Series is Needed\n=========================\n\n 1. Parallel Build Race Condition (make -j): While commit 522ea8ef7d\n    (\"osxkeychain: fix build with Rust\") updated the link command for\n    git-credential-osxkeychain to pass $(LIBS), it omitted $(RUST_LIB) from\n    the target prerequisite list. When running a parallel build (make -j)\n    from a clean working tree, Make can attempt to link\n    git-credential-osxkeychain before Cargo has finished compiling\n    libgitcore.a, causing linker failures.\n\n 2. macOS Universal Binary (lipo) Support: On macOS, Universal Binaries\n    bundle native executable code for multiple architectures (Intel x86_64\n    and Apple Silicon arm64) into a single file. This is standard practice\n    for macOS distribution and CI packaging (such as Burrito, Homebrew, and\n    Git's macOS CI runners), allowing a single artifact to run natively\n    across all Macs without Rosetta translation.\n\nWhile Apple's C compiler (clang) natively supports universal builds by\npassing -arch x86_64 -arch arm64 in CFLAGS and LDFLAGS, Cargo and rustc do\nnot support multiple -arch flags in a single invocation. Instead, Cargo must\nbe invoked separately for each target triple (--target x86_64-apple-darwin\nand --target aarch64-apple-darwin). This series bridges that gap.\n\n\nOverview of Patches\n===================\n\n * Patch 1: Makefile: add $(RUST_LIB) prerequisite to osxkeychain Adds\n   $(RUST_LIB) as a prerequisite dependency to the osxkeychain target,\n   eliminating the parallel build race condition. Additionally, wraps the\n   definitions of $(RUST_LIB) and the rust build target in ifndef NO_RUST so\n   that disabling Rust cleanly makes the dependency a no-op.\n\n * Patch 2: Makefile: support universal macOS builds via RUST_TARGETS Allows\n   users to specify space-separated target triples in RUST_TARGETS.\n   Introduces declarative pattern rules (target/%/...) to compile each\n   target slice via Cargo, and uses lipo (part of the mandatory Xcode\n   Command Line Tools) to combine the resulting static archives into a\n   universal library at target/release/libgitcore.a. Uses\n   mkdir_p_parent_template to guarantee directory creation before lipo.\n\nChanges since v4:\n\n * Changed the osxkeychain prerequisite dependency from $(LIB_FILE)\n   $(RUST_LIB) to $(GITLIBS) to match the canonical prerequisite pattern\n   used by all other core Git targets linking $(LIBS).\n\nChanges since v3:\n\n * Removed leading @ from $(call mkdir_p_parent_template) so it relies on\n   the built-in $(QUIET_MKDIR_P_PARENT) behavior, matching existing Makefile\n   conventions.\n * Replaced if [ with if test in Bourne shell recipe snippets to strictly\n   adhere to the project's CodingGuidelines.\n\nChanges since v2:\n\n * Split the original combined commit into a two-patch series to separate\n   prerequisite bug fixes from Universal Binary features.\n * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n   that parent target directories exist.\n\nShardul Natu (2):\n  Makefile: add $(GITLIBS) prerequisite to osxkeychain\n  Makefile: support universal macOS builds via RUST_TARGETS\n\n Makefile | 46 +++++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 41 insertions(+), 5 deletions(-)\n\n\nbase-commit: 602f6c329a7d99df269d382df353b4e1bbbbd8aa\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v5\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v5\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v4:\n\n 1:  41de7d391a ! 1:  e0bb18ff01 Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n     @@ Metadata\n      Author: Shardul Natu <snatu@google.com>\n      \n       ## Commit message ##\n     -    Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n     +    Makefile: add $(GITLIBS) prerequisite to osxkeychain\n      \n          When Rust is enabled, the git-credential-osxkeychain helper depends on\n          Rust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n     @@ Commit message\n          clean working tree can fail because Make does not know to invoke Cargo\n          to build libgitcore.a before linking git-credential-osxkeychain.\n      \n     -    Add $(RUST_LIB) as a prerequisite dependency to the\n     -    git-credential-osxkeychain target.\n     +    All other core Git targets that link $(LIBS) already depend on\n     +    $(GITLIBS), which bundles common-main.o, $(LIB_FILE), and $(RUST_LIB)\n     +    when Rust is enabled. Add $(GITLIBS) as a prerequisite dependency to the\n     +    git-credential-osxkeychain target to make it consistent with the rest of\n     +    the codebase.\n      \n          Additionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\n          target in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\n     @@ Makefile: $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n       \n      -contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n      +# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n     -+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n     ++contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(GITLIBS) GIT-LDFLAGS\n       \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n       \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n       \n 2:  88fc2e0bd8 ! 2:  66f71fb0d7 Makefile: support universal macOS builds via RUST_TARGETS\n     @@ Commit message\n            3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n               the mandatory Xcode Command Line Tools) to combine the resulting\n               static libraries into target/release/libgitcore.a.\n     -      4. Ensure target directory creation before invoking lipo via\n     -         mkdir_p_parent_template.\n      \n          Once $(RUST_LIB) is compiled into a universal static archive, the\n          standard C linker seamlessly links it with the C object files to\n     @@ Makefile: include shared.mak\n       # Building Rust code requires Cargo.\n       #\n      +# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n     -+# the default rust target on the system.\n     ++# the default Rust target on the system.\n      +#\n      +# On macOS, this supports specifying multiple targets, separated by a space.\n      +# This will produce a Universal static library using `lipo`.\n\n-- \ngitgitgadget\n"},{"id":"547251","messageId":"e0bb18ff0191de384ea3c947bf26ee07834782cb.1783358097.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v5.git.git.1783358097.gitgitgadget@gmail.com","subject":"[PATCH v5 1/2] Makefile: add $(GITLIBS) prerequisite to osxkeychain","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T17:14:56Z","receivedAt":"2026-07-06T17:15:01Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen Rust is enabled, the git-credential-osxkeychain helper depends on\nRust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n(\"osxkeychain: fix build with Rust\") updated the linker command line to\nuse $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\nWithout this prerequisite, running a parallel build (\"make -j\") from a\nclean working tree can fail because Make does not know to invoke Cargo\nto build libgitcore.a before linking git-credential-osxkeychain.\n\nAll other core Git targets that link $(LIBS) already depend on\n$(GITLIBS), which bundles common-main.o, $(LIB_FILE), and $(RUST_LIB)\nwhen Rust is enabled. Add $(GITLIBS) as a prerequisite dependency to the\ngit-credential-osxkeychain target to make it consistent with the rest of\nthe codebase.\n\nAdditionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\ntarget in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\nspecified, $(RUST_LIB) evaluates to empty, making the Rust dependency a\nclean no-op without needing intermediate variables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..7f4be97b90 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -939,6 +939,7 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n RUST_TARGET_DIR = target/debug\n else\n@@ -950,6 +951,7 @@ RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3019,11 +3021,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(GITLIBS) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n-- \ngitgitgadget\n\n"},{"id":"547252","messageId":"66f71fb0d712f45c51753bde0064a10e57c426f1.1783358097.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v5.git.git.1783358097.gitgitgadget@gmail.com","subject":"[PATCH v5 2/2] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T17:14:57Z","receivedAt":"2026-07-06T17:15:04Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nOn macOS, Universal Binaries contain native executable code for\nmultiple architectures (such as Intel x86_64 and Apple Silicon arm64)\nbundled into a single file. This is standard practice for macOS\ndistribution and CI packaging (such as internal distribution packages\nor tooling like Burrito/Homebrew), allowing a single build artifact\nto run natively across all Macs without Rosetta emulation or\nmaintaining separate packages.\n\nWhen building Git C code for multiple architectures on macOS, the\nApple toolchain (clang) natively supports universal builds via\nCFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n\nCargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo\nrequires invoking each target triple independently (e.g., passing\n\"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nTo bridge this gap when Rust is enabled:\n  1. Allow specifying space-separated target triples in RUST_TARGETS.\n  2. Introduce declarative pattern rules (target/%/...) to compile\n     each target-specific library slice via Cargo.\n  3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     the mandatory Xcode Command Line Tools) to combine the resulting\n     static libraries into target/release/libgitcore.a.\n\nOnce $(RUST_LIB) is compiled into a universal static archive, the\nstandard C linker seamlessly links it with the C object files to\nproduce universal Git executables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 39 +++++++++++++++++++++++++++++++++++----\n 1 file changed, 35 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7f4be97b90..335fd056fa 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default Rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -941,16 +949,17 @@ LIB_FILE = libgit.a\n \n ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t$(call mkdir_p_parent_template)\n+\t$(QUIET_GEN)\\\n+\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n+\tthen \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n-- \ngitgitgadget\n"},{"id":"547263","messageId":"xmqqmrw3aoas.fsf@gitster.g","threadId":"65595","inReplyTo":"e0bb18ff0191de384ea3c947bf26ee07834782cb.1783358097.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v5 1/2] Makefile: add $(GITLIBS) prerequisite to osxkeychain","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-06T19:52:27Z","receivedAt":"2026-07-06T19:52:29Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Shardul Natu <snatu@google.com>\n>\n> When Rust is enabled, the git-credential-osxkeychain helper depends on\n> Rust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n> (\"osxkeychain: fix build with Rust\") updated the linker command line to\n> use $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\n> Without this prerequisite, running a parallel build (\"make -j\") from a\n> clean working tree can fail because Make does not know to invoke Cargo\n> to build libgitcore.a before linking git-credential-osxkeychain.\n>\n> All other core Git targets that link $(LIBS) already depend on\n> $(GITLIBS), which bundles common-main.o, $(LIB_FILE), and $(RUST_LIB)\n> when Rust is enabled. Add $(GITLIBS) as a prerequisite dependency to the\n> git-credential-osxkeychain target to make it consistent with the rest of\n> the codebase.\n\nI do not work with macOS but doesn't this change introduce a\nbuild/link failure?\n\nSorry if I am mistaken, but as far as I can see, $(GITLIBS) includes\ncommon-main.o (and it being .o, not .a, it is always included in the\nresult), and git-credential-osxkeychain.c comes with its own main()\nfunction.  \n\nUsing a list of things to link that contains common-main.o does not\nsound like a right thing to do; in other words, linking too many is\njust as bad as linking too little.\n"},{"id":"547276","messageId":"pull.2288.v6.git.git.1783378333.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v5.git.git.1783358097.gitgitgadget@gmail.com","subject":"[PATCH v6 0/3] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T22:52:10Z","receivedAt":"2026-07-06T22:52:18Z","isPatch":true,"body":"This series improves macOS build reliability, automated CI verification, and\ndistribution support when Rust is enabled in the Git build system. It\naddresses three distinct challenges: a parallel build race condition in\ngit-credential-osxkeychain, support for macOS Universal Binaries\n(multi-architecture distribution), and missing automated CI test wiring for\nmacOS contrib utilities.\n\n\nWhy This Series is Needed\n=========================\n\n 1. Parallel Build Race Condition (make -j): While commit 522ea8ef7d\n    (\"osxkeychain: fix build with Rust\") updated the link command for\n    git-credential-osxkeychain to pass $(LIBS), it omitted $(RUST_LIB) from\n    the target prerequisite list. When running a parallel build (make -j)\n    from a clean working tree, Make can attempt to link\n    git-credential-osxkeychain before Cargo has finished compiling\n    libgitcore.a, causing linker failures.\n\n 2. macOS Universal Binary (lipo) Support: On macOS, Universal Binaries\n    bundle native executable code for multiple architectures (Intel x86_64\n    and Apple Silicon arm64) into a single file. This is standard practice\n    for macOS distribution and CI packaging (such as Burrito, Homebrew, and\n    Git's macOS CI runners), allowing a single artifact to run natively\n    across all Macs without Rosetta translation.\n\nWhile Apple's C compiler (clang) natively supports universal builds by\npassing -arch x86_64 -arch arm64 in CFLAGS and LDFLAGS, Cargo and rustc do\nnot support multiple -arch flags in a single invocation. Instead, Cargo must\nbe invoked separately for each target triple (--target x86_64-apple-darwin\nand --target aarch64-apple-darwin). This series bridges that gap.\n\n 3. Automated CI Verification for Contrib on macOS: When running make test\n    with TEST_CONTRIB_TOO=yes (default in macOS CI workflows), $(MAKE) -C\n    contrib/ test is invoked. However, contrib/Makefile only invoked tests\n    for diff-highlight and subtree, meaning git-credential-osxkeychain was\n    never compiled or verified during standard CI test runs.\n\n\nOverview of Patches\n===================\n\n * Patch 1: Makefile: add $(RUST_LIB) prerequisite to osxkeychain Adds\n   $(RUST_LIB) as a prerequisite dependency to the osxkeychain target,\n   eliminating the parallel build race condition. Additionally, wraps the\n   definitions of $(RUST_LIB) and the rust build target in ifndef NO_RUST so\n   that disabling Rust cleanly makes the dependency a no-op.\n\n * Patch 2: Makefile: support universal macOS builds via RUST_TARGETS Allows\n   users to specify space-separated target triples in RUST_TARGETS.\n   Introduces declarative pattern rules (target/%/...) to compile each\n   target slice via Cargo, and uses lipo (part of the mandatory Xcode\n   Command Line Tools) to combine the resulting static archives into a\n   universal library at target/release/libgitcore.a. Uses\n   mkdir_p_parent_template to guarantee directory creation before lipo.\n   \n   * Patch 3: contrib: wire up osxkeychain in contrib/Makefile on macOS Adds\n     a test target to contrib/credential/osxkeychain/Makefile that depends\n     on building git-credential-osxkeychain. Introduces a generic OS_CONTRIB\n     variable in contrib/Makefile to conditionally wire\n     credential/osxkeychain into all, test, and clean whenever running on\n     macOS (Darwin). This guarantees that standard CI test runs on macOS\n     automatically compile and link the helper, preventing build\n     regressions.\n\nChanges since v5:\n\n * Reverted Patch 1 to depend explicitly on $(LIB_FILE) $(RUST_LIB) rather\n   than $(GITLIBS). Unlike Git builtins or scalar (which define cmd_main()),\n   git-credential-osxkeychain.c defines its own standalone main(), meaning\n   $(GITLIBS) caused a duplicate symbol error for _main during linking.\n * Added Patch 3 (\"contrib: wire up osxkeychain in contrib/Makefile on\n   macOS\") using a scalable OS_CONTRIB variable so that running make test\n   with TEST_CONTRIB_TOO=yes in macOS CI workflows automatically verifies\n   compilation and linking integrity.\n\nChanges since v4:\n\n * Changed the osxkeychain prerequisite dependency from $(LIB_FILE)\n   $(RUST_LIB) to $(GITLIBS) to match the canonical prerequisite pattern\n   used by all other core Git targets linking $(LIBS).\n\nChanges since v3:\n\n * Removed leading @ from $(call mkdir_p_parent_template) so it relies on\n   the built-in $(QUIET_MKDIR_P_PARENT) behavior, matching existing Makefile\n   conventions.\n * Replaced if [ with if test in Bourne shell recipe snippets to strictly\n   adhere to the project's CodingGuidelines.\n\nChanges since v2:\n\n * Split the original combined commit into a two-patch series to separate\n   prerequisite bug fixes from Universal Binary features.\n * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n   that parent target directories exist.\n\nShardul Natu (3):\n  Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n  Makefile: support universal macOS builds via RUST_TARGETS\n  contrib: wire up osxkeychain in contrib/Makefile on macOS\n\n Makefile                                | 46 ++++++++++++++++++++++---\n contrib/Makefile                        | 10 ++++++\n contrib/credential/osxkeychain/Makefile |  4 ++-\n 3 files changed, 54 insertions(+), 6 deletions(-)\n\n\nbase-commit: 602f6c329a7d99df269d382df353b4e1bbbbd8aa\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v6\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v6\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v5:\n\n 1:  e0bb18ff01 ! 1:  0d21513940 Makefile: add $(GITLIBS) prerequisite to osxkeychain\n     @@ Metadata\n      Author: Shardul Natu <snatu@google.com>\n      \n       ## Commit message ##\n     -    Makefile: add $(GITLIBS) prerequisite to osxkeychain\n     +    Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n      \n          When Rust is enabled, the git-credential-osxkeychain helper depends on\n          Rust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n     @@ Commit message\n          clean working tree can fail because Make does not know to invoke Cargo\n          to build libgitcore.a before linking git-credential-osxkeychain.\n      \n     -    All other core Git targets that link $(LIBS) already depend on\n     -    $(GITLIBS), which bundles common-main.o, $(LIB_FILE), and $(RUST_LIB)\n     -    when Rust is enabled. Add $(GITLIBS) as a prerequisite dependency to the\n     -    git-credential-osxkeychain target to make it consistent with the rest of\n     -    the codebase.\n     +    Note that we depend explicitly on $(LIB_FILE) and $(RUST_LIB) rather\n     +    than $(GITLIBS). Unlike standard Git builtins and programs like scalar\n     +    (which define cmd_main() and rely on common-main.o to supply main()),\n     +    git-credential-osxkeychain.c defines its own standalone int main().\n     +    If $(GITLIBS) were used, $(filter %.o,$^) in the link recipe would\n     +    match both git-credential-osxkeychain.o and common-main.o, causing a\n     +    duplicate symbol linking error for _main on macOS.\n      \n          Additionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\n          target in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\n     @@ Makefile: $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n       \n      -contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n      +# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n     -+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(GITLIBS) GIT-LDFLAGS\n     ++contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n       \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n       \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n       \n 2:  66f71fb0d7 = 2:  21dedb91f0 Makefile: support universal macOS builds via RUST_TARGETS\n -:  ---------- > 3:  8455e449f3 contrib: wire up osxkeychain in contrib/Makefile on macOS\n\n-- \ngitgitgadget\n"},{"id":"547277","messageId":"0d215139406350586ca67554b90b47c0ae42a9fb.1783378333.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v6.git.git.1783378333.gitgitgadget@gmail.com","subject":"[PATCH v6 1/3] Makefile: add $(RUST_LIB) prerequisite to osxkeychain","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T22:52:11Z","receivedAt":"2026-07-06T22:52:20Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen Rust is enabled, the git-credential-osxkeychain helper depends on\nRust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n(\"osxkeychain: fix build with Rust\") updated the linker command line to\nuse $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\nWithout this prerequisite, running a parallel build (\"make -j\") from a\nclean working tree can fail because Make does not know to invoke Cargo\nto build libgitcore.a before linking git-credential-osxkeychain.\n\nNote that we depend explicitly on $(LIB_FILE) and $(RUST_LIB) rather\nthan $(GITLIBS). Unlike standard Git builtins and programs like scalar\n(which define cmd_main() and rely on common-main.o to supply main()),\ngit-credential-osxkeychain.c defines its own standalone int main().\nIf $(GITLIBS) were used, $(filter %.o,$^) in the link recipe would\nmatch both git-credential-osxkeychain.o and common-main.o, causing a\nduplicate symbol linking error for _main on macOS.\n\nAdditionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\ntarget in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\nspecified, $(RUST_LIB) evaluates to empty, making the Rust dependency a\nclean no-op without needing intermediate variables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..7db38ecce9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -939,6 +939,7 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n RUST_TARGET_DIR = target/debug\n else\n@@ -950,6 +951,7 @@ RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3019,11 +3021,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n-- \ngitgitgadget\n\n"},{"id":"547278","messageId":"21dedb91f093e9035f25cdf1673ff41976fe68bf.1783378333.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v6.git.git.1783378333.gitgitgadget@gmail.com","subject":"[PATCH v6 2/3] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T22:52:12Z","receivedAt":"2026-07-06T22:52:22Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nOn macOS, Universal Binaries contain native executable code for\nmultiple architectures (such as Intel x86_64 and Apple Silicon arm64)\nbundled into a single file. This is standard practice for macOS\ndistribution and CI packaging (such as internal distribution packages\nor tooling like Burrito/Homebrew), allowing a single build artifact\nto run natively across all Macs without Rosetta emulation or\nmaintaining separate packages.\n\nWhen building Git C code for multiple architectures on macOS, the\nApple toolchain (clang) natively supports universal builds via\nCFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n\nCargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo\nrequires invoking each target triple independently (e.g., passing\n\"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nTo bridge this gap when Rust is enabled:\n  1. Allow specifying space-separated target triples in RUST_TARGETS.\n  2. Introduce declarative pattern rules (target/%/...) to compile\n     each target-specific library slice via Cargo.\n  3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     the mandatory Xcode Command Line Tools) to combine the resulting\n     static libraries into target/release/libgitcore.a.\n\nOnce $(RUST_LIB) is compiled into a universal static archive, the\nstandard C linker seamlessly links it with the C object files to\nproduce universal Git executables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 39 +++++++++++++++++++++++++++++++++++----\n 1 file changed, 35 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7db38ecce9..9921af992b 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default Rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -941,16 +949,17 @@ LIB_FILE = libgit.a\n \n ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t$(call mkdir_p_parent_template)\n+\t$(QUIET_GEN)\\\n+\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n+\tthen \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n-- \ngitgitgadget\n\n"},{"id":"547279","messageId":"8455e449f388486c4468dfd528d7d96e90fe2c59.1783378333.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v6.git.git.1783378333.gitgitgadget@gmail.com","subject":"[PATCH v6 3/3] contrib: wire up osxkeychain in contrib/Makefile on macOS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-06T22:52:13Z","receivedAt":"2026-07-06T22:52:24Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen running \"make test\" with TEST_CONTRIB_TOO=yes (which is default in\nmacOS CI workflows), $(MAKE) -C contrib/ test is invoked. However,\ncontrib/Makefile only invoked tests for diff-highlight and subtree,\nmeaning git-credential-osxkeychain was never built or verified during\nstandard CI test runs.\n\nAdd a \"test\" target to contrib/credential/osxkeychain/Makefile that\ndepends on building git-credential-osxkeychain. Additionally, wire up\ncredential/osxkeychain in contrib/Makefile under \"all\", \"test\", and\n\"clean\" whenever running on macOS (Darwin).\n\nThis ensures that running \"make test\" or \"make all\" in contrib on macOS\nautomatically builds and links git-credential-osxkeychain, preventing\nfuture build or symbol linking regressions from slipping through CI.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n contrib/Makefile                        | 10 ++++++++++\n contrib/credential/osxkeychain/Makefile |  4 +++-\n 2 files changed, 13 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/Makefile b/contrib/Makefile\nindex 787cd07f52..7962a9ff12 100644\n--- a/contrib/Makefile\n+++ b/contrib/Makefile\n@@ -1,10 +1,20 @@\n+-include ../config.mak.autogen\n+-include ../config.mak\n+\n+ifeq ($(uname_S),Darwin)\n+OS_CONTRIB += credential/osxkeychain\n+endif\n+\n all::\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n \n test::\n \t$(MAKE) -C diff-highlight $@\n \t$(MAKE) -C subtree $@\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n \n clean::\n \t$(MAKE) -C contacts $@\n \t$(MAKE) -C diff-highlight $@\n \t$(MAKE) -C subtree $@\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\ndiff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile\nindex 219b0d7f49..d9fba07e8d 100644\n--- a/contrib/credential/osxkeychain/Makefile\n+++ b/contrib/credential/osxkeychain/Makefile\n@@ -10,4 +10,6 @@ install:\n clean:\n \t$(MAKE) -C ../../.. clean-git-credential-osxkeychain\n \n-.PHONY: all git-credential-osxkeychain install clean\n+test: git-credential-osxkeychain\n+\n+.PHONY: all git-credential-osxkeychain install clean test\n-- \ngitgitgadget\n"},{"id":"547364","messageId":"20260707165112.1750921-1-snatu@google.com","threadId":"65595","inReplyTo":"xmqqmrw3aoas.fsf@gitster.g","subject":"Re: [PATCH v5 1/2] Makefile: add $(GITLIBS) prerequisite to osxkeychain","fromName":"Shnatu","fromEmail":"snatu@google.com","sentAt":"2026-07-07T16:51:12Z","receivedAt":"2026-07-07T16:51:14Z","isPatch":true,"body":"> Sorry if I am mistaken, but as far as I can see, $(GITLIBS) includes\n> common-main.o (and it being .o, not .a, it is always included in the\n> result), and git-credential-osxkeychain.c comes with its own main()\n> function.\n>\n> Using a list of things to link that contains common-main.o does not\n> sound like a right thing to do; in other words, linking too many is\n> just as bad as linking too little.\n\nYou are completely right, and I missed that altogether!!\n\nIn v6, I have reverted Patch 1 back to depending explicitly on\n$(LIB_FILE) $(RUST_LIB) rather than $(GITLIBS) so that common-main.o is\nexcluded from the link step.\n\nTo ensure that linking errors in osxkeychain are caught automatically in\nfuture CI runs, I have also added a third patch to the series:\n\"contrib: wire up osxkeychain in contrib/Makefile on macOS\". This adds a\n\"test\" target to contrib/credential/osxkeychain/Makefile and wires it\ninto contrib/Makefile under \"all\", \"test\", and \"clean\" whenever running\non macOS (Darwin). Now, when CI runs \"make test\" with TEST_CONTRIB_TOO=yes\non macOS runners, osxkeychain will always be compiled and linked.\n"},{"id":"547367","messageId":"8f2bd4b14a3ed796fc58184d305e4b64ca52c9a9.1783443745.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v7.git.git.1783443745.gitgitgadget@gmail.com","subject":"[PATCH v7 1/3] Makefile: add $(RUST_LIB) prerequisite to osxkeychain","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-07T17:02:23Z","receivedAt":"2026-07-07T17:02:43Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen Rust is enabled, the git-credential-osxkeychain helper depends on\nRust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n(\"osxkeychain: fix build with Rust\") updated the linker command line to\nuse $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\nWithout this prerequisite, running a parallel build (\"make -j\") from a\nclean working tree can fail because Make does not know to invoke Cargo\nto build libgitcore.a before linking git-credential-osxkeychain.\n\nNote that we depend explicitly on $(LIB_FILE) and $(RUST_LIB) rather\nthan $(GITLIBS). Unlike standard Git builtins and programs like scalar\n(which define cmd_main() and rely on common-main.o to supply main()),\ngit-credential-osxkeychain.c defines its own standalone int main().\nIf $(GITLIBS) were used, $(filter %.o,$^) in the link recipe would\nmatch both git-credential-osxkeychain.o and common-main.o, causing a\nduplicate symbol linking error for _main on macOS.\n\nAdditionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\ntarget in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\nspecified, $(RUST_LIB) evaluates to empty, making the Rust dependency a\nclean no-op without needing intermediate variables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..7db38ecce9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -939,6 +939,7 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n RUST_TARGET_DIR = target/debug\n else\n@@ -950,6 +951,7 @@ RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3019,11 +3021,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n-- \ngitgitgadget\n\n"},{"id":"547368","messageId":"a999be6939284e4fdd9781f01fb9b9214ebc6516.1783443745.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v7.git.git.1783443745.gitgitgadget@gmail.com","subject":"[PATCH v7 2/3] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-07T17:02:24Z","receivedAt":"2026-07-07T17:02:45Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nOn macOS, Universal Binaries contain native executable code for\nmultiple architectures (such as Intel x86_64 and Apple Silicon arm64)\nbundled into a single file. This is standard practice for macOS\ndistribution and CI packaging (such as internal distribution packages\nor tooling like Burrito/Homebrew), allowing a single build artifact\nto run natively across all Macs without Rosetta emulation or\nmaintaining separate packages.\n\nWhen building Git C code for multiple architectures on macOS, the\nApple toolchain (clang) natively supports universal builds via\nCFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n\nCargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo\nrequires invoking each target triple independently (e.g., passing\n\"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nTo bridge this gap when Rust is enabled:\n  1. Allow specifying space-separated target triples in RUST_TARGETS.\n  2. Introduce declarative pattern rules (target/%/...) to compile\n     each target-specific library slice via Cargo.\n  3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     the mandatory Xcode Command Line Tools) to combine the resulting\n     static libraries into target/release/libgitcore.a.\n\nOnce $(RUST_LIB) is compiled into a universal static archive, the\nstandard C linker seamlessly links it with the C object files to\nproduce universal Git executables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 39 +++++++++++++++++++++++++++++++++++----\n 1 file changed, 35 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7db38ecce9..9921af992b 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default Rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -941,16 +949,17 @@ LIB_FILE = libgit.a\n \n ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t$(call mkdir_p_parent_template)\n+\t$(QUIET_GEN)\\\n+\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n+\tthen \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n-- \ngitgitgadget\n\n"},{"id":"547369","messageId":"32af2c51a892c2fd646a867df7eb5224d5ea39c2.1783443745.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v7.git.git.1783443745.gitgitgadget@gmail.com","subject":"[PATCH v7 3/3] contrib: wire up osxkeychain in contrib/Makefile on macOS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-07T17:02:25Z","receivedAt":"2026-07-07T17:02:47Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen running \"make test\" with TEST_CONTRIB_TOO=yes (which is default in\nmacOS CI workflows), $(MAKE) -C contrib/ test is invoked. However,\ncontrib/Makefile only invoked tests for diff-highlight and subtree,\nmeaning git-credential-osxkeychain was never built or verified during\nstandard CI test runs.\n\nAdd a \"test\" target to contrib/credential/osxkeychain/Makefile that\ndepends on building git-credential-osxkeychain. Additionally, wire up\ncredential/osxkeychain in contrib/Makefile under \"all\", \"test\", and\n\"clean\" whenever running on macOS (Darwin).\n\nThis ensures that running \"make test\" or \"make all\" in contrib on macOS\nautomatically builds and links git-credential-osxkeychain, preventing\nfuture build or symbol linking regressions from slipping through CI.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n contrib/Makefile                        | 10 ++++++++++\n contrib/credential/osxkeychain/Makefile |  4 +++-\n 2 files changed, 13 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/Makefile b/contrib/Makefile\nindex 787cd07f52..7962a9ff12 100644\n--- a/contrib/Makefile\n+++ b/contrib/Makefile\n@@ -1,10 +1,20 @@\n+-include ../config.mak.autogen\n+-include ../config.mak\n+\n+ifeq ($(uname_S),Darwin)\n+OS_CONTRIB += credential/osxkeychain\n+endif\n+\n all::\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n \n test::\n \t$(MAKE) -C diff-highlight $@\n \t$(MAKE) -C subtree $@\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n \n clean::\n \t$(MAKE) -C contacts $@\n \t$(MAKE) -C diff-highlight $@\n \t$(MAKE) -C subtree $@\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\ndiff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile\nindex 219b0d7f49..d9fba07e8d 100644\n--- a/contrib/credential/osxkeychain/Makefile\n+++ b/contrib/credential/osxkeychain/Makefile\n@@ -10,4 +10,6 @@ install:\n clean:\n \t$(MAKE) -C ../../.. clean-git-credential-osxkeychain\n \n-.PHONY: all git-credential-osxkeychain install clean\n+test: git-credential-osxkeychain\n+\n+.PHONY: all git-credential-osxkeychain install clean test\n-- \ngitgitgadget\n"},{"id":"547370","messageId":"pull.2288.v7.git.git.1783443745.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v6.git.git.1783378333.gitgitgadget@gmail.com","subject":"[PATCH v7 0/3] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-07T17:02:22Z","receivedAt":"2026-07-07T17:03:23Z","isPatch":true,"body":"This series improves macOS build reliability, automated CI verification, and\ndistribution support when Rust is enabled in the Git build system. It\naddresses three distinct challenges: a parallel build race condition in\ngit-credential-osxkeychain, support for macOS Universal Binaries\n(multi-architecture distribution), and missing automated CI test wiring for\nmacOS contrib utilities.\n\n\nWhy This Series is Needed\n=========================\n\n 1. Parallel Build Race Condition (make -j): While commit 522ea8ef7d\n    (\"osxkeychain: fix build with Rust\") updated the link command for\n    git-credential-osxkeychain to pass $(LIBS), it omitted $(RUST_LIB) from\n    the target prerequisite list. When running a parallel build (make -j)\n    from a clean working tree, Make can attempt to link\n    git-credential-osxkeychain before Cargo has finished compiling\n    libgitcore.a, causing linker failures.\n\n 2. macOS Universal Binary (lipo) Support: On macOS, Universal Binaries\n    bundle native executable code for multiple architectures (Intel x86_64\n    and Apple Silicon arm64) into a single file. This is standard practice\n    for macOS distribution and CI packaging (such as Burrito, Homebrew, and\n    Git's macOS CI runners), allowing a single artifact to run natively\n    across all Macs without Rosetta translation.\n\nWhile Apple's C compiler (clang) natively supports universal builds by\npassing -arch x86_64 -arch arm64 in CFLAGS and LDFLAGS, Cargo and rustc do\nnot support multiple -arch flags in a single invocation. Instead, Cargo must\nbe invoked separately for each target triple (--target x86_64-apple-darwin\nand --target aarch64-apple-darwin). This series bridges that gap.\n\n 3. Automated CI Verification for Contrib on macOS: When running make test\n    with TEST_CONTRIB_TOO=yes (default in macOS CI workflows), $(MAKE) -C\n    contrib/ test is invoked. However, contrib/Makefile only invoked tests\n    for diff-highlight and subtree, meaning git-credential-osxkeychain was\n    never compiled or verified during standard CI test runs.\n\n\nOverview of Patches\n===================\n\n * Patch 1: Makefile: add $(RUST_LIB) prerequisite to osxkeychain Adds\n   $(RUST_LIB) as a prerequisite dependency to the osxkeychain target,\n   eliminating the parallel build race condition. Additionally, wraps the\n   definitions of $(RUST_LIB) and the rust build target in ifndef NO_RUST so\n   that disabling Rust cleanly makes the dependency a no-op.\n\n * Patch 2: Makefile: support universal macOS builds via RUST_TARGETS Allows\n   users to specify space-separated target triples in RUST_TARGETS.\n   Introduces declarative pattern rules (target/%/...) to compile each\n   target slice via Cargo, and uses lipo (part of the mandatory Xcode\n   Command Line Tools) to combine the resulting static archives into a\n   universal library at target/release/libgitcore.a. Uses\n   mkdir_p_parent_template to guarantee directory creation before lipo.\n   \n   * Patch 3: contrib: wire up osxkeychain in contrib/Makefile on macOS Adds\n     a test target to contrib/credential/osxkeychain/Makefile that depends\n     on building git-credential-osxkeychain. Introduces a generic OS_CONTRIB\n     variable in contrib/Makefile to conditionally wire\n     credential/osxkeychain into all, test, and clean whenever running on\n     macOS (Darwin). This guarantees that standard CI test runs on macOS\n     automatically compile and link the helper, preventing build\n     regressions.\n\nChanges since v5:\n\n * Reverted Patch 1 to depend explicitly on $(LIB_FILE) $(RUST_LIB) rather\n   than $(GITLIBS). Unlike Git builtins or scalar (which define cmd_main()),\n   git-credential-osxkeychain.c defines its own standalone main(), meaning\n   $(GITLIBS) caused a duplicate symbol error for _main during linking.\n * Added Patch 3 (\"contrib: wire up osxkeychain in contrib/Makefile on\n   macOS\") using a scalable OS_CONTRIB variable so that running make test\n   with TEST_CONTRIB_TOO=yes in macOS CI workflows automatically verifies\n   compilation and linking integrity.\n\nChanges since v4:\n\n * Changed the osxkeychain prerequisite dependency from $(LIB_FILE)\n   $(RUST_LIB) to $(GITLIBS) to match the canonical prerequisite pattern\n   used by all other core Git targets linking $(LIBS).\n\nChanges since v3:\n\n * Removed leading @ from $(call mkdir_p_parent_template) so it relies on\n   the built-in $(QUIET_MKDIR_P_PARENT) behavior, matching existing Makefile\n   conventions.\n * Replaced if [ with if test in Bourne shell recipe snippets to strictly\n   adhere to the project's CodingGuidelines.\n\nChanges since v2:\n\n * Split the original combined commit into a two-patch series to separate\n   prerequisite bug fixes from Universal Binary features.\n * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n   that parent target directories exist.\n\nShardul Natu (3):\n  Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n  Makefile: support universal macOS builds via RUST_TARGETS\n  contrib: wire up osxkeychain in contrib/Makefile on macOS\n\n Makefile                                | 46 ++++++++++++++++++++++---\n contrib/Makefile                        | 10 ++++++\n contrib/credential/osxkeychain/Makefile |  4 ++-\n 3 files changed, 54 insertions(+), 6 deletions(-)\n\n\nbase-commit: 00534a21ce949ef80a5b8b9d7fc20b7d381038e9\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v7\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v7\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v6:\n\n 1:  0d215139406 = 1:  8f2bd4b14a3 Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n 2:  21dedb91f09 = 2:  a999be69392 Makefile: support universal macOS builds via RUST_TARGETS\n 3:  8455e449f38 = 3:  32af2c51a89 contrib: wire up osxkeychain in contrib/Makefile on macOS\n\n-- \ngitgitgadget\n"},{"id":"547387","messageId":"xmqqjyr638t1.fsf@gitster.g","threadId":"65595","inReplyTo":"pull.2288.v7.git.git.1783443745.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 0/3] Makefile: link osxkeychain helper against Rust","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-07T19:21:14Z","receivedAt":"2026-07-07T19:21:16Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This series improves macOS build reliability, automated CI verification, and\n> distribution support when Rust is enabled in the Git build system. It\n> addresses three distinct challenges: a parallel build race condition in\n> git-credential-osxkeychain, support for macOS Universal Binaries\n> (multi-architecture distribution), and missing automated CI test wiring for\n> macOS contrib utilities.\n> ...\n> Range-diff vs v6:\n>\n>  1:  0d215139406 = 1:  8f2bd4b14a3 Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n>  2:  21dedb91f09 = 2:  a999be69392 Makefile: support universal macOS builds via RUST_TARGETS\n>  3:  8455e449f38 = 3:  32af2c51a89 contrib: wire up osxkeychain in contrib/Makefile on macOS\n\nDid an automation go wrong, or something?  I have v6 queued already\nso I'd skip this round that is identical for now.\n\n"},{"id":"547403","messageId":"20260707203750.1860740-1-snatu@google.com","threadId":"65595","inReplyTo":"xmqqmrw3aoas.fsf@gitster.g","subject":"Re: [PATCH v7 0/3] Makefile: link osxkeychain helper against Rust","fromName":"Shnatu","fromEmail":"snatu@google.com","sentAt":"2026-07-07T20:37:50Z","receivedAt":"2026-07-07T20:37:51Z","isPatch":true,"body":"> Did an automation go wrong, or something?  I have v6 queued already\n> so I'd skip this round that is identical for now.\n\nI saw my branch being some 700 commits ahead and just rebased it on top\nof the latest on git/next. No changes to the PR code though.\n"},{"id":"547417","messageId":"xmqqa4s2z496.fsf@gitster.g","threadId":"65595","inReplyTo":"32af2c51a892c2fd646a867df7eb5224d5ea39c2.1783443745.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 3/3] contrib: wire up osxkeychain in contrib/Makefile on macOS","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-08T00:58:29Z","receivedAt":"2026-07-08T00:58:32Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Shardul Natu <snatu@google.com>\n>\n> When running \"make test\" with TEST_CONTRIB_TOO=yes (which is default in\n> macOS CI workflows), $(MAKE) -C contrib/ test is invoked. However,\n> contrib/Makefile only invoked tests for diff-highlight and subtree,\n> meaning git-credential-osxkeychain was never built or verified during\n> standard CI test runs.\n>\n> Add a \"test\" target to contrib/credential/osxkeychain/Makefile that\n> depends on building git-credential-osxkeychain. Additionally, wire up\n> credential/osxkeychain in contrib/Makefile under \"all\", \"test\", and\n> \"clean\" whenever running on macOS (Darwin).\n>\n> This ensures that running \"make test\" or \"make all\" in contrib on macOS\n> automatically builds and links git-credential-osxkeychain, preventing\n> future build or symbol linking regressions from slipping through CI.\n>\n> Signed-off-by: Shardul Natu <snatu@google.com>\n> ---\n>  contrib/Makefile                        | 10 ++++++++++\n>  contrib/credential/osxkeychain/Makefile |  4 +++-\n>  2 files changed, 13 insertions(+), 1 deletion(-)\n>\n> diff --git a/contrib/Makefile b/contrib/Makefile\n> index 787cd07f52..7962a9ff12 100644\n> --- a/contrib/Makefile\n> +++ b/contrib/Makefile\n> @@ -1,10 +1,20 @@\n> +-include ../config.mak.autogen\n> +-include ../config.mak\n> +\n> +ifeq ($(uname_S),Darwin)\n> +OS_CONTRIB += credential/osxkeychain\n> +endif\n\nIs $(uname_S) defined here at this point with only the above two\nincludes?  Don't you need to include ../config.mak.uname as well?\n\nThe top-level Makefile does this:\n\n        include config.mak.uname\n        -include config.mak.autogen\n        -include config.mak\n\nand so should this one, I think, in exactly the same order.\n\n>  all::\n> +\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n>  \n>  test::\n>  \t$(MAKE) -C diff-highlight $@\n>  \t$(MAKE) -C subtree $@\n> +\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n>  \n>  clean::\n>  \t$(MAKE) -C contacts $@\n>  \t$(MAKE) -C diff-highlight $@\n>  \t$(MAKE) -C subtree $@\n> +\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n> diff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile\n> index 219b0d7f49..d9fba07e8d 100644\n> --- a/contrib/credential/osxkeychain/Makefile\n> +++ b/contrib/credential/osxkeychain/Makefile\n> @@ -10,4 +10,6 @@ install:\n>  clean:\n>  \t$(MAKE) -C ../../.. clean-git-credential-osxkeychain\n>  \n> -.PHONY: all git-credential-osxkeychain install clean\n> +test: git-credential-osxkeychain\n> +\n> +.PHONY: all git-credential-osxkeychain install clean test\n"},{"id":"547428","messageId":"20260708031552.157939-1-snatu@google.com","threadId":"65595","inReplyTo":"xmqqmrw3aoas.fsf@gitster.g","subject":"Re: [PATCH v7 3/3] contrib: wire up osxkeychain in contrib/Makefile on macOS","fromName":"Shardul Natu","fromEmail":"snatu@google.com","sentAt":"2026-07-08T03:15:52Z","receivedAt":"2026-07-08T03:15:54Z","isPatch":true,"body":"> Is $(uname_S) defined here at this point with only the above two\n> includes?  Don't you need to include ../config.mak.uname as well?\n> \n> The top-level Makefile does this:\n> \n>         include config.mak.uname\n>         -include config.mak.autogen\n>         -include config.mak\n> \n> and so should this one, I think, in exactly the same order.\n\nAh, yes. I have updated the include sequence in contrib/Makefile to:\n  include ../config.mak.uname\n  -include ../config.mak.autogen\n  -include ../config.mak\n"},{"id":"547429","messageId":"pull.2288.v8.git.git.1783480879.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v7.git.git.1783443745.gitgitgadget@gmail.com","subject":"[PATCH v8 0/3] Makefile: link osxkeychain helper against Rust","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-08T03:21:16Z","receivedAt":"2026-07-08T03:21:22Z","isPatch":true,"body":"This series improves macOS build reliability, automated CI verification, and\ndistribution support when Rust is enabled in the Git build system. It\naddresses three distinct challenges: a parallel build race condition in\ngit-credential-osxkeychain, support for macOS Universal Binaries\n(multi-architecture distribution), and missing automated CI test wiring for\nmacOS contrib utilities.\n\n\nWhy This Series is Needed\n=========================\n\n 1. Parallel Build Race Condition (make -j): While commit 522ea8ef7d\n    (\"osxkeychain: fix build with Rust\") updated the link command for\n    git-credential-osxkeychain to pass $(LIBS), it omitted $(RUST_LIB) from\n    the target prerequisite list. When running a parallel build (make -j)\n    from a clean working tree, Make can attempt to link\n    git-credential-osxkeychain before Cargo has finished compiling\n    libgitcore.a, causing linker failures.\n\n 2. macOS Universal Binary (lipo) Support: On macOS, Universal Binaries\n    bundle native executable code for multiple architectures (Intel x86_64\n    and Apple Silicon arm64) into a single file. This is standard practice\n    for macOS distribution and CI packaging (such as Burrito, Homebrew, and\n    Git's macOS CI runners), allowing a single artifact to run natively\n    across all Macs without Rosetta translation.\n\nWhile Apple's C compiler (clang) natively supports universal builds by\npassing -arch x86_64 -arch arm64 in CFLAGS and LDFLAGS, Cargo and rustc do\nnot support multiple -arch flags in a single invocation. Instead, Cargo must\nbe invoked separately for each target triple (--target x86_64-apple-darwin\nand --target aarch64-apple-darwin). This series bridges that gap.\n\n 3. Automated CI Verification for Contrib on macOS: When running make test\n    with TEST_CONTRIB_TOO=yes (default in macOS CI workflows), $(MAKE) -C\n    contrib/ test is invoked. However, contrib/Makefile only invoked tests\n    for diff-highlight and subtree, meaning git-credential-osxkeychain was\n    never compiled or verified during standard CI test runs.\n\n\nOverview of Patches\n===================\n\n * Patch 1: Makefile: add $(RUST_LIB) prerequisite to osxkeychain Adds\n   $(RUST_LIB) as a prerequisite dependency to the osxkeychain target,\n   eliminating the parallel build race condition. Additionally, wraps the\n   definitions of $(RUST_LIB) and the rust build target in ifndef NO_RUST so\n   that disabling Rust cleanly makes the dependency a no-op.\n\n * Patch 2: Makefile: support universal macOS builds via RUST_TARGETS Allows\n   users to specify space-separated target triples in RUST_TARGETS.\n   Introduces declarative pattern rules (target/%/...) to compile each\n   target slice via Cargo, and uses lipo (part of the mandatory Xcode\n   Command Line Tools) to combine the resulting static archives into a\n   universal library at target/release/libgitcore.a. Uses\n   mkdir_p_parent_template to guarantee directory creation before lipo.\n   \n   * Patch 3: contrib: wire up osxkeychain in contrib/Makefile on macOS Adds\n     a test target to contrib/credential/osxkeychain/Makefile that depends\n     on building git-credential-osxkeychain. Introduces a generic OS_CONTRIB\n     variable in contrib/Makefile to conditionally wire\n     credential/osxkeychain into all, test, and clean whenever running on\n     macOS (Darwin). This guarantees that standard CI test runs on macOS\n     automatically compile and link the helper, preventing build\n     regressions.\n\nChanges since v7:\n\n * Added inclusion of ../config.mak.uname to the top of contrib/Makefile in\n   the canonical order. This guarantees that $(uname_S) is correctly defined\n   on the shell, preventing the OS_CONTRIB additions from being silently\n   ignored.\n\nChanges since v5:\n\n * Reverted Patch 1 to depend explicitly on $(LIB_FILE) $(RUST_LIB) rather\n   than $(GITLIBS). Unlike Git builtins or scalar (which define cmd_main()),\n   git-credential-osxkeychain.c defines its own standalone main(), meaning\n   $(GITLIBS) caused a duplicate symbol error for _main during linking.\n * Added Patch 3 (\"contrib: wire up osxkeychain in contrib/Makefile on\n   macOS\") using a scalable OS_CONTRIB variable so that running make test\n   with TEST_CONTRIB_TOO=yes in macOS CI workflows automatically verifies\n   compilation and linking integrity.\n\nChanges since v4:\n\n * Changed the osxkeychain prerequisite dependency from $(LIB_FILE)\n   $(RUST_LIB) to $(GITLIBS) to match the canonical prerequisite pattern\n   used by all other core Git targets linking $(LIBS).\n\nChanges since v3:\n\n * Removed leading @ from $(call mkdir_p_parent_template) so it relies on\n   the built-in $(QUIET_MKDIR_P_PARENT) behavior, matching existing Makefile\n   conventions.\n * Replaced if [ with if test in Bourne shell recipe snippets to strictly\n   adhere to the project's CodingGuidelines.\n\nChanges since v2:\n\n * Split the original combined commit into a two-patch series to separate\n   prerequisite bug fixes from Universal Binary features.\n * Added $(call mkdir_p_parent_template) prior to invoking lipo to guarantee\n   that parent target directories exist.\n\nShardul Natu (3):\n  Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n  Makefile: support universal macOS builds via RUST_TARGETS\n  contrib: wire up osxkeychain in contrib/Makefile on macOS\n\n Makefile                                | 46 ++++++++++++++++++++++---\n contrib/Makefile                        | 12 +++++++\n contrib/credential/osxkeychain/Makefile |  4 ++-\n 3 files changed, 56 insertions(+), 6 deletions(-)\n\n\nbase-commit: 00534a21ce949ef80a5b8b9d7fc20b7d381038e9\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2288%2Fkiranani%2Fnext-v8\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2288/kiranani/next-v8\nPull-Request: https://github.com/git/git/pull/2288\n\nRange-diff vs v7:\n\n 1:  8f2bd4b14a = 1:  8f2bd4b14a Makefile: add $(RUST_LIB) prerequisite to osxkeychain\n 2:  a999be6939 = 2:  a999be6939 Makefile: support universal macOS builds via RUST_TARGETS\n 3:  32af2c51a8 ! 3:  5659709ab4 contrib: wire up osxkeychain in contrib/Makefile on macOS\n     @@ Commit message\n      \n       ## contrib/Makefile ##\n      @@\n     ++include ../config.mak.uname\n      +-include ../config.mak.autogen\n      +-include ../config.mak\n      +\n     ++\n      +ifeq ($(uname_S),Darwin)\n      +OS_CONTRIB += credential/osxkeychain\n      +endif\n\n-- \ngitgitgadget\n"},{"id":"547430","messageId":"8f2bd4b14a3ed796fc58184d305e4b64ca52c9a9.1783480879.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v8.git.git.1783480879.gitgitgadget@gmail.com","subject":"[PATCH v8 1/3] Makefile: add $(RUST_LIB) prerequisite to osxkeychain","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-08T03:21:17Z","receivedAt":"2026-07-08T03:21:23Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen Rust is enabled, the git-credential-osxkeychain helper depends on\nRust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d\n(\"osxkeychain: fix build with Rust\") updated the linker command line to\nuse $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.\nWithout this prerequisite, running a parallel build (\"make -j\") from a\nclean working tree can fail because Make does not know to invoke Cargo\nto build libgitcore.a before linking git-credential-osxkeychain.\n\nNote that we depend explicitly on $(LIB_FILE) and $(RUST_LIB) rather\nthan $(GITLIBS). Unlike standard Git builtins and programs like scalar\n(which define cmd_main() and rely on common-main.o to supply main()),\ngit-credential-osxkeychain.c defines its own standalone int main().\nIf $(GITLIBS) were used, $(filter %.o,$^) in the link recipe would\nmatch both git-credential-osxkeychain.o and common-main.o, causing a\nduplicate symbol linking error for _main on macOS.\n\nAdditionally, wrap the definitions of $(RUST_LIB) and the \"rust\" build\ntarget in \"ifndef NO_RUST\". This ensures that when NO_RUST=1 is\nspecified, $(RUST_LIB) evaluates to empty, making the Rust dependency a\nclean no-op without needing intermediate variables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1f3f099f5c..7db38ecce9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -939,6 +939,7 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n \n LIB_FILE = libgit.a\n \n+ifndef NO_RUST\n ifdef DEBUG\n RUST_TARGET_DIR = target/debug\n else\n@@ -950,6 +951,7 @@ RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n else\n RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n endif\n+endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n EXTLIBS =\n@@ -3019,11 +3021,13 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+ifndef NO_RUST\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n \n .PHONY: rust\n rust: $(RUST_LIB)\n+endif\n \n export DEFAULT_EDITOR DEFAULT_PAGER\n \n@@ -4074,7 +4078,8 @@ $(LIBGIT_HIDDEN_EXPORT): $(LIBGIT_PARTIAL_EXPORT)\n contrib/libgit-sys/libgitpub.a: $(LIBGIT_HIDDEN_EXPORT)\n \t$(AR) $(ARFLAGS) $@ $^\n \n-contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) GIT-LDFLAGS\n+# When Rust is enabled, git-credential-osxkeychain depends on Rust symbols in $(RUST_LIB)\n+contrib/credential/osxkeychain/git-credential-osxkeychain: contrib/credential/osxkeychain/git-credential-osxkeychain.o $(LIB_FILE) $(RUST_LIB) GIT-LDFLAGS\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \\\n \t\t$(filter %.o,$^) $(LIBS) -framework Security -framework CoreFoundation\n \n-- \ngitgitgadget\n\n"},{"id":"547431","messageId":"a999be6939284e4fdd9781f01fb9b9214ebc6516.1783480879.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v8.git.git.1783480879.gitgitgadget@gmail.com","subject":"[PATCH v8 2/3] Makefile: support universal macOS builds via RUST_TARGETS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-08T03:21:18Z","receivedAt":"2026-07-08T03:21:24Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nOn macOS, Universal Binaries contain native executable code for\nmultiple architectures (such as Intel x86_64 and Apple Silicon arm64)\nbundled into a single file. This is standard practice for macOS\ndistribution and CI packaging (such as internal distribution packages\nor tooling like Burrito/Homebrew), allowing a single build artifact\nto run natively across all Macs without Rosetta emulation or\nmaintaining separate packages.\n\nWhen building Git C code for multiple architectures on macOS, the\nApple toolchain (clang) natively supports universal builds via\nCFLAGS/LDFLAGS. When \"-arch x86_64 -arch arm64\" is passed, clang\nautomatically compiles and links universal binaries for all C object\nfiles and executables out of the box.\n\nCargo and rustc, however, do not support multiple \"-arch\" flags or\nemitting universal binaries in a single invocation. Instead, Cargo\nrequires invoking each target triple independently (e.g., passing\n\"--target x86_64-apple-darwin\" and \"--target aarch64-apple-darwin\").\n\nTo bridge this gap when Rust is enabled:\n  1. Allow specifying space-separated target triples in RUST_TARGETS.\n  2. Introduce declarative pattern rules (target/%/...) to compile\n     each target-specific library slice via Cargo.\n  3. On macOS, if multiple targets are specified, use \"lipo\" (part of\n     the mandatory Xcode Command Line Tools) to combine the resulting\n     static libraries into target/release/libgitcore.a.\n\nOnce $(RUST_LIB) is compiled into a universal static archive, the\nstandard C linker seamlessly links it with the C object files to\nproduce universal Git executables.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n Makefile | 39 +++++++++++++++++++++++++++++++++++----\n 1 file changed, 35 insertions(+), 4 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7db38ecce9..9921af992b 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -500,6 +500,14 @@ include shared.mak\n #\n # Building Rust code requires Cargo.\n #\n+# Define RUST_TARGETS if you want to cross-compile. If left unspecified, it uses\n+# the default Rust target on the system.\n+#\n+# On macOS, this supports specifying multiple targets, separated by a space.\n+# This will produce a Universal static library using `lipo`.\n+#\n+# Example: RUST_TARGETS=\"aarch64-apple-darwin x86_64-apple-darwin\"\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -941,16 +949,17 @@ LIB_FILE = libgit.a\n \n ifndef NO_RUST\n ifdef DEBUG\n-RUST_TARGET_DIR = target/debug\n+RUST_BUILD_CONFIG = debug\n else\n-RUST_TARGET_DIR = target/release\n+RUST_BUILD_CONFIG = release\n endif\n \n ifeq ($(uname_S),Windows)\n-RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib\n+RUST_LIB_NAME = gitcore.lib\n else\n-RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a\n+RUST_LIB_NAME = libgitcore.a\n endif\n+RUST_LIB = target/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME)\n endif\n \n GITLIBS = common-main.o $(LIB_FILE)\n@@ -3022,8 +3031,30 @@ $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n ifndef NO_RUST\n+ifeq ($(RUST_TARGETS),)\n $(RUST_LIB): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n \t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+else\n+ifneq ($(words $(RUST_TARGETS)),1)\n+ifneq ($(uname_S),Darwin)\n+$(error Building universal Rust libraries requires macOS (lipo is not available on $(uname_S)))\n+endif\n+endif\n+\n+RUST_MEMBER_LIBS = $(foreach target,$(RUST_TARGETS),target/$(target)/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME))\n+$(RUST_MEMBER_LIBS): target/%/$(RUST_BUILD_CONFIG)/$(RUST_LIB_NAME): Cargo.toml $(RUST_SOURCES) $(LIB_FILE)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS) --target $*\n+\n+$(RUST_LIB): $(RUST_MEMBER_LIBS)\n+\t$(call mkdir_p_parent_template)\n+\t$(QUIET_GEN)\\\n+\tif test $(words $(RUST_TARGETS)) -gt 1; \\\n+\tthen \\\n+\t\tlipo -create $^ -output $@; \\\n+\telse \\\n+\t\tcp $< $@; \\\n+\tfi\n+endif\n \n .PHONY: rust\n rust: $(RUST_LIB)\n-- \ngitgitgadget\n\n"},{"id":"547432","messageId":"5659709ab4193ee4a63ea7f51cb7eb1b31fff5e0.1783480879.git.gitgitgadget@gmail.com","threadId":"65595","inReplyTo":"pull.2288.v8.git.git.1783480879.gitgitgadget@gmail.com","subject":"[PATCH v8 3/3] contrib: wire up osxkeychain in contrib/Makefile on macOS","fromName":"Shardul Natu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-07-08T03:21:19Z","receivedAt":"2026-07-08T03:21:26Z","isPatch":true,"body":"From: Shardul Natu <snatu@google.com>\n\nWhen running \"make test\" with TEST_CONTRIB_TOO=yes (which is default in\nmacOS CI workflows), $(MAKE) -C contrib/ test is invoked. However,\ncontrib/Makefile only invoked tests for diff-highlight and subtree,\nmeaning git-credential-osxkeychain was never built or verified during\nstandard CI test runs.\n\nAdd a \"test\" target to contrib/credential/osxkeychain/Makefile that\ndepends on building git-credential-osxkeychain. Additionally, wire up\ncredential/osxkeychain in contrib/Makefile under \"all\", \"test\", and\n\"clean\" whenever running on macOS (Darwin).\n\nThis ensures that running \"make test\" or \"make all\" in contrib on macOS\nautomatically builds and links git-credential-osxkeychain, preventing\nfuture build or symbol linking regressions from slipping through CI.\n\nSigned-off-by: Shardul Natu <snatu@google.com>\n---\n contrib/Makefile                        | 12 ++++++++++++\n contrib/credential/osxkeychain/Makefile |  4 +++-\n 2 files changed, 15 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/Makefile b/contrib/Makefile\nindex 787cd07f52..1203c7263d 100644\n--- a/contrib/Makefile\n+++ b/contrib/Makefile\n@@ -1,10 +1,22 @@\n+include ../config.mak.uname\n+-include ../config.mak.autogen\n+-include ../config.mak\n+\n+\n+ifeq ($(uname_S),Darwin)\n+OS_CONTRIB += credential/osxkeychain\n+endif\n+\n all::\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n \n test::\n \t$(MAKE) -C diff-highlight $@\n \t$(MAKE) -C subtree $@\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\n \n clean::\n \t$(MAKE) -C contacts $@\n \t$(MAKE) -C diff-highlight $@\n \t$(MAKE) -C subtree $@\n+\t$(foreach dir,$(OS_CONTRIB),$(MAKE) -C $(dir) $@;)\ndiff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile\nindex 219b0d7f49..d9fba07e8d 100644\n--- a/contrib/credential/osxkeychain/Makefile\n+++ b/contrib/credential/osxkeychain/Makefile\n@@ -10,4 +10,6 @@ install:\n clean:\n \t$(MAKE) -C ../../.. clean-git-credential-osxkeychain\n \n-.PHONY: all git-credential-osxkeychain install clean\n+test: git-credential-osxkeychain\n+\n+.PHONY: all git-credential-osxkeychain install clean test\n-- \ngitgitgadget\n"},{"id":"547532","messageId":"xmqq4ii9teym.fsf@gitster.g","threadId":"65595","inReplyTo":"pull.2288.v8.git.git.1783480879.gitgitgadget@gmail.com","subject":"Re: [PATCH v8 0/3] Makefile: link osxkeychain helper against Rust","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-08T20:16:01Z","receivedAt":"2026-07-08T20:16:05Z","isPatch":true,"body":"\"Shardul Natu via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> Changes since v7:\n>\n>  * Added inclusion of ../config.mak.uname to the top of contrib/Makefile in\n>    the canonical order. This guarantees that $(uname_S) is correctly defined\n>    on the shell, preventing the OS_CONTRIB additions from being silently\n>    ignored.\n\nThis round of patches looked good to me (even though I am not a\nmacOS user, so my review only goes on the surface without actual\ntesting).\n"}]}