Hi,
I have previously asked about the problem I'm describing below on openSUSE's forums [1], StackOverflow [2] and Wine's forums [3], where dimesio told me that I could try to ask here. If this is the wrong place to ask, I apologise.
Over the past few weeks, I've been re-implementing a DLL using Winelib to be able to leverage Unix sockets to communicate with a Linux process outside of Wine. For context, I'm on a 64-bit machine running openSUSE Tumbleweed. I've had success compiling the DLL as a 32-bit object using the command line
winegcc -m32 -L/usr/lib64/wine/i386-unix -shared -o myproject.dll myproject_main.c myproject.spec
This DLL (myproject.dll.so) works as expected, i.e. 32-bit Windows programs running under Wine can load and execute the DLL just fine. (I've found specifying -L/usr/lib64/wine/i386-unix to be necessary since WineGCC didn't pick up Wine's library path by itself.)
Now, I've been trying to compile this same project as a 64-bit object using
winegcc -L/usr/lib64/wine/x86_64-unix -shared -o myproject64.dll myproject_main.c myproject.spec
and I'm facing the following WineGCC output:
/usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld: cannot find -ladvapi32: No such file or directory /usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld: cannot find -luser32: No such file or directory /usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld: cannot find -lwinecrt0: No such file or directory /usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld: cannot find -lkernel32: No such file or directory /usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld: cannot find -lntdll: No such file or directory collect2: error: ld returned 1 exit status winegcc: /usr/bin/gcc failed
As I've discovered, openSUSE's wine-devel package does not provide any archive files in /usr/lib64/wine/x86_64-unix, whereas wine-devel-32bit does provide archive files under /usr/lib/wine/i386-unix (symlinked with the same directory in /usr/lib64). Interestingly, I've inspected Wine's Fedora packages [4] and haven't found these archive files for 32-bit but only for 64-bit; so, the Fedora packages seem to have the opposite "problem."
Now, I've tried to use the archive files provided by openSUSE's 64-bit wine-devel package under /usr/lib64/wine/x86_64-windows, but of course they're PE binaries so LD complains it can't link to my Winelib DLL:
/usr/bin/ld: relocatable linking with relocations from format pe-x86-64 (/usr/lib64/wine/x86_64-windows/libwinecrt0.a(debug.o)) to format elf64-x86-64 (tmp66fd686a/myproject64-00000001.spec-00000001.o) is not supported winebuild: /usr/bin/ld failed with status 1 winegcc: /usr/bin/winebuild failed
I feel like I should be able to compile this Winelib DLL as both a 32-bit and a 64-bit object respectively, on any supported system. (I haven't found any info on this skimming through the Winelib User's Guide [5].) Is this assumption wrong? If so, what's the correct way of building Winelib DLLs? If not, how can I get a 64-bit version of this DLL?
Any advice on what I might be misunderstanding or doing wrong or what might be the cause of this problem would be greatly appreciated.
Best regards, Alexander Leithner
[1]: https://forums.opensuse.org/t/wines-64-bit-archive-files-are-missing/179038 [2]: https://stackoverflow.com/questions/79058718/whats-the-correct-way-of-buildi... [3]: https://forum.winehq.org/viewtopic.php?t=39513 [4]: e.g. https://dl.winehq.org/wine-builds/fedora/40/x86_64/wine-staging-9.19-1.1.x86... under /opt/wine-staging/lib64/wine inside the package [5]: https://gitlab.winehq.org/wine/wine/-/wikis/Winelib-User%27s-Guide
Hello Alexander,
Am Dienstag, 15. Oktober 2024, 15:18:57 GMT+3 schrieb aleithner@level101.at:
I have previously asked about the problem I'm describing below on openSUSE's forums [1], StackOverflow [2] and Wine's forums [3], where dimesio told me that I could try to ask here. If this is the wrong place to ask, I apologise.
The mailing ist is the right place to ask :-)
I'll try to answer some of your questions below, but I am not much of a winelib expert and sadly winelib is getting relatively little love. In my quick test building a 32 and 64 bit .dll.so worked, but I would not be surprised if there are bugs.
Wine itself has transitioned to a more formal (fake-)syscall and unix call interface to switch between the Windows and the Linux side. I think there are no DLLs left in Wine any more that have the old hybrid PE and ELF linkage.
winegcc -m32 -L/usr/lib64/wine/i386-unix -shared -o myproject.dll myproject_main.c myproject.spec
Does the 32 bit DLL link without the -L path? You shouldn't need it, winegcc and winebuild should know their installation path.
As I've discovered, openSUSE's wine-devel package does not provide any archive files in /usr/lib64/wine/x86_64-unix, whereas wine-devel-32bit does provide archive files under /usr/lib/wine/i386-unix (symlinked with the same directory in /usr/lib64).
It is quite likely a bug on openSUSE's side. They probably didn't even test winegcc with the wine-devel packages, as it is a pretty rare case that someone needs it.
I think your best choice would be to build wine from source and install it to a custom prefix in your home directory. Hopefully the wine-devel packages pull in the right headers etc to make it easy to do.
e.g. in pseudo code:
./configure --enable-win64 --prefix=~/mywine make && make install # no need for sudo. add -j X for faster build export PATH=~/mywine/bin:$PATH
Now you should run winegcc from ~/mywine/bin/winegcc, and it has the 64 bit .a files in ~/mywine/lib/wine/x86_64-unix.
Any .dll.so generated that way should run with your system wide wine installation, so you should be able to copy it to other machines etc. If in doubt check out the oldest Wine version you want your binaries to run on.
On Tue, Oct 15, 2024 at 11:43 PM Stefan Dösinger stefandoesinger@gmail.com wrote:
Hello Alexander,
Am Dienstag, 15. Oktober 2024, 15:18:57 GMT+3 schrieb aleithner@level101.at:
I have previously asked about the problem I'm describing below on
openSUSE's
forums [1], StackOverflow [2] and Wine's forums [3], where dimesio told
me
that I could try to ask here. If this is the wrong place to ask, I apologise.
The mailing ist is the right place to ask :-)
If you post as bug on bugzilla, someone might help :-)
I'll try to answer some of your questions below, but I am not much of a winelib expert and sadly winelib is getting relatively little love. In my quick test building a 32 and 64 bit .dll.so worked, but I would not be surprised if there are bugs.
Wine itself has transitioned to a more formal (fake-)syscall and unix call interface to switch between the Windows and the Linux side. I think there are no DLLs left in Wine any more that have the old hybrid PE and ELF linkage.
winegcc -m32 -L/usr/lib64/wine/i386-unix -shared -o myproject.dll myproject_main.c myproject.spec
Does the 32 bit DLL link without the -L path? You shouldn't need it, winegcc and winebuild should know their installation path.
As I've discovered, openSUSE's wine-devel package does not provide any archive files in /usr/lib64/wine/x86_64-unix, whereas wine-devel-32bit
does
provide archive files under /usr/lib/wine/i386-unix (symlinked with the same directory in /usr/lib64).
It is quite likely a bug on openSUSE's side. They probably didn't even test winegcc with the wine-devel packages, as it is a pretty rare case that someone needs it.
I think your best choice would be to build wine from source and install it to a custom prefix in your home directory. Hopefully the wine-devel packages pull in the right headers etc to make it easy to do.
e.g. in pseudo code:
./configure --enable-win64 --prefix=~/mywine make && make install # no need for sudo. add -j X for faster build export PATH=~/mywine/bin:$PATH
Now you should run winegcc from ~/mywine/bin/winegcc, and it has the 64 bit .a files in ~/mywine/lib/wine/x86_64-unix.
Any .dll.so generated that way should run with your system wide wine installation, so you should be able to copy it to other machines etc. If in doubt check out the oldest Wine version you want your binaries to run on.
Hi Stefan,
thanks a lot for your advice!
Am 15.10.24 um 22:42 schrieb Stefan Dösinger:
Wine itself has transitioned to a more formal (fake-)syscall and unix call interface to switch between the Windows and the Linux side. I think there are no DLLs left in Wine any more that have the old hybrid PE and ELF linkage.
I've read about this transition. Just out of curiousity, would it be possible/feasible for external DLL projects (like mine) to transition too, especially if they need to call native Linux libraries? (Probably not, since we can't link between ELF and PE, right?)
Or will Winelib and the current build/call process be supported for the forseeable future?
winegcc -m32 -L/usr/lib64/wine/i386-unix -shared -o myproject.dll myproject_main.c myproject.spec
Does the 32 bit DLL link without the -L path? You shouldn't need it, winegcc and winebuild should know their installation path.
No. Winegcc as provided by openSUSE doesn't find the right path.
It is quite likely a bug on openSUSE's side. They probably didn't even test winegcc with the wine-devel packages, as it is a pretty rare case that someone needs it.
Since I also gather from your question that -L shouldn't be required, I'll think about filing a bug report with openSUSE, as was suggested on my original openSUSE Forums post if I should discover that I was doing everything correctly.
I think your best choice would be to build wine from source and install it to a custom prefix in your home directory. Hopefully the wine-devel packages pull in the right headers etc to make it easy to do.
Absolutely, building Wine from source has fixed the issue. Interestingly, I only get the following folder structure
prefix/lib64/wine +- i386-windows +- x86_64-unix +- x86_64-windows
with archive files present in all of these directories, though both 32-bit and 64-bit versions of my DLL now compile fine (i.e. I correctly get a 32-bit/64-bit ELF object). Since it works, I assume this is the expected behaviour.
Though I haven't been able to test the 64-bit binary yet, since the 32-bit version works after compiling with my self-built winegcc, I assume that I'm now able to build both versions correctly.
I don't have to pass -L to my self-built winegcc, therefore everything works as it should on Wine's side, as far as I can judge that.
Thanks again and best regards, Alexander Leithner
On Thursday, October 17th, 2024 at 20:23, Alexander Leithner aleithner@level101.at wrote:
Hi Stefan,
thanks a lot for your advice!
Am 15.10.24 um 22:42 schrieb Stefan Dösinger:
Wine itself has transitioned to a more formal (fake-)syscall and unix call interface to switch between the Windows and the Linux side. I think there are no DLLs left in Wine any more that have the old hybrid PE and ELF linkage.
I've read about this transition. Just out of curiousity, would it be possible/feasible for external DLL projects (like mine) to transition too, especially if they need to call native Linux libraries? (Probably not, since we can't link between ELF and PE, right?)
Or will Winelib and the current build/call process be supported for the forseeable future?
winegcc -m32 -L/usr/lib64/wine/i386-unix -shared -o myproject.dll myproject_main.c myproject.spec
Does the 32 bit DLL link without the -L path? You shouldn't need it, winegcc and winebuild should know their installation path.
No. Winegcc as provided by openSUSE doesn't find the right path.
It is quite likely a bug on openSUSE's side. They probably didn't even test winegcc with the wine-devel packages, as it is a pretty rare case that someone needs it.
Since I also gather from your question that -L shouldn't be required, I'll think about filing a bug report with openSUSE, as was suggested on my original openSUSE Forums post if I should discover that I was doing everything correctly.
I think your best choice would be to build wine from source and install it to a custom prefix in your home directory. Hopefully the wine-devel packages pull in the right headers etc to make it easy to do.
Absolutely, building Wine from source has fixed the issue. Interestingly, I only get the following folder structure
prefix/lib64/wine +- i386-windows +- x86_64-unix +- x86_64-windows
with archive files present in all of these directories, though both 32-bit and 64-bit versions of my DLL now compile fine (i.e. I correctly get a 32-bit/64-bit ELF object). Since it works, I assume this is the expected behaviour.
Though I haven't been able to test the 64-bit binary yet, since the 32-bit version works after compiling with my self-built winegcc, I assume that I'm now able to build both versions correctly.
I don't have to pass -L to my self-built winegcc, therefore everything works as it should on Wine's side, as far as I can judge that.
Thanks again and best regards, Alexander Leithner
Hi, I might bring an answer to your first question.
Yes, it is possible for external projects to use the new unixcall interface, which I took advantage of in my own project, wine-nvml[1]. With this approach you need to build PE and ELF parts separately then have PE one call the other only through Wine's syscall thunk/dispatcher.
This allowed me to expose Windows-side equivalents of NVML functions via PE nvml.dll, where implementations of most entrypoints pack their arguments into dedicated structs, call ELF nvml.so with appropriate unixcall number, and there they are forwarded to NVIDIA's own libnvidia-ml.so before the result is returned via the same struct to the calling application. This however comes with some limitations, with the major one being: it's very hard to call PE side from Unix side. But some (if not most) libraries won't need this at all.
[2] and [3] are nice posts that describe this interface in greater detail but if you're interested in some real world example then feel free to take a look at my repository. You'll have to run the generator (make_nvml) to see the actual C code.
Regards, Krzysztof Bogacki
[1]: https://github.com/Saancreed/wine-nvml [2]: https://blog.hiler.eu/wine-pe-to-unix/ [3]: https://blog.hiler.eu/wine-pe-to-unix-update/
Am Donnerstag, 17. Oktober 2024, 23:25:37 GMT+3 schrieb Krzysztof Bogacki:
On Thursday, October 17th, 2024 at 20:23, Alexander Leithner
I've read about this transition. Just out of curiousity, would it be possible/feasible for external DLL projects (like mine) to transition too, especially if they need to call native Linux libraries? (Probably not, since we can't link between ELF and PE, right?)
Or will Winelib and the current build/call process be supported for the forseeable future?
Hi, I might bring an answer to your first question.
Regarding question 2, I don't think we have any plans to deliberately break the old all-in-one .dll.so binaries. It is quite likely that this functionality will bitrot over time though. Also the functionality that the PE/unix split was introduced for won't be available that way:
* Make DRM systems happy that compare the on-disk DLL to the loaded image * x86 on arm emulation * 32 bit Windows programs with 64 bit Wine * Full %gs access on macos * Similar to the previous thing, support for aarch64 Windows binaries, use the x19 registers for thread local storage
So if your library is something that should be useful for the wider community then the new style is certainly the way to go.