cmake_minimum_required(VERSION 3.24)
if(NOT DEFINED NETHACK_SOURCE_DIR
OR NOT DEFINED NETHACK_LUA_INCLUDE_DIR
OR NOT DEFINED NETHACK_LUA_LIBRARY
OR NOT DEFINED NETHACK_COMPILER
OR NOT DEFINED NETHACK_ARCHIVER)
message(FATAL_ERROR "NetHack build adapter arguments are incomplete")
endif()
find_program(NETHACK_MAKE make REQUIRED)
find_program(NETHACK_SH sh REQUIRED)
set(NETHACK_COMMON_ARGS
"CC=${NETHACK_COMPILER}"
"AR=${NETHACK_ARCHIVER}"
"WANT_LIBNH=1"
"WANT_SYSTEM_LUA=1"
"LINUX_DISTRO=debian"
"PKG_EXISTS=yes"
"LUA_VERSION=5.4.9"
"LUAHEADERS=${NETHACK_LUA_INCLUDE_DIR}"
"LUACFLAGS=-I${NETHACK_LUA_INCLUDE_DIR}"
"LUALIBS=${NETHACK_LUA_LIBRARY} -lm -ldl")
function(run_nethack_make)
execute_process(
COMMAND "${NETHACK_MAKE}" ${NETHACK_COMMON_ARGS} ${ARGN}
WORKING_DIRECTORY "${NETHACK_SOURCE_DIR}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE error)
if(NOT result EQUAL 0)
message(FATAL_ERROR
"NetHack make failed with ${result}\n${output}\n${error}")
endif()
endfunction()
execute_process(
COMMAND "${NETHACK_SH}" setup.sh hints/linux.500
WORKING_DIRECTORY "${NETHACK_SOURCE_DIR}/sys/unix"
RESULT_VARIABLE setup_result
OUTPUT_VARIABLE setup_output
ERROR_VARIABLE setup_error)
if(NOT setup_result EQUAL 0)
message(FATAL_ERROR
"NetHack setup failed with ${setup_result}\n"
"${setup_output}\n${setup_error}")
endif()
# Publish NetHack's native end condition before the engine tears itself down.
set(NETHACK_END_SOURCE "${NETHACK_SOURCE_DIR}/src/end.c")
file(READ "${NETHACK_END_SOURCE}" NETHACK_END_CONTENT)
string(REPLACE
"#include \"hack.h\""
"#include \"hack.h\"\nextern void nethack_mcp_end_result(int) __attribute__((weak));"
NETHACK_END_CONTENT "${NETHACK_END_CONTENT}")
string(FIND "${NETHACK_END_CONTENT}"
" program_state.gameover = 1;" NETHACK_END_HOOK_POSITION)
if(NETHACK_END_HOOK_POSITION EQUAL -1)
message(FATAL_ERROR "Could not locate NetHack's terminal hook point")
endif()
string(REPLACE
" program_state.gameover = 1;"
" if (nethack_mcp_end_result)\n nethack_mcp_end_result(how);\n program_state.gameover = 1;"
NETHACK_END_CONTENT "${NETHACK_END_CONTENT}")
file(WRITE "${NETHACK_END_SOURCE}" "${NETHACK_END_CONTENT}")
# The upstream libnh rule archives this version-named dependency. Keep an
# empty marker here; the application links the CMake-built Lua library
# separately because ar stores nested archives as opaque members.
file(MAKE_DIRECTORY "${NETHACK_SOURCE_DIR}/lib/lua")
execute_process(
COMMAND "${NETHACK_ARCHIVER}" rcs
"${NETHACK_SOURCE_DIR}/lib/lua/liblua-5.4.9.a"
RESULT_VARIABLE archive_result
OUTPUT_VARIABLE archive_output
ERROR_VARIABLE archive_error)
if(NOT archive_result EQUAL 0)
message(FATAL_ERROR
"Could not create NetHack Lua dependency marker: ${archive_output}\n"
"${archive_error}")
endif()
# Header generation is not safe to run concurrently with the upstream
# generated-file rules. Once it is complete, source compilation is parallel.
run_nethack_make(-j1 lua_support)
run_nethack_make(-C src -j1 pregame)
run_nethack_make(-C src -j24 libnh.a)
run_nethack_make(-j1 dlb)
# The upstream rule combines the normal Unix object list with the library
# object list. Remove the normal terminal entry points before publishing the
# archive, otherwise linking the library into a host program pulls in a
# second main() and duplicate Unix support functions.
execute_process(
COMMAND "${NETHACK_ARCHIVER}" d libnh.a
unixmain.o getline.o termcap.o topl.o wintty.o
WORKING_DIRECTORY "${NETHACK_SOURCE_DIR}/src"
RESULT_VARIABLE remove_unix_result
OUTPUT_VARIABLE remove_unix_output
ERROR_VARIABLE remove_unix_error)
if(NOT remove_unix_result EQUAL 0)
message(FATAL_ERROR
"Could not remove normal Unix objects from libnh.a: "
"${remove_unix_output}\n${remove_unix_error}")
endif()
# The Linux libnh rule omits hacklib.o even though the normal executable
# links hacklib.a separately. Make the published library self-contained.
execute_process(
COMMAND "${NETHACK_ARCHIVER}" rcs libnh.a hacklib.o
WORKING_DIRECTORY "${NETHACK_SOURCE_DIR}/src"
RESULT_VARIABLE hacklib_result
OUTPUT_VARIABLE hacklib_output
ERROR_VARIABLE hacklib_error)
if(NOT hacklib_result EQUAL 0)
message(FATAL_ERROR
"Could not add NetHack hacklib.o to libnh.a: ${hacklib_output}\n"
"${hacklib_error}")
endif()
execute_process(
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${NETHACK_SOURCE_DIR}/src/libnh.a"
"${NETHACK_SOURCE_DIR}/src/libnethack.a"
RESULT_VARIABLE copy_result
OUTPUT_VARIABLE copy_output
ERROR_VARIABLE copy_error)
if(NOT copy_result EQUAL 0)
message(FATAL_ERROR
"Could not publish libnethack.a compatibility name: ${copy_output}\n"
"${copy_error}")
endif()
set(NETHACK_PLAYGROUND "${NETHACK_SOURCE_DIR}/playground")
file(MAKE_DIRECTORY "${NETHACK_PLAYGROUND}/save")
foreach(data_file nhdat symbols license)
execute_process(
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${NETHACK_SOURCE_DIR}/dat/${data_file}"
"${NETHACK_PLAYGROUND}/${data_file}"
RESULT_VARIABLE data_result
OUTPUT_VARIABLE data_output
ERROR_VARIABLE data_error)
if(NOT data_result EQUAL 0)
message(FATAL_ERROR
"Could not install NetHack data file ${data_file}: "
"${data_output}\n${data_error}")
endif()
endforeach()
execute_process(
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${NETHACK_SOURCE_DIR}/sys/libnh/sysconf"
"${NETHACK_PLAYGROUND}/sysconf"
RESULT_VARIABLE sysconf_result
OUTPUT_VARIABLE sysconf_output
ERROR_VARIABLE sysconf_error)
if(NOT sysconf_result EQUAL 0)
message(FATAL_ERROR
"Could not install NetHack sysconf: ${sysconf_output}\n"
"${sysconf_error}")
endif()
foreach(runtime_file perm record logfile xlogfile livelog)
file(WRITE "${NETHACK_PLAYGROUND}/${runtime_file}" "")
file(CHMOD "${NETHACK_PLAYGROUND}/${runtime_file}"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
endforeach()
file(CHMOD "${NETHACK_PLAYGROUND}" "${NETHACK_PLAYGROUND}/save"
DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
file(TOUCH "${NETHACK_SOURCE_DIR}/.nethack-library-built")