-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
569 lines (498 loc) · 21 KB
/
Copy pathCMakeLists.txt
File metadata and controls
569 lines (498 loc) · 21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
cmake_minimum_required(VERSION 3.16)
project(restoHack VERSION 1.1.1 LANGUAGES C)
# --- Supported build types: Debug | Release | RelWithDebInfo ---
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
endif()
set(_RESTOHACK_BUILD_TYPES "Debug;Release;RelWithDebInfo")
list(FIND _RESTOHACK_BUILD_TYPES "${CMAKE_BUILD_TYPE}" _ix)
if(_ix EQUAL -1)
message(FATAL_ERROR "Unknown CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}'. Use one of: ${_RESTOHACK_BUILD_TYPES}")
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
# Set C standard
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Ensure binaries carry a build-id for coredumpctl/gdb symbolication
# Apple's linker does not support --build-id
if(NOT APPLE)
add_link_options(-Wl,--build-id)
endif()
# makepkg compatibility: Remove -Werror flags that cause packaging failures
# This handles system-injected CFLAGS from makepkg.conf that include -Werror=format-security
string(REPLACE "-Werror=format-security" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REGEX REPLACE "-Werror[^ ]*" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(STRIP "${CMAKE_C_FLAGS}" CMAKE_C_FLAGS)
# Modern CMake: Will use target_include_directories for better scoping
# Removed global include_directories() - using target-specific includes instead
# Find required libraries - modern curses detection for NetBSD/pkgsrc compatibility
if(NOT DEFINED CURSES_FOUND)
find_package(Curses REQUIRED)
endif()
# Check for compat library (BSD-specific, might not exist on Linux)
find_library(COMPAT_LIBRARY compat)
# Feature detection for portable RNG seeding and delay_output
include(CheckIncludeFile)
include(CheckSymbolExists)
include(CheckLibraryExists)
# Check for BSD-style headers and functions
check_include_file("bsd/stdlib.h" HAVE_BSD_STDLIB_H)
check_symbol_exists(arc4random "stdlib.h" HAVE_ARC4RANDOM_IN_STDLIB)
check_symbol_exists(arc4random "bsd/stdlib.h" HAVE_ARC4RANDOM_IN_BSD_STDLIB)
check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM_BUF_IN_STDLIB)
check_symbol_exists(arc4random_buf "bsd/stdlib.h" HAVE_ARC4RANDOM_BUF_IN_BSD_STDLIB)
# Consolidated capability flags
if (HAVE_ARC4RANDOM_IN_STDLIB OR HAVE_ARC4RANDOM_IN_BSD_STDLIB)
set(HAVE_ARC4RANDOM 1)
endif()
if (HAVE_ARC4RANDOM_BUF_IN_STDLIB OR HAVE_ARC4RANDOM_BUF_IN_BSD_STDLIB)
set(HAVE_ARC4RANDOM_BUF 1)
endif()
# Check for other RNG functions
check_symbol_exists(srandomdev "stdlib.h" HAVE_SRANDOMDEV)
check_symbol_exists(getentropy "unistd.h;sys/random.h" HAVE_GETENTROPY)
# If we need libbsd for arc4random, link it
if (HAVE_BSD_STDLIB_H AND NOT HAVE_ARC4RANDOM_IN_STDLIB AND HAVE_ARC4RANDOM)
check_library_exists(bsd arc4random "" HAVE_LIBBSD_ARC4)
if (HAVE_LIBBSD_ARC4)
set(HAVE_LIBBSD 1)
message(STATUS "Linking libbsd for arc4random support")
endif()
endif()
# Check if delay_output is available in curses library
set(CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_DIR})
check_symbol_exists(delay_output "curses.h" HAVE_DELAY_OUTPUT)
# Generate config.h with feature detection results
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h.in")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_BINARY_DIR}/generated/config.h
@ONLY
)
else()
message(FATAL_ERROR "config.h.in not found at ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in")
endif()
set(HACK_SOURCES
src/alloc.c
src/hack.Decl.c
src/hack.main.c
src/hack.mkobj.c
src/hack.invent.c
src/hack.lock.c
src/hack.worn.c
src/hack.mklev.c
src/hack.lev.c
src/hack.pri.c
src/hack.topl.c
src/hack.termcap.c
src/hack.objnam.c
src/hack.o_init.c
src/hack.pager.c
src/hack.makemon.c
src/hack.tty.c
src/hack.fight.c
src/hack.mon.c
src/hack.eat.c
src/hack.end.c
src/hack.do_name.c
src/hack.search.c
src/hack.monst.c
src/hack.cmd.c
src/hack.c
src/hack.do.c
src/hack.wield.c
src/hack.engrave.c
src/hack.potion.c
src/hack.read.c
src/hack.zap.c
src/hack.trap.c
src/hack.apply.c
src/hack.dog.c
src/hack.shk.c
src/hack.unix.c
src/hack.save.c
src/hack.vault.c
src/hack.worm.c
src/hack.mkmaze.c
src/hack.bones.c
src/hack.mhitu.c
src/hack.steal.c
src/hack.wizard.c
src/hack.do_wear.c
src/hack.ioctl.c
src/hack.mkshop.c
src/hack.rumors.c
src/hack.rip.c
src/hack.shknam.c
src/hack.options.c
src/hack.timeout.c
src/hack.track.c
src/hack.u_init.c
src/hack.version.c
src/rnd.c
)
# Build makedefs utility first
add_executable(makedefs src/makedefs.c)
# Modern CMake: Generate hack.onames.h using makedefs with proper paths
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/hack.onames.h
COMMAND makedefs ${CMAKE_CURRENT_SOURCE_DIR}/src/def.objects.h > ${CMAKE_CURRENT_BINARY_DIR}/hack.onames.h
DEPENDS makedefs ${CMAKE_CURRENT_SOURCE_DIR}/src/def.objects.h
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating hack.onames.h with authentic 1984 object definitions"
)
# Main hack executable
add_executable(hack ${HACK_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/hack.onames.h)
# Modern CMake: Target-specific include directories (better than global includes)
target_include_directories(hack PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}/generated
${CURSES_INCLUDE_DIR}
)
# Enhanced Debug profile for better postmortem analysis
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(hack PRIVATE -fno-omit-frame-pointer)
target_link_options(hack PRIVATE -rdynamic)
endif()
# Compiler flags
target_compile_options(hack PRIVATE
$<$<C_COMPILER_ID:GNU>:-Wno-stringop-truncation>
$<$<C_COMPILER_ID:Clang>:-Wno-string-plus-int>
# Packaging compatibility: Suppress warnings that might be treated as errors
-Wno-error=format-security
-Wno-error
# K&R vintage code compatibility: Suppress warnings for 1984 heritage code
-Wno-deprecated-non-prototype
-Wno-parentheses
-Wno-unused-variable
-Wno-misleading-indentation
$<$<C_COMPILER_ID:Clang>:-Wno-knr-promoted-parameter>
# Buffer overflow protection for save system safety
$<$<C_COMPILER_ID:GNU>:-fstack-protector-strong>
$<$<C_COMPILER_ID:Clang>:-fstack-protector-strong>
# Enable debugging symbols for crash analysis
-g3
)
# Fortify source for additional buffer overflow detection
# Use FORTIFY_SOURCE=3 on glibc >=2.36, fallback to =2 for compatibility
include(CheckCSourceCompiles)
# Probe whether FORTIFY=3 actually works on this libc/toolchain
set(_fortify_probe_src "
#include <features.h>
int main(void) {
#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && (__GLIBC__*100+__GLIBC_MINOR__>=236)
return 0;
#else
#error no_fortify3
#endif
}")
set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
check_c_source_compiles("${_fortify_probe_src}" HAS_FORTIFY3)
if(HAS_FORTIFY3)
message(STATUS "Using FORTIFY_SOURCE=3 for optimized builds (glibc >=2.36)")
else()
message(STATUS "Using FORTIFY_SOURCE=2 (glibc <2.36 or non-glibc)")
endif()
# Optimization handled in hardening section below
# Runtime path configuration - inject absolute paths to prevent hardcoded path issues
if(DEFINED HACKDIR_OVERRIDE)
target_compile_definitions(hack PRIVATE
HACKDIR="${HACKDIR_OVERRIDE}"
SAVE_VERSION="${PROJECT_VERSION}"
)
else()
target_compile_definitions(hack PRIVATE
HACKDIR="${CMAKE_BINARY_DIR}/hackdir"
SAVE_VERSION="${PROJECT_VERSION}"
)
endif()
# Struct packing control for save system consistency
option(ENABLE_STRUCT_PACKING "Enable struct packing for save system compatibility" ON)
if(ENABLE_STRUCT_PACKING)
# Check if compiler supports pragma pack
include(CheckCSourceCompiles)
check_c_source_compiles("
#pragma pack(1)
struct test { char a; int b; };
#pragma pack()
int main() { return sizeof(struct test); }
" HAVE_PRAGMA_PACK)
if(HAVE_PRAGMA_PACK)
target_compile_definitions(hack PRIVATE HAVE_PRAGMA_PACK=1)
message(STATUS "Struct packing enabled for save system consistency")
else()
message(WARNING "Compiler doesn't support #pragma pack - save compatibility may be affected")
endif()
endif()
# Save system build options and debugging
option(ENABLE_SAVE_DEBUG "Enable save system debug logging" OFF)
if(ENABLE_SAVE_DEBUG)
target_compile_definitions(hack PRIVATE SAVE_DEBUG=1)
message(STATUS "Save system debug logging enabled")
endif()
option(ENABLE_SAVE_VALIDATION "Enable save file integrity checks" ON)
if(ENABLE_SAVE_VALIDATION)
target_compile_definitions(hack PRIVATE SAVE_VALIDATION=1)
message(STATUS "Save file validation enabled")
endif()
# Hardening and testing options
option(ENABLE_SANITIZERS "Address/UB sanitizers in Debug" OFF)
option(ENABLE_FUZZING "libFuzzer targets (Clang only)" OFF)
# Common hardening flags
target_compile_options(hack PRIVATE -Wall -Wextra -fstack-protector-strong)
# Stack clash protection (GCC feature)
include(CheckCCompilerFlag)
check_c_compiler_flag("-fstack-clash-protection" HAS_SCP)
# AppleClang accepts the flag but warns on every file; skip on macOS
if(HAS_SCP AND NOT APPLE)
target_compile_options(hack PRIVATE -fstack-clash-protection)
message(STATUS "Stack clash protection enabled")
endif()
# Optimized configs: O2, PIE, Fortify (3 if available, else 2)
target_compile_options(hack PRIVATE
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:-O2 -fPIE>
)
# ELF hardening: RELRO, BIND_NOW, noexecstack (not supported by Apple's linker)
if(NOT APPLE)
target_link_options(hack PRIVATE
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:-pie -Wl,-z,relro,-z,now -Wl,-z,noexecstack>
)
endif()
# Apply FORTIFY_SOURCE based on detection
if(HAS_FORTIFY3)
target_compile_definitions(hack PRIVATE
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:_FORTIFY_SOURCE=3>
)
else()
target_compile_definitions(hack PRIVATE
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:_FORTIFY_SOURCE=2>
)
endif()
# Debug builds:
if(ENABLE_SANITIZERS)
# With sanitizers: use -O1 for better detection + FORTIFY_SOURCE compatibility
target_compile_options(hack PRIVATE
$<$<CONFIG:Debug>:-O1 -g3 -fsanitize=address,undefined -fno-omit-frame-pointer>
)
target_link_options(hack PRIVATE
$<$<CONFIG:Debug>:-fsanitize=address,undefined>
)
# Enable FORTIFY_SOURCE=2 in Debug with sanitizers (has -O1)
target_compile_definitions(hack PRIVATE $<$<CONFIG:Debug>:_FORTIFY_SOURCE=2>)
message(STATUS "Sanitizers enabled - run with: ASAN_OPTIONS=detect_stack_use_after_return=1 ./hack")
else()
# Pure debugging: -O0 to avoid <optimized_out> in coredumps, disable FORTIFY_SOURCE
target_compile_options(hack PRIVATE $<$<CONFIG:Debug>:-O0 -g3>)
# Modern: Explicitly undefine FORTIFY_SOURCE first to override system CFLAGS
target_compile_definitions(hack PRIVATE $<$<CONFIG:Debug>:_FORTIFY_SOURCE=0>)
target_compile_options(hack PRIVATE $<$<CONFIG:Debug>:-U_FORTIFY_SOURCE>)
message(STATUS "Debug build optimized for debugging (no <optimized_out>)")
endif()
# Fuzzing (Clang)
if(ENABLE_FUZZING AND CMAKE_C_COMPILER_ID MATCHES "Clang")
target_compile_options(hack PRIVATE -fsanitize=fuzzer,address -fno-omit-frame-pointer)
target_link_options(hack PRIVATE -fsanitize=fuzzer,address)
message(STATUS "Fuzzing support enabled")
endif()
# Enhanced memory sanitizers specifically for save/load operations
option(ENABLE_SAVE_SANITIZERS "Enable memory sanitizers for save/load debugging" OFF)
if(ENABLE_SAVE_SANITIZERS)
target_compile_options(hack PRIVATE -fsanitize=memory -fsanitize-memory-track-origins -g)
target_link_options(hack PRIVATE -fsanitize=memory)
message(STATUS "Memory sanitizers enabled for save system debugging")
endif()
# --- RelWithDebInfo profile (for production servers) ---
if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
message(STATUS "Configuring RelWithDebInfo build (optimized with debug symbols)")
# Perf + debuggable backtraces
target_compile_options(hack PRIVATE -O2 -fno-omit-frame-pointer)
# PIE + RELRO/NOW + NX (noexecstack) — production-ready with symbols for debugging
target_compile_options(hack PRIVATE -fPIE)
# ELF hardening (not supported by Apple's linker)
if(NOT APPLE)
target_link_options(hack PRIVATE -pie -Wl,-z,relro,-z,now -Wl,-z,noexecstack)
endif()
# Fortify: prefer =3 when available (fallback to 2)
if(HAS_FORTIFY3)
target_compile_definitions(hack PRIVATE _FORTIFY_SOURCE=3)
else()
target_compile_definitions(hack PRIVATE _FORTIFY_SOURCE=2)
endif()
# Slightly stricter but sane warnings
target_compile_options(hack PRIVATE -Wall -Wextra -Wswitch -Wwrite-strings -Wformat=2)
endif()
# Link libraries
target_link_libraries(hack ${CURSES_LIBRARIES})
if(COMPAT_LIBRARY)
target_link_libraries(hack ${COMPAT_LIBRARY})
endif()
if(HAVE_LIBBSD)
target_link_libraries(hack bsd)
endif()
# Always handy to inspect flags locally
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Common warnings for all builds (sane, not noisy)
target_compile_options(hack PRIVATE
-Wall -Wextra -Wformat=2
-Wno-missing-field-initializers
-Wno-old-style-definition
-fno-common
)
# === Profiles ===
if(CMAKE_BUILD_TYPE STREQUAL "Release")
# General build = ship it
target_compile_options(hack PRIVATE -O2 -DNDEBUG)
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# Dev build = symbols + easy backtraces, warnings don’t kill flow
target_compile_options(hack PRIVATE -O0 -g3 -fno-omit-frame-pointer -Wwrite-strings -Wno-error)
target_link_options(hack PRIVATE -rdynamic)
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
# safe, strict, but do NOT fail on warnings
target_compile_options(hack PRIVATE
-O2 -fno-omit-frame-pointer -fPIE
-Wwrite-strings
-Wno-error
)
# Fortify (3 if toolchain supports it; harmless if ignored)
target_compile_definitions(hack PRIVATE _FORTIFY_SOURCE=3)
# ELF hardening (not supported by Apple's linker)
if(NOT APPLE)
target_link_options(hack PRIVATE
-pie
-Wl,-z,relro,-z,now
-Wl,-z,noexecstack
)
endif()
# Quiet a recent Clang nit, only if relevant
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 18)
target_compile_options(hack PRIVATE -Wno-deprecated-non-prototype)
endif()
endif()
# REMOVED: Conflicting sanitizer configuration that was overriding ENABLE_SANITIZERS
# All sanitizer control now handled by ENABLE_SANITIZERS option above (lines 306-322)
# Data files
set(DATA_FILES rumors help hh data)
# Versioned save system configuration
set(HACK_VERSION "${PROJECT_VERSION}")
set(SAVE_DIR "${CMAKE_BINARY_DIR}/hackdir/save")
set(VERSIONED_SAVE_DIR "${SAVE_DIR}/v${HACK_VERSION}")
set(BACKUP_SAVE_DIR "${SAVE_DIR}/backup")
option(RESTOHACK_COPY_ASSETS "Copy asset directories into build tree" ON)
add_custom_target(setup_hackdir ALL
# Copy hackdir structure and ensure write permissions on record file
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/hackdir ${CMAKE_BINARY_DIR}/hackdir
# Create required directories and lock files
COMMAND ${CMAKE_COMMAND} -E make_directory ${SAVE_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${VERSIONED_SAVE_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${BACKUP_SAVE_DIR}
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/hackdir/perm
# Ensure record file exists and is writable (game checks this at startup)
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/hackdir/record
# Also copy files to build root for pre-chdir access (legacy compatibility)
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/perm
# Clean all possible lock files (HLOCK, LLOCK, record_lock in all locations)
COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/record_lock ${CMAKE_BINARY_DIR}/safelock ${CMAKE_BINARY_DIR}/hackdir/record_lock ${CMAKE_BINARY_DIR}/hackdir/safelock
COMMAND ${CMAKE_COMMAND} -E remove -f ${SAVE_DIR}/* ${VERSIONED_SAVE_DIR}/* ${BACKUP_SAVE_DIR}/*
COMMENT "Setting up versioned save system: v${HACK_VERSION} with backup support"
VERBATIM
)
# Copy asset files (only if they exist and copying is enabled)
if(RESTOHACK_COPY_ASSETS)
# All assets are files, not directories
foreach(_asset data help hh rumors)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_asset})
add_custom_command(TARGET setup_hackdir POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${_asset}
${CMAKE_BINARY_DIR}/hackdir/${_asset}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${_asset}
${CMAKE_BINARY_DIR}/${_asset})
else()
message(WARNING "Asset '${_asset}' missing in source tree.")
endif()
endforeach()
endif()
# Ensure hack depends on the setup
add_dependencies(hack setup_hackdir)
# Custom clean target to remove all generated files and lock files
add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/hackdir
COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/perm ${CMAKE_BINARY_DIR}/data ${CMAKE_BINARY_DIR}/help ${CMAKE_BINARY_DIR}/hh ${CMAKE_BINARY_DIR}/rumors
COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/record_lock ${CMAKE_BINARY_DIR}/safelock
COMMENT "Clean all hack files and lock files"
)
# Install rules
install(TARGETS hack DESTINATION bin)
install(FILES ${DATA_FILES} DESTINATION share/hack)
install(FILES man/hack.6 DESTINATION share/man/man6)
# ---- Security Options ----
option(CLANG_STRICT "Enable draconian warnings under Clang" OFF)
if(CLANG_STRICT AND CMAKE_C_COMPILER_ID MATCHES "Clang")
target_compile_options(hack PRIVATE
-Weverything -Werror
-Wno-poison-system-directories
-Wno-padded -Wno-cast-align -Wno-disabled-macro-expansion
)
endif()
# ---- Packaging (optional) ----
option(RESTOHACK_ENABLE_PACKAGE "Enable CPack packaging" ON)
# Modern CMake: CPack configuration for professional distribution
set(CPACK_PACKAGE_NAME "restohack")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Authentic 1984 Hack game restoration - modernized for contemporary systems")
set(CPACK_PACKAGE_DESCRIPTION "restoHack brings the legendary 1984 Hack game back from the dead with 94.2% authentic code preservation. This isn't a reimagining - it's historical software preservation with modern compatibility. Features complete K&R to ANSI C conversion, cross-platform builds, and 100% authentic 1984 gameplay experience.")
set(CPACK_PACKAGE_VENDOR "restoHack Project")
set(CPACK_PACKAGE_CONTACT "https://github.com/Critlist/restoHack.git")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/Critlist/restoHack.git")
# Allow override via -DCPACK_RESOURCE_FILE_*; default to files in source tree.
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" CACHE FILEPATH "")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md" CACHE FILEPATH "")
# If the resources aren't present, disable packaging instead of erroring.
if(NOT EXISTS "${CPACK_RESOURCE_FILE_LICENSE}" OR NOT EXISTS "${CPACK_RESOURCE_FILE_README}")
message(WARNING "CPack resources missing; disabling packaging for this build.")
set(RESTOHACK_ENABLE_PACKAGE OFF)
endif()
# Source package configuration
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-src")
set(CPACK_SOURCE_IGNORE_FILES
"/build/"
"/\\.git/"
"/\\.gitignore"
"hackdir/record_lock"
"hackdir/safelock"
"\\.DS_Store"
".*~$"
)
# Platform-specific packaging # #I'm hopeful people want to play this on their systems, so this will be implemented for later use
if(WIN32)
# Windows NSIS installer
set(CPACK_GENERATOR "NSIS;ZIP")
set(CPACK_NSIS_DISPLAY_NAME "restoHack - Authentic 1984 Hack Game")
set(CPACK_NSIS_HELP_LINK "https://github.com/Critlist/restoHack.git")
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/Critlist/restoHack.git")
elseif(APPLE)
# macOS packages
set(CPACK_GENERATOR "TGZ;DragNDrop")
set(CPACK_DMG_VOLUME_NAME "restoHack")
else()
# Linux packages (DEB, RPM, tar.gz)
set(CPACK_GENERATOR "DEB;RPM;TGZ")
# Debian package configuration
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "restoHack Project <noreply@example.com>")
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libncurses5 | libncurses6")
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
# RPM package configuration
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
set(CPACK_RPM_PACKAGE_LICENSE "BSD-3-Clause")
set(CPACK_RPM_PACKAGE_REQUIRES "glibc, ncurses")
set(CPACK_RPM_FILE_NAME RPM-DEFAULT)
endif()
# Enable CPack only if packaging is enabled
if(RESTOHACK_ENABLE_PACKAGE)
include(CPack)
endif()