Open asparagii opened 5 years ago
That's not a Godot issue, you just need to actually link the library by appending it to LIBS
for your module_env
(like module_env.Append(LIBS=['FMOD'])
or similar). See http://docs.godotengine.org/en/latest/development/cpp/binding_to_external_libraries.html
If the docs are not clear enough for your use case, you can open an issue on https://github.com/godotengine/godot-docs to discuss it further and have the tutorial improved.
I have this issue too. I have the same setup as @MicheleLambertucci and my SCsub is:
Import('env')
fmodapifolder = "#thirdparty/FMOD Studio API Windows/api"
module_env = env.Clone()
module_env.add_source_files(env.modules_sources, "*.cpp")
module_env.Append(CPPPATH=fmodapifolder + "/studio/inc")
module_env.Append(LIBPATH=fmodapifolder + "/studio/lib")
module_env.Append(CPPPATH=fmodapifolder + "/lowlevel/inc")
module_env.Append(LIBPATH=fmodapifolder + "/lowlevel/lib")
module_env.Append(LIBS=['fmod','fmodL','fmodstudio','fmodstudioL','fmod_vc','fmodL_vc','fmodstudio_vc','fmodstudioL_vc'])
Still I get Linker errors. Note that the FMOD API is a shared library (so .lib and .dll files), and the both the docs and the engine use open source static libraries. So maybe this is not the correct way for binding an external Shared library? The docs don't say anything about it and the engine source code doesn't provide any example on how to do this.
Not an expert, but from what I remember .lib files distributed with shared libraries (or .a on linux) are exactly static libraries. They should do the loading of .dll for you when included in the executable.
@rmazzier You're close - the issue is that the libs have to be passed to the linker for the Godot binary, and thus to the main env
. This should work:
fmodapifolder = "#thirdparty/FMOD Studio API Windows/api"
module_env = env.Clone()
module_env.add_source_files(env.modules_sources, "*.cpp")
module_env.Append(CPPPATH=fmodapifolder + "/studio/inc")
module_env.Append(CPPPATH=fmodapifolder + "/lowlevel/inc")
env.Append(LIBPATH=fmodapifolder + "/studio/lib")
env.Append(LIBPATH=fmodapifolder + "/lowlevel/lib")
env.Append(LIBS=['fmod','fmodL','fmodstudio','fmodstudioL','fmod_vc','fmodL_vc','fmodstudio_vc','fmodstudioL_vc'])
Here's a test module I used (on Linux) to confirm that: sndfile.zip
module_env = env.Clone()
module_env.Append(CPPPATH=["#modules/sndfile/sndfile/include"])
env.Append(LIBPATH=["#modules/sndfile/sndfile/lib"])
env.Append(LIBS=["sndfile"])
# Special case here as sndfile depends on FLAC and vorbis
env.Append(LIBS=["FLAC", "vorbis", "vorbisenc"])
Thank you for your reply. Even if I had already tried the way you suggested, I gave it another chance. My current SCsub is:
Import('env')
fmodapifolder = "#thirdparty/fmod/"
module_env = env.Clone()
module_env.add_source_files(env.modules_sources, "*.cpp")
module_env.Append(CPPPATH=[fmodapifolder + "/studio/inc/"])
module_env.Append(CPPPATH=[fmodapifolder + "/lowlevel/inc/"])
env.Append(LIBPATH=[fmodapifolder + "/studio/lib/ "])
env.Append(LIBPATH=[fmodapifolder + "/lowlevel/lib/"])
env.Append(LIBS=['fmodstudio_ARM','fmodstudio_X64','fmodstudioL_ARM','fmodstudioL_X64'])
env.Append(LIBS=['fmod_ARM','fmod_X64','fmodL_ARM','fmodL_X64'])
But I still get linker errors. Specifically:
D:\Riccardo\Godot Build\godot-master>scons -j6 platform=windows
scons: Reading SConscript files ...
Configuring for Windows: target=debug, bits=default
Found MSVC compiler: amd64
Compiled program architecture will be a 64 bit executable (forcing bits=64).
YASM is necessary for WebM SIMD optimizations.
WebM SIMD optimizations are disabled. Check if your CPU architecture, CPU bits or platform are supported!
Checking for C header file mntent.h... (cached) no
scons: done reading SConscript files.
scons: Building targets ...
[ 97%] [91mLinking Program [95m==> [93mbin\godot.windows.tools.64.exe[0m
sibi[ 98%] le aprire il file di input 'fmodstudio_ARM.windows.tools.64.lib'
[100%] progress_finish(["progress_finish"], [])
[100%] scons: *** [bin\godot.windows.tools.64.exe] Error 1181
scons: building terminated because of errors.
Since I am not understanding whether I am doing something wrong or not , would you mind trying to compile it and see if you get the same error?
Here is the zip with the libs and my current code. Thanks.
[ 98%] le aprire il file di input 'fmodstudio_ARM.windows.tools.64.lib'
What Godot commit are you building against? And what SCons version? This extra lib suffix should be fixed in the master branch already with #20380.
Master branch, latest commit.
Using the latest SCons version:
D:\Riccardo\Godot Build\godot-master>scons --version
SCons by Steven Knight et al.:
script: v3.0.1.74b2c53bc42290e911b334a6b44f187da698a668, 2017/11/14 13:16:53, by bdbaddog on hpmicrodog
engine: v3.0.1.74b2c53bc42290e911b334a6b44f187da698a668, 2017/11/14 13:16:53, by bdbaddog on hpmicrodog
engine path: ['C:\\Python27\\scons-3.0.1\\SCons']
Copyright (c) 2001 - 2017 The SCons Foundation
Alright, it works fine on Linux but apparently #20045 is still valid on MSVC. Any idea @garyo?
We're now properly saving the original LIBSUFFIX
and SHLIBSUFFIX
in LIBSUFFIXES
prior to modifying them, but MSVC's linker still seems to try LIBSUFFIX
instead of iterating LIBSUFFIXES
as hinted by the man page? https://github.com/godotengine/godot/blob/master/SConstruct#L425-L429
I found the cause of the issue. It is caused by different format in which windows and *nix linkers take their arguments.
On *nix systems, linkers take their arguments stripped from their prefixes and suffixes. This means that linker passed -lmylib
argument actually looks for either libmylib.a
or libmylib.so
by default. $LIBPREFIXES
and $LIBSUFFIXES
are the variables that control which prefixes and suffixes the linker checks for.
MSVC linker, on the other hand, expects the arguments to be full filenames. So what SCons passes to the linker here is list of files that is constructed from list of libraries in$LIBS
variable with $LIBLINKPREFIX
and $LIBLINKSUFFIX
prepended and appended respectively. And since $LIBLINKSUFFIX
by default points to $LIBSUFFIX
, we get error messages such as LINK : fatal error LNK1181: cannot open input file 'fmodL_vc.windows.opt.tools.32.lib'
There is a way, however, to override how the arguments that get passed to the linker are formatted. I'd suggest emulating the *nix linker behaviour on windows so that $LIBPREFIXES
and $LIBSUFFIXES
would work the same way on all platforms.
I overcame this when linking mono by passing the LINKFLAGS directly.
@neikeq Looking at your code right now. Yeah, that's also a way to go around it. Maybe it would be even better solution than the one I implemented - just wrap this piece of code in custom env functions.
Reopening as it's not properly fixed yet - see #23910.
I'm having the same issue here. Trying to link FMOD using MSVC 2017.
[100%] LINK : fatal error LNK1181: cannot open input file 'fmod_vc.windows.tools.64.lib' scons: *** [bin\godot.windows.tools.64.exe] Error 1181 scons: building terminated because of errors.
Glad to see the issue mentioned here. Can somebody please suggest a temporary solution to this until it's properly fixed?
A temporary solution would be - as dumb as it sounds - renaming your libraries to match the Godot extensions, i.e. turn your fmod_vc.lib
to fmod_vc.windows.tools.64.lib
. If you are building on multiple configurations, you'd need to do have a copy of a library with each configuration's specific extension.
The other way would be taking a look at how neikeq did it with Mono. https://github.com/godotengine/godot/blob/d8c40bccbbbf74001cbd085da5f71180e054e17f/modules/mono/config.py#L113-L119
However, I am not sure how confident you are with SCons/Python. Let me know if you need some more help.
This is the first time I'm being exposed to the SCons build system and I'm still getting used to it. Renaming the files worked however and it compiled without any errors 🎉
I can confirm this is still an issue, its looking for the godot lib extensions for my libraries.
Using LINKFLAGS worked, but its not a very graceful solution.
I found an alternative workaround to using $LINKFLAGS
:
if env.msvc:
env.Append(LIBS=[File('path/to/fmod_vc.lib')])
else:
env.Append(LIBS=['fmod_vc'])
According to $LIBS document, appending File(...)
to $LIBS
will ignore $LIBLINKPREFIX
and $LIBLINKSUFFIX
. Therefore, the path provided to File(...)
construct must be relative or absolute path with the correct prefix and suffix.
@Looooong Is there something we need to fix on our end? If so, please open a pull request :slightly_smiling_face:
@Calinou Well, this is just a temporary workaround this issue when linking external static libraries with MSVC. The real issue might be on the SCons end as discussed here.
A single point solution for windows, would be to overwrite the _LIBFLAGS
environment variable in the SConstruct, which when using msvc, is just a concatenation function. The new function would check each library in the link line and if its one of Godots, it would add the custom suffix, otherwise use the standard windows .lib
. Marking godot's libraries can be done in a number of ways, but since there is a common add_library
function in methods.py, this could add a node.attribute to the library node, which indicates its a Godot library.
But looking at this issue from a higher lever, I don't think you should be messing with the LIBSUFFIX
variable in the first place. This variable is intended to set the system standard libsuffix, not for a single set of user libraries. Really what you should do is just add the suffix in your custom add_library
call, or override the Library builder to do it for you.
I like the File()
wrapping solution @Looooong mentioned. However, the issue is made more complicated when compiling a module and using Windows SDK libs for several reasons.
LIBSUFFIX
must be applied to the engine's build environment. Because LIBS
must be edited on the primary env, not the cloned env, this will affect all other modules.bcrypt
, userenv
, etc. which can't easily be wrapped in File()
. Including these libs will result in the linker looking for userenv.windows.template_release.x86_64.lib
(or whatever your Godot build config determines). See https://github.com/ashtonmeuser/godot-wasm/issues/27.@Calinou this seems like a bit of a blocker for module developers. How can I include userenv
in a Godot module built with MSVC?
fmod.zip
Godot version: 3.1
OS/device including version: Windows
Issue description: It's very likely to be my fault, but I can't include the FMOD library when linking a custom module. It's strange how the module itself compiles without problems, but when it comes to the "Linking program" step the compiler freezes for a bit and then outputs
fatal error LNK2019: unresolved external symbol "public: static enum FMOD_RESULT __cdecl FMOD::Studio::System::create(class FMOD::Studio::System * *,unsigned int)" in function "public: __cdecl FMod::FMod(void)"
.Minimal reproduction project: I placed the "FMOD Studio API Windows" under "thirdparty". The module itself basically contains just a call to FMOD's initialization function. I attached the module as a zip file. For those who don't want to download the zip, here's the SCsub:
Here's fmod.cpp:
Here's fmod.h:
Also, I don't know if this can help, but without any call to FMOD functions (only with the
includes
), scons compiles without any issue.