Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Enable basic CMake build#26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
timkpaine merged 1 commit intomainfromtkp/cmake
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
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
1 change: 1 addition & 0 deletions.gitignore
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,6 +20,7 @@ dist/
downloads/
eggs/
.eggs/
include/
lib/
lib64/
parts/
Expand Down
76 changes: 49 additions & 27 deletionshatch_cpp/plugin.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
from __future__ import annotations

import logging
import os
import platform as sysplatform
import sys
import typing as t
from logging import getLogger
from os import getenv
from pathlib import Path
from platform import machine as platform_machine
from sys import platform as sys_platform, version_info
from typing import Any

from hatchling.builders.hooks.plugin.interface import BuildHookInterface

Expand All@@ -18,13 +19,14 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
"""The hatch-cpp build hook."""

PLUGIN_NAME = "hatch-cpp"
_logger =logging.getLogger(__name__)
_logger = getLogger(__name__)

def initialize(self, version: str, build_data: dict[str,t.Any]) -> None:
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
"""Initialize the plugin."""
# Log some basic information
project_name = self.metadata.config["project"]["name"]
self._logger.info("Initializing hatch-cpp plugin version %s", version)
self._logger.info("Running hatch-cpp")
self._logger.info(f"Running hatch-cpp: {project_name}")

# Only run if creating wheel
# TODO: Add support for specify sdist-plan
Expand All@@ -34,25 +36,21 @@ def initialize(self, version: str, build_data: dict[str, t.Any]) -> None:

# Skip if SKIP_HATCH_CPP is set
# TODO: Support CLI once https://github.com/pypa/hatch/pull/1743
ifos.getenv("SKIP_HATCH_CPP"):
if getenv("SKIP_HATCH_CPP"):
self._logger.info("Skipping the build hook since SKIP_HATCH_CPP was set")
return

# Get build config class or use default
build_config_class = import_string(self.config["build-config-class"]) if "build-config-class" in self.config else HatchCppBuildConfig

# Instantiate build config
config = build_config_class(**self.config)

# Grab libraries and platform
libraries = config.libraries
platform = config.platform
config = build_config_class(name=project_name, **self.config)

# Get build plan class or use default
build_plan_class = import_string(self.config["build-plan-class"]) if "build-plan-class" in self.config else HatchCppBuildPlan

# Instantiate builder
build_plan = build_plan_class(libraries=libraries, platform=platform)
build_plan = build_plan_class(**config.model_dump())

# Generate commands
build_plan.generate()
Expand All@@ -68,24 +66,48 @@ def initialize(self, version: str, build_data: dict[str, t.Any]) -> None:
# Perform any cleanup actions
build_plan.cleanup()

# force include libraries
for library in libraries:
name = library.get_qualified_name(build_plan.platform.platform)
build_data["force_include"][name] = name
if build_plan.libraries:
# force include libraries
for library in build_plan.libraries:
name = library.get_qualified_name(build_plan.platform.platform)
build_data["force_include"][name] = name

if libraries:
build_data["pure_python"] = False
machine = sysplatform.machine()
version_major = sys.version_info.major
version_minor = sys.version_info.minor
# TODO abi3
if "darwin" in sys.platform:
machine = platform_machine()
version_major = version_info.major
version_minor = version_info.minor
if "darwin" in sys_platform:
os_name = "macosx_11_0"
elif "linux" insys.platform:
elif "linux" insys_platform:
os_name = "linux"
else:
os_name = "win"
if all([lib.py_limited_api for lib in libraries]):
if all([lib.py_limited_api for lib inbuild_plan.libraries]):
build_data["tag"] = f"cp{version_major}{version_minor}-abi3-{os_name}_{machine}"
else:
build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}"
else:
build_data["pure_python"] = False
machine = platform_machine()
version_major = version_info.major
version_minor = version_info.minor
# TODO abi3
if "darwin" in sys_platform:
os_name = "macosx_11_0"
elif "linux" in sys_platform:
os_name = "linux"
else:
os_name = "win"
build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}"

# force include libraries
for path in Path(".").rglob("*"):
if path.is_dir():
continue
if str(path).startswith(str(build_plan.cmake.build)) or str(path).startswith("dist"):
continue
if path.suffix in (".pyd", ".dll", ".so", ".dylib"):
build_data["force_include"][str(path)] = str(path)

for path in build_data["force_include"]:
self._logger.warning(f"Force include: {path}")
117 changes: 92 additions & 25 deletionshatch_cpp/structs.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
from __future__ import annotations

from os import environ, system
from os import environ, system as system_call
from pathlib import Path
from re import match
from shutil import which
from sys import executable, platform as sys_platform
from sys import executable, platform as sys_platform, version_info
from sysconfig import get_path
from typing import Any, List, Literal, Optional
from typing import Any,Dict,List, Literal, Optional

from pydantic import AliasChoices, BaseModel, Field, field_validator, model_validator

Expand All@@ -20,7 +20,7 @@
BuildType = Literal["debug", "release"]
CompilerToolchain = Literal["gcc", "clang", "msvc"]
Language = Literal["c", "c++"]
Binding = Literal["cpython", "pybind11", "nanobind"]
Binding = Literal["cpython", "pybind11", "nanobind", "generic"]
Platform = Literal["linux", "darwin", "win32"]
PlatformDefaults = {
"linux": {"CC": "gcc", "CXX": "g++", "LD": "ld"},
Expand DownExpand Up@@ -65,9 +65,9 @@

def get_qualified_name(self, platform):
if platform == "win32":
suffix = "dll" if self.binding == "none" else "pyd"
suffix = "dll" if self.binding == "generic" else "pyd"
elif platform == "darwin":
suffix = "dylib" if self.binding == "none" else "so"
suffix = "dylib" if self.binding == "generic" else "so"
else:
suffix = "so"
if self.py_limited_api and platform != "win32":
Expand All@@ -78,6 +78,8 @@
def check_binding_and_py_limited_api(self):
if self.binding == "pybind11" and self.py_limited_api:
raise ValueError("pybind11 does not support Py_LIMITED_API")
if self.binding == "generic" and self.py_limited_api:
raise ValueError("Generic binding can not support Py_LIMITED_API")

Check warning on line 82 in hatch_cpp/structs.py

View check run for this annotation

Codecov/ codecov/patch

hatch_cpp/structs.py#L82

Added line #L82 was not covered by tests
return self


Expand DownExpand Up@@ -119,7 +121,8 @@
flags = ""

# Python.h
library.include_dirs.append(get_path("include"))
if library.binding != "generic":
library.include_dirs.append(get_path("include"))

if library.binding == "pybind11":
import pybind11
Expand DownExpand Up@@ -217,36 +220,100 @@
return flags


class HatchCppBuildPlan(BaseModel):
build_type: BuildType = "release"
class HatchCppCmakeConfiguration(BaseModel):
root: Path
build: Path = Field(default_factory=lambda: Path("build"))
install: Optional[Path] = Field(default=None)

cmake_arg_prefix: Optional[str] = Field(default=None)
cmake_args: Dict[str, str] = Field(default_factory=dict)
cmake_env_args: Dict[Platform, Dict[str, str]] = Field(default_factory=dict)

include_flags: Optional[Dict[str, Any]] = Field(default=None)


class HatchCppBuildConfig(BaseModel):
"""Build config values for Hatch C++ Builder."""

verbose: Optional[bool] = Field(default=False)
name: Optional[str] = Field(default=None)
libraries: List[HatchCppLibrary] = Field(default_factory=list)
platform: HatchCppPlatform = Field(default_factory=HatchCppPlatform.default)
cmake: Optional[HatchCppCmakeConfiguration] = Field(default=None)
platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)

@model_validator(mode="after")
def check_toolchain_matches_args(self):
if self.cmake and self.libraries:
raise ValueError("Must not provide libraries when using cmake toolchain.")

Check warning on line 247 in hatch_cpp/structs.py

View check run for this annotation

Codecov/ codecov/patch

hatch_cpp/structs.py#L247

Added line #L247 was not covered by tests
return self


class HatchCppBuildPlan(HatchCppBuildConfig):
build_type: BuildType = "release"
commands: List[str] = Field(default_factory=list)

def generate(self):
self.commands = []
for library in self.libraries:
compile_flags = self.platform.get_compile_flags(library, self.build_type)
link_flags = self.platform.get_link_flags(library, self.build_type)
self.commands.append(
f"{self.platform.cc if library.language == 'c' else self.platform.cxx} {' '.join(library.sources)} {compile_flags} {link_flags}"
)
if self.libraries:
for library in self.libraries:
compile_flags = self.platform.get_compile_flags(library, self.build_type)
link_flags = self.platform.get_link_flags(library, self.build_type)
self.commands.append(
f"{self.platform.cc if library.language == 'c' else self.platform.cxx} {' '.join(library.sources)} {compile_flags} {link_flags}"
)
elif self.cmake:
# Derive prefix
if self.cmake.cmake_arg_prefix is None:
self.cmake.cmake_arg_prefix = f"{self.name.replace('.', '_').replace('-', '_').upper()}_"

# Append base command
self.commands.append(f"cmake {Path(self.cmake.root).parent} -DCMAKE_BUILD_TYPE={self.build_type} -B {self.cmake.build}")

# Setup install path
if self.cmake.install:
self.commands[-1] += f" -DCMAKE_INSTALL_PREFIX={self.cmake.install}"

Check warning on line 274 in hatch_cpp/structs.py

View check run for this annotation

Codecov/ codecov/patch

hatch_cpp/structs.py#L274

Added line #L274 was not covered by tests
else:
self.commands[-1] += f" -DCMAKE_INSTALL_PREFIX={Path(self.cmake.root).parent}"

# TODO: CMAKE_CXX_COMPILER
if self.platform.platform == "win32":
# TODO: prefix?
self.commands[-1] += f' -G "{environ.get("GENERATOR", "Visual Studio 17 2022")}"'

# Put in CMake flags
args = self.cmake.cmake_args.copy()
for platform, env_args in self.cmake.cmake_env_args.items():
if platform == self.platform.platform:
for key, value in env_args.items():
args[key] = value
for key, value in args.items():
self.commands[-1] += f" -D{self.cmake.cmake_arg_prefix}{key.upper()}={value}"

# Include customs
if self.cmake.include_flags:
if self.cmake.include_flags.get("python_version", False):
self.commands[-1] += f" -D{self.cmake.cmake_arg_prefix}PYTHON_VERSION={version_info.major}.{version_info.minor}"
if self.cmake.include_flags.get("manylinux", False) and self.platform.platform == "linux":
self.commands[-1] += f" -D{self.cmake.cmake_arg_prefix}MANYLINUX=ON"

Check warning on line 297 in hatch_cpp/structs.py

View check run for this annotation

Codecov/ codecov/patch

hatch_cpp/structs.py#L297

Added line #L297 was not covered by tests

# Include mac deployment target
if self.platform.platform == "darwin":
self.commands[-1] += f" -DCMAKE_OSX_DEPLOYMENT_TARGET={environ.get('OSX_DEPLOYMENT_TARGET', '11')}"

# Append build command
self.commands.append(f"cmake --build {self.cmake.build} --config {self.build_type}")

# Append install command
self.commands.append(f"cmake --install {self.cmake.build} --config {self.build_type}")

return self.commands

def execute(self):
for command in self.commands:
system(command)
system_call(command)
return self.commands

def cleanup(self):
if self.platform.platform == "win32":
for temp_obj in Path(".").glob("*.obj"):
temp_obj.unlink()


class HatchCppBuildConfig(BaseModel):
"""Build config values for Hatch C++ Builder."""

verbose: Optional[bool] = Field(default=False)
libraries: List[HatchCppLibrary] = Field(default_factory=list)
platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp