Spaces:
Running
Running
| set(PUZZLES_ENABLE_UNFINISHED "" | |
| CACHE STRING "List of puzzles in the 'unfinished' subdirectory \ | |
| to build as if official (separated by ';')") | |
| set(build_individual_puzzles TRUE) | |
| set(build_cli_programs FALSE) | |
| set(build_gui_programs FALSE) | |
| set(build_icons FALSE) | |
| set(need_c_icons FALSE) | |
| # Don't disable assertions, even in release mode. Our assertions | |
| # generally aren't expensive and protect against more annoying crashes | |
| # and memory corruption. | |
| string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") | |
| string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") | |
| string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") | |
| string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") | |
| string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") | |
| string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") | |
| # Include one of platforms/*.cmake to define platform-specific stuff. | |
| # Each of these is expected to: | |
| # - define get_platform_puzzle_extra_source_files(), used below | |
| # - define set_platform_puzzle_target_properties(), used below | |
| # - define build_platform_extras(), called from the top-level CMakeLists.txt | |
| # - override the above build_* settings, if necessary | |
| if(CMAKE_SYSTEM_NAME MATCHES "Windows") | |
| include(cmake/platforms/windows.cmake) | |
| elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") | |
| include(cmake/platforms/osx.cmake) | |
| elseif(CMAKE_SYSTEM_NAME MATCHES "NestedVM") | |
| include(cmake/platforms/nestedvm.cmake) | |
| elseif(CMAKE_C_COMPILER MATCHES "emcc") | |
| include(cmake/platforms/emscripten.cmake) | |
| else() # assume Unix | |
| include(cmake/platforms/unix.cmake) | |
| endif() | |
| # Accumulate lists of the puzzles' bare names and source file | |
| # locations, for use in build_platform_extras() implementations when | |
| # they want to build things based on all the puzzles at once. | |
| set(puzzle_names) | |
| set(puzzle_sources) | |
| include(CheckIncludeFile) | |
| check_include_file(stdint.h HAVE_STDINT_H) | |
| if(NOT HAVE_STDINT_H) | |
| add_compile_definitions(NO_STDINT_H) | |
| endif() | |
| # Try to normalise source file pathnames as seen in __FILE__ (e.g. | |
| # assertion failure messages). Partly to avoid bloating the binaries | |
| # with file prefixes like /home/simon/stuff/things/tmp-7x6c5d54/, but | |
| # also to make the builds more deterministic - building from the same | |
| # source should give the same binary even if you do it in a | |
| # differently named temp directory. | |
| function(map_pathname src dst) | |
| if(CMAKE_SYSTEM_NAME MATCHES "NestedVM") | |
| # Do nothing: the NestedVM gcc is unfortunately too old to support | |
| # this option. | |
| elseif(CMAKE_C_COMPILER_ID MATCHES "Clang" AND | |
| CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "MSVC") | |
| # -fmacro-prefix-map isn't available as a clang-cl option, so we | |
| # prefix it with -Xclang to pass it straight through to the | |
| # underlying clang -cc1 invocation, which spells the option the | |
| # same way. | |
| set(CMAKE_C_FLAGS | |
| "${CMAKE_C_FLAGS} -Xclang -fmacro-prefix-map=${src}=${dst}" | |
| PARENT_SCOPE) | |
| elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR | |
| CMAKE_C_COMPILER_ID MATCHES "Clang") | |
| set(CMAKE_C_FLAGS | |
| "${CMAKE_C_FLAGS} -fmacro-prefix-map=${src}=${dst}" | |
| PARENT_SCOPE) | |
| endif() | |
| endfunction() | |
| map_pathname(${CMAKE_SOURCE_DIR} /puzzles) | |
| map_pathname(${CMAKE_BINARY_DIR} /build) | |
| include(icons/icons.cmake) | |
| # The main function called from the top-level CMakeLists.txt to define | |
| # each puzzle. | |
| function(puzzle NAME) | |
| cmake_parse_arguments(OPT | |
| "" "DISPLAYNAME;DESCRIPTION;OBJECTIVE;WINDOWS_EXE_NAME" "" ${ARGN}) | |
| if(NOT DEFINED OPT_WINDOWS_EXE_NAME) | |
| set(OPT_WINDOWS_EXE_NAME ${NAME}) | |
| endif() | |
| if (CMAKE_SYSTEM_NAME MATCHES "Windows") | |
| set(EXENAME ${OPT_WINDOWS_EXE_NAME}) | |
| else() | |
| set(EXENAME ${NAME}) | |
| endif() | |
| set(exename_${NAME} ${EXENAME} PARENT_SCOPE) | |
| set(displayname_${NAME} ${OPT_DISPLAYNAME} PARENT_SCOPE) | |
| set(description_${NAME} ${OPT_DESCRIPTION} PARENT_SCOPE) | |
| set(objective_${NAME} ${OPT_OBJECTIVE} PARENT_SCOPE) | |
| set(official TRUE) | |
| if(NAME STREQUAL nullgame) | |
| # nullgame is not a playable puzzle; it has to be built (to prove | |
| # it still can build), but not installed, or included in the main | |
| # list of puzzles, or compiled into all-in-one binaries, etc. In | |
| # other words, it's not "officially" part of the puzzle | |
| # collection. | |
| set(official FALSE) | |
| endif() | |
| if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR}/unfinished) | |
| # The same goes for puzzles in the 'unfinished' subdirectory, | |
| # although we make an exception if configured to on the command | |
| # line. | |
| list(FIND PUZZLES_ENABLE_UNFINISHED ${NAME} enable_this_one) | |
| if(enable_this_one EQUAL -1) | |
| set(official FALSE) | |
| endif() | |
| endif() | |
| if (official) | |
| set(puzzle_names ${puzzle_names} ${NAME} PARENT_SCOPE) | |
| set(puzzle_sources ${puzzle_sources} ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.c PARENT_SCOPE) | |
| endif() | |
| get_platform_puzzle_extra_source_files(extra_files ${NAME}) | |
| if (build_individual_puzzles) | |
| add_executable(${EXENAME} ${NAME}.c ${extra_files}) | |
| target_link_libraries(${EXENAME} | |
| common ${platform_gui_libs} ${platform_libs}) | |
| set_property(TARGET ${EXENAME} PROPERTY exename ${EXENAME}) | |
| set_property(TARGET ${EXENAME} PROPERTY displayname ${OPT_DISPLAYNAME}) | |
| set_property(TARGET ${EXENAME} PROPERTY description ${OPT_DESCRIPTION}) | |
| set_property(TARGET ${EXENAME} PROPERTY objective ${OPT_OBJECTIVE}) | |
| set_property(TARGET ${EXENAME} PROPERTY official ${official}) | |
| set_platform_puzzle_target_properties(${NAME} ${EXENAME}) | |
| set_platform_gui_target_properties(${EXENAME}) | |
| endif() | |
| endfunction() | |
| # The main function called from the top-level CMakeLists.txt to define | |
| # a command-line helper tool. | |
| function(cliprogram NAME) | |
| cmake_parse_arguments(OPT | |
| "" "" "COMPILE_DEFINITIONS" ${ARGN}) | |
| if(build_cli_programs) | |
| add_executable(${NAME} ${CMAKE_SOURCE_DIR}/nullfe.c | |
| ${OPT_UNPARSED_ARGUMENTS}) | |
| target_link_libraries(${NAME} common ${platform_libs}) | |
| if(OPT_COMPILE_DEFINITIONS) | |
| target_compile_definitions(${NAME} PRIVATE ${OPT_COMPILE_DEFINITIONS}) | |
| endif() | |
| endif() | |
| endfunction() | |
| # Similar to cliprogram, but builds a GUI helper tool, linked against | |
| # the normal puzzle frontend. | |
| function(guiprogram NAME) | |
| cmake_parse_arguments(OPT | |
| "" "" "COMPILE_DEFINITIONS" ${ARGN}) | |
| if(build_gui_programs) | |
| get_platform_puzzle_extra_source_files(extra_files ${NAME}) | |
| add_executable(${NAME} ${OPT_UNPARSED_ARGUMENTS} ${extra_files}) | |
| target_link_libraries(${NAME} | |
| common ${platform_gui_libs} ${platform_libs}) | |
| if(OPT_COMPILE_DEFINITIONS) | |
| target_compile_definitions(${NAME} PRIVATE ${OPT_COMPILE_DEFINITIONS}) | |
| endif() | |
| set_platform_gui_target_properties(${NAME}) | |
| endif() | |
| endfunction() | |
| # A small wrapper around cliprogram, taking advantage of the common | |
| # formula that puzzle 'foo' often comes with 'foosolver'. | |
| function(solver NAME) | |
| cliprogram(${NAME}solver ${puzzle_src_prefix}${NAME}.c ${ARGN} | |
| COMPILE_DEFINITIONS STANDALONE_SOLVER) | |
| endfunction() | |
| function(write_generated_games_header) | |
| set(generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/include) | |
| set(generated_include_dir ${generated_include_dir} PARENT_SCOPE) | |
| set(header_pre ${generated_include_dir}/generated-games.h.pre) | |
| set(header ${generated_include_dir}/generated-games.h) | |
| file(MAKE_DIRECTORY ${generated_include_dir}) | |
| file(WRITE ${header_pre} "") | |
| list(SORT puzzle_names) | |
| foreach(name ${puzzle_names}) | |
| file(APPEND ${header_pre} "GAME(${name})\n") | |
| endforeach() | |
| configure_file(${header_pre} ${header} COPYONLY) | |
| endfunction() | |
| # This has to be run from the unfinished subdirectory, so that the | |
| # updates to puzzle_names etc will be propagated to the top-level scope. | |
| macro(export_variables_to_parent_scope) | |
| set(puzzle_names ${puzzle_names} PARENT_SCOPE) | |
| set(puzzle_sources ${puzzle_sources} PARENT_SCOPE) | |
| foreach(name ${puzzle_names}) | |
| set(exename_${name} ${exename_${name}} PARENT_SCOPE) | |
| set(displayname_${name} ${displayname_${name}} PARENT_SCOPE) | |
| set(description_${name} ${description_${name}} PARENT_SCOPE) | |
| set(objective_${name} ${objective_${name}} PARENT_SCOPE) | |
| endforeach() | |
| endmacro() | |
| macro(build_extras) | |
| # Write out a list of the game names, for benchmark.sh to use. | |
| file(WRITE ${CMAKE_BINARY_DIR}/gamelist.txt "") | |
| list(SORT puzzle_names) | |
| foreach(name ${puzzle_names}) | |
| file(APPEND ${CMAKE_BINARY_DIR}/gamelist.txt "${name}\n") | |
| endforeach() | |
| # Further extra stuff specific to particular platforms. | |
| build_platform_extras() | |
| endmacro() | |