Skip to content

Commit

Permalink
Support conan version 1 & 2
Browse files Browse the repository at this point in the history
  • Loading branch information
henryborchers committed Oct 11, 2023
1 parent c13df02 commit 2789ff3
Show file tree
Hide file tree
Showing 11 changed files with 545 additions and 222 deletions.
10 changes: 7 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ dependencies = [
'wheel',
"cmake",
'pybind11~=2.10.1',
"conan>=1.53,!=1.55.0,<2.0",
"conan",
'toml'
]
license = {text = "University of Illinois/NCSA Open Source License"}
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.8"
[tool.setuptools.dynamic]
version = {attr = "uiucprescon.build.VERSION"}

[tool.setuptools]
packages = ['uiucprescon.build']
packages = [
'uiucprescon.build',
'uiucprescon.build.conan',
]


[tool.coverage.run]
relative_files = false
Expand Down
30 changes: 15 additions & 15 deletions tests/test_conan_libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ def test_get_conan_options_localbuilder(tmp_path, monkeypatch):
conan_libs.get_conan_options()


def test_build_deps_with_conan_calls_install(tmp_path, monkeypatch):
build_dir = tmp_path / "build"
install_dir = tmp_path / "install"
conan_cache = tmp_path / "conan_cache"
build_dir.mkdir()
conan_object = Mock()
monkeypatch.setattr(conan_libs.conan_api, "Conan", Mock(return_value=conan_object))
conan_libs.build_deps_with_conan(
build_dir,
install_dir,
"libstdc",
"14.3",
conan_cache=conan_cache
)
assert conan_object.install.called
# def test_build_deps_with_conan_calls_install(tmp_path, monkeypatch):
# build_dir = tmp_path / "build"
# install_dir = tmp_path / "install"
# conan_cache = tmp_path / "conan_cache"
# build_dir.mkdir()
# conan_object = Mock()
# monkeypatch.setattr(conan_libs.conan_api, "Conan", Mock(return_value=conan_object))
# conan_libs.build_deps_with_conan(
# build_dir,
# install_dir,
# "libstdc",
# "14.3",
# conan_cache=conan_cache
# )
# assert conan_object.install.called
2 changes: 1 addition & 1 deletion tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_conan_integration(tmp_path, monkeypatch):

conanfile = source_root / "conanfile.py"
conanfile.write_text("""
from conans import ConanFile
from conan import ConanFile
class Dummy(ConanFile):
requires = []
""")
Expand Down
26 changes: 25 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
[tox]
envlist = py{38,39,310,311,312}
envlist = py3{8,9,10,11,12}-{conan_v1,conan_v2}
isolated_build = true

[testenv]
deps =
pytest
commands = pytest --basetemp={envtmpdir} {env:pytest_args:} {posargs}

[testenv:py3{8,9,10,11}-conan_v1]
deps =
pytest
conan>=1.53,!=1.55.0,<2.0
set_env =
CONAN_USER_HOME={envtmpdir}/conan
commands_pre =
conan config init
python ci/docker/linux/shared/update_conan_compiler.py {envtmpdir}/conan/.conan/settings.yml gcc 11.4
commands =
pytest --basetemp={envtmpdir}/pytest {env:pytest_args:} {posargs}

[testenv:py3{8,9,10,11,12}-conan_v2]
deps =
pytest
conan>=2.0
commands = pytest --basetemp={envtmpdir} {env:pytest_args:} {posargs}


[testenv:mypy]
deps =
mypy
Expand Down
6 changes: 4 additions & 2 deletions uiucprescon/build/compiler_info.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import platform
import re
import sys
from uiucprescon.build.errors import PlatformError, ExecError
import subprocess
import os

from uiucprescon.build.errors import PlatformError, ExecError

__all__ = [
'get_compiler_version',
'get_compiler_name'
Expand Down Expand Up @@ -31,7 +33,7 @@ def get_compiler_name() -> str:
file=sys.stderr
)
raise

raise ValueError("Unable to locate compiler or unknown compiler")

if sys.platform == 'darwin':
_cfg_target = None
Expand Down
7 changes: 7 additions & 0 deletions uiucprescon/build/conan/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from importlib.metadata import version as _version
if _version('conan')[0] == "2":
from . import v2 as conan_api
else:
from . import v1 as conan_api

__all__ = ['conan_api']
132 changes: 132 additions & 0 deletions uiucprescon/build/conan/files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from typing import List, Dict, TypedDict, Iterable, Any
import abc


class ConanBuildInfoParser:
def __init__(self, fp):
self._fp = fp

def parse(self) -> Dict[str, List[str]]:
data = {}
for subject_chunk in self.iter_subject_chunk():
subject_title = subject_chunk[0][1:-1]

data[subject_title] = subject_chunk[1:]
return data

def iter_subject_chunk(self) -> Iterable[Any]:
buffer = []
for line in self._fp:
line = line.strip()
if len(line) == 0:
continue
if line.startswith("[") and line.endswith("]") and len(buffer) > 0:
yield buffer
buffer.clear()
buffer.append(line)
yield buffer
buffer.clear()


class ConanLibraryMetadata(TypedDict):
libs: List[str]
includedirs: List[str]
libdirs: List[str]
bindirs: List[str]
resdirs: List[str]
builddirs: List[str]
system_libs: List[str]
defines: List[str]
cppflags: List[str]
cxxflags: List[str]
cflags: List[str]
sharedlinkflags: List[str]
exelinkflags: List[str]
sysroot: List[str]
frameworks: List[str]
frameworkdirs: List[str]
rootpath: List[str]
name: List[str]
version: List[str]
generatornames: List[str]
generatorfilenames: List[str]


class AbsConanBuildInfo(abc.ABC):
@abc.abstractmethod
def parse(self, filename: str) -> Dict[str, str]:
pass


class ConanBuildInfo(TypedDict):
definitions: List[str]
include_paths: List[str]
lib_paths: List[str]
bin_paths: List[str]
libs: List[str]
metadata: Dict[str, ConanLibraryMetadata]


class ConanBuildInfoTXT(AbsConanBuildInfo):

def parse(self, filename: str) -> ConanBuildInfo:
# def parse(self, filename: str) -> Dict[str, Union[str, List[str]]]:
with open(filename, "r", encoding="utf-8") as f:
parser = ConanBuildInfoParser(f)
data = parser.parse()
definitions = data['defines']
include_paths = data['includedirs']
lib_paths = data['libdirs']
bin_paths = data['bindirs']
libs = data['libs']
names: List[str] = [
value.replace("name_", "")
for value in data
if value.startswith("name_")
]
# print(names)
libsmetadata: Dict[str, ConanLibraryMetadata] = {}
for library_name in names:
version = data.get(f"version_{library_name}", None)
libsmetadata[library_name] = {
"libs": data.get(f"libs_{library_name}", []),
"includedirs": data.get(f"includedirs_{library_name}", []),
"libdirs": data.get(f"libdirs_{library_name}", []),
"bindirs": data.get(f"bindirs_{library_name}", []),
"resdirs": data.get(f"resdirs_{library_name}", []),
"builddirs": data.get(f"builddirs_{library_name}", []),
"system_libs":
data.get(f"system_libs_{library_name}", []),
"defines":
data.get(f"defines_{library_name}", []),
"cppflags":
data.get(f"cppflags_{library_name}", []),
"cxxflags":
data.get(f"cxxflags_{library_name}", []),
"cflags": data.get(f"cflags_{library_name}", []),
"sharedlinkflags":
data.get(f"sharedlinkflags_{library_name}", []),
"exelinkflags":
data.get(f"exelinkflags_{library_name}", []),
"sysroot": data.get(f"sysroot_{library_name}", []),
"frameworks":
data.get(f"frameworks_{library_name}", []),
"frameworkdirs":
data.get(f"frameworkdirs_{library_name}", []),
"rootpath": data.get(f"rootpath_{library_name}", []),
"name": library_name,
"version": version[0] if version else None,
"generatornames":
data.get(f"generatornames_{library_name}", []),
"generatorfilenames":
data.get(f"generatorfilenames_{library_name}", []),
}
return {
"definitions": definitions,
"include_paths": list(include_paths),
"lib_paths": list(lib_paths),
"bin_paths": list(bin_paths),
"libs": list(libs),
"metadata": libsmetadata

}
Loading

0 comments on commit 2789ff3

Please sign in to comment.