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

[WINDOWS] Cannot create a working import library. #874

Closed
carlo-bramini opened this issue May 4, 2021 · 13 comments · Fixed by #893
Closed

[WINDOWS] Cannot create a working import library. #874

carlo-bramini opened this issue May 4, 2021 · 13 comments · Fixed by #893
Labels

Comments

@carlo-bramini
Copy link
Contributor

I discovered that when you compile FluidSynth for Windows with MinGW or CYGWIN or MinGW-w64, it does not create a working import library. Or better: it creates it but later it can be overwritten by another file with the same name.
Let's take a look to the link command for libfluidsynth-3.dll:

/usr/bin/x86_64-w64-mingw32-g++.exe -Wall -W -Wpointer-arith -Wcast-qual -Wno-unused-parameter -Wcast-align -fopenmp -O2 -g -DNDEBUG -Wl,--no-undefined -shared -o libfluidsynth-3.dll -Wl,--out-implib,libfluidsynth.dll.a -Wl,--major-image-version,3,--minor-image-version,0 -Wl,--whole-archive CMakeFiles/libfluidsynth.dir/objects.a -Wl,--no-whole-archive @CMakeFiles/libfluidsynth.dir/linklibs.rsp

The option -Wl,--out-implib,libfluidsynth.dll.a instructs the compiler to create an import library called libfluidsynth.dll.a that you can use for linking a program to libfluidsynth-3.dll.
Later, the build process compiles the fluidsynth.exe test application:

/usr/bin/x86_64-w64-mingw32-gcc.exe -Wall -W -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wno-unused-parameter -Wdeclaration-after-statement -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Wbad-function-cast -Wcast-align -fopenmp -O2 -g -DNDEBUG -Wl,--as-needed -Wl,--whole-archive CMakeFiles/fluidsynth.dir/objects.a -Wl,--no-whole-archive -o fluidsynth.exe -Wl,--out-implib,libfluidsynth.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/fluidsynth.dir/linklibs.rsp

and if you look this command, you will see again -Wl,--out-implib,libfluidsynth.dll.a, identical to the previous one but generated from the test application!

In conclusion this is what happens:

  1. libfluidsynth-3.dll and libfluidsynth.dll.a are created.
  2. then, it creates fluidsynth.exe by using libfluidsynth.dll.a and it emits another libfluidsynth.dll.a that overwrites the previous one.

It was not immediate to see this issue because the build process does not fail.
Basically, this happens because "fluidsynth" is the base name for both the library and the test application. I tried to search around the net but I was not able to find a way to disable this -Wl,--out-implib option for the test application. Perhaps, in this case the only solution is to put fluidsynth.c in a separate directory with its own CMakeLists.txt file, so that it won't conflict anymore with the library.

MinGW, CYGWIN and MinGW-w64 alway show this defect.
With MSYS2, it seems there is something different: most of the times it is working fine, but sometime it does not. Perhaps it is luck, and it may depend on some locks and on which resource of the filesystem is unlocked first, I don't know.

@carlo-bramini
Copy link
Contributor Author

Here there are the logs taken from the configuration and the build processes.

cmake_config.txt
cmake_build.txt

@jjceresa
Copy link
Collaborator

jjceresa commented May 5, 2021

Basically, this happens because "fluidsynth" is the base name for both the library and the test application.
Perhaps, in this case the only solution is to put fluidsynth.c in a separate directory with its own CMakeLists.txt file, so that it won't conflict anymore with the library.

Having different name is the right solution, because for each build each generated import library (ie x.lib) is relative to the relevant generated binary(dll or exe) (ie x.dll or x.exe). Here we are faced to a name confict` which lead to a file overwritten by an another file with different content.

Perhaps, in this case the only solution is to put fluidsynth.c in a separate directory with its own CMakeLists.txt file.

We should pay attention to keep the dependency relationship. fluidsynth executable is dependent of libfluidsynth.

@jjceresa
Copy link
Collaborator

jjceresa commented May 8, 2021

I tried to search around the net but I was not able to find a way to disable this -Wl,--out-implib option for the test application.

Normally the decision to enable/disable the generation of import library should be under developer control. As MinGW is chosen by the developer via CMake, we should have the way to instruct CMake to enable/disable import library generation.
This is possible to do that when one choose MSVC generator via CMake, so I would expect this should be possible if we choose MinGW as well.

@derselbst
Copy link
Member

The import lib should not be created for the fluidsynth executable. Unfortunately, I have no idea, where this comes from. Technically, this particular case should be controllable with the CMAKE_ENABLE_EXPORTS variable. I tried setting it to OFF on this branch but it doesn't make a difference.

I had a look into the CMakeCache.txt but couldn't find any -Wl,--out-implib either. For the moment, I'm out of ideas.

@carlo-bramini
Copy link
Contributor Author

carlo-bramini commented May 23, 2021

For the moment, I'm out of ideas.

The only way that I found for fixing the problem is:

  1. create an application directory inside src.
  2. move fluidsynth.c and fluid_wasapi_device_enumerate.c into src/application.
  3. create src/application/CMakeLists.txt with some lines copied/moved from src/CMakeLists.txt.
  4. include src/application into src/CMakeLists.txt.

Do you think that it could be a (last resource) solution?

EDIT: if you look into Modules\Platform\CYGWIN-GNU.cmake or into Modules\Platform\Windows-GNU.cmake, you will see that the link command for executables is:

set(CMAKE_${lang}_LINK_EXECUTABLE
    "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")

In other words, the -Wl,--out-implib option is embedded directly, without chances of configuration, so it seems to me that we have no other solutions to hack or redefine CMAKE_${lang}_LINK_EXECUTABLE variable or move the sources of application into another directory, to avoid conflicts with the import library.
Perhaps, the choice to just move the files elsewhere looks less difficult since it won't need to distinguish between MSVC and GNU C...

@derselbst
Copy link
Member

EDIT: if you look into Modules\Platform\CYGWIN-GNU.cmake or into Modules\Platform\Windows-GNU.cmake, you will see that the link command for executables is:

Thanks for the hint. This made me find this issue: https://gitlab.kitware.com/cmake/cmake/-/issues/19805

I don't quite know where this __declspec(dllexport) comes from that makes cmake trigger the import lib creation for the fluidsynth exectuable. But overriding IMPORT_PREFIX fixes the naming clash, see #893.

@jjceresa
Copy link
Collaborator

I don't quite know where this __declspec(dllexport) comes from that makes cmake trigger the import lib creation for the fluidsynth exectuable.

__declspec(dllexport) are specified as decoration in any API name in fluidsynth library source. It seems that the source directory organisation for any target (.ddl or .exe) instructs cmake on how to trigger the import lib creation.

@derselbst
Copy link
Member

__declspec(dllexport) are specified as decoration in any API name in fluidsynth library source

In the library, i.e. libfluidsynth, yes. But I was talking about the executable.

It seems that the source directory organisation for any target (.ddl or .exe) instructs cmake on how to trigger the import lib creation.

Not according to Brad King's comment in the linked cmake issue.

@carlo-bramini
Copy link
Contributor Author

Thanks for the hint. This made me find this issue: https://gitlab.kitware.com/cmake/cmake/-/issues/19805

I tried your patch: changing the prefix of output file name for the import library has also fixed the problem with CYGWIN, MinGW-w64 and MSys2.

NOTE: When I tried MinGW-w64, at the beginning CMake was failing because a different error:

CMake Error at CMakeLists.txt:270 (if):
  if given arguments:

    "EQUAL" "10"

  Unknown arguments specified

After I forced CMAKE_SYSTEM_VERSION to a value, things worked fine on MinGW-w64 too.
The above error seems to be related to a recent change, because it was not failing before.
Perhaps, it would be worth to set CMAKE_SYSTEM_VERSION to a default value if it's undefined.

@derselbst
Copy link
Member

Hm, cmake is supposed to populate the CMAKE_SYSTEM_VERSION variable, strange. Anyway, I've made a fix #895 - feel free to test.

@carlo-bramini
Copy link
Contributor Author

Hm, cmake is supposed to populate the CMAKE_SYSTEM_VERSION variable, strange. Anyway, I've made a fix #895 - feel free to test.

That patch fixed also this issue. Thank you.

@jjceresa
Copy link
Collaborator

NOTE: When I tried MinGW-w64, at the beginning CMake was failing because a different error:
After I forced CMAKE_SYSTEM_VERSION to a value, things worked fine on MinGW-w64 too.
The above error seems to be related to a recent change, because it was not failing before.

The recent change is #871 and here CMake never failed (choosing MSVC generator).
It is really complicated to understand what is the real fix of this issue.

@carlo-bramini
Copy link
Contributor Author

It is really complicated to understand what is the real fix of this issue.

Probably not: that thing happened also if you try to cross compile FluidSynth. I suspect that I discovered it for pure case because I called MinGW-w64 from the bash of CYGWIN.

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.

3 participants