]> git.lizzy.rs Git - minetest.git/blob - src/CMakeLists.txt
Object selection: Improve distance checks (#12974)
[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         log.cpp
379         main.cpp
380         map.cpp
381         map_settings_manager.cpp
382         mapblock.cpp
383         mapnode.cpp
384         mapsector.cpp
385         metadata.cpp
386         modchannels.cpp
387         nameidmapping.cpp
388         nodedef.cpp
389         nodemetadata.cpp
390         nodetimer.cpp
391         noise.cpp
392         objdef.cpp
393         object_properties.cpp
394         particles.cpp
395         pathfinder.cpp
396         player.cpp
397         porting.cpp
398         profiler.cpp
399         raycast.cpp
400         reflowscan.cpp
401         remoteplayer.cpp
402         rollback.cpp
403         rollback_interface.cpp
404         serialization.cpp
405         server.cpp
406         serverenvironment.cpp
407         serverlist.cpp
408         settings.cpp
409         staticobject.cpp
410         terminal_chat_console.cpp
411         texture_override.cpp
412         tileanimation.cpp
413         tool.cpp
414         translation.cpp
415         version.cpp
416         voxel.cpp
417         voxelalgorithms.cpp
418         hud.cpp
419         ${common_network_SRCS}
420         ${JTHREAD_SRCS}
421         ${common_SCRIPT_SRCS}
422         ${UTIL_SRCS}
423 )
424
425 if(BUILD_UNITTESTS)
426         set(common_SRCS ${common_SRCS} ${UNITTEST_SRCS})
427 endif()
428
429 if(BUILD_BENCHMARKS)
430         set(common_SRCS ${common_SRCS} ${BENCHMARK_SRCS})
431 endif()
432
433 # This gives us the icon and file version information
434 if(WIN32)
435         set(WINRESOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../misc/winresource.rc")
436         set(MINETEST_EXE_MANIFEST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../misc/minetest.exe.manifest")
437         if(MINGW)
438                 if(NOT CMAKE_RC_COMPILER)
439                         set(CMAKE_RC_COMPILER "windres.exe")
440                 endif()
441                 ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
442                         COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_BINARY_DIR}
443                         -i${WINRESOURCE_FILE}
444                         -o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
445                         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
446                         DEPENDS ${WINRESOURCE_FILE} ${MINETEST_EXE_MANIFEST_FILE})
447                 SET(extra_windows_SRCS ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o)
448         else(MINGW) # Probably MSVC
449                 set(extra_windows_SRCS ${WINRESOURCE_FILE} ${MINETEST_EXE_MANIFEST_FILE})
450         endif(MINGW)
451 endif()
452
453
454 # Client sources
455 if (BUILD_CLIENT)
456         add_subdirectory(client)
457 endif(BUILD_CLIENT)
458
459 set(client_SRCS
460         ${client_SRCS}
461         ${common_SRCS}
462         ${gui_SRCS}
463         ${client_network_SRCS}
464         ${client_irrlicht_changes_SRCS}
465         ${client_SCRIPT_SRCS}
466 )
467
468 if(BUILD_UNITTESTS)
469         set(client_SRCS ${client_SRCS} ${UNITTEST_CLIENT_SRCS})
470 endif()
471
472 if(BUILD_BENCHMARKS)
473         set(client_SRCS ${client_SRCS} ${BENCHMARK_CLIENT_SRCS})
474 endif()
475
476 list(SORT client_SRCS)
477
478 # Server sources
479 set(server_SRCS
480         ${common_SRCS}
481 )
482 list(SORT server_SRCS)
483
484 # Avoid source_group on broken CMake version.
485 # see issue #7074 #7075
486 if (CMAKE_VERSION VERSION_GREATER 3.8.1)
487         source_group(TREE ${PROJECT_SOURCE_DIR} PREFIX "Source Files" FILES ${client_SRCS})
488         source_group(TREE ${PROJECT_SOURCE_DIR} PREFIX "Source Files" FILES ${server_SRCS})
489 endif()
490
491 include_directories(
492         ${PROJECT_BINARY_DIR}
493         ${PROJECT_SOURCE_DIR}
494         ${PROJECT_SOURCE_DIR}/script
495 )
496 include_directories(SYSTEM
497         ${ZLIB_INCLUDE_DIR}
498         ${ZSTD_INCLUDE_DIR}
499         ${SQLITE3_INCLUDE_DIR}
500         ${LUA_INCLUDE_DIR}
501         ${GMP_INCLUDE_DIR}
502         ${JSON_INCLUDE_DIR}
503         ${LUA_BIT_INCLUDE_DIR}
504 )
505
506 if(USE_GETTEXT)
507         include_directories(${GETTEXT_INCLUDE_DIR})
508 endif()
509
510 if(BUILD_CLIENT)
511         include_directories(SYSTEM
512                 ${FREETYPE_INCLUDE_DIRS}
513                 ${SOUND_INCLUDE_DIRS}
514                 ${X11_INCLUDE_DIR}
515         )
516 endif()
517
518 if(USE_CURL)
519         include_directories(${CURL_INCLUDE_DIR})
520 endif()
521
522
523 # When cross-compiling assume the user doesn't want to run the executable anyway,
524 # otherwise place it in <source dir>/bin/ since Minetest can only run from there.
525 if(NOT CMAKE_CROSSCOMPILING)
526         set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin")
527 endif()
528
529 if(BUILD_CLIENT)
530         add_executable(${PROJECT_NAME} ${client_SRCS} ${extra_windows_SRCS})
531         add_dependencies(${PROJECT_NAME} GenerateVersion)
532         target_link_libraries(
533                 ${PROJECT_NAME}
534                 ${ZLIB_LIBRARIES}
535                 IrrlichtMt::IrrlichtMt
536                 ${ZSTD_LIBRARY}
537                 ${X11_LIBRARIES}
538                 ${SOUND_LIBRARIES}
539                 ${SQLITE3_LIBRARY}
540                 ${LUA_LIBRARY}
541                 ${GMP_LIBRARY}
542                 ${JSON_LIBRARY}
543                 ${LUA_BIT_LIBRARY}
544                 ${FREETYPE_LIBRARY}
545                 ${PLATFORM_LIBS}
546         )
547         if(NOT USE_LUAJIT)
548                 set_target_properties(${PROJECT_NAME} PROPERTIES
549                         # This is necessary for dynamic Lua modules
550                         # to work when Lua is statically linked (issue #10806)
551                         ENABLE_EXPORTS 1
552                 )
553         endif()
554
555         if(USE_GETTEXT)
556                 target_link_libraries(
557                         ${PROJECT_NAME}
558                         ${GETTEXT_LIBRARY}
559                 )
560         endif()
561         if(USE_CURL)
562                 target_link_libraries(
563                         ${PROJECT_NAME}
564                         ${CURL_LIBRARY}
565                 )
566         endif()
567         if(FREETYPE_PKGCONFIG_FOUND)
568                 set_target_properties(${PROJECT_NAME}
569                         PROPERTIES
570                         COMPILE_FLAGS "${FREETYPE_CFLAGS_STR}"
571         )
572         endif()
573         if (USE_CURSES)
574                 target_link_libraries(${PROJECT_NAME} ${CURSES_LIBRARIES})
575         endif()
576         if (USE_POSTGRESQL)
577                 target_link_libraries(${PROJECT_NAME} ${PostgreSQL_LIBRARIES})
578         endif()
579         if (USE_LEVELDB)
580                 target_link_libraries(${PROJECT_NAME} ${LEVELDB_LIBRARY})
581         endif()
582         if (USE_REDIS)
583                 target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
584         endif()
585         if (USE_PROMETHEUS)
586                 target_link_libraries(${PROJECT_NAME} ${PROMETHEUS_LIBRARIES})
587         endif()
588         if (USE_SPATIAL)
589                 target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
590         endif()
591         if(BUILD_BENCHMARKS)
592                 target_link_libraries(${PROJECT_NAME} catch2)
593         endif()
594 endif(BUILD_CLIENT)
595
596
597 if(BUILD_SERVER)
598         add_executable(${PROJECT_NAME}server ${server_SRCS} ${extra_windows_SRCS})
599         add_dependencies(${PROJECT_NAME}server GenerateVersion)
600
601         get_target_property(
602                 IRRLICHT_INCLUDES IrrlichtMt::IrrlichtMt INTERFACE_INCLUDE_DIRECTORIES)
603         # Doesn't work without PRIVATE/PUBLIC/INTERFACE mode specified.
604         target_include_directories(${PROJECT_NAME}server PRIVATE ${IRRLICHT_INCLUDES})
605         target_link_libraries(
606                 ${PROJECT_NAME}server
607                 ${ZLIB_LIBRARIES}
608                 ${ZSTD_LIBRARY}
609                 ${SQLITE3_LIBRARY}
610                 ${JSON_LIBRARY}
611                 ${LUA_LIBRARY}
612                 ${LUA_BIT_LIBRARY}
613                 ${GMP_LIBRARY}
614                 ${PLATFORM_LIBS}
615         )
616         set_target_properties(${PROJECT_NAME}server PROPERTIES
617                 COMPILE_DEFINITIONS "SERVER")
618         if(NOT USE_LUAJIT)
619                 set_target_properties(${PROJECT_NAME}server PROPERTIES
620                         # This is necessary for dynamic Lua modules
621                         # to work when Lua is statically linked (issue #10806)
622                         ENABLE_EXPORTS 1
623                 )
624         endif()
625
626         if (USE_GETTEXT)
627                 target_link_libraries(${PROJECT_NAME}server ${GETTEXT_LIBRARY})
628         endif()
629         if (USE_CURSES)
630                 target_link_libraries(${PROJECT_NAME}server ${CURSES_LIBRARIES})
631         endif()
632         if (USE_POSTGRESQL)
633                 target_link_libraries(${PROJECT_NAME}server ${PostgreSQL_LIBRARIES})
634         endif()
635         if (USE_LEVELDB)
636                 target_link_libraries(${PROJECT_NAME}server ${LEVELDB_LIBRARY})
637         endif()
638         if (USE_REDIS)
639                 target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
640         endif()
641         if (USE_PROMETHEUS)
642                 target_link_libraries(${PROJECT_NAME}server ${PROMETHEUS_LIBRARIES})
643         endif()
644         if (USE_SPATIAL)
645                 target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
646         endif()
647         if(USE_CURL)
648                 target_link_libraries(
649                         ${PROJECT_NAME}server
650                         ${CURL_LIBRARY}
651                 )
652         endif()
653         if(BUILD_BENCHMARKS)
654                 target_link_libraries(${PROJECT_NAME}server catch2)
655         endif()
656 endif(BUILD_SERVER)
657
658 # Blacklisted locales that don't work.
659 # see issue #4638
660 set(GETTEXT_BLACKLISTED_LOCALES
661         ar
662         dv
663         he
664         hi
665         kn
666         ms_Arab
667         th
668 )
669
670 option(APPLY_LOCALE_BLACKLIST "Use a blacklist to avoid known broken locales" TRUE)
671
672 if (GETTEXTLIB_FOUND AND APPLY_LOCALE_BLACKLIST)
673         set(GETTEXT_USED_LOCALES "")
674         foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES})
675                 if (NOT "${LOCALE}" IN_LIST GETTEXT_BLACKLISTED_LOCALES)
676                         list(APPEND GETTEXT_USED_LOCALES ${LOCALE})
677                 endif()
678         endforeach()
679         message(STATUS "Locale blacklist applied; Locales used: ${GETTEXT_USED_LOCALES}")
680 elseif (GETTEXTLIB_FOUND)
681         set(GETTEXT_USED_LOCALES ${GETTEXT_AVAILABLE_LOCALES})
682 endif()
683
684 # Set some optimizations and tweaks
685
686 include(CheckCSourceCompiles)
687 include(CheckSymbolExists)
688
689 set(CMAKE_REQUIRED_INCLUDES ${LUA_INCLUDE_DIR})
690 if(USE_LUAJIT)
691         set(CMAKE_REQUIRED_LIBRARIES ${LUA_LIBRARY})
692         # LuaJIT provides exactly zero ways to determine how recent it is (the version
693         # is unchanged since 2017), however it happens that string buffers were added
694         # after the changes which we care about so that works as an indicator.
695         # (https://github.com/LuaJIT/LuaJIT/commit/4c6b669 March 2021)
696         unset(HAVE_RECENT_LJ CACHE)
697         check_symbol_exists(luaopen_string_buffer "lualib.h" HAVE_RECENT_LJ)
698         if(NOT HAVE_RECENT_LJ)
699                 string(CONCAT explanation_msg
700                         "You are using a relatively old version of LuaJIT. We recommend "
701                         "running a recent version (from git) as older ones are known not "
702                         "to build/work correctly in all cases.\n"
703                         "THIS APPLIES ESPECIALLY ON macOS OR Linux/aarch64!")
704                 message(WARNING ${explanation_msg})
705         endif()
706 elseif(NOT MSVC)
707         set(CMAKE_REQUIRED_LIBRARIES "")
708         unset(HAVE_ATCCALL CACHE)
709         # Note: we need to check the function without having the library
710         #       available for linking, so check_symbol_exists won't work.
711         # Incidentally this doesn't seem to work on MSVC...
712         check_c_source_compiles("#include <lua.h>\nint main(){return sizeof(lua_atccall);}" HAVE_ATCCALL)
713         if(NOT HAVE_ATCCALL)
714                 string(CONCAT explanation_msg
715                         "It looks like you're trying to build Minetest using a system-wide "
716                         "Lua installation. This is no longer supported because PUC Lua "
717                         "cannot interoperate with C++ correctly. Read src/unittest/test_lua.cpp "
718                         " for technical details.")
719                 message(FATAL_ERROR ${explanation_msg})
720         endif()
721 endif()
722
723 if(MSVC)
724         # Visual Studio
725         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D WIN32_LEAN_AND_MEAN")
726         # EHa enables SEH exceptions (used for catching segfaults)
727         set(CMAKE_CXX_FLAGS_RELEASE "/EHa /Ox /MD /GS- /Zi /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0")
728         if(CMAKE_SIZEOF_VOID_P EQUAL 4)
729                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /arch:SSE")
730         endif()
731
732         set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
733
734         set(CMAKE_CXX_FLAGS_SEMIDEBUG "/MDd /Zi /Ob0 /O1 /RTC1")
735
736         # Debug build doesn't catch exceptions by itself
737         # Add some optimizations because otherwise it's VERY slow
738         set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1")
739
740         # Flags for C files (sqlite)
741         # /MD = dynamically link to MSVCRxxx.dll
742         set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /MD")
743
744         # Flags that cannot be shared between cl and clang-cl
745         # https://clang.llvm.org/docs/UsersManual.html#clang-cl
746         if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
747                 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
748
749                 # Disable pragma-pack warning
750                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-pragma-pack")
751         else()
752                 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
753                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /TP /FD /GL")
754                 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
755         endif()
756 else()
757         # GCC or compatible compilers such as Clang
758         set(WARNING_FLAGS "-Wall -Wextra")
759         set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-unused-parameter -Wno-implicit-fallthrough")
760         if(WARN_ALL)
761                 set(RELEASE_WARNING_FLAGS "${WARNING_FLAGS}")
762         else()
763                 set(RELEASE_WARNING_FLAGS "")
764         endif()
765
766         if(MINGW)
767                 set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions")
768                 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_LEAN_AND_MEAN")
769         endif()
770
771         # Use a safe subset of flags to speed up math calculations:
772         # - we don't need errno or math exceptions
773         # - we don't deal with signed zero
774         set(MATH_FLAGS "-fno-math-errno -fno-trapping-math -fno-signed-zeros")
775
776         # Enable SSE for floating point math on 32-bit x86 by default
777         # reasoning see minetest issue #11810 and https://gcc.gnu.org/wiki/FloatingPointMath
778         if(CMAKE_SIZEOF_VOID_P EQUAL 4)
779                 check_c_source_compiles("#ifndef __i686__\n#error\n#endif\nint main(){}" IS_I686)
780                 if(IS_I686)
781                         message(STATUS "Detected Intel x86: using SSE instead of x87 FPU")
782                         set(OTHER_FLAGS "${OTHER_FLAGS} -mfpmath=sse -msse")
783                 endif()
784         endif()
785
786         set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${OTHER_FLAGS} -pipe -funroll-loops")
787         if(CMAKE_SYSTEM_NAME MATCHES "(Darwin|BSD|DragonFly)")
788                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os")
789         else()
790                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -fomit-frame-pointer")
791                 if(CMAKE_SYSTEM_NAME STREQUAL "Linux"
792                                 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
793                                 AND CMAKE_CXX_COMPILER_VERSION MATCHES "^9\\.")
794                         # Clang 9 has broken -ffast-math on glibc
795                 else()
796                         set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MATH_FLAGS}")
797                 endif()
798         endif()
799         set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -g")
800         set(CMAKE_CXX_FLAGS_SEMIDEBUG "-g -O1 ${WARNING_FLAGS} ${OTHER_FLAGS}")
801         set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 ${WARNING_FLAGS} ${OTHER_FLAGS}")
802
803         if(UNIX)
804                 # enable assertions for libstdc++ or libc++
805                 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wp,-D_GLIBCXX_ASSERTIONS -Wp,-D_LIBCPP_ENABLE_ASSERTIONS=1")
806         endif()
807         if(USE_GPROF)
808                 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
809         endif()
810
811         if(MINGW)
812                 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mwindows")
813         endif()
814 endif()
815
816
817 # Installation
818
819 if(WIN32)
820         if(EXTRA_DLL)
821                 install(FILES ${EXTRA_DLL} DESTINATION ${BINDIR})
822         endif()
823         if(VCPKG_APPLOCAL_DEPS)
824                 # Collect the dll's from the output path
825                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Release/
826                                 DESTINATION ${BINDIR}
827                                 CONFIGURATIONS Release
828                                 FILES_MATCHING PATTERN "*.dll")
829                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Debug/
830                                 DESTINATION ${BINDIR}
831                                 CONFIGURATIONS Debug
832                                 FILES_MATCHING PATTERN "*.dll")
833                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/RelWithDebInfo/
834                                 DESTINATION ${BINDIR}
835                                 CONFIGURATIONS RelWithDebInfo
836                                 FILES_MATCHING PATTERN "*.dll")
837                 install(DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/MinSizeRel/
838                                 DESTINATION ${BINDIR}
839                                 CONFIGURATIONS MinSizeRel
840                                 FILES_MATCHING PATTERN "*.dll")
841         else()
842                 # Use the old-style way to install dll's
843                 if(BUILD_CLIENT AND USE_SOUND)
844                         if(OPENAL_DLL)
845                                 install(FILES ${OPENAL_DLL} DESTINATION ${BINDIR})
846                         endif()
847                         if(OGG_DLL)
848                                 install(FILES ${OGG_DLL} DESTINATION ${BINDIR})
849                         endif()
850                         if(VORBIS_DLL)
851                                 install(FILES ${VORBIS_DLL} DESTINATION ${BINDIR})
852                         endif()
853                 endif()
854                 if(CURL_DLL)
855                         install(FILES ${CURL_DLL} DESTINATION ${BINDIR})
856                 endif()
857                 if(ZLIB_DLL)
858                         install(FILES ${ZLIB_DLL} DESTINATION ${BINDIR})
859                 endif()
860                 if(ZSTD_DLL)
861                         install(FILES ${ZSTD_DLL} DESTINATION ${BINDIR})
862                 endif()
863                 if(BUILD_CLIENT AND FREETYPE_DLL)
864                         install(FILES ${FREETYPE_DLL} DESTINATION ${BINDIR})
865                 endif()
866                 if(SQLITE3_DLL)
867                         install(FILES ${SQLITE3_DLL} DESTINATION ${BINDIR})
868                 endif()
869                 if(LEVELDB_DLL)
870                         install(FILES ${LEVELDB_DLL} DESTINATION ${BINDIR})
871                 endif()
872                 if(LUA_DLL)
873                         install(FILES ${LUA_DLL} DESTINATION ${BINDIR})
874                 endif()
875                 if(BUILD_CLIENT AND USE_GETTEXT AND GETTEXT_DLL)
876                         install(FILES ${GETTEXT_DLL} DESTINATION ${BINDIR})
877                 endif()
878         endif()
879
880         if(BUILD_CLIENT AND IRRLICHT_DLL)
881                 install(FILES ${IRRLICHT_DLL} DESTINATION ${BINDIR})
882         endif()
883 endif()
884
885 if(BUILD_CLIENT)
886         install(TARGETS ${PROJECT_NAME}
887                 RUNTIME DESTINATION ${BINDIR}
888                 LIBRARY DESTINATION ${BINDIR}
889                 ARCHIVE DESTINATION ${BINDIR}
890                 BUNDLE DESTINATION .
891         )
892
893         if(APPLE)
894                 install(CODE "
895                         set(BU_CHMOD_BUNDLE_ITEMS ON)
896                         include(BundleUtilities)
897                         fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${BUNDLE_PATH}\" \"\" \"\${CMAKE_INSTALL_PREFIX}/${BINDIR}\")
898                 " COMPONENT Runtime)
899         endif()
900
901         if(USE_GETTEXT)
902                 foreach(LOCALE ${GETTEXT_USED_LOCALES})
903                         set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
904                         set(MO_BUILD_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
905                         install(FILES ${MO_BUILD_PATH} DESTINATION ${MO_DEST_PATH})
906                 endforeach()
907         endif()
908
909         install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../fonts" DESTINATION "${SHAREDIR}"
910                         FILES_MATCHING PATTERN "*.ttf" PATTERN "*.txt")
911 endif(BUILD_CLIENT)
912
913 if(BUILD_SERVER)
914         install(TARGETS ${PROJECT_NAME}server DESTINATION ${BINDIR})
915 endif()
916
917 if (USE_GETTEXT)
918         set(MO_FILES)
919
920         foreach(LOCALE ${GETTEXT_USED_LOCALES})
921                 set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/${PROJECT_NAME}.po")
922                 set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE})
923                 set(MO_FILE_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo")
924
925                 add_custom_command(OUTPUT ${MO_BUILD_PATH}
926                         COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH}
927                         COMMENT "mo-update [${LOCALE}]: Creating locale directory.")
928
929                 add_custom_command(
930                         OUTPUT ${MO_FILE_PATH}
931                         COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH}
932                         DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH}
933                         WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}"
934                         COMMENT "mo-update [${LOCALE}]: Creating mo file."
935                         )
936
937                 set(MO_FILES ${MO_FILES} ${MO_FILE_PATH})
938         endforeach()
939
940         add_custom_target(translations ALL COMMENT "mo update" DEPENDS ${MO_FILES})
941 endif()