Skip to content

Commit

Permalink
Cmake (#93)
Browse files Browse the repository at this point in the history
* Add dll export marker

This is needed to export functions from from the shared library.

* Removed get_source and get_include functions

* Migrated to pyproject.toml

* Update MANIFEST.in

* Added cmake files

* Refactored setup.py to call cmake

* Bumped version in readme

* Added verbose logging when installing

* Removed unused optional

* Removed unused import

* Renamed extension

* Added __init__.py

* Reformatted

* Moved future to the beginning

* Added errors if compiling fails
  • Loading branch information
gentlegiantJGC authored Nov 26, 2024
1 parent eb3ef1f commit e6a030b
Show file tree
Hide file tree
Showing 27 changed files with 2,503 additions and 455 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ jobs:
shell: bash
run: |
python -m pip install --upgrade pip
pip install .[dev]
pip install -vvvv .[dev]
- name: Test with unittest
run: python -m unittest discover -v -s tests
56 changes: 56 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
cmake_minimum_required(VERSION 3.13)

project(amulet_nbt LANGUAGES CXX)
set(SRC_INSTALL_DIR "." CACHE PATH "The path to the src directory to install into.")

# Set C++20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Set platform variables
if (WIN32)
# set windows 7 as the minimum version
add_definitions(-D_WIN32_WINNT=0x0601)
elseif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
else()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()

# Add pybind11
find_package(pybind11 CONFIG REQUIRED)

# Add implementation
add_library(amulet_nbt SHARED)
target_compile_definitions(amulet_nbt PRIVATE ExportAmuletNBT)
target_include_directories(amulet_nbt PUBLIC "src/amulet_nbt/include")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/binary/read_binary.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/binary/write_binary.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/string/read_string.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/nbt_encoding/string/write_string.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/string_encoding/mutf8.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/string_encoding/utf8.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/tag/copy.cpp")
target_sources(amulet_nbt PRIVATE "src/amulet_nbt/cpp/tag/eq.cpp")

# Add python extension
pybind11_add_module(_amulet_nbt)
target_compile_definitions(_amulet_nbt PRIVATE PYBIND11_DETAILED_ERROR_MESSAGES)
target_link_libraries(_amulet_nbt PRIVATE amulet_nbt)
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/amulet_nbt.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/bnbt.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/encoding.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/snbt.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_abc_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_array_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_compound_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_float_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_int_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_list_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_named_tag.cpp")
target_sources(_amulet_nbt PRIVATE "src/amulet_nbt/pybind/tag/py_string_tag.cpp")

# Install
install(TARGETS amulet_nbt DESTINATION "${SRC_INSTALL_DIR}/amulet_nbt")
install(TARGETS _amulet_nbt DESTINATION "${SRC_INSTALL_DIR}/amulet_nbt")
5 changes: 4 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
recursive-include src/amulet_nbt *.cpp *.hpp *Config.cmake

include CMakeLists.txt

prune tests
recursive-include src *.pyi py.typed *.py *.cpp *.hpp
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SNBT (or Stringified-NBT) is the JSON like format used in Java commands.

Run this command to install from PyPi.

`pip install amulet-nbt~=3.0`
`pip install amulet-nbt~=4.0`

## Documentation

Expand Down
68 changes: 67 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,72 @@ requires = [
"setuptools >= 42",
"wheel",
"versioneer",
"pybind11 ~= 2.12",
"pybind11[global] == 2.13.6",
]
build-backend = "setuptools.build_meta"

[project]
name = "amulet-nbt"
authors = [
{name = "James Clare"},
{name = "Ben Gothard"},
]
description = "Read and write Minecraft NBT and SNBT data."
dynamic = ["version", "readme"]
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
]
dependencies = [
"amulet-compiler-target == 1.0",
"numpy >= 1.17, < 3.0"
]

[project.optional-dependencies]
docs = [
"Sphinx>=1.7.4",
"sphinx-autodoc-typehints>=1.3.0",
"sphinx_rtd_theme>=0.3.1",
]
dev = [
"black>=22.3",
"pre_commit>=1.11.1",
"mypy",
"types-pyinstaller",
"wheel",
"versioneer",
"pybind11[global] == 2.13.6",
]

[project.urls]
Homepage = "https://www.amuletmc.com"
Repository = "https://github.com/Amulet-Team/Amulet-NBT"
Issues = "https://github.com/Amulet-Team/Amulet-NBT/issues"

[tool.setuptools]
include-package-data = false

[tool.setuptools.package-data]
"*" = [
"*Config.cmake",
"**/*.hpp",
"**/*.dll",
"**/*.so",
"**/*.dylib",
"**/*.lib",
]

[tool.setuptools.dynamic]
readme = {file = ["README.md"], content-type = "text/markdown"}

[project.entry-points.pyinstaller40]
hook-dirs = "amulet_nbt.__pyinstaller:get_hook_dirs"

[tool.versioneer]
VCS = "git"
style = "pep440"
versionfile_source = "src/amulet_nbt/_version.py"
versionfile_build = "amulet_nbt/_version.py"
tag_prefix = ""
parentdir_prefix = "amulet_nbt-"
66 changes: 0 additions & 66 deletions setup.cfg

This file was deleted.

88 changes: 54 additions & 34 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
from setuptools import setup, Extension
import versioneer
import sysconfig
from distutils import ccompiler
import os
import subprocess
import sys
from pathlib import Path
import pybind11
import glob

if (sysconfig.get_config_var("CXX") or ccompiler.get_default_compiler()).split()[
0
] == "msvc":
CompileArgs = ["/std:c++20"]
else:
CompileArgs = ["-std=c++20"]
from setuptools import setup, Extension, Command
from setuptools.command.build_ext import build_ext

import versioneer


# https://github.com/pybind/cmake_example/blob/master/setup.py
class CMakeExtension(Extension):
def __init__(self, name: str, sourcedir: str = "") -> None:
super().__init__(name, sources=[])
self.sourcedir = os.fspath(Path(sourcedir).resolve())


cmdclass: dict[str, type[Command]] = versioneer.get_cmdclass()


class CMakeBuild(cmdclass.get("build_ext", build_ext)):
def build_extension(self, ext):
ext_fullpath = Path.cwd() / self.get_ext_fullpath("")
src_dir = ext_fullpath.parent.resolve()

platform_args = []
if sys.platform == "win32":
platform_args.extend(["-G", "Visual Studio 17 2022"])
if sys.maxsize > 2**32:
platform_args.extend(["-A", "x64"])
else:
platform_args.extend(["-A", "Win32"])
platform_args.extend(["-T", "v143"])

if subprocess.run(
[
"cmake",
*platform_args,
f"-DPYTHON_EXECUTABLE={sys.executable}",
f"-Dpybind11_DIR={pybind11.get_cmake_dir().replace(os.sep, '/')}",
f"-DCMAKE_INSTALL_PREFIX=install",
f"-DSRC_INSTALL_DIR={src_dir}",
"-B",
"build",
]
).returncode:
raise RuntimeError("Error configuring amulet_nbt")
if subprocess.run(["cmake", "--build", "build", "--config", "Release"]).returncode:
raise RuntimeError("Error installing amulet_nbt")
if subprocess.run(["cmake", "--install", "build", "--config", "Release"]).returncode:
raise RuntimeError("Error installing amulet_nbt")


if sys.platform == "darwin":
CompileArgs.append("-mmacosx-version-min=10.13")
cmdclass["build_ext"] = CMakeBuild


setup(
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
libraries=[
(
"amulet_nbt",
dict(
sources=glob.glob("src/amulet_nbt/cpp/**/*.cpp", recursive=True),
include_dirs=["src/amulet_nbt/include"],
cflags=CompileArgs,
),
)
],
ext_modules=[
Extension(
name="amulet_nbt.__init__",
sources=glob.glob("src/amulet_nbt/pybind/**/*.cpp", recursive=True),
include_dirs=["src/amulet_nbt/include", pybind11.get_include()],
libraries=["amulet_nbt"],
define_macros=[("PYBIND11_DETAILED_ERROR_MESSAGES", None)],
extra_compile_args=CompileArgs,
)
],
cmdclass=cmdclass,
ext_modules=[CMakeExtension("amulet_nbt.__init__")],
)
Loading

0 comments on commit e6a030b

Please sign in to comment.