Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MinGW 32-bit build requires -static-libgcc to avoid DLL migraine #1049

Closed
tormodvolden opened this issue Jan 25, 2022 · 21 comments
Closed

MinGW 32-bit build requires -static-libgcc to avoid DLL migraine #1049

tormodvolden opened this issue Jan 25, 2022 · 21 comments
Labels

Comments

@tormodvolden
Copy link
Contributor

When cross-building MinGW 32-bit (gcc 9.3 on Ubuntu 20.04) the resulting DLL depends on various gcc DLLs, so if just installing the libusb.dll the program using it will fail to execute ("libgcc_s_sjlj-1.dll was not found").

Adding the extra linker option -static-libgcc fixes this. However, this is not needed for 64-bit builds, so it is possible that there is a bug somewhere. This is not very new, but wasn't like this some years ago either.

This would better be rechecked with a newer MinGW toolchain.

@mcuee
Copy link
Member

mcuee commented Jan 28, 2022

Ah, I see the same problem with MSYS2 with 32bit build. And yes 64bit build is not affected. So this does not only affect cross build under Linux. Same thing happened under Windows.

@mcuee mcuee changed the title MinGW 32-bit (cross-)build requires -static-libgcc to avoid DLL migraine MinGW 32-bit build requires -static-libgcc to avoid DLL migraine Jan 28, 2022
@mcuee
Copy link
Member

mcuee commented Feb 6, 2022

This is not very new, but wasn't like this some years ago either.
This would better be rechecked with a newer MinGW toolchain.

It seems to me this has been there for a while. Just wondering which version you check does not cause this issue.

My GCC version is pretty new under MSYS2.

$ gcc -v
Using built-in specs.
COLLECT_GCC=C:\msys64\mingw32\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/msys64/mingw32/bin/../lib/gcc/i686-w64-mingw32/11.2.0/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: ../gcc-11.2.0/configure --prefix=/mingw32 --with-local-prefix=/mingw32/local --build=i686-w64-mingw32 --host=i686-w64-mingw32 --target=i686-w64-mingw32 --with-native-system-header-dir=/mingw32/i686-w64-mingw32/include --libexecdir=/mingw32/lib --enable-bootstrap --enable-checking=release --with-arch=i686 --with-tune=generic --enable-languages=c,lto,c++,fortran,ada,objc,obj-c++,jit --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts --enable-libstdcxx-time --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-lto --enable-libgomp --disable-multilib --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw32 --with-mpfr=/mingw32 --with-mpc=/mingw32 --with-isl=/mingw32 --with-pkgversion='Rev7, Built by MSYS2 project' --with-bugurl=https://github.com/msys2/MINGW-packages/issues --with-gnu-as --with-gnu-ld --with-boot-ldflags='-pipe -Wl,--dynamicbase,--nxcompat,--no-seh -Wl,--large-address-aware -Wl,--disable-dynamicbase -static-libstdc++ -static-libgcc' 'LDFLAGS_FOR_TARGET=-pipe -Wl,--dynamicbase,--nxcompat,--no-seh -Wl,--large-address-aware' --enable-linker-plugin-flags='LDFLAGS=-static-libstdc++\ -static-libgcc\ -pipe\ -Wl,--dynamicbase,--nxcompat,--no-seh\ -Wl,--large-address-aware\ -Wl,--stack,12582912' --disable-sjlj-exceptions --with-dwarf2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.2.0 (Rev7, Built by MSYS2 project)

@diabolo38
Copy link

diabolo38 commented Feb 6, 2022

As far as i remember i often and have always see this in 32 and or 64 bit app/lib built with mingw/gcc even with native windows built.
Mingw built lib/dll are meant to be used in mingw/msys context so isn't it armless ? The dependencies lib shall be present
User that wan't to build and distribute app/lib with mingw ibsusb dll aside shall shall be aware of it and built their stuff with static gcc or even static libusb if to avoid any dependencies issue . Or just use the msvc version of the dll

@tormodvolden
Copy link
Contributor Author

What is a MinGW context? Isn't the point of MinGW that you build standalone binaries that "just works"? I admit this is not obvious for shared libraries. I find it practical to have an application and a libusb DLL and no more dependencies but see that this is a somewhat middle ground.

The question remains, why is this different on 64 bit?

@diabolo38
Copy link

by mingw context i mean a machine where some mingw got installed so the gcc std lib dll is present.

yes it's strange that 64 bit one doesn't has it maybe some std library helper for 64 bit ops
Another dif of gcc 32/64 is the exception model sjlj vs SEH but that shoud=ld affect oly c++
if you look at dependencies symbols you should find out.

to come on inittial point anyway you right that it will avoid the migraine by adding static-gcc in the lib build ;)

@diabolo38
Copy link

diabolo38 commented Feb 6, 2022

i did on the 1.0.25 binary package
obdjump -x dll

        DLL Name: libgcc_s_sjlj-1.dll
        vma:  Hint/Ord Member-Name Bound-To
        238bc     121  __udivdi3
        238c8     122  __udivmoddi4

these are helper for 64 bit division why not needed on 64 bit version

@mcuee
Copy link
Member

mcuee commented Feb 7, 2022

The idea is to have DLL interchangeability between the official MinGW32/64 and Visual Studio binaries as much as possible. Therefore it is good to remove the dependencies of MinGW helpers if possible. If not possible, then we need to mention to the users.

My previous tests show that our official binaries are able to be interchangeable, with my simple tests (with libusb examples and openocd binary). I will try to test the 1.0.25 binaries.

When I build libftdi with MinGW32/64, I always end up with MinGW helper dependencies. So I would like to see how to remove the dependencies as well if it is possible.

My question is then how to link with the static-gcc with the configure option or things like that.

@mcuee
Copy link
Member

mcuee commented Feb 7, 2022

@diabolo38 It seems to me the 32bit MinGW DLL of libusb-1.0.25 Windows binary has dependancies on MinGW helpers but not the 64bit MinGW DLL.

Ref: https://stackoverflow.com/questions/11703000/finding-dlls-required-of-a-win-exe-on-linux-cross-compiled-with-mingw

/c/work/libusb/libusb_bin/libusb-1.0.25_bin/MinGW64/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
\%s.dll
libusb-1.0.dll
KERNEL32.dll
msvcrt.dll

/c/work/libusb/libusb_bin/libusb-1.0.25_bin/MinGW32/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
\%s.dll
libusb-1.0.dll
KERNEL32.dll
msvcrt.dll
libgcc_s_sjlj-1.dll

@mcuee
Copy link
Member

mcuee commented Feb 7, 2022

Older version of MinGW32 dll binary. They have libgcj-16.dll as the dependancy if the above method using strings is correct. It seems to me they are produced by similar toolchain (likely not from MSYS 2 MinGW32 compiler used by me, or Linux cross compilers used by Tormod).

However, the comments here say that using "strings" will create false positive.
https://stackoverflow.com/questions/11703000/finding-dlls-required-of-a-win-exe-on-linux-cross-compiled-with-mingw

BTW, usually I will use Dependancy Walker but it does not seem to work under my Windows 11 laptop.

/c/work/libusb/libusb_bin/libusb-1.0.24_bin/MinGW32/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
libgcj-16.dll
\%s.dll
libusb-1.0.dll
KERNEL32.dll
msvcrt.dll
USER32.dll

/c/work/libusb/libusb_bin/libusb-1.0.23_bin/MinGW32/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
libgcj-16.dll
libusb-1.0.dll
ADVAPI32.dll
KERNEL32.dll
msvcrt.dll
USER32.dll

/c/work/libusb/libusb_bin/libusb-1.0.22_bin/MinGW32/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
libgcj-16.dll
libusb-1.0.dll
ADVAPI32.dll
KERNEL32.dll
msvcrt.dll
USER32.dll

/c/work/libusb/libusb_bin/libusb-1.0.21_bin/MinGW32/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
libgcj-16.dll
libusb-1.0.dll
KERNEL32.dll
msvcrt.dll
USER32.dll

/c/work/libusb/libusb_bin/libusb-1.0.20_bin/MinGW32/dll
$ strings libusb-1.0.dll | grep -i '\.dll$'
libgcj-16.dll
hid.dll
Kernel32.dll
Cfgmgr32.dll
OLE32.dll
SetupAPI.dll
AdvAPI32.dll
User32.dll
libusb-1.0.dll
KERNEL32.dll
msvcrt.dll
USER32.dll

@diabolo38
Copy link

diabolo38 commented Feb 7, 2022

if you used objdump -x like i did you will see what symbols is required in the gcc dll
in the 1.0.25 i got from Sourceforge binary package it was clearly the divide 64 bit helper.

@mcuee Your investigation on past version show that even the base dll name is toolschain dependent.
One more reason to avoid it by use of static gcc lib at build

@mcuee
Copy link
Member

mcuee commented Feb 7, 2022

@diabolo38 Yes I agree that it is better to link to static gcc lib at build for MinGW toolchains.

@mcuee
Copy link
Member

mcuee commented Feb 8, 2022

if you used objdump -x like i did you will see what symbols is required in the gcc dll in the 1.0.25 i got from Sourceforge binary package it was clearly the divide 64 bit helper.

Hmm, I can not get your result for the 64bit binary.

/c/work/libusb/libusb-1.0.25_bin/MinGW64/dll
$ objdump.exe -x libusb-1.0.dll | grep DLL
        DLL
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll

For 32bit DLL, you are right, it has the dependency with libgcc_s_sjlj-1.dll which is not desired.

/c/work/libusb/libusb-1.0.25_bin/MinGW32/dll
$ objdump -x libusb-1.0.dll | grep DLL
        DLL
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: libgcc_s_sjlj-1.dll

@mcuee
Copy link
Member

mcuee commented Feb 8, 2022

@diabolo38 using your objdump method, the old version of 32bit DLLs do not seem to have an issue.

$ objdump -v
GNU objdump (GNU Binutils) 2.36.1
Copyright (C) 2021 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.

/c/work/libusb/libusb-1.0.24_bin/MinGW32/dll
$ objdump -x libusb-1.0.dll | grep DLL
        DLL
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: USER32.dll

 /c/work/libusb/libusb-1.0.23_bin/MinGW32/dll
$ objdump -x libusb-1.0.dll | grep DLL
        DLL
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: ADVAPI32.dll
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: USER32.dll

/c/work/libusb/libusb-1.0.22_bin/MinGW32/dll
$ objdump -x libusb-1.0.dll | grep DLL
        DLL
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: ADVAPI32.dll
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: USER32.dll

/c/work/libusb/libusb-1.0.21_bin/MinGW32/dll
$ objdump -x libusb-1.0.dll | grep DLL
        DLL
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: USER32.dll

@mcuee
Copy link
Member

mcuee commented Feb 8, 2022

So the only issue seems to be with the 1.0.25 MinGW32 dll as per my testing. I am not so sure why the old version does not have such an issue, probably it is due to compiler differences.

In order to be not limited by a specific MinGW toolchain, I agree it is better to link to to static gcc lib at build for MinGW toolchains.

@tormodvolden
Copy link
Contributor Author

tormodvolden commented Feb 9, 2022

In the binary package I posted on SF and GitHub I had myself compiled the MinGW binaries and it is quite possible I forgot to add the -static flag (it was already quite a mess to pull together the Windows package). However, they also get built in the appveyor service, from where I got the VS builds. The previous binary packages were maybe built with a local appveyor instance, from what I can guess from the paths used. Maybe they get the wanted DLL configuration there? For our convenience it should be possible to also download the appveyor MinGW build artifacts. I am just not sure how to configure this in the common "after_build" part. If I add a path that doesn't exists for some builds (the MinGW builds are piggy-backed on the VS15 build), then the 7z command and the whole job fails. There is probably a simple solution.

EDIT: After writing that, I had to try just one thing (ugly or not) and it worked :)
The MinGW32 built on appveyor also seems to have a gcc DLL dependency:

$ i686-w64-mingw32-objdump -x libusb-MinGW-Win32/bin/msys-usb-1.0.dll | grep DLL
	DLL
 vma:            Hint    Time      Forward  DLL       First
	DLL Name: libgcc_s_dw2-1.dll
	DLL Name: KERNEL32.dll
	DLL Name: msvcrt.dll
	DLL Name: USER32.dll

Anyway, it would be good if our build configuration does the right thing for us by default when building locally also.

@mcuee
Copy link
Member

mcuee commented Feb 9, 2022

Anyway, it would be good if our build configuration does the right thing for us by default when building locally also.

Yes that will be the goal. Maybe the configure script needs to be changed to link to static gcc library.

@diabolo38
Copy link

diabolo38 commented Feb 9, 2022

@mcuee i used objdump 2.27 without the grep dll , you will find the symbols from the dll on the lines following the dll name itself

@rom1v
Copy link
Contributor

rom1v commented Feb 10, 2022

FYI, I encounter the same missing libgcc_s_sjlj-1.dll with the win32 libusb-1.0.dll release, but no problem with the win64 libusb-1.0.dll release: Genymobile/scrcpy#3011

(I use the official dll from libusb 1.0.25 and cross-compile my project from Linux)

tormodvolden added a commit to tormodvolden/libusb that referenced this issue Feb 10, 2022
Fixes libusb#1049

Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
tormodvolden added a commit to tormodvolden/libusb that referenced this issue Feb 10, 2022
Fixes libusb#1049

Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
@tormodvolden tormodvolden linked a pull request Feb 10, 2022 that will close this issue
rom1v added a commit to Genymobile/scrcpy that referenced this issue Feb 20, 2022
Currently, there is an issue with the libusb prebuilt dll.

Refs #3011 <#3011>
Refs libusb/#1049 <libusb/libusb#1049>
rom1v added a commit to Genymobile/scrcpy that referenced this issue Feb 20, 2022
Currently, there is an issue with the libusb prebuilt dll.

Refs libusb/#1049 <libusb/libusb#1049>
PR #3011 <#3011>
tormodvolden added a commit to tormodvolden/libusb that referenced this issue Mar 15, 2022
Fixes libusb#1049

Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
@thewh1teagle
Copy link

I still get libusb-1.0.dll missing
I build like that:

cmake.exe .. -G "MinGW Makefiles" -DCMAKE_CXX_FLAGS="-static-libgcc -static-libstdc++ -static"
mingw32-make.exe -j16

@mcuee
Copy link
Member

mcuee commented Dec 31, 2023

I still get libusb-1.0.dll missing I build like that:

cmake.exe .. -G "MinGW Makefiles" -DCMAKE_CXX_FLAGS="-static-libgcc -static-libstdc++ -static"
mingw32-make.exe -j16

If you use CMake, then you may want to look at the repo here.
https://github.com/libusb/libusb-cmake

You also need to provide more details of what you are doing. Your issue is apparently not related to libusb. So please do not continue here but rather create a discussion here.
https://github.com/libusb/libusb/discussions

@thewh1teagle
Copy link

Ok, pasting here just to help others which encounter it too.
final solution to build it with static libusb:

cmake.exe .. -G "MinGW Makefiles" -DLIBUSB_LIBRARIES=/ucrt64/lib/libusb-1.0.a -DCMAKE_EXE_LINKER_FLAGS="-static -static-libgcc -static-libstdc++"

Note the line -DLIBUSB_LIBRARIES=/ucrt64/lib/libusb-1.0.a, change to the right path there to libusb.a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants