Cross-compiling NetHack with Visual Studio from an x64 platform to an ARM64
target presents some new build challenges.
In the current nethack.sln solution, the build attempts to execute the
several just-built tools during the build of various subprojects.
For example, when cross-compiling on a typical Windows 11 x64 machine
to build a target ARM64 Windows 11 package, the build process tries to
run the following just-built target tools:
(under a Debug build)
"$(ToolsDir)\Debug\ARM64\uudecode.exe"
"$(ToolsDir)\Debug\ARM64\makedefs.exe"
"$(ToolsDir)\Debug\ARM64\tilemap.exe"
"$(ToolsDir)\Debug\ARM64\tile2bmp.exe"
"$(ToolsDir)\Debug\ARM64\dlb.exe"
(under a Release build)
"$(ToolsDir)\Release\ARM64\uudecode.exe"
"$(ToolsDir)\Release\ARM64\makedefs.exe"
"$(ToolsDir)\Release\ARM64\tilemap.exe"
"$(ToolsDir)\Release\ARM64\tile2bmp.exe"
"$(ToolsDir)\Release\ARM64\dlb.exe"
Those fail to execute successfully on Intel x64 (or x86) since they
are actually ARM64 executables, and the build attempts to execute
them on the host Intel x64 hardware.
The situation is a little different if the cross-compile is carried out
on a Windows 11 ARM64 machine (such as SnapDragon).
On an ARM64 machine, the cross-compile to build a target Intel x64
Windows 11 package, tries to execute the following:
(under a Debug build)
"$(ToolsDir)\Debug\x64\uudecode.exe"
"$(ToolsDir)\Debug\x64\makedefs.exe"
"$(ToolsDir)\Debug\x64\tilemap.exe"
"$(ToolsDir)\Debug\x64\tile2bmp.exe"
"$(ToolsDir)\Debug\x64\dlb.exe"
(under a Release build)
"$(ToolsDir)\Release\x64\uudecode.exe"
"$(ToolsDir)\Release\x64\makedefs.exe"
"$(ToolsDir)\Release\x64\tilemap.exe"
"$(ToolsDir)\Release\x64\tile2bmp.exe"
"$(ToolsDir)\Release\x64\dlb.exe"
Those actual do succeed in executing on ARM64, because of the
"prism emulation" that is available on Windows 11 ARM64 operating
systems to allow x64 and x86 executables to run.
The following change adds some detection to build environment, leading
to the definition of a "HostTools" macro that leads to the native host
tools for those steps.
There is a catch:
It means that the native build of the interim tools for Windows 11 must
be executed prior to attempting a cross-compile build to a non-native
target. That ensures that the native x64 interim uudecode, makedefs,
tilemap, tile2bmp and dlb tools are available on the disk for use by
a subsequent cross-compile.
This change consistently switches to the use of the host-native
interim tools for uudecode, makedefs, tilemap, tile2bmp and dlb tools.
Technically, this change would not be strictly necessary on an
ARM64-hosted build that was targeting x64 or x86, because of the
available prism-emulation that allows ARM64, x64, and x86 images to
execute, but this maintains consistency of the build process on
either platform. It is also likely that the native host versions execute
more quickly than versions requiring the prism emulation, although
that isn't really a concern for a NetHack build.
The use of native host uudecode, makedefs, tilemap, tile2bmp and
dlb tools is done with the Unix-hosted cross-compiles to other
target platforms as well (on Linux or macOS).
This is the third of a series of savefile-related changes.
This adds early-days experimental support for a completely optional
'sfctool' utility (savefile conversion tool), to be able to export
a savefile's contents into a more portable format. There are likely
to be bugs at this stage. In this initial first-attempt, the export
format is a very simple ascii output.
NetHack can be built entirely, without also building this tool.
NetHack has no dependencies on the tool.
Attempts were made to minimize duplication of existing NetHack code.
To achieve that, unfortunately, #ifdef SFCTOOL and #ifndef SFCTOOL
had to be sprinkled around through some of the existing NetHack
source code, so that it could be re-used for building the utility.
The process for building the sfctool typically recompiles the source
files with #define SFCTOOL and a distinct object file with SF- is
produced.
sfctool notes:
Universal ctags is used and required to produce the sfctool utility.
Some targets were added to the Unix and Windows Makefiles to
facilitate the build process.
make sfctool
That should build a copy in util.
Note: At present, the Unix Makefiles do not copy sfctool over to the
NetHack playground during 'make install' or 'make update'.
Until that gets resolved by someone, The tool will
have to be manually copied there by the builder/admin if
desired.
cp util/sfctool ~/nh/install/games/lib/nethackdir/sfctool
Also, a separate Visual Studio sfctool.sln solution was written and
placed in sys/windows/vs. That has has only very limited testing.
Usage:
i) To convert an existing savefile to an exportascii format
that co-resides with the savefile:
sfctool -c savefile
That *must* be executed on the same platform / architecture /
data model that produced the save file in the first place.
ii) To unconvert an existing exportascii format export file to a
historical format savefile that can then be used by NetHack:
sfctool -u savefile
That must be executed on the same target platform / architecture /
data model that was used to build the NetHack that will
utilize the save file that results.
A Windows example:
sfctool -c Fred.NetHack-saved-game
That should result in creation of Fred.NetHack-saved-game.exportascii
from existing savefile:
%USERPROFILE%\AppData\Local\NetHack\3.7\Fred.NetHack-saved-game
A Unix example:
sfctool -c 1000wizard
That should result in creation of 1000wizard.exportascii.gz
from existing savefile in the playground save directory:
1000wizard.gz
Current Mechanics:
1. Makefile recipe, or script uses universal ctags to produce
util/sf.tags.
2. util/sftags is built and executed to read util/sf.tags and
generate: include/sfproto.h and src/sfdata.c.
3. util/sfctool is built from the following:
generated file compiled with -DSFCTOOL:
src/sfdata.c -> sfdata.o
existing files compiled with -DSFCTOOL:
util/sfctool.c -> sfctool.o
util/sfexpasc.c -> sfexpasc.o
src/alloc.c -> sf-alloc.o
src/monst.c -> sf-monst.o
src/objects.c -> sf-objects.o
src/sfbase.c -> sfbase.o
src/sfstruct.c -> sfstruct.o
src/nhlua.c -> sf-nhlua.o
util/panic.c -> panic.o
src/date.c -> sf-date.o
src/decl.c -> sf-decl.o
src/artifact.c -> sf-artifact.o
src/dungeon.c -> sf-dungeon.o
src/end.c -> sf-end.o
src/engrave.c -> sf-engrave.o
src/cfgfiles.c -> sf-cfgfiles.o
src/files.c -> sf-files.o
src/light.c -> sf-light.o
src/mdlib.c -> sf-mdlib.o
src/mkmaze.c -> sf-mkmaze.o
src/mkroom.c -> sf-mkroom.o
src/o_init.c -> sf-o_init.o
src/region.c -> sf-region.o
src/restore.c -> sf-restore.o
src/rumors.c -> sf-rumors.o
src/sys.c -> sf-sys.o
src/timeout.c -> sf-timeout.o
src/track.c -> sf-track.o
src/version.c -> sf-version.o
src/worm.c -> sf-worm.o
src/strutil.c -> strutil.o
Having a hardcoded relative path worked okay with the nmake Makefile
build but cause problems on a visual studio build. The CI caught that
right away.
Remove the relative paths, and add additional include directories for
the resouce compiler to search in the Makefile and in visual studio.
rename sys/winnt to sys/windows
move vs (visual studio) folder out of win/win32 and into sys/windows
rename include/ntconf.h to include/windconf.h
rename winnt.c to windsys.c
place visual studio projects into individual subfolders.
This will hopefully resolve GitHub issue #484 as well.