User Tools

Site Tools


user:draugthewhopper:windowsbuild-server

Compiling the server on MSYS2/MinGW

First, set up an environment like the client build environment. Reference the client autobuild Powershell script.

Before cloning the repos via git, turn off git's automatic CR/LF conversion: git config –global core.autocrlf false

The server will break pretty hard if some critical items have CRs in them. For example, you might get:

)EE] Got bonus line or otherwise unknown value before max stat! (

when trying to run the server, collect assets, etc.

When installing packages with Pacman, make sure you get ones from MinGW whenever possible. They are often prefixed by: mingw64/mingw-w64-x86_64-

I used Windows' own junctions for linking the maps and arch repos, like:

C:\autobuild.server\cfsource\cfserver\lib>mklink /j maps C:\autobuild.server\cfsource\cfmaps
Junction created for maps <<===>> C:\autobuild.server\cfsource\cfmaps

C:\autobuild.server\cfsource\cfserver\lib>mklink /j arch C:\autobuild.server\cfsource\cfarch
Junction created for arch <<===>> C:\autobuild.server\cfsource\cfarch

Run autoconf like the normal server build process: sh autogen.sh This should be mostly reliable.

At this point, you can call make. However, it'll error out twice. You need to strip out some #ifdef bits, so that the MXE cross-compile stuff applies to us too:

diff --git a/common/object.cpp b/common/object.cpp
index bd71d8ed7..cee1e7618 100644
--- a/common/object.cpp
+++ b/common/object.cpp
@@ -39,7 +39,6 @@
#include "sproto.h"
#include "stringbuffer.h"

-#ifdef CF_MXE_CROSS_COMPILE
#   define ffs(word) (__builtin_constant_p (word)                             \
					? __builtin_ffs (word)                                  \
					: ({ int __cnt, __tmp;                                  \
@@ -49,7 +48,6 @@
							: "=&r" (__cnt), "=r" (__tmp)                   \
							: "rm" (word), "1" (-1));                       \
							__cnt + 1; }))
-#endif

static int compare_ob_value_lists_one(const object *, const object *);
static int compare_ob_value_lists(const object *, const object *);
diff --git a/socket/init.cpp b/socket/init.cpp
index ed7e48940..5129d527b 100644
--- a/socket/init.cpp
+++ b/socket/init.cpp
@@ -97,11 +97,7 @@ void init_connection(socket_struct *ns, const char *from_ip) {
	SockList sl;

#ifdef WIN32 /* ***WIN32 SOCKET: init win32 non blocking socket */
-#ifdef CF_MXE_CROSS_COMPILE
	u_long temp = 1;
-#else
-    long temp = 1;
-#endif

	if (ioctlsocket(ns->fd, FIONBIO , &temp) == -1)
		LOG(llevError, "init_connection:  Error on ioctlsocket.\n");

These warnings seem mostly harmless:

CXX      win32.o
win32.cpp: In function 'void service_register()':
win32.cpp:171:29: warning: ISO C++ forbids converting a string constant to 'wchar_t*' [-Wwrite-strin
gs]
171 | #define SERVICE_DESCRIPTION L"Crossfire is a multiplayer online RPG game."
	|                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
win32.cpp:183:31: note: in expansion of macro 'SERVICE_DESCRIPTION'
183 |     wchar_t *strDescription = SERVICE_DESCRIPTION;
	|                               ^~~~~~~~~~~~~~~~~~~
win32.cpp: In function 'void service_handle()':
win32.cpp:167:29: warning: ISO C++ forbids converting a string constant to 'LPWSTR' {aka 'wchar_t*'}
[-Wwrite-strings]
167 | #define SERVICE_NAME        L"Crossfire"
	|                             ^~~~~~~~~~~~
win32.cpp:345:11: note: in expansion of macro 'SERVICE_NAME'
345 |         { SERVICE_NAME, ServiceMain },
	|           ^~~~~~~~~~~~

One of make's steps is to do some kind of collect steps, so if it fails here, note that the .exe has actually been built, and might be working. See above for the notes on CRLFs.

Even if all the config/data files are missing, you should be able to call the exe with the -h or -v flags, and it should run cleanly.

Once this step has been passed, it will attempt to do some python stuff. I got warnings here, and Python did not appear to work:

make[3]: Entering directory '/c/autobuild.server/cfsource/cfserver/plugins/cfpython'
CXX      pyi_generate-pyi-generate.o
CXX      pyi_generate-cfpython.o
CXX      pyi_generate-cfpython_archetype.o
CXX      pyi_generate-cfpython_object.o
CXX      pyi_generate-cfpython_map.o
CXX      pyi_generate-cfpython_party.o
CXX      pyi_generate-cfpython_region.o
CXX      pyi_generate-cjson.o
CXX      ../common/pyi_generate-plugin_common.o
CXXLD    pyi-generate.exe
CXX      cfpython.lo
CXX      cfpython_archetype.lo
CXX      cfpython_object.lo
CXX      cfpython_map.lo
CXX      cfpython_party.lo
CXX      cfpython_region.lo
CXX      cjson.lo
CXX      ../common/plugin_common.lo
CXXLD    cfpython.la
libtool: warning: undefined symbols not allowed in x86_64-w64-mingw32 shared libraries; building static only
make[3]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins/cfpython'
make[2]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins/cfpython'
Making all in cfanim
make[2]: Entering directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim'
Making all in include
make[3]: Entering directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim/include'
make[3]: Nothing to be done for 'all'.
make[3]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim/include'
make[3]: Entering directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim'
CXX      cfanim.lo
CXXLD    cfanim.la
libtool: warning: undefined symbols not allowed in x86_64-w64-mingw32 shared libraries; building static only
make[3]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim'

I completely skipped any make install steps.

Instead, I just pointed the server toward the correct config and lib folders:

Owner@DESKTOP-QH5PE0V MINGW64 /c/autobuild.server/cfsource/cfserver/server
$ crossfire-server.exe -conf /c/autobuild.server/cfsource/cfserver/lib/config -data /c/autobuild.server/cfsource/cfserver/lib
[II] Initializing modules

This resulted in a working server. It does throw errors about sockets, but this is not fatal. I never bothered to give it the ability to write anything to disk, so this fails as expected.

25/02/22 14:09:52 [EE] Cannot setsockopt(SO_REUSEADDR): Invalid argument
25/02/22 14:09:52 [EE] Cannot setsockopt(SO_REUSEADDR): Invalid argument
25/02/22 14:09:52 [II] Warning: Unable to open /usr/var/crossfire/accounts [No such file or directory]

Python simply doesn't work:

25/02/22 14:15:12 [EE] The requested handler doesn't exist: Python at 8/10 in map Port Gate of Scorn
25/02/22 14:15:15 [EE] The requested handler doesn't exist: Python at 6/10 in map Port Gate of Scorn

So, now trying make install. It puts stuff in these dirs, I think:

/mingw64/etc/crossfire		Contains only config files
/mingw64/libexec/crossfire	Contains only random_map.exe
/mingw64/bin			Contains lots of binaries, also crossfire-server.exe, cfdb_convert, crossloop, player_dl.pl
/mingw64/var/crossfire		Contains various "var-type" data dirs and files
/mingw64/share/crossfire	Contains various data, mostly packed
/mingw64/share/man/man6		Contains crossfire and crossloop manfiles
/mingw64/lib/crossfire/plugins	Contains cfpython and cfanim, both .a and .la

Trying to run crossfire-server.exe from the root dir fails, because it can't find maps:

[EE] Can't open C:/msys64/mingw64/share/crossfire/maps/HallOfSelection: No such file or directory
[EE] Initial map /HallOfSelection can't be found! Please ensure maps are correctly installed.
[EE] Unable to continue without initial map.
Fatal error: See last error

So, we now junction maps into this location.

Now it appears to launch, but immediately dumps back to the console. The server does not appear to be running in the background, and the exit code appears to be “3”:

Owner@DESKTOP-QH5PE0V MINGW64 /
$ crossfire-server
[II] Initializing modules
[II]   citybell (Ring bells every hour for defined temples): activated
[II]   citylife (Add NPCs in towns): activated
[II]   rhg (Add random maps to exits in towns): disabled
[II] Starting to collect assets from C:/msys64/mingw64/share/crossfire
[II] Finished collecting assets from C:/msys64/mingw64/share/crossfire
[EE] Couldn't parse todtick, using default value 0
[EE] C:/msys64/mingw64/var/crossfire/clockdata: cannot rename from C:/msys64/mingw64/var/cr
ossfire/clockdata.tmp: File exists
25/02/22 20:19:53 [II] Crossfire unknown
25/02/22 20:19:53 [II] Unable to open C:/msys64/mingw64/var/crossfire/accounts [No such fil
e or directory]. This may be because this is a new server and no accounts exist yet.
25/02/22 20:19:53 [II] Initialization complete (1217 ms). Waiting for connections.

Owner@DESKTOP-QH5PE0V MINGW64 /
$ echo $?
3

Maybe it's missing arch too? Let's try forcing a data dir:

Owner@DESKTOP-QH5PE0V MINGW64 /
$ crossfire-server.exe -conf /c/autobuild.server/cfsource/cfserver/lib/config -data /c/autobuild.server/cfsource/cfserver/lib
[II] Initializing modules
[II]   citybell (Ring bells every hour for defined temples): activated
[II]   citylife (Add NPCs in towns): activated
[II]   rhg (Add random maps to exits in towns): disabled
[II] Starting to collect assets from /c/autobuild.server/cfsource/cfserver/lib
[II] Finished collecting assets from /c/autobuild.server/cfsource/cfserver/lib
25/02/22 20:21:26 [II] Crossfire unknown
25/02/22 20:21:26 [EE] Cannot setsockopt(SO_REUSEADDR): Invalid argument
25/02/22 20:21:26 [EE] Cannot setsockopt(SO_REUSEADDR): Invalid argument
25/02/22 20:21:26 [II] Initialization complete (31585 ms). Waiting for connections.

Now it took much longer to init, and seems to keep running. The server again works, but python is broken.

Let's try linking arch, just in case.

No change.

Somehow, it's gotten worse. Now, when calling it from the root dir, it uses the wrong prefix to try to find stat_bonus:

Owner@DESKTOP-QH5PE0V MINGW64 /
$ crossfire-server.exe
[II] Initializing modules
[II]   citybell (Ring bells every hour for defined temples): activated
[II]   citylife (Add NPCs in towns): activated
[II]   rhg (Add random maps to exits in towns): disabled
[EE] Fatal error: could not open experience table (/usr/etc/crossfire/stat_bonus)

Owner@DESKTOP-QH5PE0V MINGW64 /
$

It should be looking in /mingw64/etc/crossfire/stat_bonus

Forcing it to use specific paths still works: $ crossfire-server.exe -conf /c/autobuild.server/cfsource/cfserver/lib/config -data /c/autobuild.server/cfsource/cfserver/lib

If everything is loaded, but the server exits early with exit code 0 (to check: issue echo $?), try purging var/crossfire/accounts, or all of var/crossfire.

If it exits with exit code 3, the cause is unknown, but a TCP socket stuck in TIME_WAIT is a possible culprit.

More work on python:

The libtool message about symbols is preventing an actual .dll file from being created. We can override libtool by editing libtool:7478 to read allow_undefined=no.

Now, the cfpython.dll is built, but cfanim fails:

make[3]: Entering directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim'
CXXLD    cfanim.la
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe
: .libs/cfanim.o: in function `find_by_name':
C:/autobuild.server/cfsource/cfserver/plugins/cfanim/cfanim.cpp:847:(.text+0x208c): undefined refere
nce to `map_space(mapstruct const*, int, int)'
collect2.exe: error: ld returned 1 exit status
make[3]: *** [Makefile:497: cfanim.la] Error 1
make[3]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim'
make[2]: *** [Makefile:554: all-recursive] Error 1
make[2]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins/cfanim'
make[1]: *** [Makefile:395: all-recursive] Error 1
make[1]: Leaving directory '/c/autobuild.server/cfsource/cfserver/plugins'
make: *** [Makefile:434: all-recursive] Error 1

The server looks for plugins in /usr/lib/crossfire/plugins, so we need to manually put this into C:\msys64\usr\lib\crossfire\plugins. Maybe make install would do it for us.

But, the server uses PLUGIN_SUFFIX to know what files to load as plugins. According to include/win32.h, this should be .dll, but I guess the server/Makefile.am takes precedence. So, we rename the file to have an extension of .so.

However, when the server tries to load it, we get 25/02/26 14:45:17 [EE] Plugin error while requesting /usr/lib/crossfire/plugins/cfpython.dll.so.initPlugin: No such process

user/draugthewhopper/windowsbuild-server.txt · Last modified: 2025/02/26 17:01 by draugthewhopper