ValveSoftware / Proton

Compatibility tool for Steam Play based on Wine and additional components
Other
23.34k stars 1.02k forks source link

lsteamclient compilation errors #7867

Open h0tc0d3 opened 3 days ago

h0tc0d3 commented 3 days ago

I'm trying to build the latest version of lsteamclient, but I'm getting errors. I was able to remove -Wimplicit-function-declaration errors in C files by lowering the C standard to 89. For some reason, include in CPP files does not work correctly. lsteamclinet from proton_8.0 compiles successfully. Probably newer versions of compilers are more strict about errors.

winegcc --version
gcc (GCC) 14.1.1 20240620 (Red Hat 14.1.1-6)
export CFLAGS="-O2 -std=gnu89"
export CXXFLAGS="-O2 -std=gnu++17"
winemaker --wine32 --dll \
    --nosource-fix \
    --nolower-include \
    --nodlls \
    --nomsvcrt \
    -I${SOURCE_DIR:?}/wine/include \
    -I${SOURCE_DIR:?}/wine/include/wine \
    -I/usr/include \
    -DWINE_NO_LONG_TYPES \
    -DSTEAM_API_EXPORTS \
    -Dprivate=public \
    -Dprotected=public \
    .

sed -re 's#_LDFLAGS=#_LDFLAGS= -static-libgcc -static-libstdc++#' -i Makefile
make -e CC="winegcc -m32" CXX="wineg++ -m32" -j$(nproc)
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingServerListResponse_099u::RefreshComplete(uint32_t)':
unix_steam_networking_manual.cpp:624:5: error: 'TRACE' was not declared in this scope
  624 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamMatchmakingServerListResponse_099u* create_LinuxISteamMatchmakingServerListResponse_099u(void*)':
unix_steam_networking_manual.cpp:637:5: error: 'TRACE' was not declared in this scope
  637 |     TRACE("-> %p.\n", ret);
      |     ^~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingServerListResponse_106::RefreshComplete(void*, uint32_t)':
unix_steam_networking_manual.cpp:662:5: error: 'TRACE' was not declared in this scope
  662 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp: In function 'uint32_t (__attribute__((sysv_abi)) * manual_convert_Set_SteamAPI_CCheckCallbackRegisteredInProcess_func(w_SteamAPI_CheckCallbackRegistered_t))(int32_t)':
unixlib.cpp:195:5: error: 'FIXME' was not declared in this scope
  195 |     FIXME("not implemented!\n");
      |     ^~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamMatchmakingServerListResponse_106* create_LinuxISteamMatchmakingServerListResponse_106(void*)':
unix_steam_networking_manual.cpp:675:5: error: 'TRACE' was not declared in this scope
  675 |     TRACE("-> %p.\n", ret);
      |     ^~~~~
unixlib.cpp: In function 'uint32_t (__attribute__((sysv_abi)) * manual_convert_Set_SteamAPI_CCheckCallbackRegisteredInProcess_func_156(w_SteamAPI_CheckCallbackRegistered_t_156))(int32_t)':
unixlib.cpp:206:5: error: 'FIXME' was not declared in this scope
  206 |     FIXME("not implemented!\n");
      |     ^~~~~
unixlib_generated.cpp:9:18: error: 'unixlib_entry_t' does not name a type; did you mean 'unixlib_handle_t'?
    9 | extern "C" const unixlib_entry_t __wine_unix_call_funcs[] =
      |                  ^~~~~~~~~~~~~~~
      |                  unixlib_handle_t
unixlib.cpp: In function 'void (__attribute__((sysv_abi)) * manual_convert_Set_SteamAPI_CPostAPIResultInProcess_func(w_SteamAPI_PostAPIResultInProcess_t))(uint64_t, void*, uint32_t, int)':
unixlib.cpp:216:5: error: 'FIXME' was not declared in this scope
  216 |     FIXME("not implemented!\n");
      |     ^~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingPingResponse::ServerResponded(gameserveritem_t_105*)':
unix_steam_networking_manual.cpp:689:5: error: 'TRACE' was not declared in this scope
  689 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp: In function 'void (__attribute__((sysv_abi)) * manual_convert_Remove_SteamAPI_CPostAPIResultInProcess_func(w_SteamAPI_PostAPIResultInProcess_t))(uint64_t, void*, uint32_t, int)':
unixlib.cpp:222:5: error: 'FIXME' was not declared in this scope
  222 |     FIXME("not implemented!\n");
      |     ^~~~~
unixlib.cpp: In function 'void (__attribute__((sysv_abi)) * manual_convert_DEPRECATED_Set_SteamAPI_CPostAPIResultInProcess__a(w_void_SteamAPI_PostAPIResultInProcess_t))()':
unixlib.cpp:232:5: error: 'FIXME' was not declared in this scope
  232 |     FIXME("not implemented!\n");
      |     ^~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingPingResponse::ServerFailedToRespond()':
unix_steam_networking_manual.cpp:696:5: error: 'TRACE' was not declared in this scope
  696 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp: In function 'void (__attribute__((sysv_abi)) * manual_convert_DEPRECATED_Remove_SteamAPI_CPostAPIResultInProcess__a(w_void_SteamAPI_PostAPIResultInProcess_t))()':
unixlib.cpp:238:5: error: 'FIXME' was not declared in this scope
  238 |     FIXME("not implemented!\n");
      |     ^~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamMatchmakingPingResponse* create_LinuxISteamMatchmakingPingResponse(void*)':
unix_steam_networking_manual.cpp:708:5: error: 'TRACE' was not declared in this scope
  708 |     TRACE("-> %p.\n", ret);
      |     ^~~~~
unixlib.cpp: In function 'NTSTATUS steamclient_init(void*)':
unixlib.cpp:383:9: error: 'ERR' was not declared in this scope
  383 |         ERR( "unable to load native steamclient library\n" );
      |         ^~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:394:5: note: in expansion of macro 'LOAD_FUNC'
  394 |     LOAD_FUNC( CreateInterface );
      |     ^~~~~~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingPlayersResponse::PlayersFailedToRespond()':
unix_steam_networking_manual.cpp:728:5: error: 'TRACE' was not declared in this scope
  728 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:395:5: note: in expansion of macro 'LOAD_FUNC'
  395 |     LOAD_FUNC( Steam_BGetCallback );
      |     ^~~~~~~~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:396:5: note: in expansion of macro 'LOAD_FUNC'
  396 |     LOAD_FUNC( Steam_GetAPICallResult );
      |     ^~~~~~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingPlayersResponse::PlayersRefreshComplete()':
unix_steam_networking_manual.cpp:735:5: error: 'TRACE' was not declared in this scope
  735 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:397:5: note: in expansion of macro 'LOAD_FUNC'
  397 |     LOAD_FUNC( Steam_FreeLastCallback );
      |     ^~~~~~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamMatchmakingPlayersResponse* create_LinuxISteamMatchmakingPlayersResponse(void*)':
unix_steam_networking_manual.cpp:747:5: error: 'TRACE' was not declared in this scope
  747 |     TRACE("-> %p.\n", ret);
      |     ^~~~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:398:5: note: in expansion of macro 'LOAD_FUNC'
  398 |     LOAD_FUNC( Steam_ReleaseThreadLocalMemory );
      |     ^~~~~~~~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:399:5: note: in expansion of macro 'LOAD_FUNC'
  399 |     LOAD_FUNC( Steam_IsKnownInterface );
      |     ^~~~~~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingRulesResponse::RulesFailedToRespond()':
unix_steam_networking_manual.cpp:767:5: error: 'TRACE' was not declared in this scope
  767 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp:390:9: error: 'ERR' was not declared in this scope
  390 |         ERR( "unable to load " #x "\n" );                      \
      |         ^~~
unixlib.cpp:400:5: note: in expansion of macro 'LOAD_FUNC'
  400 |     LOAD_FUNC( Steam_NotifyMissingInterface );
      |     ^~~~~~~~~
unix_steam_networking_manual.cpp: In member function 'virtual void SteamMatchmakingRulesResponse::RulesRefreshComplete()':
unix_steam_networking_manual.cpp:774:5: error: 'TRACE' was not declared in this scope
  774 |     TRACE("Deleting this %p, w_iface %p.\n", this, this->w_iface);
      |     ^~~~~
unixlib.cpp:402:49: error: 'debugstr_a' was not declared in this scope
  402 |     TRACE( "Loaded host steamclient from %s\n", debugstr_a(path) );
      |                                                 ^~~~~~~~~~
unixlib.cpp:402:5: error: 'TRACE' was not declared in this scope
  402 |     TRACE( "Loaded host steamclient from %s\n", debugstr_a(path) );
      |     ^~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamMatchmakingRulesResponse* create_LinuxISteamMatchmakingRulesResponse(void*)':
unix_steam_networking_manual.cpp:786:5: error: 'TRACE' was not declared in this scope
  786 |     TRACE("-> %p.\n", ret);
      |     ^~~~~
unixlib.cpp: In function 'void collapse_path(WCHAR*, UINT)':
unixlib.cpp:457:36: error: 'wcslen' was not declared in this scope
  457 |                 memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) );
      |                                    ^~~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamNetworkingConnectionCustomSignaling* create_LinuxISteamNetworkingConnectionCustomSignaling(void*)':
unix_steam_networking_manual.cpp:792:5: error: 'FIXME' was not declared in this scope
  792 |     FIXME( "not implemented!\n" );
      |     ^~~~~
unixlib_generated.cpp:20949:41: error: 'ARRAY_SIZE' was not declared in this scope; did you mean 'ARRAYSIZE'?
20949 | const unsigned int callback_data_size = ARRAY_SIZE(callback_data);
      |                                         ^~~~~~~~~~
      |                                         ARRAYSIZE
unixlib.cpp:494:68: error: 'wcslen' was not declared in this scope
  494 |             if (p > path + mark && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) );
      |                                                                    ^~~~~~
unix_steam_networking_manual.cpp: In function 'u_ISteamNetworkingCustomSignalingRecvContext* create_LinuxISteamNetworkingCustomSignalingRecvContext(void*)':
unix_steam_networking_manual.cpp:798:5: error: 'FIXME' was not declared in this scope
  798 |     FIXME( "not implemented!\n" );
      |     ^~~~~
h0tc0d3 commented 3 days ago

There is also probably an error in this commit: https://github.com/ValveSoftware/Proton/commit/5d374bdc2cf3b38f9be60b30ee8fc98ea4c4e381 The compiler throws an error because u""

steamclient_main.c: In function 'load_steamclient':
steamclient_main.c:347:22: error: 'u' undeclared (first use in this function)
  347 |     if (!get_env_win(u"SteamAppId", steam_app_id, sizeof(steam_app_id)))
      |                      ^
steamclient_main.c:347:22: note: each undeclared identifier is reported only once for each function it appears in
steamclient_main.c:347:23: error: expected ')' before string constant
  347 |     if (!get_env_win(u"SteamAppId", steam_app_id, sizeof(steam_app_id)))
      |                     ~ ^~~~~~~~~~~~
      |                       )
steamclient_main.c:347:10: error: too few arguments to function 'get_env_win'
  347 |     if (!get_env_win(u"SteamAppId", steam_app_id, sizeof(steam_app_id)))
      |          ^~~~~~~~~~~
steamclient_main.c:329:13: note: declared here
  329 | static BOOL get_env_win(const WCHAR *name, char *value, unsigned int size)
      |             ^~~~~~~~~~~
steamclient_main.c:352:23: error: expected ')' before string constant
  352 |     if (!get_env_win(u"IgnoreChildProcesses", ignore_child_processes, sizeof(ignore_child_processes)))
      |                     ~ ^~~~~~~~~~~~~~~~~~~~~~
      |                       )
steamclient_main.c:352:10: error: too few arguments to function 'get_env_win'
  352 |     if (!get_env_win(u"IgnoreChildProcesses", ignore_child_processes, sizeof(ignore_child_processes)))
      |          ^~~~~~~~~~~
steamclient_main.c:329:13: note: declared here
  329 | static BOOL get_env_win(const WCHAR *name, char *value, unsigned int size)
u"SteamAppId"
u"IgnoreChildProcesses"

There probably should be:

L"SteamAppId"
L"IgnoreChildProcesses"

The L symbol in front of a string literal simply means that each character in the string will be stored as a wchar_t.

https://stackoverflow.com/questions/1810343/is-a-wide-character-string-literal-starting-with-l-like-lhello-world-guarantee

h0tc0d3 commented 3 days ago

Compilation error: Include_winsock_h_before_stdlib_h_or_use_the_MSVCRT_library

In file included from wine/include/winsock2.h:160,
                 from steamclient_main.c:13:
wine/include/winsock2.h:561:19: error: redefinition of 'struct timeval'
  561 | typedef struct WS(timeval)
      |                   ^~~~~~~
wine/include/ws2def.h:27:18: note: in definition of macro 'WS'
   27 | #define WS(x)    x
      |                  ^
In file included from /usr/include/sys/select.h:37,
                 from /usr/include/sys/types.h:179,
                 from /usr/include/stdlib.h:514,
                 from steamclient_main.c:2:
/usr/include/bits/types/struct_timeval.h:8:8: note: originally defined here
    8 | struct timeval
      |        ^~~~~~~
winegcc -c -O2 -std=gnu89  -Iwine/include -Iwine/include/wine -I/usr/include -I. -DWINE_NO_LONG_TYPES -DSTEAM_API_EXPORTS -Dprivate=public -Dprotected=public  -o winISteamScreenshots.o winISteamScreenshots.c
winegcc -c -O2 -std=gnu89  -Iwine/include -Iwine/include/wine -I/usr/include -I. -DWINE_NO_LONG_TYPES -DSTEAM_API_EXPORTS -Dprivate=public -Dprotected=public  -o winISteamUGC.o winISteamUGC.c
wine/include/winsock2.h:51:22: error: unknown type name 'Include_winsock_h_before_stdlib_h_or_use_the_MSVCRT_library'
   51 | #  define fd_set     Include_winsock_h_before_stdlib_h_or_use_the_MSVCRT_library
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wine/include/ws2def.h:27:18: note: in definition of macro 'WS'
   27 | #define WS(x)    x
      |                  ^
wine/include/winsock2.h:1078:56: note: in expansion of macro 'fd_set'
 1078 | WINSOCK_API_LINKAGE int WINAPI __WSAFDIsSet(SOCKET, WS(fd_set) *);
Saancreed commented 2 days ago
error: 'TRACE' was not declared in this scope
error: 'FIXME' was not declared in this scope
error: 'ERR' was not declared in this scope

As expected, you are building a Wine (side-)module so __WINESRC__ is required to be defined and this is how the lack of it usually manifests. You probably forgot to add -D__WINESRC__ somewhere.

error: 'u' undeclared (first use in this function)

That's just a UTF-16 string literal. Don't cripple your compiler with custom/old -std=… and it should work as long as it knows what C11 is.

error: redefinition of 'struct timeval'
…
In file included from /usr/include/sys/select.h:37,
                 from /usr/include/sys/types.h:179,
                 from /usr/include/stdlib.h:514,
                 from steamclient_main.c:2:

Hmm, looks like steamclient_main.c is not a part of the unixlib and therefore it should probably be compiled with winegcc -b x86_64-w64-mingw32 (or winegcc -b i686-w64-mingw32 for 32-bit). I think this means that either your Makefile (generator?) is broken because it isn't using the correct cross-compiler or your Mingw is broken because it's including system/unixside headers from /usr/include while it should be looking at something closer to /usr/{x86_64,i686}-w64-mingw32/include (like it does on Arch).

…_or_use_the_MSVCRT_library

This is probably the way to go if commit message from https://github.com/ValveSoftware/Proton/commit/838d14d66ee1e5ae535f49b7634f2ea937e77938 is to be trusted :sweat_smile:

But why is MSVCRT not the default I have no idea, even though it should for PE builds since 2022. Try explicit -mno-cygwin?

h0tc0d3 commented 2 days ago

@Saancreed Thx. Yes you are right, I looked at the header files and they require __WINESRC__ to be set. Also need to remove --nomsvcrt.

winemaker --wine32 --dll \
    --nosource-fix \
    --nolower-include \
    --nodlls \
    --nobackup \
    -D__WINESRC__ \
    -I${SOURCE_DIR:?}/wine/include \
    -I${SOURCE_DIR:?}/wine/include/wine \
    -I/usr/include \
    -DWINE_NO_LONG_TYPES \
    -DSTEAM_API_EXPORTS \
    -Dprivate=public \
    -Dprotected=public \
    -lws2_32 \
    .

sed -re 's@_LDFLAGS=@_LDFLAGS= -static-libgcc -static-libstdc++@' -i Makefile
make -s -e CC="winegcc -m32" CXX="wineg++ -m32" -j$(nproc)

Now I'm facing another problem:

/usr/bin/ld: /home/user/wine/bin/../lib/wine/i386-unix/libwinecrt0.a(unix_lib.o): warning: relocation in read-only section `.text'
/usr/bin/ld: unixlib.o: in function `steamclient_dos_to_unix_path':
unixlib.cpp:(.text+0x1827): undefined reference to `ntdll_umbstowcs'
/usr/bin/ld: unixlib.o: in function `steamclient_dos_to_unix_path_array':
unixlib.cpp:(.text+0x1afd): undefined reference to `ntdll_umbstowcs'
/usr/bin/ld: unixlib.o: in function `steamclient_unix_path_to_dos_path':
unixlib.cpp:(.text+0x1fb4): undefined reference to `ntdll_wcstoumbs'
/usr/bin/ld: warning: creating DT_TEXTREL in a shared object
collect2: error: ld returned 1 exit status
winegcc: /usr/bin/g++ failed
make: *** [Makefile:363: lsteamclient.dll.so] Error 2

I also tried to compile the dll inside wine and registered the module in configure.ac, the module compiles successfully, but after start game raise exception Access violation in https://github.com/ValveSoftware/Proton/commit/a287ebaaf970c5ca34639264d1dbc5156fbb2f5f

Saancreed commented 2 days ago

ntdll_umbstowcs ntdll_wcstoumbs

They are implemented in Unix-side ntdll.so, try -l:ntdll.so. It's a bit hack-ish, yeah, but I'm not sure how to convince winegcc to link to ntdll.so otherwise.

warning: relocation in read-only section '.text'

Curious, maybe due to lack of -fPIC?

Access violation in

Unfortunately that's not very helpful. Either it's caused by some other build issue or it's gdb time.

h0tc0d3 commented 2 days ago

They are implemented in Unix-side ntdll.so, try -l:ntdll.so. It's a bit hack-ish, yeah, but I'm not sure how to convince winegcc to link to ntdll.so otherwise.

Did not help. I also tried -lntdll and -intdll.

Saancreed commented 1 day ago

Welp, my sample works for me when I do that. Check if it's searching correct directories for that library, e.g. when I compile with -Wl,--verbose -Wl,-l:ntdll.so the linker prints something like

…
/usr/bin/ld: mode elf_x86_64
attempt to open /usr/lib/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../lib/crti.o
attempt to open /usr/lib/gcc/x86_64-pc-linux-gnu/14.1.1/crtbeginS.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/14.1.1/crtbeginS.o
attempt to open /usr/bin/../lib/wine/x86_64-unix/ntdll.so succeeded
/usr/bin/../lib/wine/x86_64-unix/ntdll.so
…

Which exports wanted symbols:

$ nm -D /usr/lib/wine/x86_64-unix/ntdll.so | grep ntdll_
0000000000013430 T ntdll_get_build_dir
0000000000013440 T ntdll_get_data_dir
000000000005e600 T ntdll_set_exception_jmp_buf
00000000000118e0 T ntdll_umbstowcs
0000000000011d90 T ntdll_wcsicmp
0000000000011e20 T ntdll_wcsnicmp
0000000000011b80 T ntdll_wcstoumbs

But if -Wl,--verbose doesn't help you to find the cause then I have no idea how else you could debug this, sorry. You'd probably have to check exactly how the full Proton build handles lsteamclient and capture relevant arguments from there.