diff --git a/README.md b/README.md index 9950ef0..79c7033 100644 --- a/README.md +++ b/README.md @@ -36,5 +36,15 @@ cd bindings/python pip install . ``` +### Build the Rust bindings + +You'll need [Meson][1] and [Ninja][2] to build the [Rust][3] bindings. + +```shell +cd bindings/rust +cargo run --example bidi +``` + [1]: https://mesonbuild.com [2]: https://ninja-build.org +[3]: https://www.rust-lang.org diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py index b9db1cf..01e7c21 100644 --- a/bindings/python/__init__.py +++ b/bindings/python/__init__.py @@ -1,9 +1,6 @@ # ruff: noqa: F401 F821 -from .lib import Font # type: ignore -from .types import FontStyle, Glyph, Path, PathVerb, Point, Transform - -del lib -del types +from ._subset import Font # type: ignore +from ._types import FontStyle, Glyph, Path, PathVerb, Point, Transform __all__ = [ "Font", diff --git a/bindings/python/lib.pyi b/bindings/python/_subset.pyi similarity index 100% rename from bindings/python/lib.pyi rename to bindings/python/_subset.pyi diff --git a/bindings/python/types.py b/bindings/python/_types.py similarity index 100% rename from bindings/python/types.py rename to bindings/python/_types.py diff --git a/bindings/python/layout.py b/bindings/python/layout.py index 50e5f98..d7bf824 100644 --- a/bindings/python/layout.py +++ b/bindings/python/layout.py @@ -4,7 +4,7 @@ from collections.abc import Callable, Generator from dataclasses import dataclass, field -from .lib import GlyphDrawer, Font, ShapeContext, find_best_font_match, text_runs # type: ignore +from ._subset import GlyphDrawer, Font, ShapeContext, find_best_font_match, text_runs # type: ignore from .types import FontRun, FontStyle, Glyph, GlyphRun, Path, PathVerb, Point diff --git a/bindings/python/meson.build b/bindings/python/meson.build index ffcc606..0fae6f4 100644 --- a/bindings/python/meson.build +++ b/bindings/python/meson.build @@ -1,25 +1,29 @@ project('subset-python', 'c', 'cpp', 'cython') -subdir('deps/extern') -subdir('deps/lib') +subset_proj = subproject( + 'subset', + default_options: ['default_library=static'], +) + +subset_dep = subset_proj.get_variable('subset_dep') py = import('python').find_installation(pure: false) py.extension_module( - 'lib', + '_subset', 'subset.pyx', - cython_args: ['--module-name', 'lib'], - dependencies: subset_lib_dep, + cython_args: ['--module-name', '_subset'], + dependencies: subset_dep, install: true, subdir: 'subset', ) python_sources = files( '__init__.py', + '_subset.pyi', + '_types.py', 'layout.py', - 'lib.pyi', 'py.typed', - 'types.py', ) py.install_sources( diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 9ea3c16..0d5041e 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -8,3 +8,6 @@ version = "0.0.1" requires-python = ">=3.11" authors = [{ name = "Christer Sandberg", email = "chrsan@gmail.com" }] license = { file = "../../LICENSE" } + +[tool.meson-python.args] +install = ["--skip-subprojects"] diff --git a/bindings/python/subprojects/.gitignore b/bindings/python/subprojects/.gitignore new file mode 100644 index 0000000..8d11103 --- /dev/null +++ b/bindings/python/subprojects/.gitignore @@ -0,0 +1,3 @@ +harfbuzz +sheenbidi +*.wrap diff --git a/bindings/python/subprojects/subset/meson.build b/bindings/python/subprojects/subset/meson.build new file mode 120000 index 0000000..1e0f645 --- /dev/null +++ b/bindings/python/subprojects/subset/meson.build @@ -0,0 +1 @@ +../../../../meson.build \ No newline at end of file diff --git a/bindings/python/subprojects/subset/src b/bindings/python/subprojects/subset/src new file mode 120000 index 0000000..b3e266f --- /dev/null +++ b/bindings/python/subprojects/subset/src @@ -0,0 +1 @@ +../../../../src \ No newline at end of file diff --git a/bindings/python/subprojects/subset/subprojects b/bindings/python/subprojects/subset/subprojects new file mode 120000 index 0000000..ff9bb1c --- /dev/null +++ b/bindings/python/subprojects/subset/subprojects @@ -0,0 +1 @@ +../../../../subprojects \ No newline at end of file diff --git a/bindings/python/subset.pyx b/bindings/python/subset.pyx index d6308e3..68588ee 100644 --- a/bindings/python/subset.pyx +++ b/bindings/python/subset.pyx @@ -10,7 +10,7 @@ from cpython.mem cimport PyMem_Malloc, PyMem_Free from libc.stddef cimport size_t from libc.stdint cimport int32_t, uint8_t, uint32_t -cdef extern from "deps/lib/subset.h": +cdef extern from "subset.h": ctypedef struct SubsetGlyphDrawer: pass diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 6e4bad9..54f2fe9 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -18,6 +18,8 @@ fn main() { cmd.arg("setup"); cmd.arg("--buildtype"); cmd.arg(build_type); + cmd.arg("--default-library"); + cmd.arg("static"); cmd.arg(&build_dir); assert!(cmd.status().unwrap().success()); } @@ -25,13 +27,14 @@ fn main() { cmd.current_dir(&build_dir); cmd.arg("compile"); assert!(cmd.status().unwrap().success()); + println!("cargo:rustc-link-search=native={}", build_dir.display()); println!( "cargo:rustc-link-search=native={}", - build_dir.join("extern").display() + build_dir.join("subprojects/harfbuzz").display() ); println!( "cargo:rustc-link-search=native={}", - build_dir.join("lib").display() + build_dir.join("subprojects/sheenbidi").display() ); println!("cargo:rustc-link-lib=static=harfbuzz"); println!("cargo:rustc-link-lib=static=sheenbidi"); @@ -40,9 +43,5 @@ fn main() { "cargo:rerun-if-changed={}", root_dir.join("meson.build").display() ); - println!( - "cargo:rerun-if-changed={}", - root_dir.join("extern").display() - ); - println!("cargo:rerun-if-changed={}", root_dir.join("lib").display()); + println!("cargo:rerun-if-changed={}", root_dir.join("src").display()); } diff --git a/extern/deps.json b/extern/deps.json deleted file mode 100644 index 8c91bde..0000000 --- a/extern/deps.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "repo": "https://github.com/harfbuzz/harfbuzz", - "branch": "8.3.1" - }, - { - "repo": "https://github.com/Tehreer/SheenBidi", - "tag": "v2.7" - } -] diff --git a/extern/meson.build b/extern/meson.build deleted file mode 100644 index 4a2ab9f..0000000 --- a/extern/meson.build +++ /dev/null @@ -1,36 +0,0 @@ -harbuzz_public_cpp_args = ['-DHB_NO_FALLBACK_SHAPE', '-DHB_NO_WIN1256'] -harfbuzz_inc = include_directories('harfbuzz/src') -harfbuzz_sources = files('harfbuzz/src/harfbuzz.cc') -harfbuzz_lib = static_library( - 'harfbuzz', - harfbuzz_sources, - cpp_args: harbuzz_public_cpp_args + [ - '-std=c++11', - '-fno-exceptions', - '-fno-rtti', - '-fno-threadsafe-statics', - ], - include_directories: harfbuzz_inc, -) - -harfbuzz_dep = declare_dependency( - compile_args: harbuzz_public_cpp_args, - include_directories: harfbuzz_inc, - link_with: harfbuzz_lib, -) - -sheenbidi_public_c_args = ['-DSB_CONFIG_UNITY'] -sheenbidi_inc = include_directories('SheenBidi/Headers') -sheenbidi_sources = files('SheenBidi/Source/SheenBidi.c') -sheenbidi_lib = static_library( - 'sheenbidi', - sheenbidi_sources, - c_args: sheenbidi_public_c_args, - include_directories: sheenbidi_inc, -) - -sheenbidi_dep = declare_dependency( - compile_args: sheenbidi_public_c_args, - include_directories: sheenbidi_inc, - link_with: sheenbidi_lib, -) diff --git a/lib/meson.build b/lib/meson.build deleted file mode 100644 index 73d32d5..0000000 --- a/lib/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -subset_lib_inc = include_directories('.') -subset_lib_sources = files('subset.cc') -subset_lib = static_library( - 'subset', - subset_lib_sources, - cpp_args: ['-std=c++17', '-fno-exceptions', '-fno-rtti'], - dependencies: [harfbuzz_dep, sheenbidi_dep], - include_directories: subset_lib_inc, -) - -subset_lib_dep = declare_dependency( - include_directories: subset_lib_inc, - link_with: subset_lib, -) diff --git a/meson.build b/meson.build index 92c7164..8c32300 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,30 @@ project('subset', 'c', 'cpp') -subdir('extern') -subdir('lib') +harfbuzz_proj = subproject( + 'harfbuzz', + default_options: ['default_library=static'], +) + +harfbuzz_dep = harfbuzz_proj.get_variable('harfbuzz_dep') + +sheenbidi_proj = subproject( + 'sheenbidi', + default_options: ['default_library=static'], +) + +sheenbidi_dep = sheenbidi_proj.get_variable('sheenbidi_dep') + +subset_inc = include_directories('src') +subset_sources = files('src/subset.cc') +subset_lib = library( + 'subset', + subset_sources, + cpp_args: ['-std=c++17', '-fno-exceptions', '-fno-rtti'], + dependencies: [harfbuzz_dep, sheenbidi_dep], + include_directories: subset_inc, +) + +subset_dep = declare_dependency( + include_directories: subset_inc, + link_with: subset_lib, +) diff --git a/lib/subset.cc b/src/subset.cc similarity index 100% rename from lib/subset.cc rename to src/subset.cc diff --git a/lib/subset.h b/src/subset.h similarity index 100% rename from lib/subset.h rename to src/subset.h diff --git a/subprojects/.gitignore b/subprojects/.gitignore new file mode 100644 index 0000000..81c9acd --- /dev/null +++ b/subprojects/.gitignore @@ -0,0 +1,2 @@ +harfbuzz +sheenbidi diff --git a/subprojects/harfbuzz.wrap b/subprojects/harfbuzz.wrap new file mode 100644 index 0000000..7069e56 --- /dev/null +++ b/subprojects/harfbuzz.wrap @@ -0,0 +1,5 @@ +[wrap-git] +url = https://github.com/harfbuzz/harfbuzz.git +revision = 8.4.0 +depth = 1 +patch_directory = harfbuzz diff --git a/subprojects/sheenbidi.wrap b/subprojects/sheenbidi.wrap new file mode 100644 index 0000000..6b0db3b --- /dev/null +++ b/subprojects/sheenbidi.wrap @@ -0,0 +1,4 @@ +[wrap-git] +url = https://github.com/Tehreer/SheenBidi.git +revision = v2.7 +depth = 1 diff --git a/tools/download_deps.py b/tools/download_deps.py deleted file mode 100644 index 12873c9..0000000 --- a/tools/download_deps.py +++ /dev/null @@ -1,25 +0,0 @@ -import json -import os -import subprocess -import sys - -HERE = os.path.dirname(__file__) -DEST = os.path.abspath(os.path.join(HERE, "../extern")) - - -def download(repo: str, branch_or_tag: str): - subprocess.check_call( - ["git", "clone", "--depth=1", "-b", branch_or_tag, repo], cwd=DEST - ) - - -def main(argv): - deps_file_path = argv[0] if argv else os.path.join(DEST, "deps.json") - with open(deps_file_path) as file: - deps = json.load(file) - for dep in deps: - download(dep["repo"], dep.get("branch") or dep["tag"]) - - -if __name__ == "__main__": - main(sys.argv[1:])