{"thread":{"id":"27535","subject":"[PATCH v2] Embed an application manifest on MinGW","startedAt":"2011-06-02T10:35:37Z","lastAt":"2011-06-02T22:56:47Z","messageCount":4,"participants":["Cesar Eduardo Barros","Johannes Schindelin","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"169183","messageId":"1307010937-2894-1-git-send-email-cesarb@cesarb.net","threadId":"27535","inReplyTo":null,"subject":"[PATCH v2] Embed an application manifest on MinGW","fromName":"Cesar Eduardo Barros","fromEmail":"cesarb@cesarb.net","sentAt":"2011-06-02T10:35:37Z","receivedAt":"2011-06-02T10:35:37Z","isPatch":true,"sender":{"key":"cesarb@cesarb.net","avatar":"https://avatars.githubusercontent.com/u/31324?v=4"},"body":"On Windows Vista, not having an application manifest with a\nrequestedExecutionLevel can cause several kinds of confusing behavior.\n\nThe first and more obvious is Installer Detection, where sometimes\nWindows decides (by looking at things like the file name and even\nsequences of bytes within the executable) that an executable is an\ninstaller and should run elevated (causing the well-known popup dialog\nto appear). On git, this happens for executables with names containing\n\"patch\" or \"update\".\n\nThe second and more confusing is File Virtualization. With it, writes to\nsome files which should fail are instead redirected to somewhere else,\nand reads to files might return different contents if a previous write\nwas redirected. Even more confusing, not all writes are redirected; I\nrecall reading somewhere that for instance writes to .exe files will\nfail instead of redirecting.\n\nNeedless to say, git wants none of that. Not only that, but File\nVirtualization has been blamed for dramatic slowdowns in git (see for\ninstance http://code.google.com/p/msysgit/issues/detail?id=320).\n\nThere are two ways to turn off these annoyances. Either you embed an\napplication manifest within all your executables, or you add an external\nmanifest (a file with the same name followed by .manifest) to all your\nexecutables. Since for git some executables are copied (or hardlinked)\nwith several names, it is simpler and more robust to embed an internal\nmanifest.\n\nA recent enough MSVC compiler should already embed a working internal\nmanifest, but for mingw you have to do so by hand.\n\nVery lightly tested on Wine, where like on Windows XP it should not make\nany difference.\n\nReferences:\n  - New UAC Technologies for Windows Vista\n    http://msdn.microsoft.com/en-us/library/bb756960.aspx\n  - Create and Embed an Application Manifest (UAC)\n    http://msdn.microsoft.com/en-us/library/bb756929.aspx\n\nv2: Create GITLIBDEPS and use it instead of GITLIBS. RESOURCE_OBJS\n    cannot be added directly to GITLIBS because it would add the\n    manifest twice to executables which use $(filter %.o,$^) in the\n    Makefile rule (since LIBS also includes GITLIBS).\n\nSigned-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>\n---\n Makefile                  |   31 +++++++++++++++++++++++--------\n compat/win32/git.manifest |   11 +++++++++++\n compat/win32/resource.rc  |    1 +\n 3 files changed, 35 insertions(+), 8 deletions(-)\n create mode 100644 compat/win32/git.manifest\n create mode 100644 compat/win32/resource.rc\n\ndiff --git a/Makefile b/Makefile\nindex b2e1759..da371c2 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -324,6 +324,7 @@ XGETTEXT = xgettext\n PTHREAD_LIBS = -lpthread\n PTHREAD_CFLAGS =\n GCOV = gcov\n+WINDRES = windres\n \n export TCL_PATH TCLTK_PATH\n \n@@ -344,6 +345,7 @@ BUILTIN_OBJS =\n BUILT_INS =\n COMPAT_CFLAGS =\n COMPAT_OBJS =\n+RESOURCE_OBJS =\n EXTRA_CPPFLAGS =\n LIB_H =\n LIB_OBJS =\n@@ -786,6 +788,8 @@ BUILTIN_OBJS += builtin/write-tree.o\n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n EXTLIBS =\n \n+GITLIBDEPS = $(RESOURCE_OBJS) $(GITLIBS)\n+\n #\n # Platform specific tweaks\n #\n@@ -1181,6 +1185,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_INET_PTON = YesPlease\n \tNO_INET_NTOP = YesPlease\n \tNO_POSIX_GOODIES = UnfortunatelyYes\n+\tAPPLICATION_MANIFEST = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/winansi.o \\\n@@ -1575,6 +1580,11 @@ ifdef USE_NED_ALLOCATOR\n        COMPAT_OBJS += compat/nedmalloc/nedmalloc.o\n endif\n \n+ifdef APPLICATION_MANIFEST\n+\t# Cannot be in LIB_OBJS because it must always be linked in\n+\tRESOURCE_OBJS += compat/win32/resource.o\n+endif\n+\n ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT\n \texport GIT_TEST_CMP_USE_COPIED_CONTEXT\n endif\n@@ -1610,6 +1620,7 @@ ifndef V\n \tQUIET_LNCP     = @echo '   ' LN/CP $@;\n \tQUIET_XGETTEXT = @echo '   ' XGETTEXT $@;\n \tQUIET_GCOV     = @echo '   ' GCOV $@;\n+\tQUIET_WINDRES  = @echo '   ' RC $@;\n \tQUIET_SP       = @echo '   ' SP $<;\n \tQUIET_SUBDIR0  = +@subdir=\n \tQUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \\\n@@ -1711,9 +1722,9 @@ git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='\"$(GIT_VERSION)\"' \\\n \t'-DGIT_MAN_PATH=\"$(mandir_SQ)\"' \\\n \t'-DGIT_INFO_PATH=\"$(infodir_SQ)\"'\n \n-git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)\n+git$X: git.o $(BUILTIN_OBJS) $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \\\n-\t\t$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)\n+\t\t$(BUILTIN_OBJS) $(RESOURCE_OBJS) $(ALL_LDFLAGS) $(LIBS)\n \n help.sp help.o: common-cmds.h\n \n@@ -2011,17 +2022,17 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \\\n \t-DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR\n endif\n \n-git-%$X: %.o $(GITLIBS)\n+git-%$X: %.o $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)\n \n-git-imap-send$X: imap-send.o $(GITLIBS)\n+git-imap-send$X: imap-send.o $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)\n \n-git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)\n+git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL)\n-git-http-push$X: revision.o http.o http-push.o $(GITLIBS)\n+git-http-push$X: revision.o http.o http-push.o $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)\n \n@@ -2031,10 +2042,14 @@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY)\n \tln -s $< $@ 2>/dev/null || \\\n \tcp $< $@\n \n-$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)\n+$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)\n \n+%.o: %.rc\n+\t$(QUIET_WINDRES)$(WINDRES) $< $@\n+compat/win32/resource.o: compat/win32/git.manifest\n+\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)\n \n@@ -2172,7 +2187,7 @@ test-svn-fe$X: vcs-svn/lib.a\n \n .PRECIOUS: $(TEST_OBJS)\n \n-test-%$X: test-%.o $(GITLIBS)\n+test-%$X: test-%.o $(GITLIBDEPS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)\n \n check-sha1:: test-sha1$X\ndiff --git a/compat/win32/git.manifest b/compat/win32/git.manifest\nnew file mode 100644\nindex 0000000..a82605c\n--- /dev/null\n+++ b/compat/win32/git.manifest\n@@ -0,0 +1,11 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n+<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n+\t<assemblyIdentity type=\"win32\" name=\"Git\" processorArchitecture=\"x86\" version=\"0.0.0.0\" />\n+\t<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n+\t\t<security>\n+\t\t\t<requestedPrivileges>\n+\t\t\t\t<requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\" />\n+\t\t\t</requestedPrivileges>\n+\t\t</security>\n+\t</trustInfo>\n+</assembly>\ndiff --git a/compat/win32/resource.rc b/compat/win32/resource.rc\nnew file mode 100644\nindex 0000000..c2bf4a6\n--- /dev/null\n+++ b/compat/win32/resource.rc\n@@ -0,0 +1 @@\n+1 24 \"git.manifest\"\n-- \n1.7.4.4\n"},{"id":"169196","messageId":"alpine.DEB.1.00.1106021625100.1594@bonsai2","threadId":"27535","inReplyTo":"1307010937-2894-1-git-send-email-cesarb@cesarb.net","subject":"Re: [PATCH v2] Embed an application manifest on MinGW","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2011-06-02T14:26:54Z","receivedAt":"2011-06-02T14:26:54Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Dear Cesar,\n\nOn Thu, 2 Jun 2011, Cesar Eduardo Barros wrote:\n\n> v2: Create GITLIBDEPS and use it instead of GITLIBS. RESOURCE_OBJS\n>     cannot be added directly to GITLIBS because it would add the\n>     manifest twice to executables which use $(filter %.o,$^) in the\n>     Makefile rule (since LIBS also includes GITLIBS).\n\nThis is still changing too much for my liking (and if I were to accept \nthe introduction of GITLIBDEPS as an elegant solution, it would have to be \na separate patch anyway).\n\nI may get some time in a week to play with the issue myself,\nJohannes\n"},{"id":"169204","messageId":"7vfwnsdwqf.fsf@alter.siamese.dyndns.org","threadId":"27535","inReplyTo":"1307010937-2894-1-git-send-email-cesarb@cesarb.net","subject":"Re: [PATCH v2] Embed an application manifest on MinGW","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-06-02T16:27:52Z","receivedAt":"2011-06-02T16:27:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Does the output from $WINDRES define any external symbol the rest of the\ncode can refer to?  If so, you could throw resource.o into one of the .a\nfile and make sure that the symbol is referred to from main(); perhaps the\ndefinition of main in compat/mingw.h can refer to it.\n\nIf you can do that, you wouldn't need any change to the Makefile other\nthan the rule to build compat/win32/resource.o and conditionally add that\nobject to LIB_OBJS, perhaps like this (obviously untested as I do not have\naccess to windows boxes).\n\n Makefile |    7 +++++++\n 1 files changed, 7 insertions(+), 0 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex cbc3fce..0a18e56 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -320,6 +320,7 @@ XGETTEXT = xgettext\n PTHREAD_LIBS = -lpthread\n PTHREAD_CFLAGS =\n GCOV = gcov\n+WINDRES = windres\n \n export TCL_PATH TCLTK_PATH\n \n@@ -1169,6 +1170,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_INET_PTON = YesPlease\n \tNO_INET_NTOP = YesPlease\n \tNO_POSIX_GOODIES = UnfortunatelyYes\n+\tLIB_OBJS += compat/win32/resource.o\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/winansi.o \\\n@@ -1580,6 +1582,7 @@ ifndef V\n \tQUIET_LNCP     = @echo '   ' LN/CP $@;\n \tQUIET_XGETTEXT = @echo '   ' XGETTEXT $@;\n \tQUIET_GCOV     = @echo '   ' GCOV $@;\n+\tQUIET_WINDRES  = @echo '   ' WINDRES $@;\n \tQUIET_SUBDIR0  = +@subdir=\n \tQUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \\\n \t\t\t $(MAKE) $(PRINT_DIR) -C $$subdir\n@@ -2022,6 +2025,10 @@ $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)\n \n+%.o: %.rc\n+\t$(QUIET_WINDRES)$(WINDRES) $< $@\n+compat/win32/resource.o: compat/win32/git.manifest\n+\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)\n \n"},{"id":"169230","messageId":"4DE8152F.3010903@cesarb.net","threadId":"27535","inReplyTo":"7vfwnsdwqf.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] Embed an application manifest on MinGW","fromName":"Cesar Eduardo Barros","fromEmail":"cesarb@cesarb.net","sentAt":"2011-06-02T22:56:47Z","receivedAt":"2011-06-02T22:56:47Z","isPatch":true,"sender":{"key":"cesarb@cesarb.net","avatar":"https://avatars.githubusercontent.com/u/31324?v=4"},"body":"Em 02-06-2011 13:27, Junio C Hamano escreveu:\n> Does the output from $WINDRES define any external symbol the rest of the\n> code can refer to?  If so, you could throw resource.o into one of the .a\n> file and make sure that the symbol is referred to from main(); perhaps the\n> definition of main in compat/mingw.h can refer to it.\n\nUnfortunately no:\n\n$ i686-pc-mingw32-nm compat/win32/resource.o\n00000000 d .rsrc\n\nThe only thing it has is the .rsrc section.\n\nI could perhaps create a dummy C file with a dummy variable, compile it, \nand use incremental linking (ld -r) to bolt both object files together. \nI am not sure this hack wouldn't be uglier than the Makefile changes.\n\nAnother possibility would be a linker script (like /usr/lib/libc.so on \nmodern distributions). This might be the most elegant option if it \nworks. I will have to take a look on how it works to see if it is a \nviable alternative.\n\n> If you can do that, you wouldn't need any change to the Makefile other\n> than the rule to build compat/win32/resource.o and conditionally add that\n> object to LIB_OBJS, perhaps like this (obviously untested as I do not have\n> access to windows boxes).\n\nYou do not need access to Windows boxes, you can always use Wine ;-) \n(msysgit even has a script to open a shell under Wine with everything \nset up).\n\n-- \nCesar Eduardo Barros\ncesarb@cesarb.net\ncesar.barros@gmail.com\n"}]}