]> git.lizzy.rs Git - minetest.git/blob - src/CMakeLists.txt
8x block meshes (#13133)
[minetest.git] / src / CMakeLists.txt
1 project(minetest)
2
3 INCLUDE(CheckTypeSize)
4 INCLUDE(CheckIncludeFiles)
5 INCLUDE(CheckLibraryExists)
6
7 check_type_size(int SIZEOF_INT BUILTIN_TYPES_ONLY LANGUAGE CXX)
8 if(SIZEOF_INT LESS 4)
9         message(FATAL_ERROR "Minetest will not work with int less than 32 bits wide.")
10 endif()
11
12 check_type_size(size_t SIZEOF_SIZE_T LANGUAGE CXX)
13 if(SIZEOF_SIZE_T LESS 4)
14         message(FATAL_ERROR "Minetest will not work with size_t less than 32 bits wide.")
15 endif()
16
17 # Add custom SemiDebug build mode
18 set(CMAKE_CXX_FLAGS_SEMIDEBUG "-O1 -g -Wall" CACHE STRING
19         "Flags used by the C++ compiler during semidebug builds."
20         FORCE
21 )
22 set(CMAKE_C_FLAGS_SEMIDEBUG "-O1 -g -Wall -pedantic" CACHE STRING
23         "Flags used by the C compiler during semidebug builds."
24         FORCE
25 )
26 mark_as_advanced(
27         CMAKE_CXX_FLAGS_SEMIDEBUG
28         CMAKE_C_FLAGS_SEMIDEBUG
29 )
30 set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
31         "Choose the type of build. Options are: None Debug SemiDebug RelWithDebInfo MinSizeRel."
32         FORCE
33 )
34
35
36 # Set some random things default to not being visible in the GUI
37 mark_as_advanced(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
38
39
40 if(NOT (BUILD_CLIENT OR BUILD_SERVER))
41         message(WARNING "Neither BUILD_CLIENT nor BUILD_SERVER is set! Setting BUILD_SERVER=true")
42         set(BUILD_SERVER TRUE)
43 endif()
44
45
46 option(ENABLE_CURL "Enable cURL support for fetching media" TRUE)
47 set(USE_CURL FALSE)
48
49 if(ENABLE_CURL)
50         find_package(CURL)
51         if (CURL_FOUND)
52                 message(STATUS "cURL support enabled.")
53                 set(USE_CURL TRUE)
54         endif()
55 else()
56         mark_as_advanced(CLEAR CURL_LIBRARY CURL_INCLUDE_DIR)
57 endif()
58
59 if(NOT USE_CURL)
60         if(BUILD_CLIENT)
61                 message(WARNING "cURL is required to load the server list")
62         endif()
63         if(BUILD_SERVER)
64                 message(WARNING "cURL is required to announce to the server list")
65         endif()
66 endif()
67
68
69 option(ENABLE_GETTEXT "Use GetText for internationalization" ${BUILD_CLIENT})
70 set(USE_GETTEXT FALSE)
71
72 if(ENABLE_GETTEXT)
73         find_package(GettextLib)
74         if(GETTEXTLIB_FOUND)
75                 if(WIN32)
76                         message(STATUS "GetText library: ${GETTEXT_LIBRARY}")
77                         message(STATUS "GetText DLL(s): ${GETTEXT_DLL}")
78                 endif()
79                 set(USE_GETTEXT TRUE)
80                 message(STATUS "GetText enabled; locales found: ${GETTEXT_AVAILABLE_LOCALES}")
81         endif(GETTEXTLIB_FOUND)
82 else()
83         mark_as_advanced(GETTEXT_INCLUDE_DIR GETTEXT_LIBRARY GETTEXT_MSGFMT)
84         message(STATUS "GetText disabled.")
85 endif()
86
87
88 option(ENABLE_SOUND "Enable sound" TRUE)
89 set(USE_SOUND FALSE)
90
91 if(BUILD_CLIENT AND ENABLE_SOUND)
92         # Sound libraries
93         find_package(OpenAL)
94         find_package(Vorbis)
95         if(NOT OPENAL_FOUND)
96                 message(STATUS "Sound enabled, but OpenAL not found!")
97                 mark_as_advanced(CLEAR OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
98         endif()
99         if(NOT VORBIS_FOUND)
100                 message(STATUS "Sound enabled, but Vorbis libraries not found!")
101                 mark_as_advanced(CLEAR OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY)
102         endif()
103         if(OPENAL_FOUND AND VORBIS_FOUND)
104                 set(USE_SOUND TRUE)
105                 message(STATUS "Sound enabled.")
106         else()
107                 message(FATAL_ERROR "Sound enabled, but cannot be used.\n"
108                         "To continue, either fill in the required paths or disable sound. (-DENABLE_SOUND=0)")
109         endif()
110 endif()
111
112 # TODO: this should be removed one day, we can enable it unconditionally
113 option(ENABLE_GLES "Enable extra support code for OpenGL ES" FALSE)
114 mark_as_advanced(ENABLE_GLES)
115
116 option(ENABLE_TOUCH "Enable Touchscreen support" FALSE)
117 if(ENABLE_TOUCH)
118         add_definitions(-DHAVE_TOUCHSCREENGUI)
119 endif()
120
121 if(BUILD_CLIENT)
122         find_package(Freetype REQUIRED)
123 endif()
124
125 option(ENABLE_CURSES "Enable ncurses console" TRUE)
126 set(USE_CURSES FALSE)
127
128 if(ENABLE_CURSES)
129         find_package(Ncursesw)
130         if(CURSES_FOUND)
131                 set(USE_CURSES TRUE)
132                 message(STATUS "ncurses console enabled.")
133                 include_directories(${CURSES_INCLUDE_DIRS})
134         else()
135                 message(STATUS "ncurses not found!")
136         endif()
137 endif(ENABLE_CURSES)
138
139 option(ENABLE_POSTGRESQL "Enable PostgreSQL backend" TRUE)
140 set(USE_POSTGRESQL FALSE)
141
142 if(ENABLE_POSTGRESQL)
143         if(CMAKE_VERSION VERSION_LESS "3.20")
144                 find_package(PostgreSQL QUIET)
145                 # Before CMake 3.20 FindPostgreSQL.cmake always looked for server includes
146                 # but we don't need them, so continue anyway if only those are missing.
147                 if(PostgreSQL_INCLUDE_DIR AND PostgreSQL_LIBRARY)
148                         set(PostgreSQL_FOUND TRUE)
149                         set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR})
150                         set(PostgreSQL_LIBRARIES ${PostgreSQL_LIBRARY})
151                 endif()
152         else()
153                 find_package(PostgreSQL)
154         endif()
155
156         if(PostgreSQL_FOUND)
157                 set(USE_POSTGRESQL TRUE)
158                 message(STATUS "PostgreSQL backend enabled")
159                 # This variable is case sensitive, don't try to change it to POSTGRESQL_INCLUDE_DIR
160                 message(STATUS "PostgreSQL includes: ${PostgreSQL_INCLUDE_DIRS}")
161                 include_directories(${PostgreSQL_INCLUDE_DIRS})
162         else()
163                 message(STATUS "PostgreSQL not found!")
164         endif()
165 endif(ENABLE_POSTGRESQL)
166
167 option(ENABLE_LEVELDB "Enable LevelDB backend" TRUE)
168 set(USE_LEVELDB FALSE)
169
170 if(ENABLE_LEVELDB)
171         find_library(LEVELDB_LIBRARY NAMES leveldb libleveldb)
172         find_path(LEVELDB_INCLUDE_DIR db.h PATH_SUFFIXES leveldb)
173         if(LEVELDB_LIBRARY AND LEVELDB_INCLUDE_DIR)
174                 set(USE_LEVELDB TRUE)
175                 message(STATUS "LevelDB backend enabled.")
176                 include_directories(${LEVELDB_INCLUDE_DIR})
177         else()
178                 message(STATUS "LevelDB not found!")
179         endif()
180 endif(ENABLE_LEVELDB)
181
182
183 OPTION(ENABLE_REDIS "Enable Redis backend" TRUE)
184 set(USE_REDIS FALSE)
185
186 if(ENABLE_REDIS)
187         find_library(REDIS_LIBRARY hiredis)
188         find_path(REDIS_INCLUDE_DIR hiredis.h PATH_SUFFIXES hiredis)
189         if(REDIS_LIBRARY AND REDIS_INCLUDE_DIR)
190                 set(USE_REDIS TRUE)
191                 message(STATUS "Redis backend enabled.")
192                 include_directories(${REDIS_INCLUDE_DIR})
193         else(REDIS_LIBRARY AND REDIS_INCLUDE_DIR)
194                 message(STATUS "Redis not found!")
195         endif(REDIS_LIBRARY AND REDIS_INCLUDE_DIR)
196 endif(ENABLE_REDIS)
197
198
199 find_package(SQLite3 REQUIRED)
200
201
202 OPTION(ENABLE_PROMETHEUS "Enable prometheus client support" FALSE)
203 set(USE_PROMETHEUS FALSE)
204
205 if(ENABLE_PROMETHEUS)
206         find_path(PROMETHEUS_CPP_INCLUDE_DIR NAMES prometheus/counter.h)
207         find_library(PROMETHEUS_PULL_LIBRARY NAMES prometheus-cpp-pull)
208         find_library(PROMETHEUS_CORE_LIBRARY NAMES prometheus-cpp-core)
209         if(PROMETHEUS_CPP_INCLUDE_DIR AND PROMETHEUS_PULL_LIBRARY AND PROMETHEUS_CORE_LIBRARY)
210                 set(PROMETHEUS_LIBRARIES ${PROMETHEUS_PULL_LIBRARY} ${PROMETHEUS_CORE_LIBRARY})
211                 set(USE_PROMETHEUS TRUE)
212                 include_directories(${PROMETHEUS_CPP_INCLUDE_DIR})
213         endif(PROMETHEUS_CPP_INCLUDE_DIR AND PROMETHEUS_PULL_LIBRARY AND PROMETHEUS_CORE_LIBRARY)
214 endif(ENABLE_PROMETHEUS)
215
216 if(USE_PROMETHEUS)
217         message(STATUS "Prometheus client enabled.")
218 else(USE_PROMETHEUS)
219         message(STATUS "Prometheus client disabled.")
220 endif(USE_PROMETHEUS)
221
222 OPTION(ENABLE_SPATIAL "Enable SpatialIndex AreaStore backend" TRUE)
223 set(USE_SPATIAL FALSE)
224
225 if(ENABLE_SPATIAL)
226         find_library(SPATIAL_LIBRARY spatialindex)
227         find_path(SPATIAL_INCLUDE_DIR spatialindex/SpatialIndex.h)
228         if(SPATIAL_LIBRARY AND SPATIAL_INCLUDE_DIR)
229                 set(USE_SPATIAL TRUE)
230                 message(STATUS "SpatialIndex AreaStore backend enabled.")
231                 include_directories(${SPATIAL_INCLUDE_DIR})
232         else(SPATIAL_LIBRARY AND SPATIAL_INCLUDE_DIR)
233                 message(STATUS "SpatialIndex not found!")
234         endif(SPATIAL_LIBRARY AND SPATIAL_INCLUDE_DIR)
235 endif(ENABLE_SPATIAL)
236
237
238 find_package(ZLIB REQUIRED)
239 find_package(Zstd REQUIRED)
240
241
242 if(NOT MSVC)
243         set(USE_GPROF FALSE CACHE BOOL "Use -pg flag for g++")
244 endif()
245
246 # Haiku endian support
247 if(HAIKU)
248         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE")
249         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_BSD_SOURCE")
250 endif()
251
252 # Use cmake_config.h
253 add_definitions(-DUSE_CMAKE_CONFIG_H)
254
255 set(THREADS_PREFER_PTHREAD_FLAG ON)
256 find_package(Threads REQUIRED)
257 set(PLATFORM_LIBS Threads::Threads)
258
259 if(WIN32)
260         # Windows
261         if(MSVC) # MSVC Specifics
262                 set(PLATFORM_LIBS dbghelp.lib ${PLATFORM_LIBS})
263                 # Surpress some useless warnings
264                 add_definitions ( /D "_CRT_SECURE_NO_DEPRECATE" /W1 )
265                 # Get M_PI to work
266                 add_definitions(/D "_USE_MATH_DEFINES")
267                 # Don't define min/max macros in minwindef.h
268                 add_definitions(/D "NOMINMAX")
269         endif()
270         set(PLATFORM_LIBS ws2_32.lib version.lib shlwapi.lib winmm.lib ${PLATFORM_LIBS})
271
272         set(EXTRA_DLL "" CACHE FILEPATH "Optional paths to additional DLLs that should be packaged")
273
274         # DLLs are automatically copied to the output directory by vcpkg when VCPKG_APPLOCAL_DEPS=ON
275         if(NOT VCPKG_APPLOCAL_DEPS)
276                 set(ZLIB_DLL "" CACHE FILEPATH "Path to Zlib DLL for installation (optional)")
277                 set(ZSTD_DLL "" CACHE FILEPATH "Path to Zstd DLL for installation (optional)")
278                 if(ENABLE_SOUND)
279                         set(OPENAL_DLL "" CACHE FILEPATH "Path to OpenAL32.dll for installation (optional)")
280                         set(OGG_DLL "" CACHE FILEPATH "Path to libogg.dll for installation (optional)")
281                         set(VORBIS_DLL "" CACHE FILEPATH "Path to Vorbis DLLs for installation (optional)")
282                 endif()
283                 if(USE_GETTEXT)
284                         set(GETTEXT_DLL "" CACHE FILEPATH "Path to Intl/Iconv DLLs for installation (optional)")
285                 endif()
286                 if(USE_LUAJIT)
287                         set(LUA_DLL "" CACHE FILEPATH "Path to luajit-5.1.dll for installation (optional)")
288                 endif()
289         endif()
290 else()
291         # Unix probably
292         if(BUILD_CLIENT)
293                 if(NOT HAIKU AND NOT APPLE)
294                         find_package(X11 REQUIRED)
295                 endif(NOT HAIKU AND NOT APPLE)
296         endif()
297
298         set(PLATFORM_LIBS ${PLATFORM_LIBS} ${CMAKE_DL_LIBS})
299         if(APPLE)
300                 set(PLATFORM_LIBS "-framework CoreFoundation" ${PLATFORM_LIBS})
301         else()
302                 check_library_exists(rt clock_gettime "" HAVE_LIBRT)
303                 if (HAVE_LIBRT)
304                         set(PLATFORM_LIBS -lrt ${PLATFORM_LIBS})
305                 endif(HAVE_LIBRT)
306         endif(APPLE)
307
308         find_library(ICONV_LIBRARY iconv)
309         mark_as_advanced(ICONV_LIBRARY)
310         if (ICONV_LIBRARY)
311                 set(PLATFORM_LIBS ${PLATFORM_LIBS} ${ICONV_LIBRARY})
312         endif()
313
314         if (HAIKU)
315                 set(PLATFORM_LIBS ${PLATFORM_LIBS} network)
316         endif()
317 endif()
318
319 check_include_files(endian.h HAVE_ENDIAN_H)
320
321 configure_file(
322         "${PROJECT_SOURCE_DIR}/cmake_config.h.in"
323         "${PROJECT_BINARY_DIR}/cmake_config.h"
324 )
325
326
327 # Add a target that always rebuilds cmake_config_githash.h
328 add_custom_target(GenerateVersion
329         COMMAND ${CMAKE_COMMAND}
330         -D "GENERATE_VERSION_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}"
331         -D "GENERATE_VERSION_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
332         -D "VERSION_STRING=${VERSION_STRING}"
333         -D "DEVELOPMENT_BUILD=${DEVELOPMENT_BUILD}"
334         -P "${CMAKE_SOURCE_DIR}/cmake/Modules/GenerateVersion.cmake"
335         WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
336
337
338 add_subdirectory(threading)
339 add_subdirectory(content)
340 add_subdirectory(database)
341 add_subdirectory(gui)
342 add_subdirectory(mapgen)
343 add_subdirectory(network)
344 add_subdirectory(script)
345 add_subdirectory(unittest)
346 add_subdirectory(benchmark)
347 add_subdirectory(util)
348 add_subdirectory(irrlicht_changes)
349 add_subdirectory(server)
350
351 set(common_SRCS
352         ${database_SRCS}
353         ${mapgen_SRCS}
354         ${server_SRCS}
355         ${content_SRCS}
356         ban.cpp
357         chat.cpp
358         clientiface.cpp
359         collision.cpp
360         content_mapnode.cpp
361         content_nodemeta.cpp
362         convert_json.cpp
363         craftdef.cpp
364         debug.cpp
365         defaultsettings.cpp
366         emerge.cpp
367         environment.cpp
368         face_position_cache.cpp
369         filesys.cpp
370         gettext.cpp
371         httpfetch.cpp
372         hud.cpp
373         inventory.cpp
374         inventorymanager.cpp
375         itemdef.cpp
376         itemstackmetadata.cpp
377         light.cpp
378         lighting.cpp
379         log.cpp
380         main.cpp
381         map.cpp
382         map_settings_manager.cpp
383         mapblock.cpp
384         mapnode.cpp
385         mapsector.cpp
386         metadata.cpp
387         modchannels.cpp
388         nameidmapping.cpp
389         nodedef.cpp
390         nodemetadata.cpp
391         nodetimer.cpp
392         noise.cpp
393         objdef.cpp
394         object_properties.cpp
395         particles.cpp
396         pathfinder.cpp
397         player.cpp
398         porting.cpp
399         profiler.cpp
400         raycast.cpp
401         reflowscan.cpp
402         remoteplayer.cpp
403         rollback.cpp
404         rollback_interface.cpp
405         serialization.cpp
406         server.cpp
407         serverenvironment.cpp
408         serverlist.cpp
409         settings.cpp
410         staticobject.cpp
411         terminal_chat_console.cpp
412         texture_override.cpp
413         tileanimation.cpp
414         tool.cpp
415         translation.cpp
416         version.cpp
417         voxel.cpp
418         voxelalgorithms.cpp
419         hud.cpp
420         ${common_network_SRCS}
421         ${JTHREAD_SRCS}
422         ${common_SCRIPT_SRCS}
423         ${UTIL_SRCS}
424 )
425
426 if(BUILD_UNITTESTS)
427         set(common_SRCS ${common_SRCS} ${UNITTEST_SRCS})
428 endif()
429
430 if(BUILD_BENCHMARKS)
431         set(common_SRCS ${common_SRCS} ${BENCHMARK_SRCS})
432 endif()
433
434 # This gives us the icon and file version information
435 if(WIN32)
436         set(WINRESOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../misc/winresource.rc")
437         set(MINETEST_EXE_MANIFEST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../misc/minetest.exe.manifest")
438         if(MINGW)
439                 if(NOT CMAKE_RC_COMPILER)
440                         set(CMAKE_RC_COMPILER "windres.exe")
441                 endif()
442                 ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
443                         COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_BINARY_DIR}
444                         -i${WINRESOURCE_FILE}
445                         -o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
446                         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
447                         DEPENDS ${WINRESOURCE_FILE} ${MINETEST_EXE_MANIFEST_FILE})
448                 SET(extra_windows_SRCS ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
449         else(MINGW) # Probably MSVC
450                 set(extra_windows_SRCS ${WINRESOURCE_FILE} ${MINETEST_EXE_MANIFEST_FILE})
451         endif(MINGW)
452 endif()
453
454
455 # Client sources
456 if (BUILD_CLIENT)
457         add_subdirectory(client)
458 endif(BUILD_CLIENT)
459
460 set(client_SRCS
461         ${client_SRCS}
462         ${common_SRCS}
463         ${gui_SRCS}
464         ${client_network_SRCS}
465         ${client_irrlicht_changes_SRCS}
466         ${client_SCRIPT_SRCS}
467 )
468
469 if(BUILD_UNITTESTS)
470         set(client_SRCS ${client_SRCS} ${UNITTEST_CLIENT_SRCS})
471 endif()
472
473 if(BUILD_BENCHMARKS)
474         set(client_SRCS ${client_SRCS} ${BENCHMARK_CLIENT_SRCS})
475 endif()
476
477 list(SORT client_SRCS)
478
479 # Server sources
480 set(server_SRCS
481         ${common_SRCS}
482 )
483 list(SORT server_SRCS)
484
485 # Avoid source_group on broken CMake version.
486 # see issue #7074 #7075
487 if (CMAKE_VERSION VERSION_GREATER 3.8.1)
488         source_group(TREE ${PROJECT_SOURCE_DIR} PREFIX "Source Files" FILES ${client_SRCS})
489         source_group(TREE ${PROJECT_SOURCE_DIR} PREFIX "Source Files" FILES ${server_SRCS})
490 endif()
491
492 include_directories(
493         ${PROJECT_BINARY_DIR}
494         ${PROJECT_SOURCE_DIR}
495         ${PROJECT_SOURCE_DIR}/script
496 )
497 include_directories(SYSTEM
498         ${ZLIB_INCLUDE_DIR}
499         ${ZSTD_INCLUDE_DIR}
500         ${SQLITE3_INCLUDE_DIR}
501         ${LUA_INCLUDE_DIR}
502         ${GMP_INCLUDE_DIR}
503         ${JSON_INCLUDE_DIR}
504         ${LUA_BIT_INCLUDE_DIR}
505 )
506
507 if(USE_GETTEXT)
508         include_directories(${GETTEXT_INCLUDE_DIR})
509 endif()
510
511 if(BUILD_CLIENT)
512         include_directories(SYSTEM
513                 ${FREETYPE_INCLUDE_DIRS}
514                 ${SOUND_INCLUDE_DIRS}
515                 ${X11_INCLUDE_DIR}
516         )
517 endif()
518
519 if(USE_CURL)
520         include_directories(${CURL_INCLUDE_DIR})
521 endif()
522
523
524 # When cross-compiling assume the user doesn't want to run the executable anyway,
525 # otherwise place it in <source dir>/bin/ since Minetest can only run from there.
526 if(NOT CMAKE_CROSSCOMPILING)
527         set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin")
528 endif()
529
530 if(BUILD_CLIENT)
531         add_executable(${PROJECT_NAME} ${client_SRCS} ${extra_windows_SRCS})
532         add_dependencies(${PROJECT_NAME} GenerateVersion)
533         target_link_libraries(
534                 ${PROJECT_NAME}
535                 ${ZLIB_LIBRARIES}
536                 IrrlichtMt::IrrlichtMt
537                 ${ZSTD_LIBRARY}
538                 ${X11_LIBRARIES}
539                 ${SOUND_LIBRARIES}
540                 ${SQLITE3_LIBRARY}
541                 ${LUA_LIBRARY}
542                 ${GMP_LIBRARY}
543                 ${JSON_LIBRARY}
544                 ${LUA_BIT_LIBRARY}
545                 ${FREETYPE_LIBRARY}
546                 ${PLATFORM_LIBS}
547         )
548         if(NOT USE_LUAJIT)
549                 set_target_properties(${PROJECT_NAME} PROPERTIES
550                         # This is necessary for dynamic Lua modules
551                         # to work when Lua is statically linked (issue #10806)
552                         ENABLE_EXPORTS 1
553                 )
554         endif()
555
556         if(USE_GETTEXT)
557                 target_link_libraries(
558                         ${PROJECT_NAME}
559                         ${GETTEXT_LIBRARY}
560                 )
561         endif()
562         if(USE_CURL)
563                 target_link_libraries(
564                         ${PROJECT_NAME}
565                         ${CURL_LIBRARY}
566                 )
567         endif()
568         if(FREETYPE_PKGCONFIG_FOUND)
569                 set_target_properties(${PROJECT_NAME}
570                         PROPERTIES
571                         COMPILE_FLAGS "${FREETYPE_CFLAGS_STR}"
572         )
573         endif()
574         if (USE_CURSES)
575                 target_link_libraries(${PROJECT_NAME} ${CURSES_LIBRARIES})
576         endif()
577         if (USE_POSTGRESQL)
578                 target_link_libraries(${PROJECT_NAME} ${PostgreSQL_LIBRARIES})
579         endif()
580         if (USE_LEVELDB)
581                 target_link_libraries(${PROJECT_NAME} ${LEVELDB_LIBRARY})
582         endif()
583         if (USE_REDIS)
584                 target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
585         endif()
586         if (USE_PROMETHEUS)
587                 target_link_libraries(${PROJECT_NAME} ${PROMETHEUS_LIBRARIES})
588         endif()
589         if (USE_SPATIAL)
590                 target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
591         endif()
592         if(BUILD_BENCHMARKS)
593                 target_link_libraries(${PROJECT_NAME} catch2)
594         endif()
595 endif(BUILD_CLIENT)
596
597
598 if(BUILD_SERVER)
599         add_executable(${PROJECT_NAME}server ${server_SRCS} ${extra_windows_SRCS})
600         add_dependencies(${PROJECT_NAME}server GenerateVersion)
601
602         get_target_property(
603                 IRRLICHT_INCLUDES IrrlichtMt::IrrlichtMt INTERFACE_INCLUDE_DIRECTORIES)
604         # Doesn't work without PRIVATE/PUBLIC/INTERFACE mode specified.
605         target_include_directories(${PROJECT_NAME}server PRIVATE ${IRRLICHT_INCLUDES})
606         target_link_libraries(
607                 ${PROJECT_NAME}server
608                 ${ZLIB_LIBRARIES}
609                 ${ZSTD_LIBRARY}
610                 ${SQLITE3_LIBRARY}
611                 ${JSON_LIBRARY}
612                 ${LUA_LIBRARY}
613                 ${LUA_BIT_LIBRARY}
614                 ${GMP_LIBRARY}
615                 ${PLATFORM_LIBS}
616         )
617         set_target_properties(${PROJECT_NAME}server PROPERTIES
618                 COMPILE_DEFINITIONS "SERVER")
619         if(NOT USE_LUAJIT)
620                 set_target_properties(${PROJECT_NAME}server PROPERTIES
621                         # This is necessary for dynamic Lua modules
622                         # to work when Lua is statically linked (issue #10806)
623                         ENABLE_EXPORTS 1
624                 )
625         endif()
626
627         if (USE_GETTEXT)
628                 target_link_libraries(${PROJECT_NAME}server ${GETTEXT_LIBRARY})
629         endif()
630         if (USE_CURSES)
631                 target_link_libraries(${PROJECT_NAME}server ${CURSES_LIBRARIES})
632         endif()
633         if (USE_POSTGRESQL)
634                 target_link_libraries(${PROJECT_NAME}server ${PostgreSQL_LIBRARIES})
635         endif()
636         if (USE_LEVELDB)
637                 target_link_libraries(${PROJECT_NAME}server ${LEVELDB_LIBRARY})
638         endif()
639         if (USE_REDIS)
640                 target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
641         endif()
642         if (USE_PROMETHEUS)
643                 target_link_libraries(${PROJECT_NAME}server ${PROMETHEUS_LIBRARIES})
644         endif()
645         if (USE_SPATIAL)
646                 target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
647         endif()
648         if(USE_CURL)
649                 target_link_libraries(
650                         ${PROJECT_NAME}server
651                         ${CURL_LIBRARY}
652                 )
653         endif()
654         if(BUILD_BENCHMARKS)
655                 target_link_libraries(${PROJECT_NAME}server catch2)
656         endif()
657 endif(BUILD_SERVER)
658
659 # Blacklisted locales that don't work.
660 # see issue #4638
661 set(GETTEXT_BLACKLISTED_LOCALES
662         ar
663         dv
664         he
665         hi
666         kn
667         ms_Arab
668         th
669 )
670
671 option(APPLY_LOCALE_BLACKLIST "Use a blacklist to avoid known broken locales" TRUE)
672
673 if (GETTEXTLIB_FOUND AND APPLY_LOCALE_BLACKLIST)
674         set(GETTEXT_USED_LOCALES "")
675         foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
676                 if (NOT "${LOCALE}" IN_LIST GETTEXT_BLACKLISTED_LOCALES)
677                         list(APPEND GETTEXT_USED_LOCALES ${LOCALE})
678                 endif()
679         endforeach()
680         message(STATUS "Locale blacklist applied; Locales used: ${GETTEXT_USED_LOCALES}")
681 elseif (GETTEXTLIB_FOUND)
682         set(GETTEXT_USED_LOCALES ${GETTEXT_AVAILABLE_LOCALES})
683 endif()
684
685 # Set some optimizations and tweaks
686
687 include(CheckCSourceCompiles)
688 include(CheckSymbolExists)
689
690 set(CMAKE_REQUIRED_INCLUDES ${LUA_INCLUDE_DIR})
691 if(USE_LUAJIT)
692         set(CMAKE_REQUIRED_LIBRARIES ${LUA_LIBRARY})
693         # LuaJIT provides exactly zero ways to determine how recent it is (the version
694         # is unchanged since 2017), however it happens that string buffers were added
695         # after the changes which we care about so that works as an indicator.
696         # (https://github.com/LuaJIT/LuaJIT/commit/4c6b669 March 2021)
697         unset(HAVE_RECENT_LJ CACHE)
698         check_symbol_exists(luaopen_string_buffer "lualib.h" HAVE_RECENT_LJ)
699         if(NOT HAVE_RECENT_LJ)
700                 string(CONCAT explanation_msg
701                         "You are using a relatively old version of LuaJIT. We recommend "
702                         "running a recent version (from git) as older ones are known not "
703                         "to build/work correctly in all cases.\n"
704                         "THIS APPLIES ESPECIALLY ON macOS OR Linux/aarch64!")
705                 message(WARNING ${explanation_msg})
706         endif()
707 elseif(NOT MSVC)
708         set(CMAKE_REQUIRED_LIBRARIES "")
709         unset(HAVE_ATCCALL CACHE)
710         # Note: we need to check the function without having the library
711         #       available for linking, so check_symbol_exists won't work.
712         # Incidentally this doesn't seem to work on MSVC...
713         check_c_source_compiles("#include <lua.h>\nint main(){return sizeof(lua_atccall);}" HAVE_ATCCALL)
714         if(NOT HAVE_ATCCALL)
715                 string(CONCAT explanation_msg
716                         "It looks like you're trying to build Minetest using a system-wide "
717                         "Lua installation. This is no longer supported because PUC Lua "
718                         "cannot interoperate with C++ correctly. Read src/unittest/test_lua.cpp "
719                         " for technical details.")
720                 message(FATAL_ERROR ${explanation_msg})
721         endif()
722 endif()
723
724 if(MSVC)
725         # Visual Studio
726         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D WIN32_LEAN_AND_MEAN")
727         # EHa enables SEH exceptions (used for catching segfaults)
728         set(CMAKE_CXX_FLAGS_RELEASE "/EHa /Ox /MD /GS- /Zi /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0")
729         if(CMAKE_SIZEOF_VOID_P EQUAL 4)
730                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /arch:SSE")
731         endif()
732
733         set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
734
735         set(CMAKE_CXX_FLAGS_SEMIDEBUG "/MDd /Zi /Ob0 /O1 /RTC1")
736
737         # Debug build doesn't catch exceptions by itself
738         # Add some optimizations because otherwise it's VERY slow
739         set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1")
740
741         # Flags for C files (sqlite)
742         # /MD = dynamically link to MSVCRxxx.dll
743         set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /MD")
744
745         # Flags that cannot be shared between cl and clang-cl
746         # https://clang.llvm.org/docs/UsersManual.html#clang-cl
747         if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
748                 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
749
750                 # Disable pragma-pack warning
751                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-pragma-pack")
752         else()
753                 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
754                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /TP /FD /GL")
755                 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
756         endif()
757 else()
758         # GCC or compatible compilers such as Clang
759         set(WARNING_FLAGS "-Wall -Wextra")
760         set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-parameter -Wno-implicit-fallthrough")
761         if(WARN_ALL)
762                 set(RELEASE_WARNING_FLAGS "${WARNING_FLAGS}")
763         else()
764                 set(RELEASE_WARNING_FLAGS "")
765         endif()
766
767         if(MINGW)
768                 set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions")
769                 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_LEAN_AND_MEAN")
770         endif()
771
772         # Use a safe subset of flags to speed up math calculations:
773         # - we don't need errno or math exceptions
774         # - we don't deal with signed zero
775         set(MATH_FLAGS "-fno-math-errno -fno-trapping-math -fno-signed-zeros")
776
777         # Enable SSE for floating point math on 32-bit x86 by default
778         # reasoning see minetest issue #11810 and https://gcc.gnu.org/wiki/FloatingPointMath
779         if(CMAKE_SIZEOF_VOID_P EQUAL 4)
780                 check_c_source_compiles("#ifndef __i686__\n#error\n#endif\nint main(){}" IS_I686)
781                 if(IS_I686)
782                         message(STATUS "Detected Intel x86: using SSE instead of x87 FPU")
783                         set(OTHER_FLAGS "${OTHER_FLAGS} -mfpmath=sse -msse")
784                 endif()
785         endif()
786
787         set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${OTHER_FLAGS} -pipe -funroll-loops -O3 -fomit-frame-pointer")
788         if(CMAKE_SYSTEM_NAME STREQUAL "Linux"
789                         AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
790                         AND CMAKE_CXX_COMPILER_VERSION MATCHES "^9\\.")
791                 # Clang 9 has broken -ffast-math on glibc
792         else()
793                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MATH_FLAGS}")
794         endif()
795         set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -g")
796         set(CMAKE_CXX_FLAGS_SEMIDEBUG "-g -O1 ${WARNING_FLAGS} ${OTHER_FLAGS}")
797         set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 ${WARNING_FLAGS} ${OTHER_FLAGS}")
798
799         if(UNIX)
800                 # enable assertions for libstdc++ or libc++
801                 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wp,-D_GLIBCXX_ASSERTIONS -Wp,-D_LIBCPP_ENABLE_ASSERTIONS=1")
802         endif()
803         if(USE_GPROF)
804                 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
805         endif()
806
807         if(MINGW)
808                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mwindows")
809         endif()
810 endif()
811
812
813 # Installation
814
815 if(WIN32)
816         if(EXTRA_DLL)
817                 install(FILES ${EXTRA_DLL} DESTINATION ${BINDIR})
818         endif()
819         if(VCPKG_APPLOCAL_DEPS)
820                 # Collect the dll's from the output path
821                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Release/
822                                 DESTINATION ${BINDIR}
823                                 CONFIGURATIONS Release
824                                 FILES_MATCHING PATTERN "*.dll")
825                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Debug/
826                                 DESTINATION ${BINDIR}
827                                 CONFIGURATIONS Debug
828                                 FILES_MATCHING PATTERN "*.dll")
829                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/RelWithDebInfo/
830                                 DESTINATION ${BINDIR}
831                                 CONFIGURATIONS RelWithDebInfo
832                                 FILES_MATCHING PATTERN "*.dll")
833                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/MinSizeRel/
834                                 DESTINATION ${BINDIR}
835                                 CONFIGURATIONS MinSizeRel
836                                 FILES_MATCHING PATTERN "*.dll")
837         else()
838                 # Use the old-style way to install dll's
839                 if(BUILD_CLIENT AND USE_SOUND)
840                         if(OPENAL_DLL)
841                                 install(FILES ${OPENAL_DLL} DESTINATION ${BINDIR})
842                         endif()
843                         if(OGG_DLL)
844                                 install(FILES ${OGG_DLL} DESTINATION ${BINDIR})
845                         endif()
846                         if(VORBIS_DLL)
847                                 install(FILES ${VORBIS_DLL} DESTINATION ${BINDIR})
848                         endif()
849                 endif()
850                 if(CURL_DLL)
851                         install(FILES ${CURL_DLL} DESTINATION ${BINDIR})
852                 endif()
853                 if(ZLIB_DLL)
854                         install(FILES ${ZLIB_DLL} DESTINATION ${BINDIR})
855                 endif()
856                 if(ZSTD_DLL)
857                         install(FILES ${ZSTD_DLL} DESTINATION ${BINDIR})
858                 endif()
859                 if(BUILD_CLIENT AND FREETYPE_DLL)
860                         install(FILES ${FREETYPE_DLL} DESTINATION ${BINDIR})
861                 endif()
862                 if(SQLITE3_DLL)
863                         install(FILES ${SQLITE3_DLL} DESTINATION ${BINDIR})
864                 endif()
865                 if(LEVELDB_DLL)
866                         install(FILES ${LEVELDB_DLL} DESTINATION ${BINDIR})
867                 endif()
868                 if(LUA_DLL)
869                         install(FILES ${LUA_DLL} DESTINATION ${BINDIR})
870                 endif()
871                 if(BUILD_CLIENT AND USE_GETTEXT AND GETTEXT_DLL)
872                         install(FILES ${GETTEXT_DLL} DESTINATION ${BINDIR})
873                 endif()
874         endif()
875
876         if(BUILD_CLIENT AND IRRLICHT_DLL)
877                 install(FILES ${IRRLICHT_DLL} DESTINATION ${BINDIR})
878         endif()
879 endif()
880
881 if(BUILD_CLIENT)
882         install(TARGETS ${PROJECT_NAME}
883                 RUNTIME DESTINATION ${BINDIR}
884                 LIBRARY DESTINATION ${BINDIR}
885                 ARCHIVE DESTINATION ${BINDIR}
886                 BUNDLE DESTINATION .
887         )
888
889         if(APPLE)
890                 install(CODE "
891                         set(BU_CHMOD_BUNDLE_ITEMS ON)
892                         include(BundleUtilities)
893                         fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${BUNDLE_PATH}\" \"\" \"\${CMAKE_INSTALL_PREFIX}/${BINDIR}\")
894                 " COMPONENT Runtime)
895         endif()
896
897         if(USE_GETTEXT)
898                 foreach(LOCALE ${GETTEXT_USED_LOCALES})
899                         set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
900                         set(MO_BUILD_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
901                         install(FILES ${MO_BUILD_PATH} DESTINATION ${MO_DEST_PATH})
902                 endforeach()
903         endif()
904
905         install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../fonts" DESTINATION "${SHAREDIR}"
906                         FILES_MATCHING PATTERN "*.ttf" PATTERN "*.txt")
907 endif(BUILD_CLIENT)
908
909 if(BUILD_SERVER)
910         install(TARGETS ${PROJECT_NAME}server DESTINATION ${BINDIR})
911 endif()
912
913 if (USE_GETTEXT)
914         set(MO_FILES)
915
916         foreach(LOCALE ${GETTEXT_USED_LOCALES})
917                 set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/${PROJECT_NAME}.po")
918                 set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
919                 set(MO_FILE_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
920
921                 add_custom_command(OUTPUT ${MO_BUILD_PATH}
922                         COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH}
923                         COMMENT "mo-update [${LOCALE}]: Creating locale directory.")
924
925                 add_custom_command(
926                         OUTPUT ${MO_FILE_PATH}
927                         COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH}
928                         DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH}
929                         WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
930                         COMMENT "mo-update [${LOCALE}]: Creating mo file."
931                         )
932
933                 set(MO_FILES ${MO_FILES} ${MO_FILE_PATH})
934         endforeach()
935
936         add_custom_target(translations ALL COMMENT "mo update" DEPENDS ${MO_FILES})
937 endif()