Fix: [NewGRF] Ensure that stations always have an even number of sprite layouts.
[openttd-github.git] / CMakeLists.txt
blobf4e08daf4a4ce383f2f5c5fac440252ebf38e726
1 cmake_minimum_required(VERSION 3.9)
3 if(NOT BINARY_NAME)
4     set(BINARY_NAME openttd)
5 endif()
7 project(${BINARY_NAME}
8     VERSION 13.0
11 if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
12     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.")
13 endif()
15 # Debug mode by default.
16 if(NOT CMAKE_BUILD_TYPE)
17     set(CMAKE_BUILD_TYPE Debug)
18 endif()
20 if (EMSCRIPTEN)
21     set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/os/emscripten/cmake")
22 endif()
24 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
25 set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14)
27 # Use GNUInstallDirs to allow customisation
28 # but set our own default data and bin dir
29 if(NOT CMAKE_INSTALL_DATADIR)
30     set(CMAKE_INSTALL_DATADIR "share/games")
31 endif()
32 if(NOT CMAKE_INSTALL_BINDIR)
33     set(CMAKE_INSTALL_BINDIR "games")
34 endif()
35 include(GNUInstallDirs)
37 include(Options)
38 set_options()
39 set_directory_options()
41 include(Static)
42 set_static_if_needed()
44 set(CMAKE_CXX_STANDARD 17)
45 set(CMAKE_CXX_STANDARD_REQUIRED YES)
46 set(CMAKE_CXX_EXTENSIONS NO)
48 set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
50 # An empty target for the tools
51 add_custom_target(tools)
53 include(Endian)
54 add_endian_definition()
56 include(CompileFlags)
57 compile_flags()
59 if(APPLE OR UNIX)
60     add_definitions(-DUNIX)
61 endif()
63 if(UNIX)
64     find_package(Doxygen)
65 endif()
67 list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp")
68 if(WIN32)
69     list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc")
70 endif()
72 # Generate a target to determine version, which is execute every 'make' run
73 add_custom_target(find_version
74         ${CMAKE_COMMAND}
75                 -DFIND_VERSION_BINARY_DIR=${CMAKE_BINARY_DIR}/generated
76                 -DCPACK_BINARY_DIR=${CMAKE_BINARY_DIR}
77                 -DREV_MAJOR=${PROJECT_VERSION_MAJOR}
78                 -DREV_MINOR=${PROJECT_VERSION_MINOR}
79                 -DWINDOWS=${WIN32}
80                 -P "${CMAKE_SOURCE_DIR}/cmake/scripts/FindVersion.cmake"
81         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
82         BYPRODUCTS ${GENERATED_SOURCE_FILES}
85 # Documentation
86 if(DOXYGEN_EXECUTABLE)
87     add_custom_target(docs)
88     add_custom_target(docs_source
89         ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs
90         COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
91         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
92         COMMENT "Generating documentation for source"
93     )
94     add_dependencies(docs_source
95         find_version
96     )
97     add_dependencies(docs
98         docs_source
99     )
100 endif()
102 include(AddCustomXXXTimestamp)
104 if(OPTION_TOOLS_ONLY)
105     if(HOST_BINARY_DIR)
106         unset(HOST_BINARY_DIR CACHE)
107     endif()
108     add_subdirectory(${CMAKE_SOURCE_DIR}/src)
109     return()
110 endif()
112 if(APPLE)
113         # Avoid searching for headers in Frameworks, and libraries in LIBDIR.
114         set(CMAKE_FIND_FRAMEWORK LAST)
115 endif()
117 # Prefer -pthread over -lpthread, which is often the better option of the two.
118 set(CMAKE_THREAD_PREFER_PTHREAD YES)
119 # Make sure we have Threads available.
120 find_package(Threads REQUIRED)
122 find_package(ZLIB)
123 find_package(LibLZMA)
124 find_package(LZO)
125 find_package(PNG)
127 if(NOT OPTION_DEDICATED)
128     if(NOT WIN32)
129         find_package(Allegro)
130         if(NOT APPLE)
131             find_package(Freetype)
132             find_package(SDL2)
133             if(NOT SDL2_FOUND)
134                 find_package(SDL)
135             endif()
136             find_package(Fluidsynth)
137             find_package(Fontconfig)
138             find_package(ICU OPTIONAL_COMPONENTS i18n lx)
139         endif()
140     endif()
141 endif()
142 if(APPLE)
143     find_package(Iconv)
145     find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
146     find_library(AUDIOUNIT_LIBRARY AudioUnit)
147     find_library(COCOA_LIBRARY Cocoa)
148     find_library(QUARTZCORE_LIBRARY QuartzCore)
149 endif()
151 if(NOT EMSCRIPTEN AND NOT OPTION_DEDICATED)
152     find_package(OpenGL COMPONENTS OpenGL)
153 endif()
155 if(MSVC)
156     find_package(Editbin REQUIRED)
157 endif()
159 find_package(SSE)
160 find_package(Xaudio2)
162 find_package(Grfcodec)
164 include(CheckIPOSupported)
165 check_ipo_supported(RESULT IPO_FOUND)
167 show_options()
169 if(UNIX AND NOT APPLE AND NOT OPTION_DEDICATED)
170     if(NOT SDL_FOUND AND NOT SDL2_FOUND AND NOT ALLEGRO_FOUND)
171         message(FATAL_ERROR "SDL, SDL2 or Allegro is required for this platform")
172     endif()
173 endif()
174 if(APPLE)
175     if(NOT AUDIOTOOLBOX_LIBRARY)
176         message(FATAL_ERROR "AudioToolbox is required for this platform")
177     endif()
178     if(NOT AUDIOUNIT_LIBRARY)
179         message(FATAL_ERROR "AudioUnit is required for this platform")
180     endif()
181     if(NOT COCOA_LIBRARY)
182         message(FATAL_ERROR "Cocoa is required for this platform")
183     endif()
184     if(NOT QUARTZCORE_LIBRARY)
185         message(FATAL_ERROR "QuartzCore is required for this platform")
186     endif()
187 endif()
189 if(OPTION_PACKAGE_DEPENDENCIES)
190     if(NOT UNIX)
191         message(FATAL_ERROR "Can only package dependencies on Linux")
192     endif()
193     if(OPTION_INSTALL_FHS)
194         message(FATAL_ERROR "Cannot install in FHS folders when we are packaging dependencies")
195     endif()
196     if(${CMAKE_VERSION} VERSION_LESS "3.16.0")
197         message(FATAL_ERROR "OPTION_PACKAGE_DEPENDENCIES can only work with CMake 3.16+; you are using ${CMAKE_VERSION}")
198     endif()
200     # If we are packaging dependencies, we do two things:
201     # 1) set the RPATH to include $ORIGIN/lib; $ORIGIN (that literal string)
202     #    is a Linux indicator for "path where application is". In CMake, we
203     #    have to do this before add_executable() is executed.
204     # 2) copy the libraries that we compile against to the "lib" folder.
205     #    This is done in InstallAndPackage.cmake.
206     set(CMAKE_INSTALL_RPATH "\$ORIGIN/lib")
207     set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
208 endif()
210 include(SourceList)
212 # Needed by rev.cpp
213 include_directories(${CMAKE_SOURCE_DIR}/src)
214 # Needed by everything that uses Squirrel
215 include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/squirrel/include)
217 include(MSVCFilters)
219 add_executable(openttd WIN32 ${GENERATED_SOURCE_FILES})
220 set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}")
221 # All other files are added via target_sources()
223 if(MSVC)
224     # Add DPI manifest to project; other WIN32 targets get this via ottdres.rc
225     target_sources(openttd PRIVATE "${CMAKE_SOURCE_DIR}/os/windows/openttd.manifest")
226 endif()
228 add_subdirectory(${CMAKE_SOURCE_DIR}/bin)
229 add_subdirectory(${CMAKE_SOURCE_DIR}/src)
230 add_subdirectory(${CMAKE_SOURCE_DIR}/media)
232 add_dependencies(openttd
233     find_version)
235 target_link_libraries(openttd
236     openttd::languages
237     openttd::settings
238     openttd::media
239     openttd::basesets
240     openttd::script_api
241     Threads::Threads
244 if(HAIKU)
245     target_link_libraries(openttd "be" "network" "midi")
246 endif()
248 if(IPO_FOUND)
249     set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE True)
250     set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL True)
251     set_target_properties(openttd PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO True)
252 endif()
253 set_target_properties(openttd PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
254 process_compile_flags()
256 include(LinkPackage)
257 link_package(PNG TARGET PNG::PNG ENCOURAGED)
258 link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED)
259 link_package(LIBLZMA TARGET LibLZMA::LibLZMA ENCOURAGED)
260 link_package(LZO)
262 if(NOT OPTION_DEDICATED)
263     link_package(Fluidsynth)
264     link_package(SDL)
265     link_package(SDL2 TARGET SDL2::SDL2)
266     link_package(Allegro)
267     link_package(FREETYPE TARGET Freetype::Freetype)
268     link_package(Fontconfig TARGET Fontconfig::Fontconfig)
269     link_package(ICU_lx)
270     link_package(ICU_i18n)
272     if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
273         # SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when
274         # on Linux. For Windows, we need to link to OpenGL as we also have a win32
275         # driver using it.
276         add_definitions(-DWITH_OPENGL)
277         message(STATUS "OpenGL found -- -DWITH_OPENGL -- (via SDL2)")
278     else()
279         link_package(OpenGL TARGET OpenGL::GL)
280     endif()
281 endif()
283 if(APPLE)
284     link_package(Iconv TARGET Iconv::Iconv)
286     target_link_libraries(openttd
287         ${AUDIOTOOLBOX_LIBRARY}
288         ${AUDIOUNIT_LIBRARY}
289         ${COCOA_LIBRARY}
290         ${QUARTZCORE_LIBRARY}
291     )
293     add_definitions(
294         -DWITH_COCOA
295     )
296 endif()
298 if(EMSCRIPTEN)
299     add_library(WASM::WASM INTERFACE IMPORTED)
301     # Allow heap-growth, and start with a bigger memory size.
302     target_link_libraries(WASM::WASM INTERFACE "-s ALLOW_MEMORY_GROWTH=1")
303     target_link_libraries(WASM::WASM INTERFACE "-s INITIAL_MEMORY=33554432")
304     target_link_libraries(WASM::WASM INTERFACE "-s DISABLE_EXCEPTION_CATCHING=0")
305     add_definitions(-s DISABLE_EXCEPTION_CATCHING=0)
307     # Export functions to Javascript.
308     target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
310     # Preload all the files we generate during build.
311     # As we do not compile with FreeType / FontConfig, we also have no way to
312     # render several languages (like Chinese, ..), so where do you draw the
313     # line what languages to include and which not? In the end, especially as
314     # the more languages you add the slower downloading becomes, we decided to
315     # only ship the English language.
316     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/baseset@/baseset")
317     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/lang/english.lng@/lang/english.lng")
318     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/ai@/ai")
319     target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/game@/game")
321     # We use IDBFS for persistent storage.
322     target_link_libraries(WASM::WASM INTERFACE "-lidbfs.js")
324     # Use custom pre-js and shell.html.
325     target_link_libraries(WASM::WASM INTERFACE "--pre-js ${CMAKE_SOURCE_DIR}/os/emscripten/pre.js")
326     target_link_libraries(WASM::WASM INTERFACE "--shell-file ${CMAKE_SOURCE_DIR}/os/emscripten/shell.html")
328     # Build the .html (which builds the .js, .wasm, and .data too).
329     set_target_properties(openttd PROPERTIES SUFFIX ".html")
330     target_link_libraries(openttd WASM::WASM)
331 endif()
333 if(NOT PERSONAL_DIR STREQUAL "(not set)")
334     add_definitions(
335         -DWITH_PERSONAL_DIR
336         -DPERSONAL_DIR="${PERSONAL_DIR}"
337     )
338 endif()
340 if(NOT SHARED_DIR STREQUAL "(not set)")
341     add_definitions(
342         -DWITH_SHARED_DIR
343         -DSHARED_DIR="${SHARED_DIR}"
344     )
345 endif()
347 if(NOT GLOBAL_DIR STREQUAL "(not set)")
348     add_definitions(
349         -DGLOBAL_DATA_DIR="${GLOBAL_DIR}"
350     )
351 endif()
353 link_package(SSE)
355 add_definitions_based_on_options()
357 if(WIN32)
358     add_definitions(
359         -DUNICODE
360         -D_UNICODE
361         -DWITH_UNISCRIBE
362         -DPSAPI_VERSION=1
363     )
365     target_link_libraries(openttd
366         ws2_32
367         winmm
368         imm32
369         usp10
370         psapi
371     )
372 endif()
374 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
375     add_definitions(-DPOINTER_IS_64BIT)
376 endif()
378 include(CreateRegression)
379 create_regression()
381 if(APPLE OR WIN32)
382     find_package(Pandoc)
383 endif()
385 include(InstallAndPackage)