Skip to content

Commit

Permalink
Check absolute minumum CMake requirement (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
tttapa committed May 20, 2022
1 parent cc72fc7 commit c9a3950
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 25 deletions.
2 changes: 1 addition & 1 deletion examples/minimal-program/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.15)
project(minimal-program-dev)

# You can add development-specific options here, such as warnings, tests,
Expand Down
1 change: 1 addition & 0 deletions examples/minimal-program/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ directory = "src-python"
include = ["CMakeLists.txt", "src/*"]

[tool.py-build-cmake.cmake]
minimum_version = "3.15"
build_type = "RelWithDebInfo"
source_path = "src"
build_args = ["-j"]
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal-program/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.15)
project(minimal-program)

# Add the executable to compile
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.17)
project(minimal-dev)

# You can add development-specific options here, such as warnings, tests,
Expand Down
5 changes: 5 additions & 0 deletions examples/minimal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ You can use the `exclude` option to exclude specific files.

```toml
[tool.py-build-cmake.cmake]
minimum_version = "3.17"
build_type = "RelWithDebInfo"
source_path = "src"
build_args = ["-j"]
Expand All @@ -187,6 +188,10 @@ project. The most important option is the `source_path`, the folder containing
your main CMakeLists.txt file. The `-j` flag enables parallel builds, and the
`install_components` option defines which CMake components to install. In this
example, the `python_modules` component is defined in src/CMakeLists.txt.
The `minimum_version` option defines which version of CMake is required to build
this project. If this version or newer is not found in the PATH, it is added as
a build requirement and installed by the build frontend (e.g. pip) before
building.
There are many other options, see the py-build-cmake documentation for more
details.

Expand Down
1 change: 1 addition & 0 deletions examples/minimal/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ directory = "src-python"
include = ["CMakeLists.txt", "src/*"]

[tool.py-build-cmake.cmake]
minimum_version = "3.17"
build_type = "RelWithDebInfo"
source_path = "src"
build_args = ["-j"]
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.17)
project(minimal)

# Find the Python development files
Expand Down
2 changes: 1 addition & 1 deletion examples/pybind11-project/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.17)
project(py-build-cmake VERSION 0.0.11)
set(PY_VERSION_SUFFIX "a0")
set(PY_FULL_VERSION ${PROJECT_VERSION}${PY_VERSION_SUFFIX})
Expand Down
2 changes: 1 addition & 1 deletion examples/pybind11-project/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ include = ["CMakeLists.txt", "cmake/*.cmake", "src/*.cpp", "src/*.hpp"]
exclude = []

[tool.py-build-cmake.cmake]
minimum_version = "3.18"
minimum_version = "3.17"
build_type = "Release"
source_path = "." # Containing CMakeLists.txt
options = { "WITH_PY_STUBS:BOOL" = "On" }
Expand Down
47 changes: 28 additions & 19 deletions src/py_build_cmake/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

from .config import Config

from distlib.version import NormalizedVersion

_CMAKE_MINIMUM_REQUIRED = NormalizedVersion('3.15')


class _BuildBackend(object):

Expand All @@ -23,13 +27,12 @@ def __init__(self) -> None:
def check_program_version(
self,
program: str,
minimum_version: Optional[str],
minimum_version: Optional[NormalizedVersion],
name: Optional[str],
check_version: bool = True,
):
"""Check if there's a new enough version of the given command available
in PATH."""
from distlib.version import NormalizedVersion
name = name or program
try:
# Try running the command
Expand All @@ -43,8 +46,8 @@ def check_program_version(
program_version = NormalizedVersion(m.group(0))
if self.verbose: print("Found", name, program_version)
# Check if the version is new enough
if minimum_version:
if program_version < NormalizedVersion(minimum_version):
if minimum_version is not None:
if program_version < minimum_version:
raise RuntimeError(f"{name} too old")
except CalledProcessError as e:
if self.verbose:
Expand Down Expand Up @@ -76,27 +79,33 @@ def get_requires_for_build_wheel(self, config_settings=None):

def check_cmake_program(self, cfg: Config, deps: List[str]):
assert cfg.cmake
min_cmake_ver = cfg.cmake[self.get_os_name()].get('minimum_version')
# If CMake in PATH doesn't work, add it as a build requirement
# Do we need to perform a native build?
native = not cfg.cross or self.needs_cross_native_build(cfg)
native_cfg = cfg.cmake[self.get_os_name()] if native else {}
# Do we need to perform a cross build?
cross = cfg.cross
cross_cfg = cfg.cmake.get('cross', {})
# Find the strictest version requirement
min_cmake_ver = max(
_CMAKE_MINIMUM_REQUIRED,
NormalizedVersion(native_cfg.get('minimum_version', '0.0')),
NormalizedVersion(cross_cfg.get('minimum_version', '0.0')),
)
# If CMake in PATH doesn't work or is too old, add it as a build
# requirement
if not self.check_program_version('cmake', min_cmake_ver, "CMake"):
req = "cmake"
if min_cmake_ver: req += ">=" + min_cmake_ver
deps.append(req)
deps.append("cmake>=" + str(min_cmake_ver))

# Check if we need Ninja
cfgs = []
# Native build?
native = not cfg.cross
crossnative = self.needs_cross_native_build(cfg)
if native or crossnative:
cfgs.append(cfg.cmake[self.get_os_name()])
# Cross build?
cross = cfg.cross
if cross:
cfgs.append(cfg.cmake['cross'])
# Do any of the configs need Ninja as a generator?
if native: cfgs.append(native_cfg)
if cross: cfgs.append(cross_cfg)
# Do any of the configs require Ninja as a generator?
needs_ninja = lambda c: 'ninja' in c.get('generator', '').lower()
need_ninja = any(map(needs_ninja, cfgs))
if need_ninja:
# If so, check if a working version exists in the PATH, otherwise,
# add it as a build requirement
if not self.check_program_version('ninja', None, "Ninja"):
deps.append("ninja")

Expand Down

0 comments on commit c9a3950

Please sign in to comment.