Can you run a 32 bit Cygwin application in a 64 bit installation?

只愿长相守 提交于 2019-12-02 03:14:43

Like any Lnx distribution, the Cygwin 64 emulator allows running 32 bit executables (as long as they are compatible). You only need to either have:

  • The right packages installed
  • The right .dlls in the right place (as you mentioned) - but manually copying them (especially in system locations) is neither scalable, nor does it guarantee that the system will properly work afterwards

First, you'd need the cygwin32 package (at least) installed:

Since I don't have your 32 bit executable (I didn't fell like searching downloading, unpacking, and so on ...), I created a small example (to make it run, you'd need the gcc toolchains as well - which I have for other purposes, but anyway this is not related to the question) that reproduces the behavior.

code.c:

#include <stdio.h>


int main() {
    printf("\"void*\" is %d bits long.\n", sizeof(void*) * 8);
    return 0;
}

Output:

[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> uname -a
CYGWIN_NT-10.0 cfati-5510-0 2.11.2(0.329/5/3) 2018-11-08 14:34 x86_64 Cygwin
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ls
code.c
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> x86_64-pc-cygwin-gcc.exe -o exe-gcc-064.exe code.c
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> i686-pc-cygwin-gcc.exe -o exe-gcc-032.exe code.c -m32
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ls -al
total 433
drwxrwx---+ 1 Administrators None      0 Jan 16 12:45 .
drwxrwx---+ 1 Administrators None      0 Jan 16 10:33 ..
-rwxrwx---+ 1 Administrators None    118 Jan 16 10:39 code.c
-rwxrwxr-x+ 1 cfati          None 151062 Jan 16 12:45 exe-gcc-032.exe
-rwxrwxr-x+ 1 cfati          None 157755 Jan 16 12:45 exe-gcc-064.exe
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]>
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> file exe-gcc-064.exe
exe-gcc-064.exe: PE32+ executable (console) x86-64, for MS Windows
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ldd exe-gcc-064.exe
        ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffcaf990000)
        KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7ffcaf300000)
        KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7ffcabe60000)
        cygwin1.dll => /usr/bin/cygwin1.dll (0x180040000)
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ./exe-gcc-064.exe
"void*" is 64 bits long.
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]>
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> file exe-gcc-032.exe
exe-gcc-032.exe: PE32 executable (console) Intel 80386, for MS Windows
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ldd exe-gcc-032.exe
        ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffcaf990000)
        ??? => ??? (0x77150000)
        wow64.dll => /cygdrive/c/WINDOWS/System32/wow64.dll (0x7ffcaf800000)
        wow64win.dll => /cygdrive/c/WINDOWS/System32/wow64win.dll (0x7ffcad570000)
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ./exe-gcc-032.exe
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]>
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> echo $?
127

As you can see, I ran into the exact same problem for exe-gcc-032.exe. The ??? dependency is the 32 bit cygwin1.dll. Let's explore the problem:

[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> find /usr -name cygwin1.dll
/usr/i686-pc-cygwin/sys-root/usr/bin/cygwin1.dll
/usr/bin/cygwin1.dll
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> cygcheck -f /usr/bin/cygwin1.dll
cygwin-2.11.2-1
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> file /usr/bin/cygwin1.dll
/usr/bin/cygwin1.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]>
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> cygcheck -f /usr/i686-pc-cygwin/sys-root/usr/bin/cygwin1.dll
cygwin32-2.10.0-1
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> file /usr/i686-pc-cygwin/sys-root/usr/bin/cygwin1.dll
/usr/i686-pc-cygwin/sys-root/usr/bin/cygwin1.dll: PE32 executable (DLL) (console) Intel 80386 (stripped to external PDB), for MS Windows
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]>
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> echo ${PATH}
/usr/local/bin:/usr/bin:/cygdrive/c/Program Files (x86)/Common Files/Oracle/Java/javapath:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/WINDOWS/System32/WindowsPowerShell/v1.0:/cygdrive/c/Install/x64/NVidia/GPU Computing Toolkit/CUDA/AllVers/bin:/cygdrive/c/Install/x64/NVidia/GPU Computing Toolkit/CUDA/AllVers/libnvvp:/cygdrive/c/Install/x86/Borland/Delphi/7/Bin:/cygdrive/c/Install/x86/Borland/Delphi/7/Projects/Bpl:/cygdrive/c/ProgramData/Oracle/Java/javapath:/cygdrive/c/Program Files (x86)/Intel/iCLS Client:/cygdrive/c/Program Files/Intel/iCLS Client:/cygdrive/c/Program Files (x86)/Intel/Intel(R) Management Engine Components/DAL:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/DAL:/cygdrive/c/Program Files (x86)/Intel/Intel(R) Management Engine Components/IPT:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/IPT:/cygdrive/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/cygdrive/c/WINDOWS/System32/OpenSSH:/cygdrive/c/Install/x86/IVI Foundation/VISA/AllVers/WinNT/Bin:/cygdrive/c/Program Files/IVI Foundation/VISA/Win64/Bin:/cygdrive/c/Install/x86/IVI Foundation/VISA/AllVers/WinNT/Bin:/cygdrive/e/Work/Dev/Utils/cfati-5510-0/windows:/cygdrive/c/Install/x64/NVidia/GPU Computing Toolkit/cuDNN/AllVers/bin:/cygdrive/c/Users/cfati/AppData/Local/Microsoft/WindowsApps:/cygdrive/c/Install/Qt/Qt/5.9.1/msvc2015/bin

So, the 32 bit .dll exists (installed by the above package), but it can't be found, as its dir is not in ${PATH} (due to the content length this isn't immediately visible). Note that Cygwin doesn't honour ${LD_LIBRARY_PATH} in this scenario.

The obvious step is to let the system know about this .dll, by adding its dir in ${PATH} (at the beginning):

[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> export PATH=/usr/i686-pc-cygwin/sys-root/usr/bin:${PATH}
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ./exe-gcc-032.exe
"void*" is 32 bits long.
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054206577]> ./exe-gcc-064.exe
"void*" is 64 bits long.

There you go.

Final notes:

  • (64 bit) ldd which is an .exe (unlike on Nix, where it's a script), doesn't gracefully handle dependencies for 32 bit artefacts. Unfortunately, cygwin32-binutils package doesn't provide a 32 bit counterpart that wouldn't have this problem, so at the current moment this is as good as it gets
  • You might run into some issues when running your .exe, because of possible differences between cygwin1.dll versions (the one that rxvt-native.exe expects, and the one present on the system). If so, I'd suggest that you start your Cygwin 32 environment, get the cygwin package version (let's call it ${CYGWIN_PKG_VER}), and on the Cygwin 64t environment, install the cygwin32 version that is closest to ${CYGWIN_PKG_VER}

@EDIT0:

I added system("echo ${PATH}"); (and implicitly #include <stdlib.h>) in my test program, and on the 32 bit variant, system returned 127 (just like exe-gcc-032.exe's exit code when not having the proper path). I suspect the 2 can't be unrelated, and something happens with the environment, when launching 32 bit applications, and probably rxvt-native tries to launch bash (or any other command) via system.

@EDIT1:

So, it is possible to run a 32 bit application from Cygwin 64 (a brief check, didn't reveal any official sources stating that it's an Unsupported Configuration). But in this particular case, since the app is complex (it's a terminal, required to run multiple other applications), there is a problem. Possible ways (some suggested by other people) to go further:

  • Time to let go (probably there is a good reason why it wasn't ported). Switch to a modern replacement (Mintty)
  • Search for an unofficial prebuilt 64 bit version of rxvt, or try building it yourself (there are some other people who like it)
  • Have both environments (Cygwin 32 and Cygwin 64) installed on your PC
    • Use your favorite terminal (from Cygwin 32). This will be your "main" environment
    • Administrate Cygwin 64 "remotely", e.g. via:
      • ssh: I didn't check for restrictions regarding the 2 sshds running in parallel on the same machine, but if there aren't any, you should change the listening port from default (22) for one of them. I'd suggest to do that for the former, so that the latter is available from "outside" using default settings
  • Continue research on this direction, but as I see things, it's starting (if it hasn't already) to become a castle card - this seems more like a workaround (gainarie)

No you can't.
The 32 bit application requires the 32bit cygwin1.dll, while the 64 bit cygwin needs the 64bit cygwin1.dll.

The rxvt win32 native was replaced by mintty that is the default cygwin terminal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!