On Nov 20 16:01, Corinna Vinschen wrote: > On Nov 20 09:47, Charles Wilson wrote: > > On 11/20/2013 8:28 AM, Corinna Vinschen wrote: > > >Apart from the fact that it would be nice if our linker would do this > > >automatically and transparently, > > > > Or libtool, if you use it to link your exe? PTC...since > > $new-libtool is pretty high on my to-do list. > > > > It'd be better if there was an option to ld/gcc, of course -- but > > the details would be rather complicated. You wouldn't want to > > invoke a separate executable like windres b/c then your build > > recipe/makefile would have to change. Best if $LD_FLAGS could be > > used... maybe something hideously ugly like -w32-manifest-compat > > <file> [1] where <file> is not a full XML manifest, but rather > > contains a list of GUIDs [2], and ld/gcc autogenerates the manifest > > with just that stuff. > > > > That way, if you manually create a manifest (for other purposes), > > you could just /not/ use the new flag. > > The other way around. If your project does not link in a resource > anyway, which means that your project is WIn32 aware, then ld should > add the manifest resource by default. Everything else means that > you have to tweak all project configury, which is only barely descibed > by a can of worms... > > A simple windres call in cygport would be nice, but unfortunately windres > does not yet have this capability to add a resource to an existing exe. > > > I know, SHTDI... > > Yes, that's pretty much the problem. Even my ugly workaround is bad, > because it only works on Windows. No more cross-building on Linux :-P
I added the sources for my now radically simplified test to this mail. It consists of three files: add-cygwin-default-manifest.c: The source code adding the manifest. cygwin-default-mainfest.rc: The default resource containing the manifest. It's target-agnostic. Makefile: The Makefile. To build the executable, just run `make'. This creates the add-cygwin-default-manifest executable with the embedded manifest. To add a manifest to binary "foo.exe", run `make doit EXE=foo.exe' add-cygwin-default-manifest.exe pulls its own manifest and copies it over to foo.exe. This is the step which I didn't manage to reproduce via objcopy. Note the crude way how `make doit' works. The UpdateResource functionality is *extremly* sensitive against having an open handle to the file still open in the same binary somewhere. If you try something like this: doit: strip $(EXE) objcopy --remove-section=.gnu_debuglink $(EXE) ./add-cygwin-default-manifest $(EXE) then you'll get an error message "EndUpdateResource: Win32 error 5". Apparently, `make' has an open handle to $(EXE) and this is propagated somehow to the child processes. As a side note, trying to call, say, GetBinaryType before calling BeginUpdateResource, or even stuff like CreateFile/CloseHandle(!!!) will end up with "EndUpdateResource: Win32 error 5". As I wrote, *extremly* sensitive. That sounds much better than "badly written"... Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <locale.h> #include <sys/cygwin.h> int main (int argc, char **argv) { PWCHAR wpath; HGLOBAL hResLoad; // handle to loaded resource HMODULE hExe; // handle to existing .EXE file HRSRC hRes; // handle/ptr. to res. info. in hExe LPVOID lpResLock; // pointer to resource data HANDLE h; setlocale (LC_ALL, ""); if (argc != 2) { fprintf (stderr, "Usage: %s file\n", argv[0]); return 1; } wpath = cygwin_create_path (CCP_POSIX_TO_WIN_W, argv[1]); if (!wpath) { fprintf (stderr, "cygwin_create_path: %s\n", strerror (errno)); return 1; } hExe = GetModuleHandle (NULL); hRes = FindResourceW(hExe, MAKEINTRESOURCEW (CREATEPROCESS_MANIFEST_RESOURCE_ID), MAKEINTRESOURCEW (RT_MANIFEST)); if (!hRes) { fprintf (stderr, "FindResourceW: Win32 error %d\n", GetLastError ()); return 1; } hResLoad = LoadResource(hExe, hRes); if (!hResLoad) { fprintf (stderr, "LoadResource: Win32 error %d\n", GetLastError ()); return 1; } lpResLock = LockResource(hResLoad); if (!lpResLock) { fprintf (stderr, "LockResource: Win32 error %d\n", GetLastError ()); return 1; } h = BeginUpdateResourceW (wpath, FALSE); if (!h) { fprintf (stderr, "BeginUpdateResourceW: Win32 error %d\n", GetLastError ()); return 1; } if (!UpdateResourceW (h, MAKEINTRESOURCEW (RT_MANIFEST), MAKEINTRESOURCEW (CREATEPROCESS_MANIFEST_RESOURCE_ID), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), lpResLock, SizeofResource(hExe, hRes))) { fprintf (stderr, "UpdateResourceW: Win32 error %d\n", GetLastError ()); return 1; } if (!EndUpdateResource (h, FALSE)) { fprintf (stderr, "EndUpdateResource: Win32 error %d\n", GetLastError ()); return 1; } return 0; }
#include <windows.h> LANGUAGE 0, 0 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST MOVEABLE PURE DISCARDABLE BEGIN "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>\n" "<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">\n" " <trustInfo xmlns=""urn:schemas-microsoft-com:asm.v3"">\n" " <security>\n" " <requestedPrivileges>\n" " <requestedExecutionLevel level=""asInvoker"" uiAccess=""false""/>\n" " </requestedPrivileges>\n" " </security>\n" " </trustInfo>\n" " <compatibility xmlns=""urn:schemas-microsoft-com:compatibility.v1"">\n" " <application>\n" " <!--The ID below indicates application support for Windows Vista -->\n" " <supportedOS Id=""{e2011457-1546-43c5-a5fe-008deee3d3f0}""/>\n" " <!--The ID below indicates application support for Windows 7 -->\n" " <supportedOS Id=""{35138b9a-5d96-4fbd-8e2d-a2440225f93a}""/>\n" " <!--The ID below indicates application support for Windows 8 -->\n" " <supportedOS Id=""{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}""/>\n" " <!--The ID below indicates application support for Windows 8.1 -->\n" " <supportedOS Id=""{1f676c76-80e1-4239-95bb-83d0f6d0da78}""/> \n" " </application>\n" " </compatibility>\n" "</assembly>\n" END
OBJS=add-cygwin-default-manifest.o cygwin-default-manifest.o all: add-cygwin-default-manifest.exe cygwin-default-manifest.o: cygwin-default-manifest.rc windres -o $@ $< add-cygwin-default-manifest.exe: $(OBJS) gcc $(CFLAGS) -o $@ $(OBJS) doit: objcopy --remove-section=.gnu_debuglink $(EXE) $(EXE).out \ && ./add-cygwin-default-manifest $(EXE).out \ && strip $(EXE).out \ && mv $(EXE).out $(EXE)
pgp31GQPU8edP.pgp
Description: PGP signature