diff options
Diffstat (limited to 'cmake')
| -rwxr-xr-x | cmake/glob-symlinks.py | 65 | ||||
| -rw-r--r-- | cmake/nestedvm-toolchain.cmake | 10 | ||||
| -rw-r--r-- | cmake/platforms/emscripten.cmake | 47 | ||||
| -rw-r--r-- | cmake/platforms/nestedvm.cmake | 60 | ||||
| -rw-r--r-- | cmake/platforms/osx.cmake | 58 | ||||
| -rw-r--r-- | cmake/platforms/unix.cmake | 68 | ||||
| -rw-r--r-- | cmake/platforms/windows.cmake | 40 | ||||
| -rw-r--r-- | cmake/setup.cmake | 133 | ||||
| -rw-r--r-- | cmake/testbuild.c | 23 | ||||
| -rw-r--r-- | cmake/windows-dummy-toolchain.cmake | 14 |
10 files changed, 518 insertions, 0 deletions
diff --git a/cmake/glob-symlinks.py b/cmake/glob-symlinks.py new file mode 100755 index 0000000..23a869c --- /dev/null +++ b/cmake/glob-symlinks.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +# Helper script used by the NestedVM cmake build script. +# +# Usage: glob-symlinks.py <srcdir> <wildcard> [<srcdir> <wildcard> ...] +# +# Each pair of command-line arguments is treated as a source +# directory, followed by either a single filename or a wildcard. +# +# The result is to create symlinks in the program's working directory +# mirroring all the files matched by the filenames/wildcards, each +# pointing at the appropriate source directory. +# +# For example, this command +# glob-symlinks.py /foo \*.txt /bar wibble.blah +# might create symlinks as follows: +# this.txt -> /foo/this.txt +# that.txt -> /foo/that.txt +# wibble.blah -> /bar/wibble.blah +# +# CMake could mostly do this itself, except that some of the files +# that need symlinking during the NestedVM build (to make a tree that +# we archive up into a .jar file) are Java class files with some +# '$suffix' in the name, and CMake doesn't escape the $ signs, so that +# the suffix vanishes during shell expansion. + +import sys +import os +import glob + +def get_arg_pairs(): + args = iter(sys.argv) + next(args) # skip program name + while True: + try: + yield next(args), next(args) + except StopIteration: + break + +def get_globbed_pairs(): + for srcdir, pattern in get_arg_pairs(): + if glob.escape(pattern) == pattern: + # Assume that unglobbed filenames exist + #print("non-glob:", srcdir, pattern) + yield srcdir, pattern + else: + #print("globbing:", srcdir, pattern) + prefix = srcdir + "/" + for filename in glob.iglob(prefix + pattern): + assert filename.startswith(prefix) + filename = filename[len(prefix):] + #print(" ->", srcdir, filename) + yield srcdir, filename + +for srcdir, filename in get_globbed_pairs(): + dirname = os.path.dirname(filename) + if len(dirname) > 0: + try: + os.makedirs(dirname) + except FileExistsError: + pass + try: + os.symlink(os.path.join(srcdir, filename), filename) + except FileExistsError: + pass diff --git a/cmake/nestedvm-toolchain.cmake b/cmake/nestedvm-toolchain.cmake new file mode 100644 index 0000000..337410c --- /dev/null +++ b/cmake/nestedvm-toolchain.cmake @@ -0,0 +1,10 @@ +SET(CMAKE_SYSTEM_NAME NestedVM) +SET(CMAKE_SYSTEM_PROCESSOR mips) + +SET(CMAKE_C_COMPILER ${NESTEDVM}/upstream/install/bin/mips-unknown-elf-gcc) + +SET(CMAKE_FIND_ROOT_PATH ${NESTEDVM}/upstream/install) +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/cmake/platforms/emscripten.cmake b/cmake/platforms/emscripten.cmake new file mode 100644 index 0000000..d6b5cd2 --- /dev/null +++ b/cmake/platforms/emscripten.cmake @@ -0,0 +1,47 @@ +set(platform_common_sources emcc.c) +set(platform_gui_libs) +set(platform_libs) +set(CMAKE_EXECUTABLE_SUFFIX ".js") + +set(emcc_export_list + # Event handlers for mouse and keyboard input + _mouseup + _mousedown + _mousemove + _key + # Callback when the program activates timing + _timer_callback + # Callback from button presses in the UI outside the canvas + _command + # Game-saving and game-loading functions + _get_save_file + _free_save_file + _load_game + # Callbacks to return values from dialog boxes + _dlg_return_sval + _dlg_return_ival + # Callbacks when the resizing controls are used + _resize_puzzle + _restore_puzzle_size + # Main program, run at initialisation time + _main) + +list(TRANSFORM emcc_export_list PREPEND \") +list(TRANSFORM emcc_export_list APPEND \") +string(JOIN "," emcc_export_string ${emcc_export_list}) +set(CMAKE_C_LINK_FLAGS "-s ASM_JS=1 -s EXPORTED_FUNCTIONS='[${emcc_export_string}]'") +message("link=${CMAKE_C_LINK_EXECUTABLE}") + +set(build_cli_programs FALSE) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + em_link_pre_js(${TARGET} ${CMAKE_SOURCE_DIR}/emccpre.js) + em_link_js_library(${TARGET} ${CMAKE_SOURCE_DIR}/emcclib.js) +endfunction() + +function(build_platform_extras) +endfunction() diff --git a/cmake/platforms/nestedvm.cmake b/cmake/platforms/nestedvm.cmake new file mode 100644 index 0000000..e5de2ee --- /dev/null +++ b/cmake/platforms/nestedvm.cmake @@ -0,0 +1,60 @@ +set(platform_common_sources nestedvm.c printing.c) +set(platform_libs -lm) + +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/applet.manifest + "Main-Class: PuzzleApplet\n") + +include(FindJava) +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/PuzzleApplet.class + COMMAND ${Java_JAVAC_EXECUTABLE} + -source 1.7 -target 1.7 -d . -cp ${NESTEDVM}/build + ${CMAKE_SOURCE_DIR}/PuzzleApplet.java + DEPENDS ${CMAKE_SOURCE_DIR}/PuzzleApplet.java) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + set(build_subdir ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}-tmp) + + add_custom_command(OUTPUT ${build_subdir} + COMMAND ${CMAKE_COMMAND} -E make_directory ${build_subdir}) + add_custom_command(OUTPUT ${build_subdir}/PuzzleApplet.class + COMMAND ${CMAKE_SOURCE_DIR}/cmake/glob-symlinks.py + ${CMAKE_BINARY_DIR} applet.manifest + ${CMAKE_BINARY_DIR} PuzzleApplet\\*.class + ${NESTEDVM}/build org/ibex/nestedvm/Registers.class + ${NESTEDVM}/build org/ibex/nestedvm/UsermodeConstants.class + ${NESTEDVM}/build org/ibex/nestedvm/Runtime*.class + ${NESTEDVM}/build org/ibex/nestedvm/util/Platform\\*.class + ${NESTEDVM}/build org/ibex/nestedvm/util/Seekable\\*.class + WORKING_DIRECTORY ${build_subdir} + DEPENDS + ${build_subdir} + ${CMAKE_BINARY_DIR}/PuzzleApplet.class + ${CMAKE_SOURCE_DIR}/cmake/glob-symlinks.py) + + add_custom_command(OUTPUT ${build_subdir}/PuzzleEngine.class + COMMAND ${Java_JAVA_EXECUTABLE} + -cp ${NESTEDVM}/build:${NESTEDVM}/upstream/build/classgen/build + org.ibex.nestedvm.Compiler -outformat class -d . + PuzzleEngine ${CMAKE_CURRENT_BINARY_DIR}/${EXENAME} + DEPENDS + ${build_subdir} + ${CMAKE_CURRENT_BINARY_DIR}/${EXENAME} + WORKING_DIRECTORY ${build_subdir}) + + add_custom_target(${TARGET}-jar ALL + COMMAND ${Java_JAR_EXECUTABLE} + cfm ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.jar + applet.manifest PuzzleEngine.class PuzzleApplet*.class org + WORKING_DIRECTORY ${build_subdir} + DEPENDS + ${CMAKE_BINARY_DIR}/PuzzleApplet.class + ${build_subdir}/PuzzleApplet.class + ${build_subdir}/PuzzleEngine.class) +endfunction() + +function(build_platform_extras) +endfunction() diff --git a/cmake/platforms/osx.cmake b/cmake/platforms/osx.cmake new file mode 100644 index 0000000..4577a73 --- /dev/null +++ b/cmake/platforms/osx.cmake @@ -0,0 +1,58 @@ +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) +find_program(HALIBUT halibut REQUIRED) +set(CPACK_GENERATOR DragNDrop) +set(CPACK_PACKAGE_FILE_NAME Puzzles) +set(CPACK_DMG_VOLUME_NAME "Simon Tatham's Puzzle Collection") +include(CPack) +set(build_individual_puzzles FALSE) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) +endfunction() + +function(build_platform_extras) + write_generated_games_header() + + set(resources + ${CMAKE_CURRENT_SOURCE_DIR}/osx/Puzzles.icns) + set_source_files_properties(${resources} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + + add_executable(puzzles MACOSX_BUNDLE + osx.m list.c ${puzzle_sources} + ${resources}) + + set_target_properties(puzzles PROPERTIES + OUTPUT_NAME Puzzles + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/osx/Info.plist) + + target_compile_definitions(puzzles PRIVATE COMBINED) + target_include_directories(puzzles PRIVATE ${generated_include_dir}) + target_link_libraries(puzzles common ${platform_gui_libs} ${platform_libs} + "-framework Cocoa") + + get_property(bundle_basename TARGET puzzles PROPERTY OUTPUT_NAME) + set(help_dir ${CMAKE_CURRENT_BINARY_DIR}/${bundle_basename}.app/Contents/Resources/Help) + message(${help_dir}) + add_custom_command(OUTPUT ${help_dir} + COMMAND ${CMAKE_COMMAND} -E make_directory ${help_dir} + DEPENDS puzzles) + add_custom_command(OUTPUT ${help_dir}/index.html + COMMAND ${HALIBUT} --html + ${CMAKE_CURRENT_SOURCE_DIR}/osx-help.but + ${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but + DEPENDS + ${help_dir} + ${CMAKE_CURRENT_SOURCE_DIR}/osx-help.but + ${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but + WORKING_DIRECTORY ${help_dir}) + add_custom_target(osx_help ALL + DEPENDS ${help_dir}/index.html) + + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Puzzles.app + USE_SOURCE_PERMISSIONS + DESTINATION .) +endfunction() diff --git a/cmake/platforms/unix.cmake b/cmake/platforms/unix.cmake new file mode 100644 index 0000000..1bed675 --- /dev/null +++ b/cmake/platforms/unix.cmake @@ -0,0 +1,68 @@ +find_package(PkgConfig REQUIRED) + +set(PUZZLES_GTK_FOUND FALSE) +macro(try_gtk_package VER PACKAGENAME) + if(NOT PUZZLES_GTK_FOUND AND + (NOT DEFINED PUZZLES_GTK_VERSION OR + PUZZLES_GTK_VERSION STREQUAL ${VER})) + pkg_check_modules(GTK ${PACKAGENAME}) + if(GTK_FOUND) + set(PUZZLES_GTK_FOUND TRUE) + endif() + endif() +endmacro() + +try_gtk_package(3 gtk+-3.0) +try_gtk_package(2 gtk+-2.0) + +if(NOT PUZZLES_GTK_FOUND) + message(FATAL_ERROR "Unable to find any usable version of GTK.") +endif() + +include_directories(${GTK_INCLUDE_DIRS}) +link_directories(${GTK_LIBRARY_DIRS}) + +set(platform_common_sources gtk.c printing.c) +set(platform_gui_libs ${GTK_LIBRARIES}) + +set(platform_libs -lm) + +set(build_icons TRUE) + +function(try_append_cflag flag) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}") + try_compile(compile_passed ${CMAKE_BINARY_DIR} + SOURCES ${CMAKE_SOURCE_DIR}/cmake/testbuild.c + OUTPUT_VARIABLE test_compile_output + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${GTK_INCLUDE_DIRS}") + if(compile_passed) + set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} PARENT_SCOPE) + endif() +endfunction() +if (CMAKE_C_COMPILER_ID MATCHES "GNU" OR + CMAKE_C_COMPILER_ID MATCHES "Clang") + try_append_cflag(-Wall) + try_append_cflag(-Werror) + try_append_cflag(-std=c89) + try_append_cflag(-pedantic) + try_append_cflag(-Wwrite-strings) +endif() + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + if(build_icons AND EXISTS ${CMAKE_SOURCE_DIR}/icons/${NAME}.sav) + build_icon(${NAME}) + set(c_icon_file ${CMAKE_BINARY_DIR}/icons/${NAME}-icon.c) + else() + set(c_icon_file ${CMAKE_SOURCE_DIR}/no-icon.c) + endif() + + set(${OUTVAR} ${c_icon_file} PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + install(TARGETS ${TARGET}) +endfunction() + +function(build_platform_extras) +endfunction() diff --git a/cmake/platforms/windows.cmake b/cmake/platforms/windows.cmake new file mode 100644 index 0000000..dd27148 --- /dev/null +++ b/cmake/platforms/windows.cmake @@ -0,0 +1,40 @@ +set(platform_common_sources windows.c printing.c) + +set(platform_gui_libs + user32.lib gdi32.lib comctl32.lib comdlg32.lib winspool.lib) + +set(platform_libs) + +add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + +function(get_platform_puzzle_extra_source_files OUTVAR NAME) + set(${OUTVAR} ${CMAKE_SOURCE_DIR}/puzzles.rc PARENT_SCOPE) +endfunction() + +function(set_platform_puzzle_target_properties NAME TARGET) + if(DEFINED ICO_DIR AND EXISTS ${ICO_DIR}/${NAME}.ico) + target_compile_definitions(${TARGET} PRIVATE ICON_FILE=\"${ICO_DIR}/${NAME}.ico\") + endif() + set_target_properties(${TARGET} PROPERTIES WIN32_EXECUTABLE ON) +endfunction() + +function(build_platform_extras) + write_generated_games_header() + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/gamedesc.txt "") + list(SORT puzzle_names) + foreach(name ${puzzle_names}) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/gamedesc.txt "\ +${name}:\ +${exename_${name}}.exe:\ +${displayname_${name}}:\ +${description_${name}}:\ +${objective_${name}}\n") + endforeach() + + add_executable(puzzles windows.c list.c ${puzzle_sources}) + target_compile_definitions(puzzles PRIVATE COMBINED) + target_include_directories(puzzles PRIVATE ${generated_include_dir}) + target_link_libraries(puzzles common ${platform_gui_libs} ${platform_libs}) + set_target_properties(puzzles PROPERTIES WIN32_EXECUTABLE ON) +endfunction() diff --git a/cmake/setup.cmake b/cmake/setup.cmake new file mode 100644 index 0000000..8afa455 --- /dev/null +++ b/cmake/setup.cmake @@ -0,0 +1,133 @@ +set(build_individual_puzzles TRUE) +set(build_cli_programs TRUE) +set(build_icons FALSE) +set(need_c_icons FALSE) + +# 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(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_platform_puzzle_target_properties(${NAME} ${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() + +# 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) + + file(MAKE_DIRECTORY ${generated_include_dir}) + file(WRITE ${generated_include_dir}/generated-games.h "") + list(SORT puzzle_names) + foreach(name ${puzzle_names}) + file(APPEND ${generated_include_dir}/generated-games.h "GAME(${name})\n") + endforeach() +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() diff --git a/cmake/testbuild.c b/cmake/testbuild.c new file mode 100644 index 0000000..67a6879 --- /dev/null +++ b/cmake/testbuild.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <time.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <math.h> + +#include <sys/time.h> +#include <sys/resource.h> + +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> + +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include <gdk/gdkx.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +int dummy; diff --git a/cmake/windows-dummy-toolchain.cmake b/cmake/windows-dummy-toolchain.cmake new file mode 100644 index 0000000..493652b --- /dev/null +++ b/cmake/windows-dummy-toolchain.cmake @@ -0,0 +1,14 @@ +# Fake CMake toolchain file, good enough to make cmake's initial +# configuration think it's going to build for Windows, but not good +# enough to actually do any building. The purpose is so that I can run +# Puzzles's CMakeLists.txt in Windows mode as far as making +# gamedesc.txt. + +set(CMAKE_SYSTEM_NAME Windows) + +set(CMAKE_C_COMPILER /bin/false) +set(CMAKE_LINKER /bin/false) +set(CMAKE_MT /bin/false) +set(CMAKE_RC_COMPILER /bin/false) + +set(CMAKE_C_COMPILER_WORKS ON) |