diff --git a/.gitignore b/.gitignore index a090202..858d10c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,12 @@ __pycache__/ *$py.class # C extensions +*.a *.so +*.obj +*.dll +*.exp +*.lib # Distribution / packaging .Python diff --git a/hatch_cpp/plugin.py b/hatch_cpp/plugin.py index 0ce6f53..0de620f 100644 --- a/hatch_cpp/plugin.py +++ b/hatch_cpp/plugin.py @@ -49,6 +49,7 @@ def initialize(self, version: str, _: dict[str, t.Any]) -> None: for command in build_plan.commands: self._logger.info(command) build_plan.execute() + build_plan.cleanup() # build_kwargs = config.build_kwargs # if version == "editable": diff --git a/hatch_cpp/structs.py b/hatch_cpp/structs.py index 0412aef..cc9c99c 100644 --- a/hatch_cpp/structs.py +++ b/hatch_cpp/structs.py @@ -2,7 +2,8 @@ from dataclasses import dataclass, field from os import environ, system -from sys import platform as sys_platform +from pathlib import Path +from sys import executable, platform as sys_platform from sysconfig import get_path from typing import Literal @@ -80,7 +81,7 @@ def default() -> HatchCppPlatform: raise Exception(f"Unrecognized toolchain: {CC}, {CXX}") return HatchCppPlatform(cc=CC, cxx=CXX, platform=platform, toolchain=toolchain) - def get_flags(self, library: HatchCppLibrary) -> str: + def get_compile_flags(self, library: HatchCppLibrary) -> str: flags = "" if self.toolchain == "gcc": flags = f"-I{get_path('include')}" @@ -109,20 +110,28 @@ def get_flags(self, library: HatchCppLibrary) -> str: elif self.toolchain == "msvc": flags = f"/I{get_path('include')} " flags += " ".join(f"/I{d}" for d in library.include_dirs) - flags += " /LD" flags += " " + " ".join(library.extra_compile_args) flags += " " + " ".join(library.extra_link_args) flags += " " + " ".join(library.extra_objects) - flags += " " + " ".join(f"{lib}.lib" for lib in library.libraries) - flags += " " + " ".join(f"/LIBPATH:{lib}" for lib in library.library_dirs) flags += " " + " ".join(f"/D{macro}" for macro in library.define_macros) flags += " " + " ".join(f"/U{macro}" for macro in library.undef_macros) - flags += f" /Fo{library.name}.pyd" + flags += " /EHsc /DWIN32 /LD" + flags += f" /Fo:{library.name}.obj" + flags += f" /Fe:{library.name}.pyd" + flags += " /link /DLL" + if (Path(executable).parent / "libs").exists(): + flags += f" /LIBPATH:{str(Path(executable).parent / 'libs')}" + flags += " " + " ".join(f"{lib}.lib" for lib in library.libraries) + flags += " " + " ".join(f"/LIBPATH:{lib}" for lib in library.library_dirs) # clean while flags.count(" "): flags = flags.replace(" ", " ") return flags + def get_link_flags(self, library: HatchCppLibrary) -> str: + flags = "" + return flags + @dataclass class HatchCppBuildPlan(object): @@ -133,7 +142,7 @@ class HatchCppBuildPlan(object): def generate(self): self.commands = [] for library in self.libraries: - flags = self.platform.get_flags(library) + flags = self.platform.get_compile_flags(library) self.commands.append(f"{self.platform.cc} {' '.join(library.sources)} {flags}") return self.commands @@ -141,3 +150,10 @@ def execute(self): for command in self.commands: system(command) return self.commands + + def cleanup(self): + if self.platform.platform == "win32": + for library in self.libraries: + temp_obj = Path(f"{library.name}.obj") + if temp_obj.exists(): + temp_obj.unlink() diff --git a/hatch_cpp/tests/test_project_basic.py b/hatch_cpp/tests/test_project_basic.py index b70fff5..03de9f9 100644 --- a/hatch_cpp/tests/test_project_basic.py +++ b/hatch_cpp/tests/test_project_basic.py @@ -1,7 +1,8 @@ from os import listdir +from pathlib import Path from shutil import rmtree from subprocess import check_output -from sys import platform +from sys import path, platform class TestProject: @@ -20,3 +21,8 @@ def test_basic(self): assert "extension.pyd" in listdir("hatch_cpp/tests/test_project_basic/basic_project") else: assert "extension.so" in listdir("hatch_cpp/tests/test_project_basic/basic_project") + here = Path(__file__).parent / "test_project_basic" + path.insert(0, str(here)) + import basic_project.extension + + assert basic_project.extension.hello() == "A string"