Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
30e6b63
Python Bindings
o2161405 Aug 1, 2025
d065336
Clang formatting + vector regression
o2161405 Aug 1, 2025
db5a246
clang-format fix
o2161405 Aug 1, 2025
6583d3a
Update CMakeLists.txt
o2161405 Aug 1, 2025
ca97156
Update source/bindings/KBindSystem.cc
o2161405 Aug 1, 2025
9deecc4
Update source/bindings/KBindSystem.hh
o2161405 Aug 1, 2025
b2e0648
Update source/bindings/KBindSystem.cc
o2161405 Aug 1, 2025
2899f38
Update source/bindings/bindings.cc
o2161405 Aug 1, 2025
925f72f
Update source/bindings/KBindSystem.cc
o2161405 Aug 1, 2025
cca75aa
Update source/bindings/KBindSystem.hh
o2161405 Aug 1, 2025
4b6ca31
Cleanup of scenario settings + method name changes
o2161405 Aug 1, 2025
ec1ea61
Update source/bindings/KBindSystem.hh
o2161405 Aug 1, 2025
7995939
Script bug fix
o2161405 Aug 2, 2025
51ec4e5
Merge branch 'main' of https://github.com/o2161405/Kinoko
o2161405 Aug 2, 2025
b3d6736
Inherit from KSystem instead of EGG::Disposer
o2161405 Aug 2, 2025
a9e21b3
Ninja bindings support
o2161405 Aug 2, 2025
b998a30
clang-format changes
o2161405 Aug 2, 2025
60cc7b9
Build bug fix + Moved bindings to Host
o2161405 Aug 2, 2025
ca6fa29
Fix typo in bindings_test.py [skip ci]
o2161405 Aug 2, 2025
bbda373
Ninja script bug fix + Heap.hh std compliance
o2161405 Aug 3, 2025
5680fc0
Fix build script for Linux
o2161405 Aug 3, 2025
8deb1a1
Add "no-format" flag for bindings
o2161405 Aug 3, 2025
934ca6d
Variable reordering
o2161405 Aug 3, 2025
f6298d7
KartObjectProxy bindings
o2161405 Aug 3, 2025
3d8baa0
Function rename
o2161405 Aug 3, 2025
29f6c40
Merge branch 'vabold:main' into main
o2161405 Aug 3, 2025
8f08051
Update source/host/KBindings.cc
o2161405 Aug 3, 2025
b2b5b2a
Update configure.py
o2161405 Aug 3, 2025
63eb28d
Merge branch 'main' of https://github.com/o2161405/Kinoko
o2161405 Aug 3, 2025
5acca4c
SetCourse now in header
o2161405 Aug 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.22)
project(Kinoko CXX)

# Compiler and flags
Expand All @@ -8,10 +8,10 @@ set(CMAKE_CXX_EXTENSIONS OFF)

# Common flags
set(COMMON_CXX_FLAGS
-fPIC
-DREVOLUTION
-fno-asynchronous-unwind-tables
-fno-exceptions
-fno-rtti
-fshort-wchar
-fstack-protector-strong
-Wall
Expand All @@ -22,14 +22,32 @@ set(COMMON_CXX_FLAGS
-Wsuggest-override
)

# Bindings flags
set(BINDINGS_CXX_FLAGS
-DREVOLUTION
-fstack-protector-strong
-Wall
-Werror
-Wextra
-Wno-delete-non-virtual-dtor
-Wno-packed-bitfield-compat
-Wsuggest-override
)

set(RK_INCLUDE_DIRS
include
source
)


# +-------------------------------------------+
# - LIBKINOKO -
# +-------------------------------------------+

# Source files
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/**/*.cc)
list(FILTER SOURCE_FILES EXCLUDE REGEX ".*/host/main\\.cc$")
list(FILTER SOURCE_FILES EXCLUDE REGEX ".*/host/KBind.*\\.cc$")

add_library(libkinoko ${SOURCE_FILES})
target_include_directories(libkinoko SYSTEM
Expand All @@ -43,13 +61,42 @@ add_executable(kinoko source/host/main.cc)
target_link_libraries(kinoko libkinoko)
target_compile_options(kinoko PRIVATE ${COMMON_CXX_FLAGS})

# +-------------------------------------------+
# - BINDINGS -
# +-------------------------------------------+

# Include Python
find_package(Python REQUIRED COMPONENTS Development)

# Fetch Nanobind
include(FetchContent)
FetchContent_Declare(
nanobind
GIT_REPOSITORY https://github.com/wjakob/nanobind.git
)
FetchContent_MakeAvailable(nanobind)

# Add a target
nanobind_add_module(bindings
source/host/KBindSystem.cc
source/host/KBindings.cc
)

# Link libraries
target_link_libraries(bindings PRIVATE libkinoko Python::Python)
target_compile_options(bindings PRIVATE ${BINDINGS_CXX_FLAGS})

# +-------------------------------------------+
# - TEST CASES -
# +-------------------------------------------+

# Add a custom target to generate testCases.json
set(TEST_JSON ${CMAKE_CURRENT_SOURCE_DIR}/testCases.json)
set(TEST_BIN ${CMAKE_CURRENT_BINARY_DIR}/testCases.bin)
add_custom_command(
OUTPUT ${TEST_BIN} # The file generated by this rule
DEPENDS ${TEST_JSON} # Dependency
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_tests.py ${TEST_JSON} ${TEST_BIN}
COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_tests.py ${TEST_JSON} ${TEST_BIN}
COMMENT "Running generate_tests.py to create test cases"
)
add_custom_target(
Expand Down
242 changes: 138 additions & 104 deletions configure.py
Original file line number Diff line number Diff line change
@@ -1,154 +1,188 @@
#!/usr/bin/env python3

from glob import glob
import io
import glob
import os
import re
import io
import sys
from tools.generate_tests import generate_tests
import sysconfig
import subprocess
from dataclasses import dataclass, field
from vendor.ninja_syntax import Writer
from tools.generate_tests import generate_tests

generate_tests()

ON_WINDOWS = True if sys.platform.startswith("win32") else False

# Ninja variables and rules
out_buf = io.StringIO()
n = Writer(out_buf)

file_extension = ''
if sys.platform.startswith('win32'):
file_extension = '.exe'
build_dir = "build"

n.variable('ninja_required_version', '1.3')
n.variable("ninja_required_version", "1.3")
n.variable("builddir", build_dir)
n.variable("outdir", "out")
n.variable("compiler", "g++")
n.variable("ar", "ar")
n.newline()

n.variable('builddir', 'build')
n.variable('outdir', 'out')
n.rule("cc", command="$compiler -MD -MT $out -MF $out.d $ccflags -c $in -o $out", depfile="$out.d", deps="gcc", description="CC $out")
n.rule("ar", command="$ar rcs $out $in", description="AR $out")
n.newline()

n.variable('compiler', 'g++')
n.rule("ld", command="$compiler $in $ldflags -o $out", description="LD $out")
n.newline()
n.rule("ld_shared", command="$compiler -shared $in $ldflags -o $out", description="LD_SHARED $out")
n.newline()

# Download dependancies
deps_path = os.path.join(build_dir, "_deps")
nanobind_path = os.path.join(deps_path, "nanobind")
robin_path = os.path.join(deps_path, "robin-map")

os.makedirs(deps_path, exist_ok=True)

if not os.path.isdir(nanobind_path):
subprocess.run(["git", "clone", "https://github.com/wjakob/nanobind", nanobind_path], check=True)

if not os.path.isdir(robin_path):
subprocess.run(["git", "clone", "https://github.com/Tessil/robin-map.git", robin_path], check=True)

python_include_path = sysconfig.get_paths()["include"]
python_lib_path = os.path.join(sysconfig.get_paths()["data"], "libs", f"libpython{sys.version_info.major}.{sys.version_info.minor}.a")
nanobind_include_path = os.path.join(nanobind_path, "include")
nanobind_src_path = os.path.join(nanobind_path, "src")
robin_include_path = os.path.join(robin_path, "include")

# Flags
common_ccflags = [
'-DREVOLUTION',
'-fno-asynchronous-unwind-tables',
'-fno-exceptions',
'-fno-rtti',
'-fshort-wchar',
'-fstack-protector-strong',
'-isystem', '.',
'-isystem', 'include',
'-isystem', 'source',
'-isystem', 'vendor',
'-isystem', 'build',
'-std=c++23',
'-Wall',
'-Wdouble-promotion',
'-Werror',
'-Wextra',
'-Wno-delete-non-virtual-dtor',
'-Wno-packed-bitfield-compat',
'-Wsuggest-override',
'-std=c++23',
'-fPIC',
'-fno-exceptions',
]

target_cflags = [
'-O3',
bindings_ccflags = [
'-DREVOLUTION',
'-fstack-protector-strong',
'-isystem', 'include',
'-isystem', 'source',
'-isystem', python_include_path,
'-isystem', nanobind_include_path,
'-isystem', robin_include_path,
'-Wall',
'-Werror',
'-Wextra',
'-Wno-format',
'-Wno-delete-non-virtual-dtor',
'-Wno-packed-bitfield-compat',
'-Wsuggest-override',
'-std=c++23',
'-fPIC',
]

debug_cflags = [
'-DBUILD_DEBUG',
'-O0',
'-ggdb',
# Define build types
@dataclass
class Build:
name: str
suffix: str
flags: list[str]
obj_files: dict = field(default_factory=lambda: {
"common": [],
"main": [],
"bindings": []
})

builds = [
Build(name="target", suffix="", flags=["-O3"]),
Build(name="debug", suffix="D", flags=["-DBUILD_DEBUG", "-O0", "-ggdb"])
]

common_ldflags = []
# Compile files
def get_files():
sep = re.escape(os.path.sep)
main_regex = re.compile(rf".*{sep}host{sep}main\.cc$")
bindings_regex = re.compile(rf".*{sep}host{sep}KBind.*\.cc$")

n.rule(
'cc',
command='$compiler -MD -MT $out -MF $out.d $ccflags -c $in -o $out',
depfile='$out.d',
deps='gcc',
description='CC $out',
)
n.newline()
main_files = []
bindings_files = []
common_files = []

n.rule(
'ld',
command='$compiler $ldflags $in -o $out',
description='LD $out',
)
for file in glob.glob(os.path.join("source", "**", "*.cc"), recursive=True):
if main_regex.search(file):
main_files.append(file)
continue

code_in_files = [file for file in glob('**/*.cc', recursive=True)]
if bindings_regex.search(file):
bindings_files.append(file)
continue

target_code_out_files = []
debug_code_out_files = []
common_files.append(file)

for in_file in code_in_files:
_, ext = os.path.splitext(in_file)
bindings_files.append(os.path.join(nanobind_src_path, "nb_combined.cpp"))

target_out_file = os.path.join('$builddir', in_file + '.o')
target_code_out_files.append(target_out_file)
return common_files, main_files, bindings_files

debug_out_file = os.path.join('$builddir', in_file + 'D.o')
debug_code_out_files.append(debug_out_file)
def compile(files, builds, obj_key, flags):
for in_file in files:
base_name, _ = os.path.splitext(in_file)
for build in builds:
out_file = os.path.join("$builddir", f"{base_name}{build.suffix}.o")
build.obj_files[obj_key].append(out_file)
n.build(out_file, "cc", in_file, variables={"ccflags": " ".join([*flags, *build.flags])})

n.build(
target_out_file,
ext[1:],
in_file,
variables={
'ccflags': ' '.join([*common_ccflags, *target_cflags])
}
)
n.newline()
common_files, main_files, bindings_files = get_files()
compile(common_files, builds, "common", common_ccflags)
compile(main_files, builds, "main", common_ccflags)
compile(bindings_files, builds, "bindings", bindings_ccflags)
n.newline()

n.build(
debug_out_file,
ext[1:],
in_file,
variables={
'ccflags': ' '.join([*common_ccflags, *debug_cflags])
}
)
# Link files
binary_extension = ".exe" if ON_WINDOWS else ""
lib_extension = ".pyd" if ON_WINDOWS else ".so"

for build in builds:
# libkinoko
libkinoko_name = f"libkinoko{build.suffix}.a"
libkinoko_path = os.path.join("$builddir", libkinoko_name)
libkinoko_objs = build.obj_files["common"]
n.build(libkinoko_path, "ar", libkinoko_objs)
n.newline()

# kinoko
exe_name = f"kinoko{build.suffix}{binary_extension}"
exe_path = os.path.join("$outdir", exe_name)
exe_obj = build.obj_files["main"] + [libkinoko_path]
n.build(exe_path, "ld", exe_obj)

# bindings
lib_name = f"bindings{build.suffix}{lib_extension}"
lib_path = os.path.join("$outdir", lib_name)
lib_objs = build.obj_files["bindings"] + [libkinoko_path]

# Python library
if ON_WINDOWS:
n.build(lib_path, "ld_shared", lib_objs, variables={"ldflags": f"{sysconfig.get_config_var('LDFLAGS')} -L{os.path.dirname(python_lib_path)} -lpython{sys.version_info.major}.{sys.version_info.minor}"})
else:
n.build(lib_path, "ld_shared", lib_objs, variables={"ldflags": f"{sysconfig.get_config_var('LDFLAGS')} -L{os.path.dirname(python_lib_path)}"})
n.newline()

n.build(
os.path.join('$outdir', f'kinoko{file_extension}'),
'ld',
target_code_out_files,
variables={
'ldflags': ' '.join([
*common_ldflags,
])
},
)

n.build(
os.path.join('$outdir', f'kinokoD{file_extension}'),
'ld',
debug_code_out_files,
variables={
'ldflags': ' '.join([
*common_ldflags,
])
},
)

n.variable('configure', 'configure.py')
n.rule("configure", command=f"{sys.executable} configure.py", generator=True)
n.build("build.ninja", "configure", implicit=["configure.py", os.path.join("vendor", "ninja_syntax.py")])
n.newline()

n.rule(
'configure',
command=f'{sys.executable} $configure',
generator=True,
)
n.build(
'build.ninja',
'configure',
implicit=[
'$configure',
os.path.join('vendor', 'ninja_syntax.py'),
],
)

with open('build.ninja', 'w') as out_file:
out_file.write(out_buf.getvalue())
n.close()
with open("build.ninja", "w") as f:
f.write(out_buf.getvalue())
n.close()
Loading