Skip to content

Commit 849a02b

Browse files
committed
More work on vcpkg toolchain, combining cmake and vcpkg toolchains
1 parent e49505d commit 849a02b

File tree

7 files changed

+90
-16
lines changed

7 files changed

+90
-16
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,6 @@ hatch_cpp/labextension
157157

158158
# Rust
159159
target
160+
161+
vcpkg
162+
vcpkg_installed

hatch_cpp/config.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
from __future__ import annotations
22

3+
from logging import getLogger
34
from os import system as system_call
45
from pathlib import Path
56
from typing import List, Optional
67

78
from pydantic import BaseModel, Field, model_validator
89

9-
from .toolchains import BuildType, HatchCppCmakeConfiguration, HatchCppLibrary, HatchCppPlatform, HatchCppVcpkgConfiguration
10+
from .toolchains import BuildType, HatchCppCmakeConfiguration, HatchCppLibrary, HatchCppPlatform, HatchCppVcpkgConfiguration, Toolchain
1011

1112
__all__ = (
1213
"HatchCppBuildConfig",
1314
"HatchCppBuildPlan",
1415
)
1516

1617

18+
_log = getLogger(__name__)
19+
20+
1721
class HatchCppBuildConfig(BaseModel):
1822
"""Build config values for Hatch C++ Builder."""
1923

@@ -22,7 +26,7 @@ class HatchCppBuildConfig(BaseModel):
2226
libraries: List[HatchCppLibrary] = Field(default_factory=list)
2327
cmake: Optional[HatchCppCmakeConfiguration] = Field(default=None)
2428
platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)
25-
vcpkg: Optional[HatchCppVcpkgConfiguration] = Field(default=None)
29+
vcpkg: Optional[HatchCppVcpkgConfiguration] = Field(default_factory=HatchCppVcpkgConfiguration)
2630

2731
@model_validator(mode="wrap")
2832
@classmethod
@@ -41,6 +45,8 @@ def validate_model(cls, data, handler):
4145
if "ld" in data:
4246
data["platform"].ld = data["ld"]
4347
data.pop("ld")
48+
if "vcpkg" in data and data["vcpkg"] == "false":
49+
data["vcpkg"] = None
4450
model = handler(data)
4551
if model.cmake and model.libraries:
4652
raise ValueError("Must not provide libraries when using cmake toolchain.")
@@ -51,20 +57,35 @@ class HatchCppBuildPlan(HatchCppBuildConfig):
5157
build_type: BuildType = "release"
5258
commands: List[str] = Field(default_factory=list)
5359

60+
_active_toolchains: List[Toolchain] = []
61+
5462
def generate(self):
5563
self.commands = []
5664

65+
# Evaluate toolchains
5766
if self.vcpkg and Path(self.vcpkg.vcpkg).exists():
58-
self.commands.extend(self.vcpkg.generate(self.platform))
59-
67+
self._active_toolchains.append("vcpkg")
6068
if self.libraries:
69+
self._active_toolchains.append("vanilla")
70+
elif self.cmake:
71+
self._active_toolchains.append("cmake")
72+
73+
# Collect toolchain commands
74+
if "vcpkg" in self._active_toolchains:
75+
self.commands.extend(self.vcpkg.generate(self))
76+
77+
if "vanilla" in self._active_toolchains:
78+
if "vcpkg" in self._active_toolchains:
79+
_log.warning("vcpkg toolchain is active; ensure that your compiler is configured to use vcpkg includes and libs.")
80+
6181
for library in self.libraries:
6282
compile_flags = self.platform.get_compile_flags(library, self.build_type)
6383
link_flags = self.platform.get_link_flags(library, self.build_type)
6484
self.commands.append(
6585
f"{self.platform.cc if library.language == 'c' else self.platform.cxx} {' '.join(library.sources)} {compile_flags} {link_flags}"
6686
)
67-
elif self.cmake:
87+
88+
if "cmake" in self._active_toolchains:
6889
self.commands.extend(self.cmake.generate(self))
6990

7091
return self.commands

hatch_cpp/tests/test_project_cmake_vcpkg/vcpkg.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "main",
33
"version-string": "latest",
44
"dependencies": [
5-
"arrow"
5+
"nlohmann-json"
66
],
77
"builtin-baseline": "b94ade01f19e4436d8c8a16a5c52e8c802ef67dd"
88
}

hatch_cpp/tests/test_project_pybind_vcpkg/vcpkg.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "main",
33
"version-string": "latest",
44
"dependencies": [
5-
"arrow"
5+
"nlohmann-json"
66
],
77
"builtin-baseline": "b94ade01f19e4436d8c8a16a5c52e8c802ef67dd"
88
}

hatch_cpp/toolchains/cmake.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111

1212
__all__ = ("HatchCppCmakeConfiguration",)
1313

14+
DefaultMSVCGenerator = {
15+
"12": "Visual Studio 12 2013",
16+
"14": "Visual Studio 14 2015",
17+
"14.0": "Visual Studio 14 2015",
18+
"14.1": "Visual Studio 15 2017",
19+
"14.2": "Visual Studio 16 2019",
20+
"14.3": "Visual Studio 17 2022",
21+
"14.4": "Visual Studio 17 2022",
22+
}
23+
1424

1525
class HatchCppCmakeConfiguration(BaseModel):
1626
root: Path
@@ -33,6 +43,10 @@ def generate(self, config) -> Dict[str, Any]:
3343
# Append base command
3444
commands.append(f"cmake {Path(self.root).parent} -DCMAKE_BUILD_TYPE={config.build_type} -B {self.build}")
3545

46+
# Hook in to vcpkg if active
47+
if "vcpkg" in config._active_toolchains:
48+
commands[-1] += f" -DCMAKE_TOOLCHAIN_FILE={Path(config.vcpkg.vcpkg_root) / 'scripts' / 'buildsystems' / 'vcpkg.cmake'}"
49+
3650
# Setup install path
3751
if self.install:
3852
commands[-1] += f" -DCMAKE_INSTALL_PREFIX={self.install}"
@@ -42,7 +56,7 @@ def generate(self, config) -> Dict[str, Any]:
4256
# TODO: CMAKE_CXX_COMPILER
4357
if config.platform.platform == "win32":
4458
# TODO: prefix?
45-
commands[-1] += f' -G "{environ.get("GENERATOR", "Visual Studio 17 2022")}"'
59+
commands[-1] += f' -G "{environ.get("CMAKE_GENERATOR", "Visual Studio 17 2022")}"'
4660

4761
# Put in CMake flags
4862
args = self.cmake_args.copy()

hatch_cpp/toolchains/common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
__all__ = (
1414
"BuildType",
1515
"CompilerToolchain",
16+
"Toolchain",
1617
"Language",
1718
"Binding",
1819
"Platform",
@@ -24,6 +25,7 @@
2425

2526
BuildType = Literal["debug", "release"]
2627
CompilerToolchain = Literal["gcc", "clang", "msvc"]
28+
Toolchain = Literal["vcpkg", "cmake", "vanilla"]
2729
Language = Literal["c", "c++"]
2830
Binding = Literal["cpython", "pybind11", "nanobind", "generic"]
2931
Platform = Literal["linux", "darwin", "win32"]

hatch_cpp/toolchains/vcpkg.py

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,64 @@
11
from __future__ import annotations
22

33
from pathlib import Path
4+
from platform import machine as platform_machine
45
from sys import platform as sys_platform
5-
from typing import Optional
6+
from typing import Literal, Optional
67

78
from pydantic import BaseModel, Field
89

910
__all__ = ("HatchCppVcpkgConfiguration",)
1011

1112

13+
VcpkgTriplet = Literal[
14+
"x64-android",
15+
"x64-osx",
16+
"x64-linux",
17+
"x64-uwp",
18+
"x64-windows",
19+
"x64-windows-release",
20+
"x64-windows-static",
21+
"x64-windows-static-md",
22+
"x86-windows",
23+
"arm-neon-android",
24+
"arm64-android",
25+
"arm64-osx",
26+
"arm64-uwp",
27+
"arm64-windows",
28+
"arm64-windows-static-md",
29+
]
30+
VcpkgPlatformDefaults = {
31+
("linux", "x86_64"): "x64-linux",
32+
# ("linux", "arm64"): "",
33+
("darwin", "x86_64"): "x64-osx",
34+
("darwin", "arm64"): "arm64-osx",
35+
("win32", "x86_64"): "x64-windows-static-md",
36+
("win32", "arm64"): "arm64-windows-static-md",
37+
}
38+
39+
1240
class HatchCppVcpkgConfiguration(BaseModel):
1341
vcpkg: Optional[str] = Field(default="vcpkg.json")
1442
vcpkg_root: Optional[Path] = Field(default=Path("vcpkg"))
1543
vcpkg_repo: Optional[str] = Field(default="https://github.com/microsoft/vcpkg.git")
44+
vcpkg_triplet: Optional[VcpkgTriplet] = Field(default=None)
45+
46+
# TODO: overlay
1647

1748
def generate(self, config):
1849
commands = []
1950

20-
if self.vcpkg and Path(self.vcpkg.vcpkg).exists():
21-
if not Path(self.vcpkg.vcpkg_root).exists():
22-
commands.append(f"git clone {self.vcpkg.vcpkg_repo} {self.vcpkg.vcpkg_root}")
51+
if self.vcpkg_triplet is None:
52+
self.vcpkg_triplet = VcpkgPlatformDefaults.get((sys_platform, platform_machine()))
53+
if self.vcpkg_triplet is None:
54+
raise ValueError(f"Could not determine vcpkg triplet for platform {sys_platform} and architecture {platform_machine()}")
55+
56+
if self.vcpkg and Path(self.vcpkg).exists():
57+
if not Path(self.vcpkg_root).exists():
58+
commands.append(f"git clone {self.vcpkg_repo} {self.vcpkg_root}")
2359
commands.append(
24-
f"./{self.vcpkg.vcpkg_root / 'bootstrap-vcpkg.sh' if sys_platform != 'win32' else self.vcpkg.vcpkg_root / 'sbootstrap-vcpkg.bat'}"
60+
f"./{self.vcpkg_root / 'bootstrap-vcpkg.sh' if sys_platform != 'win32' else self.vcpkg_root / 'sbootstrap-vcpkg.bat'}"
2561
)
26-
commands.append(
27-
f"./{self.vcpkg.vcpkg_root / 'vcpkg'} install --triplet {config.platform.platform}-{config.platform.toolchain} --manifest-root {Path(self.vcpkg.vcpkg).parent}"
28-
)
62+
commands.append(f"./{self.vcpkg_root / 'vcpkg'} install --triplet {self.vcpkg_triplet}")
2963

3064
return commands

0 commit comments

Comments
 (0)