changeset 315:3bfaaf5342a9

cmake: add support for Visual Studio 2019
author David Demelier <markand@malikania.fr>
date Wed, 22 Sep 2021 10:04:15 +0200
parents d01e83210ca2
children 1a6125ffebff
files CMakeLists.txt INSTALL.md LICENSE.md cmake/FindJansson.cmake cmake/FindSDL2.cmake cmake/MlkExecutable.cmake cmake/MlkLibrary.cmake config.h.in libmlk-adventure/adventure/dialog/save.c libmlk-adventure/adventure/mapscene/mapscene.c libmlk-core/CMakeLists.txt libmlk-core/core/port.c libmlk-core/core/port.h libmlk-core/core/sys.c libmlk-core/core/util.c libmlk-core/core/zfile.c libmlk-port/CMakeLists.txt libmlk-port/port/port.c libmlk-port/port/port.h libmlk-rpg/rpg/battle.c libmlk-rpg/rpg/map-file.c libmlk-rpg/rpg/tileset-file.c mlk-adventure/CMakeLists.txt tools/bcc/CMakeLists.txt tools/bcc/main.c tools/map/CMakeLists.txt tools/map/main.c tools/tileset/CMakeLists.txt
diffstat 28 files changed, 682 insertions(+), 241 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Wed Sep 22 07:22:20 2021 +0200
+++ b/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -23,8 +23,15 @@
 
 set(CMAKE_C_STANDARD 11)
 set(CMAKE_C_STANDARD_REQUIRED On)
+set(CMAKE_C_EXTENSIONS Off)
 set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
 
+if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
+	set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic ${CMAKE_C_FLAGS}")
+elseif (CMAKE_C_COMPILER_ID MATCHES "MSVC")
+	set(CMAKE_C_FLAGS "/wd4090 /wd5105 /wd6031 /wd6001 /wd26451 ${CMAKE_C_FLAGS}")
+endif ()
+
 option(MLK_WITH_NLS "Enable NLS support" On)
 option(MLK_WITH_ZSTD "Enable zstd compression" On)
 option(MLK_WITH_TESTS "Enable unit tests" On)
@@ -37,10 +44,6 @@
 include(cmake/MlkTileset.cmake)
 
 include(GNUInstallDirs)
-include(CheckFunctionExists)
-
-check_function_exists(strlcpy MLK_HAS_STRLCPY)
-check_function_exists(fmemopen MLK_HAS_FMEMOPEN)
 
 find_package(SDL2 REQUIRED COMPONENTS image mixer ttf)
 find_package(Jansson REQUIRED)
@@ -67,6 +70,7 @@
 add_subdirectory(tools/tileset)
 add_subdirectory(tools/map)
 
+add_subdirectory(libmlk-port)
 add_subdirectory(libmlk-core)
 add_subdirectory(libmlk-ui)
 add_subdirectory(libmlk-rpg)
--- a/INSTALL.md	Wed Sep 22 07:22:20 2021 +0200
+++ b/INSTALL.md	Wed Sep 22 10:04:15 2021 +0200
@@ -6,14 +6,15 @@
 Requirements
 ------------
 
-- C11 compliant compiler,
-- POSIX system (make, ar, shell),
-- [pkg-config][], Helper for libraries.
-- [Jansson][], JSON parsing library,
-- [SDL2][], Multimedia library,
-- [SDL2_image][], Image loading addon for SDL2,
+- C11 compliant compiler.
+- [CMake][], CMake build system.
+- [Jansson][], JSON parsing library.
+- [SDL2][], Multimedia library.
+- [SDL2_image][], Image loading addon for SDL2.
+- [SDL2_mixer][], Audio addon for SDL2.
 - [SDL2_ttf][], Fonts addon for SDL2,
-- [SDL2_mixer][], Audio addon for SDL2.
+- [gettext][], For translations (optional).
+- [zstd][], For compression (optional).
 
 Basic installation
 ------------------
@@ -22,17 +23,20 @@
 
 	$ tar xvzf molko-x.y.z-tar.xz
 	$ cd molko-x.y.z
-	$ make
-	# sudo make install
-	$ molko
-
-Available general make targets:
+	$ cmake -S. -Bbuild
+	$ cmake --build build --target all
+	# cmake --build build --target install
+	$ mlk-adventure
 
-- `all`: (default): build only molko.
-- `tools`: build tools (e.g. molko-map).
-- `tests`: build tests and run them.
-- `everything`: build molko, tools and tests without running them.
-- `run`: run molko with data installed in the source tree.
+Available options
+-----------------
+
+The following options are available:
+
+- `MLK_WITH_NLS`: Enable Native Language Support 
+- `MLK_WITH_ZSTD`: Enable map and tileset compression through [zstd][] (default:
+  on).
+- `MLK_WITH_TESTS`: Enable unit tests (default: on).
 
 Direct use in source tree
 -------------------------
@@ -41,48 +45,52 @@
 directory, when building those are not already discoverable because targets are
 not already installed.
 
-You need to install at least the data once using `install-data` target, you can
+You need to install at least the data once using `install` target, you can
 do this without root access by using a temporary directory and set the
 `MLK_ROOT` environment variable.
 
-The directory `out` is recommended, see below.
-
-	$ make DESTDIR=out install-data
-	$ MLK_ROOT=out ./mlk-adventure/mlk-adventure
-	(or to run examples:)
-	$ MLK_ROOT=out ./examples/example-action/main
-
-There is a special target `run` that automatically create the diretory `out`
-with all data and binaries installed and runs `mlk-adventure`.
-
 Platform: Windows
 -----------------
 
-On Windows, only [MSYS2][] is supported.
+On Windows, [MSYS2][] and Visual Studio are supported.
 
-The code may compile on Microsoft Visual Studio but no support for it is
-provided as it is not opensource and not standard compliant.
+### MSYS2
 
 Once you have MSYS2 installed, simply install the following packages from the
 appropriate MinGW shell prior to the chapter above.
 
 - *make*
-- *mingw-w64-x86_64-pkg-config*
 - *mingw-w64-x86_64-gcc*
 - *mingw-w64-x86_64-SDL2*
 - *mingw-w64-x86_64-SDL2_image*
 - *mingw-w64-x86_64-SDL2_mixer*
 - *mingw-w64-x86_64-SDL2_ttf*
 - *mingw-w64-x86_64-jansson* (only for mlk-map/mlk-tileset tools)
+- *mingw-w64-x86_64-zstd* (only if `MLK_WITH_ZSTD` is set)
 
 Note: replace `x86_64` with `i686` if you have a deprecated system or if you
       have issues while debugging (MinGW-w64 and/or gdb have known issues in
       this area).
 
+### Visual Studio
+
+On Visual Studio you will need to download or build libraries yourself. It is
+recommended to install all of them in a same directory and hierarchy as
+following:
+
+- <dir>/bin
+- <dir>/lib
+- <dir>/include
+
+Then adding `<dir>/bin` to *PATH* and `<dir>` to *CMAKE_PREFIX_PATH* will allow
+CMake to find libraries.
+
+[CMake][]: http://cmake.org
 [Jansson][]: http://www.digip.org/jansson
+[MSYS2]: http://www.msys2.org
 [SDL2]: http://libsdl.org
 [SDL2_image]: https://www.libsdl.org/projects/SDL_image
+[SDL2_mixer]: https://www.libsdl.org/projects/SDL_mixer
 [SDL2_ttf]: https://www.libsdl.org/projects/SDL_ttf
-[SDL2_mixer]: https://www.libsdl.org/projects/SDL_mixer
-[MSYS2]: http://www.msys2.org
-[pkg-config]: http://pkgconf.org
+[gettext]: https://www.gnu.org/software/gettext
+[zstd]: http://facebook.github.io/zstd
--- a/LICENSE.md	Wed Sep 22 07:22:20 2021 +0200
+++ b/LICENSE.md	Wed Sep 22 10:04:15 2021 +0200
@@ -14,3 +14,11 @@
 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Third party code
+----------------
+
+A few other licenses are used with third party code incorporated if the system
+lacks feature.
+
+Those licenses are listed in the libmlk-port/port/port.c file.
--- a/cmake/FindJansson.cmake	Wed Sep 22 07:22:20 2021 +0200
+++ b/cmake/FindJansson.cmake	Wed Sep 22 10:04:15 2021 +0200
@@ -13,7 +13,7 @@
 #
 
 find_path(Jansson_INCLUDE_DIR NAMES jansson.h)
-find_library(Jansson_LIBRARY NAMES libjansson jansson)
+find_library(Jansson_LIBRARY NAMES libjansson jansson jansson_d libjansson_d)
 
 include(FindPackageHandleStandardArgs)
 
--- a/cmake/FindSDL2.cmake	Wed Sep 22 07:22:20 2021 +0200
+++ b/cmake/FindSDL2.cmake	Wed Sep 22 10:04:15 2021 +0200
@@ -34,8 +34,8 @@
 	PATH_SUFFIXES include/SDL2 include
 )
 
-find_library(SDL2_LIBRARY NAMES SDL2 libSDL2)
-find_library(SDL2_MAIN_LIBRARY NAMES SDL2main libSDL2main)
+find_library(SDL2_LIBRARY NAMES SDL2 libSDL2 SDL2d libSDL2d)
+find_library(SDL2_MAIN_LIBRARY NAMES SDL2main libSDL2main SDL2maind libSDL2maind)
 
 # Standard components.
 foreach (c ${SDL2_FIND_COMPONENTS})
--- a/cmake/MlkExecutable.cmake	Wed Sep 22 07:22:20 2021 +0200
+++ b/cmake/MlkExecutable.cmake	Wed Sep 22 10:04:15 2021 +0200
@@ -17,7 +17,7 @@
 #
 
 function(mlk_executable)
-	set(options "")
+	set(options "INSTALL")
 	set(oneValueArgs "NAME;FOLDER")
 	set(multiValueArgs "SOURCES;LIBRARIES;INCLUDES;FLAGS")
 
@@ -40,4 +40,8 @@
 	if (EXE_INCLUDES)
 		target_include_directories(${EXE_NAME} ${EXE_INCLUDES})
 	endif ()
+
+	if (EXE_INSTALL)
+		install(TARGETS ${EXE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
+	endif ()
 endfunction()
--- a/cmake/MlkLibrary.cmake	Wed Sep 22 07:22:20 2021 +0200
+++ b/cmake/MlkLibrary.cmake	Wed Sep 22 10:04:15 2021 +0200
@@ -21,7 +21,7 @@
 
 function(mlk_library)
 	set(options "")
-	set(oneValueArgs "NAME;FOLDER")
+	set(oneValueArgs "NAME;FOLDER;TYPE")
 	set(multiValueArgs "SOURCES;ASSETS;LANGS;LIBRARIES;INCLUDES;FLAGS")
 
 	cmake_parse_arguments(LIB "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -35,7 +35,7 @@
 		source_group(build/assets FILES ${HEADERS})
 	endif ()
 
-	if (LIB_LANGS)
+	if (LIB_LANGS AND MLK_WITH_NLS)
 		mlk_nls(
 			NAME ${LIB_NAME}
 			LANGS ${LIB_LANGS}
@@ -45,7 +45,7 @@
 		source_group(build/nls FILES ${MO})
 	endif ()
 
-	add_library(${LIB_NAME} ${LIB_SOURCES} ${HEADERS} ${MO})
+	add_library(${LIB_NAME} ${LIB_TYPE} ${LIB_SOURCES} ${HEADERS} ${MO})
 
 	if (LIB_FOLDER)
 		set_target_properties(${LIB_NAME} PROPERTIES FOLDER extern)
@@ -63,5 +63,5 @@
 		target_include_directories(${LIB_NAME} ${LIB_INCLUDES})
 	endif ()
 
-    set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
+	set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
 endfunction()
--- a/config.h.in	Wed Sep 22 07:22:20 2021 +0200
+++ b/config.h.in	Wed Sep 22 10:04:15 2021 +0200
@@ -3,6 +3,11 @@
 
 #cmakedefine MLK_HAS_STRLCPY
 #cmakedefine MLK_HAS_FMEMOPEN
+#cmakedefine MLK_HAS_BASENAME
+#cmakedefine MLK_HAS_DIRNAME
+#cmakedefine MLK_HAS_GETOPT
+#cmakedefine MLK_HAS_PATH_MAX
+#cmakedefine MLK_HAS_SSIZE_T
 
 #define MLK_PREFIX      "@CMAKE_INSTALL_PREFIX@"
 #define MLK_BINDIR      "@CMAKE_INSTALL_BINDIR@"
--- a/libmlk-adventure/adventure/dialog/save.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-adventure/adventure/dialog/save.c	Wed Sep 22 10:04:15 2021 +0200
@@ -20,13 +20,14 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <port/port.h>
+
 #include <core/event.h>
 #include <core/font.h>
 #include <core/maths.h>
 #include <core/painter.h>
 #include <core/sprite.h>
 #include <core/window.h>
-#include <core/port.h>
 
 #include <ui/align.h>
 #include <ui/label.h>
--- a/libmlk-adventure/adventure/mapscene/mapscene.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-adventure/adventure/mapscene/mapscene.c	Wed Sep 22 10:04:15 2021 +0200
@@ -94,6 +94,8 @@
 	{ "teleport",   load_teleport   }
 };
 
+#if 0
+
 /* Per map actions, name refer to map names. Must be sorted. */
 static const struct action_loader maploaders[] = {
 };
@@ -102,6 +104,8 @@
 static const struct mapscene_loader mapscenes[] = {
 };
 
+#endif
+
 static int
 cmp_name(const char *key, const struct action_loader *ld)
 {
@@ -126,9 +130,11 @@
 	if ((ld = SEARCH(exec, loaders, sizeof (*ld), cmp_name)))
 		ld->load(m, x, y, w, h, exec + strcspn(exec, "|"));
 
+#if 0
 	/* 2. Load per map objects. */
 	if ((ld = SEARCH(m->title, maploaders, sizeof (*ld), cmp_title)))
 		ld->load(m, x, y, w, h, exec);
+#endif
 }
 
 void
@@ -138,9 +144,11 @@
 
 	struct mapscene_loader *ld;
 
+#if 0
 	/* Same layout, can use cmp_title as well. */
 	if ((ld = SEARCH(m->title, mapscenes, sizeof (*ld), cmp_title)))
 		ld->load(m);
+#endif
 
 	/* Add the trace hud. */
 	action_stack_add(&m->astack_par, trace_hud_action());
--- a/libmlk-core/CMakeLists.txt	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-core/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -55,8 +55,6 @@
 	${libmlk-core_SOURCE_DIR}/core/painter.h
 	${libmlk-core_SOURCE_DIR}/core/panic.c
 	${libmlk-core_SOURCE_DIR}/core/panic.h
-	${libmlk-core_SOURCE_DIR}/core/port.c
-	${libmlk-core_SOURCE_DIR}/core/port.h
 	${libmlk-core_SOURCE_DIR}/core/script.c
 	${libmlk-core_SOURCE_DIR}/core/script.h
 	${libmlk-core_SOURCE_DIR}/core/sound.c
@@ -100,7 +98,7 @@
 	NAME libmlk-core
 	SOURCES ${SOURCES} ${NLS}
 	LANGS ${NLS}
-	LIBRARIES PUBLIC ${LIBRARIES} SDL2::SDL2 SDL2::image SDL2::ttf SDL2::mixer
+	LIBRARIES PUBLIC ${LIBRARIES} SDL2::SDL2 SDL2::image SDL2::ttf SDL2::mixer libmlk-port
 	INCLUDES
 		PUBLIC $<BUILD_INTERFACE:${libmlk-core_SOURCE_DIR}>
 )
--- a/libmlk-core/core/port.c	Wed Sep 22 07:22:20 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * port.c -- portability bits
- *
- * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "port.h"
-
-/* {{{ strlcpy (BSD extension, incoming in next POSIX). */
-
-#if !defined(MLK_HAS_STRLCPY)
-
-/*	$OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $	*/
-
-/*
- * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * Copy string src to buffer dst of size dsize.  At most dsize-1
- * chars will be copied.  Always NUL terminates (unless dsize == 0).
- * Returns strlen(src); if retval >= dsize, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t dsize)
-{
-	const char *osrc = src;
-	size_t nleft = dsize;
-
-	/* Copy as many bytes as will fit. */
-	if (nleft != 0) {
-		while (--nleft != 0) {
-			if ((*dst++ = *src++) == '\0')
-				break;
-		}
-	}
-
-	/* Not enough room in dst, add NUL and traverse rest of src. */
-	if (nleft == 0) {
-		if (dsize != 0)
-			*dst = '\0';		/* NUL-terminate dst */
-		while (*src++)
-			;
-	}
-
-	return (src - osrc - 1);	/* count does not include NUL */
-}
-
-#endif /* !MLK_HAS_STRLCPY */
-
-/* }}} */
-
-/* {{{ fmemopen (POSIX). */
-
-#if !defined(MLK_HAS_FMEMOPEN)
-
-#if defined(_WIN32)
-
-/* https://github.com/Arryboom/fmemopen_windows */
-#include <stdio.h>
-#include <windows.h>
-#include <share.h>
-#include <io.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-FILE *
-fmemopen(void *buf, size_t len, const char *type)
-{
-	int fd;
-	FILE *fp;
-	char tp[MAX_PATH - 13];
-	char fn[MAX_PATH + 1];
-	int * pfd = &fd;
-	int retner = -1;
-	char tfname[] = "MemTF_";
-
-	if (!GetTempPathA(sizeof(tp), tp))
-		return NULL;
-	if (!GetTempFileNameA(tp, tfname, 0, fn))
-		return NULL;
-	retner = _sopen_s(pfd, fn, _O_CREAT | _O_SHORT_LIVED | _O_TEMPORARY | _O_RDWR | _O_BINARY | _O_NOINHERIT, _SH_DENYRW, _S_IREAD | _S_IWRITE);
-	if (retner != 0)
-		return NULL;
-	if (fd == -1)
-		return NULL;
-	fp = _fdopen(fd, "wb+");
-	if (!fp) {
-		_close(fd);
-		return NULL;
-	}
-
-	/*
-	 * File descriptors passed into _fdopen are owned by the returned FILE
-	 * stream.If _fdopen is successful, do not call _close on the file
-	 * descriptor. Calling fclose on the returned FILE * also closes the
-	 * file descriptor.
-	 */
-	fwrite(buf, len, 1, fp);
-	rewind(fp);
-
-	return fp;
-}
-
-#endif /* !_WIN32 */
-
-#endif /* !MLK_HAS_FMEMOPEN */
-
-/* }}} */
--- a/libmlk-core/core/port.h	Wed Sep 22 07:22:20 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * port.h -- portability bits
- *
- * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MOLKO_CORE_PORT_H
-#define MOLKO_CORE_PORT_H
-
-#include "config.h"
-
-/* {{{ strlcpy (BSD extension, incoming in next POSIX). */
-
-#if !defined(MLK_HAS_STRLCPY)
-
-#include <stddef.h>
-
-size_t
-strlcpy(char *, const char *, size_t);
-
-#endif /* !MLK_HAS_STRLCPY */
-
-/* }}} */
-
-/* {{{ fmemopen (POSIX). */
-
-#if !defined(MLK_HAS_FMEMOPEN)
-
-#include <stdio.h>
-
-FILE *
-fmemopen(void *, size_t, const char *);
-
-#endif /* !MLK_HAS_FMEMOPEN */
-
-/* }}} */
-
-#endif /* !MOLKO_CORE_PORT_H */
--- a/libmlk-core/core/sys.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-core/core/sys.c	Wed Sep 22 10:04:15 2021 +0200
@@ -37,8 +37,9 @@
 #include <SDL_mixer.h>
 #include <SDL_ttf.h>
 
+#include <port/port.h>
+
 #include "error.h"
-#include "port.h"
 #include "sound.h"
 #include "sys.h"
 
--- a/libmlk-core/core/util.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-core/core/util.c	Wed Sep 22 10:04:15 2021 +0200
@@ -22,6 +22,8 @@
 
 #include <SDL.h>
 
+#include <port/port.h>
+
 #include "util.h"
 
 void
--- a/libmlk-core/core/zfile.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-core/core/zfile.c	Wed Sep 22 10:04:15 2021 +0200
@@ -42,7 +42,8 @@
 #       define O_BINARY 0
 #endif
 
-#include "port.h"
+#include <port/port.h>
+
 #include "zfile.h"
 
 static int
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-port/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -0,0 +1,61 @@
+#
+# CMakeLists.txt -- CMake build system for Molko's Adventure
+#
+# Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(libmlk-port)
+
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+
+check_function_exists(strlcpy MLK_HAS_STRLCPY)
+check_function_exists(fmemopen MLK_HAS_FMEMOPEN)
+check_function_exists(basename MLK_HAS_BASENAME)
+check_function_exists(dirname MLK_HAS_DIRNAME)
+check_function_exists(getopt MLK_HAS_GETOPT)
+check_include_file(stdnoreturn.h MLK_HAS_STDNORETURN_H)
+check_include_file(libgen.h MLK_HAS_LIBGEN_H)
+check_include_file(unistd.h MLK_HAS_UNISTD_H)
+check_symbol_exists(PATH_MAX limits.h MLK_HAS_PATH_MAX)
+check_type_size(ssize_t MLK_HAS_SSIZE_T)
+
+if (NOT MLK_HAS_STDNORETURN_H)
+	file(WRITE ${CMAKE_BINARY_DIR}/stdnoreturn.h "#define noreturn\n")
+endif ()
+if (NOT MLK_HAS_LIBGEN_H)
+	file(TOUCH ${CMAKE_BINARY_DIR}/libgen.h)
+endif ()
+if (NOT MLK_HAS_UNISTD_H)
+	file(TOUCH ${CMAKE_BINARY_DIR}/unistd.h)
+endif ()
+
+set(
+	SOURCES
+	${libmlk-port_SOURCE_DIR}/port/port.c
+	${libmlk-port_SOURCE_DIR}/port/port.h
+)
+
+mlk_library(
+	NAME libmlk-port
+	SOURCES ${SOURCES}
+	TYPE STATIC
+	INCLUDES
+		PUBLIC $<BUILD_INTERFACE:${libmlk-port_SOURCE_DIR}>
+)
+
+source_group(TREE ${libmlk-port_SOURCE_DIR} FILES ${SOURCES})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-port/port/port.c	Wed Sep 22 10:04:15 2021 +0200
@@ -0,0 +1,414 @@
+/*
+ * port.c -- portability bits
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "port.h"
+
+int
+mlk_port_exists(void)
+{
+	/* ISO C forbids empty source file. */
+	return 1;
+}
+
+/* {{{ strlcpy (BSD extension, incoming in next POSIX). */
+
+#if !defined(MLK_HAS_STRLCPY)
+
+/*	$OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copy string src to buffer dst of size dsize.  At most dsize-1
+ * chars will be copied.  Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t dsize)
+{
+	const char *osrc = src;
+	size_t nleft = dsize;
+
+	/* Copy as many bytes as will fit. */
+	if (nleft != 0) {
+		while (--nleft != 0) {
+			if ((*dst++ = *src++) == '\0')
+				break;
+		}
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src. */
+	if (nleft == 0) {
+		if (dsize != 0)
+			*dst = '\0';		/* NUL-terminate dst */
+		while (*src++)
+			;
+	}
+
+	return (src - osrc - 1);	/* count does not include NUL */
+}
+
+#endif /* !MLK_HAS_STRLCPY */
+
+/* }}} */
+
+/* {{{ fmemopen (POSIX). */
+
+#if !defined(MLK_HAS_FMEMOPEN)
+
+#if defined(_WIN32)
+
+/* https://github.com/Arryboom/fmemopen_windows */
+#include <stdio.h>
+#include <windows.h>
+#include <share.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+FILE *
+fmemopen(void *buf, size_t len, const char *type)
+{
+	int fd;
+	FILE *fp;
+	char tp[MAX_PATH - 13];
+	char fn[MAX_PATH + 1];
+	int * pfd = &fd;
+	int retner = -1;
+	char tfname[] = "MemTF_";
+
+	if (!GetTempPathA(sizeof(tp), tp))
+		return NULL;
+	if (!GetTempFileNameA(tp, tfname, 0, fn))
+		return NULL;
+	retner = _sopen_s(pfd, fn, _O_CREAT | _O_SHORT_LIVED | _O_TEMPORARY | _O_RDWR | _O_BINARY | _O_NOINHERIT, _SH_DENYRW, _S_IREAD | _S_IWRITE);
+	if (retner != 0)
+		return NULL;
+	if (fd == -1)
+		return NULL;
+	fp = _fdopen(fd, "wb+");
+	if (!fp) {
+		_close(fd);
+		return NULL;
+	}
+
+	/*
+	 * File descriptors passed into _fdopen are owned by the returned FILE
+	 * stream.If _fdopen is successful, do not call _close on the file
+	 * descriptor. Calling fclose on the returned FILE * also closes the
+	 * file descriptor.
+	 */
+	fwrite(buf, len, 1, fp);
+	rewind(fp);
+
+	return fp;
+}
+
+#endif /* !_WIN32 */
+
+#endif /* !MLK_HAS_FMEMOPEN */
+
+/* }}} */
+
+/* {{{ basename (POSIX). */
+
+#if !defined(MLK_HAS_BASENAME)
+
+/*	$OpenBSD: basename.c,v 1.17 2020/10/20 19:30:14 naddy Exp $	*/
+
+/*
+ * Copyright (c) 1997, 2004 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#ifndef PATH_MAX
+#       define PATH_MAX 2048
+#endif
+
+char *
+basename(char *path)
+{
+	static char bname[PATH_MAX];
+	size_t len;
+	const char *endp, *startp;
+
+	/* Empty or NULL string gets treated as "." */
+	if (path == NULL || *path == '\0') {
+		bname[0] = '.';
+		bname[1] = '\0';
+		return (bname);
+	}
+
+	/* Strip any trailing slashes */
+	endp = path + strlen(path) - 1;
+	while (endp > path && *endp == '/')
+		endp--;
+
+	/* All slashes becomes "/" */
+	if (endp == path && *endp == '/') {
+		bname[0] = '/';
+		bname[1] = '\0';
+		return (bname);
+	}
+
+	/* Find the start of the base */
+	startp = endp;
+	while (startp > path && *(startp - 1) != '/')
+		startp--;
+
+	len = endp - startp + 1;
+	if (len >= sizeof(bname)) {
+		errno = ENAMETOOLONG;
+		return (NULL);
+	}
+	memcpy(bname, startp, len);
+	bname[len] = '\0';
+	return (bname);
+}
+
+#endif /* !MLK_HAS_BASENAME */
+
+/* }}} */
+
+/* {{{ dirname (POSIX). */
+
+#if !defined(MLK_HAS_BASENAME)
+
+/*	$OpenBSD: dirname.c,v 1.17 2020/10/20 19:30:14 naddy Exp $	*/
+
+/*
+ * Copyright (c) 1997, 2004 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#ifndef PATH_MAX
+#       define PATH_MAX 2048
+#endif
+
+char *
+dirname(char *path)
+{
+	static char dname[PATH_MAX];
+	size_t len;
+	const char *endp;
+
+	/* Empty or NULL string gets treated as "." */
+	if (path == NULL || *path == '\0') {
+		dname[0] = '.';
+		dname[1] = '\0';
+		return (dname);
+	}
+
+	/* Strip any trailing slashes */
+	endp = path + strlen(path) - 1;
+	while (endp > path && *endp == '/')
+		endp--;
+
+	/* Find the start of the dir */
+	while (endp > path && *endp != '/')
+		endp--;
+
+	/* Either the dir is "/" or there are no slashes */
+	if (endp == path) {
+		dname[0] = *endp == '/' ? '/' : '.';
+		dname[1] = '\0';
+		return (dname);
+	}
+	else {
+		/* Move forward past the separating slashes */
+		do {
+			endp--;
+		} while (endp > path && *endp == '/');
+	}
+
+	len = endp - path + 1;
+	if (len >= sizeof(dname)) {
+		errno = ENAMETOOLONG;
+		return (NULL);
+	}
+	memcpy(dname, path, len);
+	dname[len] = '\0';
+	return (dname);
+}
+
+#endif /* !MLK_HAS_DIRNAME */
+
+/* }}} */
+
+/* {{{ getopt (POSIX) */
+
+#if !defined(MLK_HAS_GETOPT)
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int	opterr = 1,		/* if error message should be printed */
+	optind = 1,		/* index into parent argv vector */
+	optopt,			/* character checked for validity */
+	optreset;		/* reset getopt */
+char	*optarg;		/* argument associated with option */
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt(int nargc, char **nargv, const char *ostr)
+{
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+
+	if (ostr == NULL)
+		return (-1);
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-') {	/* found "--" */
+			++optind;
+			place = EMSG;
+			return (-1);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (optopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "illegal option -- %c\n", optopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	}
+	else {					/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if (*ostr == ':')
+				return (BADARG);
+			if (opterr)
+				(void)fprintf(stderr,
+				    "option requires an argument -- %c\n",
+				    optopt);
+			return (BADCH);
+		}
+		else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* dump back option letter */
+}
+
+#endif /* !MLK_HAS_GETOPT */
+
+/* }}} */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-port/port/port.h	Wed Sep 22 10:04:15 2021 +0200
@@ -0,0 +1,98 @@
+/*
+ * port.h -- portability bits
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MOLKO_CORE_PORT_H
+#define MOLKO_CORE_PORT_H
+
+#include "config.h"
+
+/* {{{ strlcpy (BSD extension, incoming in next POSIX). */
+
+#if !defined(MLK_HAS_STRLCPY)
+
+#include <stddef.h>
+
+size_t
+strlcpy(char *, const char *, size_t);
+
+#endif /* !MLK_HAS_STRLCPY */
+
+/* }}} */
+
+/* {{{ fmemopen (POSIX). */
+
+#if !defined(MLK_HAS_FMEMOPEN)
+
+#include <stdio.h>
+
+FILE *
+fmemopen(void *, size_t, const char *);
+
+#endif /* !MLK_HAS_FMEMOPEN */
+
+/* }}} */
+
+/* {{{ basename (POSIX). */
+
+#if !defined(MLK_HAS_BASENAME)
+
+char *
+basename(char *);
+
+#endif /* !MLK_HAS_BASENAME */
+
+/* }}} */
+
+/* {{{ dirname (POSIX). */
+
+#if !defined(MLK_HAS_BASENAME)
+
+char *
+dirname(char *);
+
+#endif /* !MLK_HAS_DIRNAME */
+
+/* }}} */
+
+/* {{{ getopt (POSIX) */
+
+#if !defined(MLK_HAS_GETOPT)
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+
+int
+getopt(int, char **, const char *);
+
+#endif /* !MLK_HAS_GETOPT */
+
+/* }}} */
+
+/* PATH_MAX (defined in limits.h) (POSIX) */
+#if !defined(MLK_HAS_PATH_MAX)
+#       define PATH_MAX 2048
+#endif
+
+/* ssize_t (defined in sys/types.h) (POSIX) */
+#if !defined(MLK_HAS_SSIZE_T)
+typedef long long int ssize_t;
+#endif
+
+#endif /* !MOLKO_CORE_PORT_H */
--- a/libmlk-rpg/rpg/battle.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-rpg/rpg/battle.c	Wed Sep 22 10:04:15 2021 +0200
@@ -449,7 +449,7 @@
 
 	drawable_stack_draw(&bt->effects);
 
-	return battle_state_draw(bt->state, bt);
+	battle_state_draw(bt->state, bt);
 }
 
 void
--- a/libmlk-rpg/rpg/map-file.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-rpg/rpg/map-file.c	Wed Sep 22 10:04:15 2021 +0200
@@ -25,10 +25,11 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <port/port.h>
+
 #include <core/alloc.h>
 #include <core/error.h>
 #include <core/image.h>
-#include <core/port.h>
 #include <core/trace.h>
 #include <core/zfile.h>
 
--- a/libmlk-rpg/rpg/tileset-file.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/libmlk-rpg/rpg/tileset-file.c	Wed Sep 22 10:04:15 2021 +0200
@@ -25,11 +25,12 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <port/port.h>
+
 #include <core/alloc.h>
 #include <core/animation.h>
 #include <core/error.h>
 #include <core/image.h>
-#include <core/port.h>
 #include <core/util.h>
 #include <core/zfile.h>
 
--- a/mlk-adventure/CMakeLists.txt	Wed Sep 22 07:22:20 2021 +0200
+++ b/mlk-adventure/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -22,6 +22,7 @@
 	NAME mlk-adventure
 	SOURCES ${mlk-adventure_SOURCE_DIR}/main.c
 	LIBRARIES libmlk-adventure
+	INSTALL
 )
 
 source_group("" FILES ${mlk-adventure_SOURCE_DIR}/main.c)
--- a/tools/bcc/CMakeLists.txt	Wed Sep 22 07:22:20 2021 +0200
+++ b/tools/bcc/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -21,5 +21,7 @@
 mlk_executable(
 	NAME mlk-bcc
 	SOURCES ${mlk-bcc_SOURCE_DIR}/main.c
+	LIBRARIES libmlk-port
+	INSTALL
 	FOLDER tools
 )
--- a/tools/bcc/main.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/tools/bcc/main.c	Wed Sep 22 10:04:15 2021 +0200
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <port/port.h>
+
 static const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
 static char findentchar = '\t';
 static int findent = 1;
--- a/tools/map/CMakeLists.txt	Wed Sep 22 07:22:20 2021 +0200
+++ b/tools/map/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -21,6 +21,7 @@
 mlk_executable(
 	NAME mlk-map
 	SOURCES ${mlk-map_SOURCE_DIR}/main.c
-	LIBRARIES Jansson::Jansson
+	LIBRARIES Jansson::Jansson libmlk-port
 	FOLDER tools
+	INSTALL
 )
--- a/tools/map/main.c	Wed Sep 22 07:22:20 2021 +0200
+++ b/tools/map/main.c	Wed Sep 22 10:04:15 2021 +0200
@@ -29,6 +29,8 @@
 
 #include <jansson.h>
 
+#include <port/port.h>
+
 static void
 die(const char *fmt, ...)
 {
--- a/tools/tileset/CMakeLists.txt	Wed Sep 22 07:22:20 2021 +0200
+++ b/tools/tileset/CMakeLists.txt	Wed Sep 22 10:04:15 2021 +0200
@@ -21,6 +21,7 @@
 mlk_executable(
 	NAME mlk-tileset
 	SOURCES ${mlk-tileset_SOURCE_DIR}/main.c
-	LIBRARIES Jansson::Jansson
+	LIBRARIES Jansson::Jansson libmlk-port
 	FOLDER tools
+	INSTALL
 )