proj-flow 0.20.3__py3-none-any.whl → 0.22.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- proj_flow/__init__.py +1 -1
- proj_flow/api/arg.py +2 -0
- proj_flow/api/completers.py +1 -1
- proj_flow/api/env.py +45 -15
- proj_flow/api/release.py +1 -1
- proj_flow/api/step.py +20 -5
- proj_flow/{ext/cplusplus/cmake/presets.py → base/cmake_presets.py} +40 -16
- proj_flow/base/plugins.py +12 -7
- proj_flow/cli/finder.py +4 -3
- proj_flow/dependency.py +6 -2
- proj_flow/ext/cplusplus/cmake/__init__.py +2 -2
- proj_flow/ext/cplusplus/cmake/parser.py +4 -3
- proj_flow/ext/cplusplus/cmake/steps.py +9 -9
- proj_flow/ext/cplusplus/conan/__init__.py +8 -4
- proj_flow/ext/github/cli.py +1 -3
- proj_flow/ext/github/publishing.py +1 -0
- proj_flow/ext/python/rtdocs.py +37 -8
- proj_flow/ext/python/steps.py +5 -4
- proj_flow/ext/python/version.py +12 -12
- proj_flow/ext/sign/__init__.py +2 -2
- proj_flow/ext/test_runner/__init__.py +6 -0
- proj_flow/ext/test_runner/cli.py +416 -0
- proj_flow/ext/test_runner/driver/__init__.py +2 -0
- proj_flow/ext/test_runner/driver/commands.py +74 -0
- proj_flow/ext/test_runner/driver/test.py +610 -0
- proj_flow/ext/test_runner/driver/testbed.py +141 -0
- proj_flow/ext/test_runner/utils/__init__.py +2 -0
- proj_flow/ext/test_runner/utils/archives.py +56 -0
- proj_flow/log/rich_text/api.py +3 -4
- proj_flow/minimal/list.py +126 -10
- proj_flow/minimal/run.py +3 -2
- proj_flow/project/api.py +1 -0
- {proj_flow-0.20.3.dist-info → proj_flow-0.22.0.dist-info}/METADATA +17 -7
- {proj_flow-0.20.3.dist-info → proj_flow-0.22.0.dist-info}/RECORD +37 -29
- {proj_flow-0.20.3.dist-info → proj_flow-0.22.0.dist-info}/WHEEL +0 -0
- {proj_flow-0.20.3.dist-info → proj_flow-0.22.0.dist-info}/entry_points.txt +0 -0
- {proj_flow-0.20.3.dist-info → proj_flow-0.22.0.dist-info}/licenses/LICENSE +0 -0
proj_flow/__init__.py
CHANGED
proj_flow/api/arg.py
CHANGED
proj_flow/api/completers.py
CHANGED
|
@@ -57,7 +57,7 @@ def _str_arg(arg: Union[bool, str]):
|
|
|
57
57
|
def matrix_completer(prefix: str, parser, **kwargs):
|
|
58
58
|
flow_cfg = cast(api.env.FlowConfig, parser.flow)
|
|
59
59
|
|
|
60
|
-
matrix_yml =
|
|
60
|
+
matrix_yml = flow_cfg.root / ".flow" / "matrix.yml"
|
|
61
61
|
with open(matrix_yml, "r", encoding="UTF-8") as contents:
|
|
62
62
|
data: Dict[str, List[Any]] = yaml.load(contents, Loader=yaml.Loader).get(
|
|
63
63
|
"matrix", {}
|
proj_flow/api/env.py
CHANGED
|
@@ -21,10 +21,12 @@ import subprocess
|
|
|
21
21
|
import sys
|
|
22
22
|
from dataclasses import dataclass
|
|
23
23
|
from enum import Enum
|
|
24
|
+
from pathlib import Path
|
|
24
25
|
from typing import Any, Callable, Dict, List, Optional, Union, cast
|
|
25
26
|
|
|
26
27
|
from proj_flow.api import ctx
|
|
27
28
|
from proj_flow.base import plugins, uname
|
|
29
|
+
from proj_flow.base.cmake_presets import get_binary_dirs
|
|
28
30
|
|
|
29
31
|
platform = uname.uname()[0]
|
|
30
32
|
|
|
@@ -32,6 +34,25 @@ platform = uname.uname()[0]
|
|
|
32
34
|
_flow_config_default_compiler: Optional[Dict[str, str]] = None
|
|
33
35
|
|
|
34
36
|
|
|
37
|
+
class CMakeBinaryDirsCache:
|
|
38
|
+
_dirs: dict[str, Path] | None = None
|
|
39
|
+
_loaded: bool = False
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def dirs(self):
|
|
43
|
+
if not self._loaded:
|
|
44
|
+
self._loaded = True
|
|
45
|
+
self._dirs = get_binary_dirs()
|
|
46
|
+
|
|
47
|
+
return self._dirs
|
|
48
|
+
|
|
49
|
+
def binary_dir(self, key: str):
|
|
50
|
+
return (self.dirs or {}).get(key)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
CMAKE_BINARY_DIRS = CMakeBinaryDirsCache()
|
|
54
|
+
|
|
55
|
+
|
|
35
56
|
def default_compiler():
|
|
36
57
|
try:
|
|
37
58
|
return os.environ["DEV_CXX"]
|
|
@@ -152,7 +173,7 @@ def _flatten_dict(dst: ctx.SettingsType, defaults: Dict[str, Any], prefix=""):
|
|
|
152
173
|
dst[this_key] = str(val)
|
|
153
174
|
|
|
154
175
|
|
|
155
|
-
def _merge(cfg: dict, defaults: ctx.SettingsType, path:
|
|
176
|
+
def _merge(cfg: dict, defaults: ctx.SettingsType, path: Path):
|
|
156
177
|
config = plugins.load_data(path)
|
|
157
178
|
if not isinstance(config, dict):
|
|
158
179
|
return
|
|
@@ -173,35 +194,41 @@ def load_extensions(extensions: List[str]):
|
|
|
173
194
|
for extension in extensions:
|
|
174
195
|
try:
|
|
175
196
|
importlib.import_module(extension)
|
|
176
|
-
except
|
|
197
|
+
except ImportError as ex:
|
|
198
|
+
print(
|
|
199
|
+
f"-- error: loading module `{extension}` resulted in import error: {ex}",
|
|
200
|
+
file=sys.stderr,
|
|
201
|
+
)
|
|
202
|
+
except BaseException as ex:
|
|
177
203
|
print(
|
|
178
|
-
f"-- error: module `{extension}
|
|
204
|
+
f"-- error: there was an error while loading module `{extension}`: {ex}",
|
|
179
205
|
file=sys.stderr,
|
|
180
206
|
)
|
|
181
207
|
|
|
208
|
+
|
|
182
209
|
class FlowConfig:
|
|
183
210
|
_cfg: dict
|
|
184
211
|
steps: list = []
|
|
185
212
|
aliases: List[RunAlias] = []
|
|
186
|
-
root:
|
|
213
|
+
root: Path
|
|
187
214
|
|
|
188
|
-
def __init__(self, cfg: Optional["FlowConfig"] = None, root:
|
|
215
|
+
def __init__(self, cfg: Optional["FlowConfig"] = None, root: Path = Path()):
|
|
189
216
|
if cfg is not None:
|
|
190
217
|
self._cfg = cfg._cfg
|
|
191
218
|
self.steps = cfg.steps
|
|
192
219
|
self.aliases = cfg.aliases
|
|
193
220
|
self.root = cfg.root
|
|
194
221
|
else:
|
|
195
|
-
self.root =
|
|
222
|
+
self.root = root.absolute()
|
|
196
223
|
defaults: ctx.SettingsType = {}
|
|
197
224
|
dest: dict = {}
|
|
198
225
|
|
|
199
226
|
_merge(
|
|
200
227
|
dest,
|
|
201
228
|
defaults,
|
|
202
|
-
|
|
229
|
+
Path("~").expanduser() / ".config" / "proj-flow.json",
|
|
203
230
|
)
|
|
204
|
-
_merge(dest, defaults,
|
|
231
|
+
_merge(dest, defaults, self.root / ".flow" / "config.json")
|
|
205
232
|
|
|
206
233
|
self._cfg = dest
|
|
207
234
|
self._cfg["defaults"] = defaults
|
|
@@ -217,11 +244,9 @@ class FlowConfig:
|
|
|
217
244
|
extensions = cast(List[str], self._cfg.get("extensions", []))
|
|
218
245
|
extensions.insert(0, "proj_flow.minimal")
|
|
219
246
|
|
|
220
|
-
local_extensions =
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if os.path.isdir(local_extensions):
|
|
224
|
-
sys.path.insert(0, local_extensions)
|
|
247
|
+
local_extensions = (self.root / ".flow" / "extensions").resolve()
|
|
248
|
+
if local_extensions.is_dir():
|
|
249
|
+
sys.path.insert(0, local_extensions.as_posix())
|
|
225
250
|
|
|
226
251
|
load_extensions(extensions)
|
|
227
252
|
|
|
@@ -459,8 +484,13 @@ class Config:
|
|
|
459
484
|
return self.items.get("build_name", "")
|
|
460
485
|
|
|
461
486
|
@property
|
|
462
|
-
def build_dir(self) ->
|
|
463
|
-
|
|
487
|
+
def build_dir(self) -> Path:
|
|
488
|
+
cmake_binary_dir = CMAKE_BINARY_DIRS.binary_dir(
|
|
489
|
+
f"{self.preset}-{self.build_generator}"
|
|
490
|
+
)
|
|
491
|
+
if cmake_binary_dir:
|
|
492
|
+
return cmake_binary_dir
|
|
493
|
+
return Path("build") / self.preset
|
|
464
494
|
|
|
465
495
|
@property
|
|
466
496
|
def preset(self) -> str:
|
proj_flow/api/release.py
CHANGED
|
@@ -113,5 +113,5 @@ def get_project(rt: env.Runtime):
|
|
|
113
113
|
|
|
114
114
|
_, project = project_suites.find(wrap)
|
|
115
115
|
if project is None:
|
|
116
|
-
rt.fatal(f"Cannot get project information from {rt.root}")
|
|
116
|
+
rt.fatal(f"Cannot get project information from {rt.root.as_posix()}")
|
|
117
117
|
return project
|
proj_flow/api/step.py
CHANGED
|
@@ -7,6 +7,7 @@ The **proj_flow.api.step** exposes APIs used by run extensions.
|
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
9
|
from abc import ABC, abstractmethod
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from typing import List, cast
|
|
11
12
|
|
|
12
13
|
from proj_flow.api.env import Config, Runtime
|
|
@@ -34,7 +35,7 @@ class Step(ABC):
|
|
|
34
35
|
def is_active(self, config: Config, rt: Runtime) -> bool:
|
|
35
36
|
return True
|
|
36
37
|
|
|
37
|
-
def directories_to_remove(self, config: Config) -> List[
|
|
38
|
+
def directories_to_remove(self, config: Config) -> List[Path]:
|
|
38
39
|
return []
|
|
39
40
|
|
|
40
41
|
@abstractmethod
|
|
@@ -59,7 +60,7 @@ class SerialStep(Step):
|
|
|
59
60
|
return False
|
|
60
61
|
return True
|
|
61
62
|
|
|
62
|
-
def directories_to_remove(self, config: Config) -> List[
|
|
63
|
+
def directories_to_remove(self, config: Config) -> List[Path]:
|
|
63
64
|
return matrix.flatten(
|
|
64
65
|
[child.directories_to_remove(config) for child in self.children]
|
|
65
66
|
)
|
|
@@ -87,8 +88,10 @@ def _register_step(step: Step, replace: bool):
|
|
|
87
88
|
return
|
|
88
89
|
|
|
89
90
|
if "READTHEDOCS" not in os.environ:
|
|
90
|
-
raise NameError(
|
|
91
|
-
|
|
91
|
+
raise NameError(
|
|
92
|
+
f"Step {name} is marked as replacing, but there is no previous step with that name"
|
|
93
|
+
)
|
|
94
|
+
|
|
92
95
|
if name in [step.name for step in __steps]:
|
|
93
96
|
if "READTHEDOCS" not in os.environ:
|
|
94
97
|
raise NameError(f"Step {name} already registered")
|
|
@@ -133,6 +136,12 @@ def _make_private(f: _inspect.Function):
|
|
|
133
136
|
f.__doc__ = ":meta private:\n"
|
|
134
137
|
|
|
135
138
|
|
|
139
|
+
def _make_private_property(f):
|
|
140
|
+
if isinstance(f, property):
|
|
141
|
+
_make_private(cast(_inspect.Function, f))
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
|
|
136
145
|
_dummy_config = Config(
|
|
137
146
|
{
|
|
138
147
|
"os": "${os}",
|
|
@@ -154,7 +163,10 @@ def _extend_docstring(conv, step: Step):
|
|
|
154
163
|
_name_list("Requires", step.platform_dependencies(), template="``{}``"),
|
|
155
164
|
_name_list(
|
|
156
165
|
"Removes",
|
|
157
|
-
|
|
166
|
+
[
|
|
167
|
+
dirname.as_posix()
|
|
168
|
+
for dirname in step.directories_to_remove(_dummy_config)
|
|
169
|
+
],
|
|
158
170
|
template="``{}``",
|
|
159
171
|
),
|
|
160
172
|
)
|
|
@@ -163,6 +175,9 @@ def _extend_docstring(conv, step: Step):
|
|
|
163
175
|
doc = conv.__doc__ or "*Docstring is missing!*"
|
|
164
176
|
conv.__doc__ = f"{doc}\n{info}"
|
|
165
177
|
|
|
178
|
+
_make_private_property(conv.name)
|
|
179
|
+
_make_private_property(conv.runs_before)
|
|
180
|
+
_make_private_property(conv.runs_after)
|
|
166
181
|
_make_private(conv.is_active)
|
|
167
182
|
_make_private(conv.run)
|
|
168
183
|
_make_private(conv.platform_dependencies)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
The **proj_flow.
|
|
5
|
+
The **proj_flow.project.cplusplus.cmake_presets** check build directories for CMake step.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import json
|
|
@@ -11,7 +11,7 @@ import platform
|
|
|
11
11
|
from dataclasses import dataclass
|
|
12
12
|
from enum import Enum
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import cast
|
|
14
|
+
from typing import Callable, TypeVar, cast
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class MacroType(Enum):
|
|
@@ -40,6 +40,7 @@ MACROS: dict[str, Path | str | MacroType] = {
|
|
|
40
40
|
class Preset:
|
|
41
41
|
name: str
|
|
42
42
|
binary_dir: str | None
|
|
43
|
+
build_type: str | None
|
|
43
44
|
generator: str | None
|
|
44
45
|
inherits: list[str]
|
|
45
46
|
file_dir: Path
|
|
@@ -82,12 +83,15 @@ class Presets:
|
|
|
82
83
|
if dirname is None:
|
|
83
84
|
return self.result
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
self.
|
|
86
|
+
try:
|
|
87
|
+
includes, presets = Presets.__load_file(filename)
|
|
88
|
+
self.__visit_includes(dirname, includes)
|
|
89
|
+
for preset in presets:
|
|
90
|
+
self.__visit_preset(dirname, preset)
|
|
91
|
+
for preset in self.result.values():
|
|
92
|
+
self.__merge_preset(preset)
|
|
93
|
+
except FileNotFoundError:
|
|
94
|
+
return None
|
|
91
95
|
|
|
92
96
|
return self.result
|
|
93
97
|
|
|
@@ -109,9 +113,12 @@ class Presets:
|
|
|
109
113
|
binary_dir = cast(str | None, preset.get("binaryDir"))
|
|
110
114
|
generator = cast(str | None, preset.get("generator"))
|
|
111
115
|
inherits = cast(list[str], preset.get("inherits", []))
|
|
116
|
+
cache = cast(dict, preset.get("cacheVariables", {}))
|
|
117
|
+
build_type = cast(str | None, cache.get("CMAKE_BUILD_TYPE"))
|
|
112
118
|
self.result[name] = Preset(
|
|
113
119
|
name=name,
|
|
114
120
|
binary_dir=binary_dir,
|
|
121
|
+
build_type=build_type,
|
|
115
122
|
generator=generator,
|
|
116
123
|
inherits=inherits,
|
|
117
124
|
file_dir=dirname,
|
|
@@ -132,6 +139,8 @@ class Presets:
|
|
|
132
139
|
preset.binary_dir = parent_preset.binary_dir
|
|
133
140
|
if parent_preset.generator and not preset.generator:
|
|
134
141
|
preset.generator = parent_preset.generator
|
|
142
|
+
if parent_preset.build_type and not preset.build_type:
|
|
143
|
+
preset.build_type = parent_preset.build_type
|
|
135
144
|
|
|
136
145
|
@staticmethod
|
|
137
146
|
def __load_file(filename: Path):
|
|
@@ -143,18 +152,33 @@ class Presets:
|
|
|
143
152
|
return (includes, presets)
|
|
144
153
|
|
|
145
154
|
|
|
155
|
+
def binary_dir_from_preset(preset: Preset, cwd: Path):
|
|
156
|
+
path = preset.expand()
|
|
157
|
+
if not path:
|
|
158
|
+
return None
|
|
159
|
+
if path.is_relative_to(cwd):
|
|
160
|
+
path = path.relative_to(cwd)
|
|
161
|
+
return path
|
|
162
|
+
|
|
163
|
+
|
|
146
164
|
def get_binary_dirs():
|
|
165
|
+
return visit_presets(binary_dir_from_preset)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
T = TypeVar("T")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def visit_presets(mapper: Callable[[Preset, Path], T | None]):
|
|
147
172
|
presets = Presets().visit_file(Path("CMakePresets.json"))
|
|
173
|
+
if presets is None:
|
|
174
|
+
return None
|
|
148
175
|
|
|
149
|
-
cwd =
|
|
150
|
-
result: dict[str,
|
|
176
|
+
cwd = Path.cwd()
|
|
177
|
+
result: dict[str, T] = {}
|
|
151
178
|
for preset in presets.values():
|
|
152
|
-
|
|
153
|
-
if
|
|
179
|
+
mapped = mapper(preset, cwd)
|
|
180
|
+
if mapped is None:
|
|
154
181
|
continue
|
|
155
|
-
|
|
156
|
-
if rel[: len(cwd)] == cwd:
|
|
157
|
-
rel = rel[len(cwd) :]
|
|
158
|
-
result[preset.name] = rel
|
|
182
|
+
result[preset.name] = mapped
|
|
159
183
|
|
|
160
184
|
return result
|
proj_flow/base/plugins.py
CHANGED
|
@@ -6,18 +6,23 @@ The **proj_flow.base.plugins** provide the plugin enumeration helpers.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import json
|
|
9
|
-
import
|
|
9
|
+
from pathlib import Path
|
|
10
10
|
from typing import cast
|
|
11
11
|
|
|
12
12
|
import yaml
|
|
13
13
|
|
|
14
|
+
try:
|
|
15
|
+
from yaml import CLoader as Loader
|
|
16
|
+
except ImportError:
|
|
17
|
+
from yaml import Loader
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
|
|
20
|
+
def load_yaml(filename: Path):
|
|
16
21
|
with open(filename) as src:
|
|
17
|
-
return cast(dict, yaml.load(src, Loader=
|
|
22
|
+
return cast(dict, yaml.load(src, Loader=Loader))
|
|
18
23
|
|
|
19
24
|
|
|
20
|
-
def load_json(filename:
|
|
25
|
+
def load_json(filename: Path):
|
|
21
26
|
with open(filename) as src:
|
|
22
27
|
return cast(dict, json.load(src))
|
|
23
28
|
|
|
@@ -29,8 +34,8 @@ LOADERS = {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
|
|
32
|
-
def load_data(filename:
|
|
33
|
-
|
|
37
|
+
def load_data(filename: Path):
|
|
38
|
+
ext = filename.suffix
|
|
34
39
|
loader = LOADERS.get(ext.lower())
|
|
35
40
|
if loader:
|
|
36
41
|
try:
|
|
@@ -39,7 +44,7 @@ def load_data(filename: str):
|
|
|
39
44
|
pass
|
|
40
45
|
|
|
41
46
|
for new_ext, loader in LOADERS.items():
|
|
42
|
-
new_filename =
|
|
47
|
+
new_filename = filename.with_suffix(new_ext)
|
|
43
48
|
try:
|
|
44
49
|
return loader(new_filename)
|
|
45
50
|
except Exception:
|
proj_flow/cli/finder.py
CHANGED
|
@@ -9,6 +9,7 @@ contains ``-C`` argument.
|
|
|
9
9
|
|
|
10
10
|
import os
|
|
11
11
|
import shlex
|
|
12
|
+
from pathlib import Path
|
|
12
13
|
from typing import List
|
|
13
14
|
|
|
14
15
|
from argcomplete import finders
|
|
@@ -43,7 +44,7 @@ class CompletionFinder(finders.CompletionFinder):
|
|
|
43
44
|
|
|
44
45
|
def find_project(self):
|
|
45
46
|
if not self.active():
|
|
46
|
-
return
|
|
47
|
+
return Path()
|
|
47
48
|
|
|
48
49
|
comp_line = os.environ["COMP_LINE"]
|
|
49
50
|
comp_point = int(os.environ["COMP_POINT"])
|
|
@@ -51,9 +52,9 @@ class CompletionFinder(finders.CompletionFinder):
|
|
|
51
52
|
pos = find_dash_see(args)
|
|
52
53
|
|
|
53
54
|
if pos < 0:
|
|
54
|
-
return
|
|
55
|
+
return Path()
|
|
55
56
|
|
|
56
|
-
return args[pos]
|
|
57
|
+
return Path(args[pos])
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
autocomplete = CompletionFinder()
|
proj_flow/dependency.py
CHANGED
|
@@ -57,14 +57,18 @@ class Dependency:
|
|
|
57
57
|
version_expression: str
|
|
58
58
|
kind: DepKind = DepKind.APP
|
|
59
59
|
|
|
60
|
-
def __lt__(self, rhs:
|
|
60
|
+
def __lt__(self, rhs: object):
|
|
61
|
+
if not isinstance(rhs, Dependency):
|
|
62
|
+
return False
|
|
61
63
|
if self.kind != rhs.kind:
|
|
62
64
|
return self.kind.value < rhs.kind.value
|
|
63
65
|
if self.name != rhs.name:
|
|
64
66
|
return self.name < rhs.name
|
|
65
67
|
return self.version_expression < rhs.version_expression
|
|
66
68
|
|
|
67
|
-
def __eq__(self, rhs:
|
|
69
|
+
def __eq__(self, rhs: object):
|
|
70
|
+
if not isinstance(rhs, Dependency):
|
|
71
|
+
return False
|
|
68
72
|
return (
|
|
69
73
|
self.kind == rhs.kind
|
|
70
74
|
and self.name == rhs.name
|
|
@@ -7,6 +7,6 @@ The **proj_flow.ext.cplusplus.cmake** provides ``"CMake"``, ``"Build"``,
|
|
|
7
7
|
context.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
from . import parser,
|
|
10
|
+
from . import parser, project, steps
|
|
11
11
|
|
|
12
|
-
__all__ = ["parser", "
|
|
12
|
+
__all__ = ["parser", "project", "steps"]
|
|
@@ -7,6 +7,7 @@ The **proj_flow.ext.cplusplus.cmake.parser** contains simple CMake parser.
|
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
9
|
import re
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from typing import Iterator, List, NamedTuple, Optional
|
|
11
12
|
|
|
12
13
|
from proj_flow.api.release import NO_ARG, Arg
|
|
@@ -76,7 +77,7 @@ def _command(cmd: Token, stream: Iterator[Token]):
|
|
|
76
77
|
return result
|
|
77
78
|
|
|
78
79
|
|
|
79
|
-
def _cmake(filename:
|
|
80
|
+
def _cmake(filename: Path):
|
|
80
81
|
commands: List[Command] = []
|
|
81
82
|
|
|
82
83
|
with open(filename, "r", encoding="UTF-8") as f:
|
|
@@ -102,9 +103,9 @@ def _patch(directory: str, arg: Arg, value: str):
|
|
|
102
103
|
input.write(patched)
|
|
103
104
|
|
|
104
105
|
|
|
105
|
-
def get_project(dirname:
|
|
106
|
+
def get_project(dirname: Path) -> Optional[CMakeProject]:
|
|
106
107
|
try:
|
|
107
|
-
commands = _cmake(
|
|
108
|
+
commands = _cmake(dirname / "CMakeLists.txt")
|
|
108
109
|
except FileNotFoundError:
|
|
109
110
|
return None
|
|
110
111
|
|
|
@@ -7,12 +7,12 @@ building and archiving.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import os
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from typing import Dict, List, cast
|
|
11
12
|
|
|
12
13
|
from proj_flow import api
|
|
13
14
|
from proj_flow.api import env, step
|
|
14
15
|
from proj_flow.base.__cmake_version__ import CMAKE_VERSION
|
|
15
|
-
from proj_flow.ext.cplusplus.cmake.presets import get_binary_dirs
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class CMakeBase(api.step.Step):
|
|
@@ -22,14 +22,17 @@ class CMakeBase(api.step.Step):
|
|
|
22
22
|
|
|
23
23
|
@property
|
|
24
24
|
def name(self):
|
|
25
|
+
""":meta private:"""
|
|
25
26
|
return self._name
|
|
26
27
|
|
|
27
28
|
@property
|
|
28
29
|
def runs_after(self):
|
|
30
|
+
""":meta private:"""
|
|
29
31
|
return self._runs_after
|
|
30
32
|
|
|
31
33
|
@property
|
|
32
34
|
def runs_before(self):
|
|
35
|
+
""":meta private:"""
|
|
33
36
|
return self._runs_before
|
|
34
37
|
|
|
35
38
|
def __init__(
|
|
@@ -47,6 +50,7 @@ class CMakeBase(api.step.Step):
|
|
|
47
50
|
return [f"cmake>={CMAKE_VERSION}"]
|
|
48
51
|
|
|
49
52
|
def dep_with_tool(self, tool: str):
|
|
53
|
+
""":meta private:"""
|
|
50
54
|
return [f"cmake>={CMAKE_VERSION}", f"{tool}>={CMAKE_VERSION}"]
|
|
51
55
|
|
|
52
56
|
|
|
@@ -56,16 +60,12 @@ class CMakeConfig(CMakeBase):
|
|
|
56
60
|
|
|
57
61
|
def __init__(self):
|
|
58
62
|
super().__init__(name="CMake")
|
|
59
|
-
self.binary_dirs = get_binary_dirs()
|
|
60
63
|
|
|
61
64
|
def is_active(self, config: env.Config, rt: env.Runtime) -> bool:
|
|
62
65
|
return os.path.isfile("CMakeLists.txt") and os.path.isfile("CMakePresets.json")
|
|
63
66
|
|
|
64
|
-
def directories_to_remove(self, config: env.Config) -> List[
|
|
65
|
-
|
|
66
|
-
if not binary_dir:
|
|
67
|
-
return []
|
|
68
|
-
return [binary_dir]
|
|
67
|
+
def directories_to_remove(self, config: env.Config) -> List[Path]:
|
|
68
|
+
return [config.build_dir]
|
|
69
69
|
|
|
70
70
|
def run(self, config: env.Config, rt: env.Runtime) -> int:
|
|
71
71
|
cmake_vars = cast(Dict[str, str], rt._cfg.get("cmake", {}).get("vars", {}))
|
|
@@ -78,10 +78,10 @@ class CMakeConfig(CMakeBase):
|
|
|
78
78
|
value = value[1:]
|
|
79
79
|
|
|
80
80
|
if value.startswith("config:"):
|
|
81
|
-
value = value[len("config:"):]
|
|
81
|
+
value = value[len("config:") :]
|
|
82
82
|
value = config.get_path(value)
|
|
83
83
|
elif value.startswith("runtime:"):
|
|
84
|
-
value = value[len("runtime:"):]
|
|
84
|
+
value = value[len("runtime:") :]
|
|
85
85
|
value = getattr(rt, value, None)
|
|
86
86
|
|
|
87
87
|
if is_flag:
|
|
@@ -7,6 +7,7 @@ The **proj_flow.ext.cplusplus.conan** provides the ``"Conan"`` step.
|
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
9
|
import textwrap
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from typing import List
|
|
11
12
|
|
|
12
13
|
from proj_flow.api import env, step
|
|
@@ -14,7 +15,7 @@ from proj_flow.project import cplusplus
|
|
|
14
15
|
|
|
15
16
|
from ._conan import conan_api
|
|
16
17
|
|
|
17
|
-
CONAN_DIR = "build/conan"
|
|
18
|
+
CONAN_DIR = Path("build/conan")
|
|
18
19
|
CONAN_PROFILE = "_profile-compiler"
|
|
19
20
|
CONAN_PROFILE_GEN = "_profile-build_type"
|
|
20
21
|
|
|
@@ -23,7 +24,9 @@ CONAN_PROFILE_GEN = "_profile-build_type"
|
|
|
23
24
|
class ConanConfig:
|
|
24
25
|
"""Configures the project for ``preset`` config using ``build_type`` config."""
|
|
25
26
|
|
|
27
|
+
#: :meta private:
|
|
26
28
|
name = "Conan"
|
|
29
|
+
#: :meta private:
|
|
27
30
|
runs_before = ["CMake"]
|
|
28
31
|
|
|
29
32
|
def platform_dependencies(self):
|
|
@@ -32,13 +35,13 @@ class ConanConfig:
|
|
|
32
35
|
def is_active(self, config: env.Config, rt: env.Runtime) -> int:
|
|
33
36
|
return os.path.isfile("conanfile.txt") or os.path.isfile("conanfile.py")
|
|
34
37
|
|
|
35
|
-
def directories_to_remove(self, _: env.Config) -> List[
|
|
38
|
+
def directories_to_remove(self, _: env.Config) -> List[Path]:
|
|
36
39
|
return [CONAN_DIR]
|
|
37
40
|
|
|
38
41
|
def run(self, config: env.Config, rt: env.Runtime) -> int:
|
|
39
42
|
api = conan_api()
|
|
40
43
|
|
|
41
|
-
profile_gen = f"{CONAN_DIR}/{CONAN_PROFILE_GEN}-{config.preset}"
|
|
44
|
+
profile_gen = f"{CONAN_DIR.as_posix()}/{CONAN_PROFILE_GEN}-{config.preset}"
|
|
42
45
|
if not rt.dry_run:
|
|
43
46
|
os.makedirs(CONAN_DIR, exist_ok=True)
|
|
44
47
|
with open(profile_gen, "w", encoding="UTF-8") as profile:
|
|
@@ -58,7 +61,8 @@ class ConanConfig:
|
|
|
58
61
|
]:
|
|
59
62
|
print(setting, file=profile)
|
|
60
63
|
|
|
61
|
-
|
|
64
|
+
conan_dir = CONAN_DIR.as_posix()
|
|
65
|
+
if api.config(rt, conan_dir, f"./{conan_dir}/{CONAN_PROFILE}", profile_gen):
|
|
62
66
|
return 1
|
|
63
67
|
if not rt.dry_run and os.path.exists("CMakeUserPresets.json"):
|
|
64
68
|
os.remove("CMakeUserPresets.json")
|
proj_flow/ext/github/cli.py
CHANGED
|
@@ -32,9 +32,7 @@ def github():
|
|
|
32
32
|
|
|
33
33
|
@arg.command("github", "matrix")
|
|
34
34
|
def matrix(
|
|
35
|
-
pretty: typing.Annotated[
|
|
36
|
-
bool, arg.FlagArgument(help="Indent JSON document")
|
|
37
|
-
],
|
|
35
|
+
pretty: typing.Annotated[bool, arg.FlagArgument(help="Indent JSON document")],
|
|
38
36
|
official: typing.Annotated[
|
|
39
37
|
bool, arg.FlagArgument(help="Cut matrix to release builds only")
|
|
40
38
|
],
|