Fix #12957: 1-in-X proportion of towns being cities is unnecessarily random. (#12960)
[openttd-github.git] / CMakeLists.txt
blob487eb8520d9997a5201a147915cdc7e614363265
1 cmake_minimum_required(VERSION 3.16)
3 if(NOT BINARY_NAME)
4     set(BINARY_NAME openttd)
5 endif()
7 project(${BINARY_NAME}
8     VERSION 15.0
9     LANGUAGES CXX
12 if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
13     message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the build directory. You may need to delete \"${CMAKE_SOURCE_DIR}/CMakeCache.txt\" first.")
14 endif()
16 # Debug mode by default.
17 if(NOT CMAKE_BUILD_TYPE)
18     set(CMAKE_BUILD_TYPE Debug)
19 endif()
21 if (EMSCRIPTEN)
22     set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/os/emscripten/cmake")
23 endif()
25 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
26 set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15)
28 # Use GNUInstallDirs to allow customisation
29 # but set our own default data and bin dir
30 if(NOT CMAKE_INSTALL_DATADIR)
31     set(CMAKE_INSTALL_DATADIR "share/games")
32 endif()
33 if(NOT CMAKE_INSTALL_BINDIR)
34     set(CMAKE_INSTALL_BINDIR "games")
35 endif()
36 include(GNUInstallDirs)
38 include(Options)
39 set_options()
40 set_directory_options()
42 include(Static)
43 set_static_if_needed()
45 set(CMAKE_CXX_STANDARD 20)
46 set(CMAKE_CXX_STANDARD_REQUIRED YES)
47 set(CMAKE_CXX_EXTENSIONS NO)
49 set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
51 # An empty target for the tools
52 add_custom_target(tools)
54 include(Endian)
55 add_endian_definition()
57 include(CompileFlags)
58 compile_flags()
60 if(APPLE OR UNIX)
61     add_definitions(-DUNIX)
62 endif()
64 if(UNIX)
65     find_package(Doxygen)
66 endif()
68 list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp")
69 if(WIN32)
70     list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc")
71 endif()
73 # Generate a target to determine version, which is execute every 'make' run
74 add_custom_target(find_version
75         ${CMAKE_COMMAND}
76                 -DFIND_VERSION_BINARY_DIR=${CMAKE_BINARY_DIR}/generated
77                 -DCPACK_BINARY_DIR=${CMAKE_BINARY_DIR}
78                 -DREV_MAJOR=${PROJECT_VERSION_MAJOR}
79                 -DREV_MINOR=${PROJECT_VERSION_MINOR}
80                 -DWINDOWS=${WIN32}
81                 -P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake"
82         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
83         BYPRODUCTS ${GENERATED_SOURCE_FILES}
86 # Documentation
87 if(DOXYGEN_EXECUTABLE)
88     add_custom_target(docs)
89     add_custom_target(docs_source
90         ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs
91         COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
92         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
93         COMMENT "Generating documentation for source"
94     )
95     add_dependencies(docs_source
96         find_version
97     )
98     add_dependencies(docs
99         docs_source
100     )
101 endif()
103 include(AddCustomXXXTimestamp)
105 if(OPTION_TOOLS_ONLY)
106     if(HOST_BINARY_DIR)
107         unset(HOST_BINARY_DIR CACHE)
108     endif()
109     add_subdirectory(${CMAKE_SOURCE_DIR}/src)
110     return()
111 endif()
113 if(APPLE)
114         # Avoid searching for headers in Frameworks, and libraries in LIBDIR.
115         set(CMAKE_FIND_FRAMEWORK LAST)
116 endif()
118 # Prefer -pthread over -lpthread, which is often the better option of the two.
119 set(CMAKE_THREAD_PREFER_PTHREAD YES)
120 # Make sure we have Threads available.
121 find_package(Threads REQUIRED)
123 find_package(ZLIB)
124 find_package(LibLZMA)
125 find_package(LZO)
126 find_package(PNG)
128 if(WIN32 OR EMSCRIPTEN)
129     # Windows uses WinHttp for HTTP requests.
130     # Emscripten uses Javascript for HTTP requests.
131 else()
132     # All other targets use libcurl.
133     find_package(CURL)
134 endif()
136 # Breakpad doesn't support emscripten.
137 if(NOT EMSCRIPTEN)
138     find_package(unofficial-breakpad)
139 endif()
141 if(NOT OPTION_DEDICATED)
142     if(NOT WIN32)
143         find_package(Allegro)
144         if(NOT APPLE)
145             find_package(Freetype)
146             find_package(SDL2)
147             if(NOT SDL2_FOUND)
148                 find_package(SDL)
149             endif()
150             find_package(Fluidsynth)
151             if(Freetype_FOUND)
152                 find_package(Fontconfig)
153             endif()
154             find_package(Harfbuzz)
155             find_package(ICU OPTIONAL_COMPONENTS i18n)
156         endif()
157     endif()
158 endif()
159 if(APPLE)
160     enable_language(OBJCXX)
162     find_package(Iconv)
164     find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
165     find_library(AUDIOUNIT_LIBRARY AudioUnit)
166     find_library(COCOA_LIBRARY Cocoa)
167     find_library(QUARTZCORE_LIBRARY QuartzCore)
168 endif()
170 if(NOT EMSCRIPTEN AND NOT OPTION_DEDICATED)
171     find_package(OpenGL COMPONENTS OpenGL)
172 endif()
174 if(MSVC)
175     find_package(Editbin REQUIRED)
176 endif()
178 find_package(SSE)
179 find_package(Xaudio2)
181 find_package(Grfcodec)
183 include(CheckIPOSupported)
184 check_ipo_supported(RESULT IPO_FOUND)
186 show_options()
188 if(UNIX AND NOT APPLE AND NOT OPTION_DEDICATED)
189     if(NOT SDL_FOUND AND NOT SDL2_FOUND AND NOT ALLEGRO_FOUND)
190         message(FATAL_ERROR "SDL, SDL2 or Allegro is required for this platform")
191     endif()
192     if(HARFBUZZ_FOUND AND NOT ICU_i18n_FOUND)
193         message(WARNING "HarfBuzz depends on ICU i18n to function; HarfBuzz will be disabled")
194     endif()
195     if(NOT HARFBUZZ_FOUND)
196         message(WARNING "Without HarfBuzz and ICU i18n the game will not be able to render right-to-left languages correctly")
197     endif()
198 endif()
199 if(APPLE)
200     if(NOT AUDIOTOOLBOX_LIBRARY)
201         message(FATAL_ERROR "AudioToolbox is required for this platform")
202     endif()
203     if(NOT AUDIOUNIT_LIBRARY)
204         message(FATAL_ERROR "AudioUnit is required for this platform")
205     endif()
206     if(NOT COCOA_LIBRARY)
207         message(FATAL_ERROR "Cocoa is required for this platform")
208     endif()
209     if(NOT QUARTZCORE_LIBRARY)
210         message(FATAL_ERROR "QuartzCore is required for this platform")
211     endif()
212 endif()
214 if(OPTION_PACKAGE_DEPENDENCIES)
215     if(NOT UNIX)
216         message(FATAL_ERROR "Can only package dependencies on Linux")
217     endif()
218     if(OPTION_INSTALL_FHS)
219         message(FATAL_ERROR "Cannot install in FHS folders when we are packaging dependencies")
220     endif()
221     if(${CMAKE_VERSION} VERSION_LESS "3.16.0")
222         message(FATAL_ERROR "OPTION_PACKAGE_DEPENDENCIES can only work with CMake 3.16+; you are using ${CMAKE_VERSION}")
223     endif()
225     # If we are packaging dependencies, we do two things:
226     # 1) set the RPATH to include $ORIGIN/lib; $ORIGIN (that literal string)
227     #    is a Linux indicator for "path where application is". In CMake, we
228     #    have to do this before add_executable() is executed.
229     # 2) copy the libraries that we compile against to the "lib" folder.
230     #    This is done in InstallAndPackage.cmake.
231     set(CMAKE_INSTALL_RPATH "\$ORIGIN/lib")
232     set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
233 endif()
235 include(CTest)
236 include(SourceList)
238 # Needed by rev.cpp
239 include_directories(${CMAKE_SOURCE_DIR}/src)
240 # Needed by everything that uses Squirrel
241 include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/squirrel/include)
243 include(MSVCFilters)
245 add_library(openttd_lib OBJECT ${GENERATED_SOURCE_FILES})
246 add_executable(openttd WIN32)
247 add_executable(openttd_test)
248 set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}")
249 # All other files are added via target_sources()
251 if(MSVC)
252     # Add DPI manifest to project; other WIN32 targets get this via ottdres.rc
253     target_sources(openttd PRIVATE "${CMAKE_SOURCE_DIR}/os/windows/openttd.manifest")
255     # If target -static is used, switch our project to static (/MT) too.
256     # If the target ends on -static-md, it will remain dynamic (/MD).
257     if(VCPKG_TARGET_TRIPLET MATCHES "-static" AND NOT VCPKG_TARGET_TRIPLET MATCHES "-md")
258         set_property(TARGET openttd_lib PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
259         set_property(TARGET openttd PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
260         set_property(TARGET openttd_test PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
261      endif()
262 endif()
264 target_precompile_headers(openttd_lib
265     PRIVATE
266     src/stdafx.h
267     src/core/format.hpp
270 add_subdirectory(${CMAKE_SOURCE_DIR}/bin)
271 add_subdirectory(${CMAKE_SOURCE_DIR}/src)
272 add_subdirectory(${CMAKE_SOURCE_DIR}/media)
274 add_dependencies(openttd
275     find_version)
277 target_link_libraries(openttd_lib
278     openttd::languages
279     openttd::settings
280     openttd::script_api
281     Threads::Threads
284 target_link_libraries(openttd
285     openttd_lib
286     openttd::media
287     openttd::basesets
290 target_link_libraries(openttd_test PRIVATE openttd_lib)
291 if(ANDROID)
292     target_link_libraries(openttd_test PRIVATE log)
293 endif()
295 include(Catch)
296 catch_discover_tests(openttd_test)
298 if(HAIKU)
299     target_link_libraries(openttd_lib "be" "network" "midi")
300 endif()
302 if(IPO_FOUND)
303     set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE True)
304     set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL True)
305     set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO True)
306 endif()
307 set_target_properties(openttd PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
308 process_compile_flags()
310 include(LinkPackage)
311 link_package(PNG TARGET PNG::PNG ENCOURAGED)
312 link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED)
313 link_package(LIBLZMA TARGET LibLZMA::LibLZMA ENCOURAGED)
314 link_package(LZO)
316 if(NOT WIN32 AND NOT EMSCRIPTEN)
317     link_package(CURL ENCOURAGED)
318     target_link_libraries(openttd_lib ${CMAKE_DL_LIBS})
319 endif()
321 if(NOT EMSCRIPTEN)
322     link_package(unofficial-breakpad TARGET unofficial::breakpad::libbreakpad_client ENCOURAGED)
323 endif()
325 if(NOT OPTION_DEDICATED)
326     link_package(Fluidsynth)
327     link_package(SDL)
328     link_package(SDL2 TARGET SDL2::SDL2)
329     link_package(Allegro)
330     link_package(FREETYPE TARGET Freetype::Freetype)
331     link_package(Fontconfig TARGET Fontconfig::Fontconfig)
332     link_package(Harfbuzz TARGET harfbuzz::harfbuzz)
333     link_package(ICU_i18n)
335     if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
336         # SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when
337         # on Linux. For Windows, we need to link to OpenGL as we also have a win32
338         # driver using it.
339         add_definitions(-DWITH_OPENGL)
340         message(STATUS "OpenGL found -- -DWITH_OPENGL -- (via SDL2)")
341     else()
342         link_package(OpenGL TARGET OpenGL::GL)
343     endif()
344 endif()
346 include(3rdparty/llvm/CheckAtomic)
348 if(APPLE)
349     link_package(Iconv TARGET Iconv::Iconv)
351     target_link_libraries(openttd_lib
352         ${AUDIOTOOLBOX_LIBRARY}
353         ${AUDIOUNIT_LIBRARY}
354         ${COCOA_LIBRARY}
355         ${QUARTZCORE_LIBRARY}
356     )
358     add_definitions(
359         -DWITH_COCOA
360     )
361 endif()
363 if(EMSCRIPTEN)
364     add_library(WASM::WASM INTERFACE IMPORTED)
366     # Allow heap-growth, and start with a bigger memory size.
367     target_link_libraries(WASM::WASM INTERFACE "-s ALLOW_MEMORY_GROWTH=1")
368     target_link_libraries(WASM::WASM INTERFACE "-s INITIAL_MEMORY=33554432")
369     target_link_libraries(WASM::WASM INTERFACE "-s DISABLE_EXCEPTION_CATCHING=0")
370     target_link_libraries(WASM::WASM INTERFACE "-s WASM_BIGINT")
371     add_definitions(-s DISABLE_EXCEPTION_CATCHING=0)
373     # Export functions to Javascript.
374     target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
376     # Preload all the files we generate during build.
377     # As we do not compile with FreeType / FontConfig, we also have no way to
378     # render several languages (like Chinese, ..), so where do you draw the
379     # line what languages to include and which not? In the end, especially as
380     # the more languages you add the slower downloading becomes, we decided to
381     # only ship the English language.
382     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/baseset@/baseset")
383     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/lang/english.lng@/lang/english.lng")
384     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/ai@/ai")
385     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/game@/game")
386     # Documentation files for the in-game text file viewer
387     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/README.md@/README.md")
388     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/CREDITS.md@/CREDITS.md")
389     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/CONTRIBUTING.md@/CONTRIBUTING.md")
390     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/COPYING.md@/COPYING.md")
391     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/known-bugs.txt@/known-bugs.txt")
392     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/changelog.txt@/changelog.txt")
393     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/admin_network.md@/docs/admin_network.md")
394     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/debugging_desyncs.md@/docs/debugging_desyncs.md")
395     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/desync.md@/docs/desync.md")
396     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/directory_structure.md@/docs/directory_structure.md")
397     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/eints.md@/docs/eints.md")
398     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/linkgraph.md@/docs/linkgraph.md")
399     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/logging_and_performance_metrics.md@/docs/logging_and_performance_metrics.md")
400     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/multiplayer.md@/docs/multiplayer.md")
401     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/savegame_format.md@/docs/savegame_format.md")
402     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/docs/symbol_server.md@/docs/symbol_server.md")
404     # We use IDBFS for persistent storage.
405     target_link_libraries(WASM::WASM INTERFACE "-lidbfs.js")
407     # Use custom pre-js and shell.html.
408     target_link_libraries(WASM::WASM INTERFACE "--pre-js ${CMAKE_SOURCE_DIR}/os/emscripten/pre.js")
409     target_link_libraries(WASM::WASM INTERFACE "--shell-file ${CMAKE_SOURCE_DIR}/os/emscripten/shell.html")
411     # Build the .html (which builds the .js, .wasm, and .data too).
412     set_target_properties(openttd PROPERTIES SUFFIX ".html")
413     target_link_libraries(openttd WASM::WASM)
414 endif()
416 if(NOT PERSONAL_DIR STREQUAL "(not set)")
417     add_definitions(
418         -DWITH_PERSONAL_DIR
419         -DPERSONAL_DIR="${PERSONAL_DIR}"
420     )
421 endif()
423 if(NOT SHARED_DIR STREQUAL "(not set)")
424     add_definitions(
425         -DWITH_SHARED_DIR
426         -DSHARED_DIR="${SHARED_DIR}"
427     )
428 endif()
430 if(NOT GLOBAL_DIR STREQUAL "(not set)")
431     add_definitions(
432         -DGLOBAL_DATA_DIR="${GLOBAL_DIR}"
433     )
434 endif()
436 link_package(SSE)
438 add_definitions_based_on_options()
440 if(WIN32)
441     add_definitions(
442         -DUNICODE
443         -D_UNICODE
444         -DWITH_UNISCRIBE
445         -DPSAPI_VERSION=1
446     )
448     target_link_libraries(openttd_lib
449         ws2_32
450         winmm
451         imm32
452         usp10
453         psapi
454         winhttp
455         bcrypt
456     )
457 endif()
459 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
460     add_definitions(-DPOINTER_IS_64BIT)
461 endif()
463 enable_testing()
465 add_subdirectory(regression)
467 if(APPLE OR WIN32)
468     find_package(Pandoc)
469 endif()
471 include(InstallAndPackage)