Description
When building a "hello world" program with sfml and visual studio (configured to use static triplets), build fails on link step. It seems that vcpkg does not define SFML_STATIC, which is required for static builds. But even after defining it manually linking still fails (build log below). Dynamic SFML builds fine.
Environment
sfml:x86-windows, sfml:x64-windows, sfml:x86-windows-static, sfml:x64-windows-static<PropertyGroup Label="Globals">
...
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
</PropertyGroup>
To Reproduce
Steps to reproduce the behavior:
#define SFML_STATIC // This is a bug by itself - shouldn't vcpkg define this for me?
#include <SFML/Graphics.hpp>
int main() {
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
return 0;
}
Failure logs
This is a build log with normal verbosity, building x86 debug application and manually defining SFML_STATIC:
1>------ Build started: Project: Test Project (Static Linking), Configuration: Debug Win32 ------
1>Build started 03.11.19 02:21:59.
1>Target InitializeBuildStatus:
1> Touching "Debug\Test Pro.75f51cad.tlog\unsuccessfulbuild".
1>Target VcpkgTripletSelection:
1> Using triplet "x86-windows-static" from "C:\Users\andreasxp\vcpkg\installed\x86-windows-static\"
1>Target ClCompile:
1> main.cpp
1>Target Link:
1> sfml-window-s-d.lib(JoystickImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__joyGetPosEx@8 referenced in function "public: static bool __cdecl sf::priv::JoystickImpl::isConnected(unsigned int)" (?isConnected@JoystickImpl@priv@sf@@SA_NI@Z)
1> sfml-window-s-d.lib(JoystickImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__joyGetDevCapsW@12 referenced in function "public: bool __thiscall sf::priv::JoystickImpl::open(unsigned int)" (?open@JoystickImpl@priv@sf@@QAE_NI@Z)
1> sfml-system-s-d.lib(SleepImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__timeGetDevCaps@8 referenced in function "void __cdecl sf::priv::sleepImpl(class sf::Time)" (?sleepImpl@priv@sf@@YAXVTime@2@@Z)
1> sfml-system-s-d.lib(SleepImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__timeBeginPeriod@4 referenced in function "void __cdecl sf::priv::sleepImpl(class sf::Time)" (?sleepImpl@priv@sf@@YAXVTime@2@@Z)
1> sfml-system-s-d.lib(SleepImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__timeEndPeriod@4 referenced in function "void __cdecl sf::priv::sleepImpl(class sf::Time)" (?sleepImpl@priv@sf@@YAXVTime@2@@Z)
1> D:\Files\Develop\VS Projects\Test Project (Static Linking)\Debug\Test Project (Static Linking).exe : fatal error LNK1120: 5 unresolved externals
1>Done building target "Link" in project "Test Project (Static Linking).vcxproj" -- FAILED.
1>
1>Done building project "Test Project (Static Linking).vcxproj" -- FAILED.
1>
1>Build FAILED.
1>
1>sfml-window-s-d.lib(JoystickImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__joyGetPosEx@8 referenced in function "public: static bool __cdecl sf::priv::JoystickImpl::isConnected(unsigned int)" (?isConnected@JoystickImpl@priv@sf@@SA_NI@Z)
1>sfml-window-s-d.lib(JoystickImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__joyGetDevCapsW@12 referenced in function "public: bool __thiscall sf::priv::JoystickImpl::open(unsigned int)" (?open@JoystickImpl@priv@sf@@QAE_NI@Z)
1>sfml-system-s-d.lib(SleepImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__timeGetDevCaps@8 referenced in function "void __cdecl sf::priv::sleepImpl(class sf::Time)" (?sleepImpl@priv@sf@@YAXVTime@2@@Z)
1>sfml-system-s-d.lib(SleepImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__timeBeginPeriod@4 referenced in function "void __cdecl sf::priv::sleepImpl(class sf::Time)" (?sleepImpl@priv@sf@@YAXVTime@2@@Z)
1>sfml-system-s-d.lib(SleepImpl.cpp.obj) : error LNK2019: unresolved external symbol __imp__timeEndPeriod@4 referenced in function "void __cdecl sf::priv::sleepImpl(class sf::Time)" (?sleepImpl@priv@sf@@YAXVTime@2@@Z)
1>D:\Files\Develop\VS Projects\Test Project (Static Linking)\Debug\Test Project (Static Linking).exe : fatal error LNK1120: 5 unresolved externals
1> 0 Warning(s)
1> 6 Error(s)
1>
1>Time Elapsed 00:00:01.05
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Additional context
Digging around in SFML, I found out that sfml-system requires winmm library for joystick support. Maybe this library is not linked properly, which is causing joystick-related linking errors. I do not know what's causing the sleep-related errors.
@ras0219-msft I reproduce it on my VM with Visual Studio 2019 16.3.8. I found these code in SFML source file.
vcpkgbuildtrees\sfml\src\2.5.1-f499a1097e\src\SFML\Window\CMakeLists.txt L278-279:
elseif(SFML_OS_WINDOWS)
target_link_libraries(sfml-window PRIVATE winmm gdi32)
vcpkgbuildtrees\sfml\src\2.5.1-f499a1097e\src\SFML\System\CMakeLists.txt L98-99:
elseif(SFML_OS_WINDOWS)
target_link_libraries(sfml-system PRIVATE winmm)
The macro SFML_OS_WINDOWS is correct. But I can't find why there is no link to winmm.lib. Target_link_libraries failed here. Ask for your help.
Thanks.
When you're statically linking, you need to link against all of SFML's dependencies, which include winmm. Yes, SFML links against winmm as well, but that is only relevant for the dynamic builds, for the static builds all SFML symbols are integrated into your application, thus it also needs to directly link SFML's dependencies.
This should probably also list winmm and potentially gdi32 (VS will by default link this):
https://github.com/microsoft/vcpkg/blob/53183733000b3c4b025960ee04db939256556da0/ports/sfml/usage#L4-L5
I tried to understand what the port file is doing, but it looks really odd and wouldn't know where you'd have to specify winmm. My guess would be somewhere in here:
@LilyWangL:
Patch PRIVATE to PUBLIC and the cmake generated targets should contain winmm in the INTERFACE_LINK_LIBRARIES property
PRIVATE = build requirement; INTERFACE = usage requirement; PUBLIC = both
As discussed in Slack: The VS integration does not automatically link libraries which are outside of vcpkg. Has such winmm must be linked manually.
In the msvc project, vcpkg sets _VCPKG_PATH/installed/TRIPLETS/lib/ .lib_ or _VCPKG_PATH/installed/TRIPLETS/debug/lib/.lib_ as additional link libraries so that custom projects can link them .
However, the dependency system libraries will not be linked because they do not exist in the path.
Hi guys, I can confirm I've fixed this issue in #9190.
So please update vcpkg and rebuild sfml. Then try to use it.
Thanks.
Most helpful comment
@LilyWangL:
PatchPRIVATEtoPUBLICand the cmake generated targets should contain winmm in theINTERFACE_LINK_LIBRARIESpropertyAs discussed in Slack: The VS integration does not automatically link libraries which are outside of vcpkg. Has such winmm must be linked manually.