Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update umbase to 0.1.7 #6

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
22 changes: 21 additions & 1 deletion recipes/umbase/StandardProjectSettings.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
include(GNUInstallDirs) # Standard install dirs

# Generate compile_commands.json to make it easier to work with clang based tools
message(STATUS "Generating compile commands to ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Ultimaker uniform Thread linking method
function(use_threads project_name)
message(STATUS "Enabling threading support for ${project_name}")
Expand Down Expand Up @@ -88,6 +92,22 @@ function(set_project_warnings project_name)
endif()
endfunction()

# This function will prevent in-source builds
function(AssureOutOfSourceBuilds)
# make sure the user doesn't play dirty with symlinks
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)

# disallow in-source builds
if("${srcdir}" STREQUAL "${bindir}")
message("######################################################")
message("Warning: in-source builds are disabled")
message("Please create a separate build directory and run cmake from there")
message("######################################################")
message(FATAL_ERROR "Quitting configuration")
endif()
endfunction()

function(enable_sanitizers project_name)

if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
Expand Down Expand Up @@ -194,4 +214,4 @@ if(ENABLE_INCLUDE_WHAT_YOU_USE)
else()
message(WARNING "include-what-you-use requested but executable not found")
endif()
endif()
endif()
165 changes: 17 additions & 148 deletions recipes/umbase/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import sys
import os
from os import path

from io import StringIO
from pathlib import Path
from typing import Optional

from conans import ConanFile, tools
from conans.errors import ConanException
from conan import ConanFile
from conan.tools.files import copy
from conan.tools.scm import Version
from conan.errors import ConanException


class UMBaseConanfile(object):
Expand All @@ -15,159 +12,31 @@ class UMBaseConanfile(object):
https://docs.conan.io/en/latest/extending/python_requires.html
"""

def _umdefault_version(self):
return list(self.conan_data)[0]

def _um_data(self) -> dict:
"""
Extract the version specific data out of a conandata.yml
"""
try:
recipe_version = self.version
except ConanException:
recipe_version = "None"

try:
channel = self.channel
except ConanException:
channel = ""

if channel:

if channel == "testing":
self.output.info(f"Using conandata.yml from channel: {channel}")
return self.conan_data["None"]

elif channel == "stable" or channel == "_" or channel == "":
if recipe_version:
if recipe_version in self.conan_data:
self.output.info(f"Using conandata.yml from channel: {channel} and recipe version: {recipe_version}")
return self.conan_data[recipe_version]

recipe_version = tools.Version(recipe_version)
all_versions = []
for k in self.conan_data:
try:
v = tools.Version(k)
except ConanException:
continue
all_versions.append(v)

# First try to find a version which might take into account prereleases
satifying_versions = sorted([v for v in all_versions if v <= recipe_version])
if len(satifying_versions) == 0:
# Then try to find a version which only takes into account major.minor.patch
satifying_versions = sorted([v for v in all_versions if tools.Version(f"{v.major}.{v.minor}.{v.patch}") <= tools.Version(f"{recipe_version.major}.{recipe_version.minor}.{recipe_version.patch}")])
if len(satifying_versions) == 0:
self.output.warn(f"Could not find a maximum satisfying version from channel: {channel} for {recipe_version} in {[str(v) for v in all_versions]}, defaulting to testing channel")
return self.conan_data["None"]
version = str(satifying_versions[-1])
self.output.info(f"Using conandata.yml from channel: {channel} and recipe version: {version}")
return self.conan_data[version]

elif channel in self.conan_data:
self.output.info(f"Using conandata.yml from channel: {channel}")
return self.conan_data[channel]

self.output.info(f"Using conandata.yml defaulting to testing channel")
return self.conan_data["None"]

@property
def _python_venv_bin_path(self) -> str:
if self.settings.os == "Windows":
return "Scripts"
return "bin"

@property
def _python_interp(self) -> str:
"""
The Python interpreter to use. If the recipe has `cpython` as a dependency it uses that interpreter otherwise it will use the system
interpreter. Which in this case is the same as the Conan version.
:return: str with the path to the Python interpreter
"""

if "cpython" in self.deps_user_info:
py_interp = Path(self.deps_user_info["cpython"].python)
else:
py_interp = Path(sys.executable)

# When on Windows execute as Windows Path
if self.settings.os == "Windows":
py_interp = Path(*[f'"{p}"' if " " in p else p for p in py_interp.parts])

return str(py_interp)

@property
def _py_venv_interp(self) -> str:
if self.__py_venv_interp is not None:
return self.__py_venv_interp
else:
self.output.warn("Virtual Python environment not yet generated, but requesting the path to interpreter")
py_venv_interp = Path(self.install_folder, self._venv_path, Path(sys.executable).stem + Path(sys.executable).suffix)

if self.settings.os == "Windows":
py_venv_interp = Path(*[f'"{p}"' if " " in p else p for p in py_venv_interp.parts])

return str(py_venv_interp)

@_py_venv_interp.setter
def _py_venv_interp(self, value: str):
self.__py_venv_interp = value

def _site_packages_path(self, interp: str) -> str:
buffer = StringIO()
outer = '"' if self.settings.os == "Windows" else "'"
inner = "'" if self.settings.os == "Windows" else '"'
self.run(f"{interp} -c {outer}import sysconfig; print(sysconfig.get_path({inner}purelib{inner})){outer}", env = "conanrun", output = buffer)
pythonpath = buffer.getvalue().splitlines()[-1]
return pythonpath

def _generate_virtual_python_env(self, *initial_reqs):
"""
Generates a virtual Python Environment and initializes is

TODO: Check if we aren't in an actual virtual Python environment yet. Because running a venv in a venv is asking for troubles

:param initial_reqs: Python modules which should be installed (strings)
"""
self.output.info("Generating virtual Python environment")
self.run(f"{self._python_interp} -m venv {self.install_folder}", run_environment = True, env = "conanrun")

# Make sure there executable is named the same on all three OSes this allows it to be called with `python`
# simplifying GH Actions steps
if self.settings.os != "Windows":
py_venv_interp = Path(self.install_folder, self._python_venv_bin_path, "python")
if not py_venv_interp.exists():
py_venv_interp.hardlink_to(Path(self.install_folder, self._python_venv_bin_path, Path(sys.executable).stem + Path(sys.executable).suffix))
else:
py_venv_interp = Path(self.install_folder, self._python_venv_bin_path, Path(sys.executable).stem + Path(sys.executable).suffix)

if not py_venv_interp.exists():
raise ConanException(f"Virtual environment Python interpreter not found at: {py_venv_interp}")
if self.settings.os == "Windows":
py_venv_interp = Path(*[f'"{p}"' if " " in p else p for p in py_venv_interp.parts])

# Updating the run environment
self.runenv_info.define_path("VIRTUAL_ENV", self.install_folder)
self.runenv_info.prepend_path("PATH", os.path.join(self.install_folder, self._python_venv_bin_path))
self.runenv_info.prepend_path("PYTHONPATH", self._site_packages_path(py_venv_interp))
self.runenv_info.unset("PYTHONHOME")

# Installing the initial_reqs
reqs = " ".join(initial_reqs)
self.run(f"{py_venv_interp} -m pip install {reqs}", run_environment = True, env = "conanrun")

self.output.success(f"Created a Virtual Python Environment in {self.install_folder}")
self._py_venv_interp = str(py_venv_interp)
if self.version in self.conan_data:
return self.conan_data[self.version]

recipe_version = Version(self.version)
available_versions = max(sorted([version for version in self.conan_data.keys() if Version(version) <= recipe_version]))
self.output.warn(f"Using dependencies specified in conandata.yml for version: {available_versions} while recipe is build for version: {self.version}")
return self.conan_data[available_versions]

class Pkg(ConanFile):
name = "umbase"
version = "0.1.6"
version = "0.1.7"
default_user = "ultimaker"
default_channel = "stable"
exports_sources = "StandardProjectSettings.cmake"

def package(self):
self.copy("StandardProjectSettings.cmake", "cmake")
copy(self, "StandardProjectSettings.cmake", src = self.export_sources_folder, dst = path.join(self.package_folder, "share", "cmake"))

def package_info(self):
self.cpp_info.set_property("name", "umbase")
self.cpp_info.set_property("cmake_build_modules", [os.path.join("cmake", "StandardProjectSettings.cmake")])
self.cpp_info.set_property("cmake_build_modules", [path.join("share", "cmake", "StandardProjectSettings.cmake")])