cja 0.2.2__tar.gz → 0.2.4__tar.gz
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.
- {cja-0.2.2 → cja-0.2.4}/PKG-INFO +1 -1
- {cja-0.2.2 → cja-0.2.4}/pyproject.toml +1 -1
- {cja-0.2.2 → cja-0.2.4}/src/cja/build_context.py +26 -2
- {cja-0.2.2 → cja-0.2.4}/src/cja/commands.py +58 -34
- cja-0.2.4/src/cja/config_utils.py +274 -0
- cja-0.2.2/src/cja/generator.py → cja-0.2.4/src/cja/configurator.py +194 -1840
- {cja-0.2.2 → cja-0.2.4}/src/cja/find_package.py +139 -2
- cja-0.2.4/src/cja/frame.py +20 -0
- cja-0.2.4/src/cja/generator.py +1641 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/parser.py +20 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/syntax.py +3 -2
- {cja-0.2.2 → cja-0.2.4}/src/cja/utils.py +55 -2
- {cja-0.2.2 → cja-0.2.4}/README.md +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/__init__.py +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/__main__.py +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/cli.py +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/cmake/Modules/FindGTest.cmake +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/ninja_syntax.py +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/py.typed +0 -0
- {cja-0.2.2 → cja-0.2.4}/src/cja/targets.py +0 -0
{cja-0.2.2 → cja-0.2.4}/PKG-INFO
RENAMED
|
@@ -47,6 +47,21 @@ class CustomCommand:
|
|
|
47
47
|
defined_line: int = 0
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
@dataclass
|
|
51
|
+
class CustomTarget:
|
|
52
|
+
"""A custom target (phony build target)."""
|
|
53
|
+
|
|
54
|
+
name: str
|
|
55
|
+
commands: list[list[str]]
|
|
56
|
+
depends: list[str]
|
|
57
|
+
all: bool = False
|
|
58
|
+
working_directory: str | None = None
|
|
59
|
+
verbatim: bool = False
|
|
60
|
+
comment: str = ""
|
|
61
|
+
defined_file: Path | None = None
|
|
62
|
+
defined_line: int = 0
|
|
63
|
+
|
|
64
|
+
|
|
50
65
|
@dataclass
|
|
51
66
|
class BuildContext:
|
|
52
67
|
"""Context for processing CMake commands."""
|
|
@@ -58,7 +73,9 @@ class BuildContext:
|
|
|
58
73
|
project_name: str = ""
|
|
59
74
|
variables: dict[str, str] = field(default_factory=dict)
|
|
60
75
|
cache_variables: set[str] = field(default_factory=set) # Variables from -D flags
|
|
61
|
-
cli_variables: dict[str, str] = field(
|
|
76
|
+
cli_variables: dict[str, str] = field(
|
|
77
|
+
default_factory=dict
|
|
78
|
+
) # Original -D flag values
|
|
62
79
|
libraries: list[Library] = field(default_factory=list)
|
|
63
80
|
executables: list[Executable] = field(default_factory=list)
|
|
64
81
|
imported_targets: dict[str, ImportedTarget] = field(default_factory=dict)
|
|
@@ -69,6 +86,9 @@ class BuildContext:
|
|
|
69
86
|
custom_commands: list[CustomCommand] = field(
|
|
70
87
|
default_factory=list
|
|
71
88
|
) # Custom build commands
|
|
89
|
+
custom_targets: list[CustomTarget] = field(
|
|
90
|
+
default_factory=list
|
|
91
|
+
) # Custom targets (phony)
|
|
72
92
|
functions: dict[str, FunctionDef] = field(
|
|
73
93
|
default_factory=dict
|
|
74
94
|
) # User-defined functions
|
|
@@ -116,6 +136,8 @@ class BuildContext:
|
|
|
116
136
|
def get_library(self, name: str) -> Library | None:
|
|
117
137
|
for lib in self.libraries:
|
|
118
138
|
if lib.name == name:
|
|
139
|
+
if lib.is_alias and lib.alias_for:
|
|
140
|
+
return self.get_library(lib.alias_for)
|
|
119
141
|
return lib
|
|
120
142
|
return None
|
|
121
143
|
|
|
@@ -179,7 +201,9 @@ class BuildContext:
|
|
|
179
201
|
if allow_undefined_empty:
|
|
180
202
|
return ""
|
|
181
203
|
if allow_undefined_warning:
|
|
182
|
-
self.print_warning(
|
|
204
|
+
self.print_warning(
|
|
205
|
+
f"undefined variable referenced: {var_name}", line
|
|
206
|
+
)
|
|
183
207
|
return ""
|
|
184
208
|
level = self.print_error if strict else self.print_warning
|
|
185
209
|
level(f"undefined variable referenced: {var_name}", line)
|
|
@@ -21,6 +21,7 @@ from .parser import Command
|
|
|
21
21
|
from .targets import Executable, ImportedTarget, Library
|
|
22
22
|
from .utils import (
|
|
23
23
|
UNDEFINED_VAR_SENTINEL,
|
|
24
|
+
cmake_regex_to_python,
|
|
24
25
|
is_truthy,
|
|
25
26
|
resolve_cmake_path,
|
|
26
27
|
strip_generator_expressions,
|
|
@@ -67,7 +68,15 @@ def handle_project(
|
|
|
67
68
|
ctx.variables["PROJECT_NAME"] = args[0]
|
|
68
69
|
ctx.variables["CMAKE_PROJECT_NAME"] = args[0]
|
|
69
70
|
ctx.variables["CMAKE_C_FLAGS"] = "" # TODO: Only set when C is enabled
|
|
71
|
+
ctx.variables["CMAKE_C_FLAGS_DEBUG"] = ""
|
|
72
|
+
ctx.variables["CMAKE_C_FLAGS_RELEASE"] = ""
|
|
73
|
+
ctx.variables["CMAKE_C_FLAGS_RELWITHDEBINFO"] = ""
|
|
74
|
+
ctx.variables["CMAKE_C_FLAGS_MINSIZEREL"] = ""
|
|
70
75
|
ctx.variables["CMAKE_CXX_FLAGS"] = "" # TODO: Only set when CXX is enabled
|
|
76
|
+
ctx.variables["CMAKE_CXX_FLAGS_DEBUG"] = ""
|
|
77
|
+
ctx.variables["CMAKE_CXX_FLAGS_RELEASE"] = ""
|
|
78
|
+
ctx.variables["CMAKE_CXX_FLAGS_RELWITHDEBINFO"] = ""
|
|
79
|
+
ctx.variables["CMAKE_CXX_FLAGS_MINSIZEREL"] = ""
|
|
71
80
|
ctx.variables["PROJECT_SOURCE_DIR"] = str(ctx.current_source_dir)
|
|
72
81
|
ctx.variables["PROJECT_BINARY_DIR"] = str(ctx.build_dir)
|
|
73
82
|
source_var = f"{args[0]}_SOURCE_DIR"
|
|
@@ -185,41 +194,42 @@ def handle_target_link_libraries(
|
|
|
185
194
|
elif arg == "PRIVATE":
|
|
186
195
|
visibility = "PRIVATE"
|
|
187
196
|
else:
|
|
188
|
-
# It's a library name
|
|
197
|
+
# It's a library name (may be a semicolon-separated list from
|
|
198
|
+
# a CMake variable expansion like "${LIBS_PRIVATE}")
|
|
189
199
|
if "$<" in arg:
|
|
190
200
|
arg = strip_generator_expressions(arg, ctx.variables)
|
|
191
201
|
if not arg:
|
|
192
202
|
continue
|
|
193
203
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
else:
|
|
204
|
-
lib.link_libraries.append(arg)
|
|
205
|
-
else:
|
|
206
|
-
exe = ctx.get_executable(target_name)
|
|
207
|
-
if exe:
|
|
208
|
-
exe.link_libraries.append(arg)
|
|
209
|
-
elif target_name in ctx.imported_targets:
|
|
210
|
-
imported_target = ctx.imported_targets[target_name]
|
|
211
|
-
existing = shlex.split(imported_target.libs) if imported_target.libs else []
|
|
212
|
-
if arg in ctx.imported_targets and ctx.imported_targets[arg].libs:
|
|
213
|
-
existing.extend(shlex.split(ctx.imported_targets[arg].libs))
|
|
214
|
-
elif (
|
|
215
|
-
arg.startswith("-")
|
|
216
|
-
or "/" in arg
|
|
217
|
-
or arg.endswith((".a", ".so", ".dylib", ".lib", ".dll"))
|
|
218
|
-
):
|
|
219
|
-
existing.append(arg)
|
|
204
|
+
parts = [p for p in arg.split(";") if p]
|
|
205
|
+
for part in parts:
|
|
206
|
+
lib = ctx.get_library(target_name)
|
|
207
|
+
if lib:
|
|
208
|
+
if visibility == "PUBLIC":
|
|
209
|
+
lib.link_libraries.append(part)
|
|
210
|
+
lib.public_link_libraries.append(part)
|
|
211
|
+
elif visibility == "INTERFACE":
|
|
212
|
+
lib.public_link_libraries.append(part)
|
|
220
213
|
else:
|
|
221
|
-
|
|
222
|
-
|
|
214
|
+
lib.link_libraries.append(part)
|
|
215
|
+
else:
|
|
216
|
+
exe = ctx.get_executable(target_name)
|
|
217
|
+
if exe:
|
|
218
|
+
exe.link_libraries.append(part)
|
|
219
|
+
elif target_name in ctx.imported_targets:
|
|
220
|
+
imported_target = ctx.imported_targets[target_name]
|
|
221
|
+
existing = shlex.split(imported_target.libs) if imported_target.libs else []
|
|
222
|
+
if part in ctx.imported_targets and ctx.imported_targets[part].libs:
|
|
223
|
+
existing.extend(shlex.split(ctx.imported_targets[part].libs))
|
|
224
|
+
elif (
|
|
225
|
+
part.startswith("-")
|
|
226
|
+
or "/" in part
|
|
227
|
+
or part.endswith((".a", ".so", ".dylib", ".lib", ".dll"))
|
|
228
|
+
):
|
|
229
|
+
existing.append(part)
|
|
230
|
+
else:
|
|
231
|
+
existing.append(f"-l{part}")
|
|
232
|
+
imported_target.libs = " ".join(dict.fromkeys(existing))
|
|
223
233
|
|
|
224
234
|
|
|
225
235
|
def handle_target_link_directories(
|
|
@@ -1442,15 +1452,16 @@ def handle_list(
|
|
|
1442
1452
|
items = list_val.split(";")
|
|
1443
1453
|
import re as regex_module
|
|
1444
1454
|
|
|
1455
|
+
py_pattern = cmake_regex_to_python(pattern)
|
|
1445
1456
|
if mode == "INCLUDE":
|
|
1446
1457
|
items = [
|
|
1447
|
-
item for item in items if regex_module.search(
|
|
1458
|
+
item for item in items if regex_module.search(py_pattern, item)
|
|
1448
1459
|
]
|
|
1449
1460
|
elif mode == "EXCLUDE":
|
|
1450
1461
|
items = [
|
|
1451
1462
|
item
|
|
1452
1463
|
for item in items
|
|
1453
|
-
if not regex_module.search(
|
|
1464
|
+
if not regex_module.search(py_pattern, item)
|
|
1454
1465
|
]
|
|
1455
1466
|
ctx.variables[list_name] = ";".join(items)
|
|
1456
1467
|
else:
|
|
@@ -1864,7 +1875,7 @@ def handle_string(
|
|
|
1864
1875
|
out_var = args[3]
|
|
1865
1876
|
inputs = args[4:]
|
|
1866
1877
|
full_input = "".join(inputs)
|
|
1867
|
-
match = re.search(pattern, full_input)
|
|
1878
|
+
match = re.search(cmake_regex_to_python(pattern), full_input)
|
|
1868
1879
|
reset_cmake_match_vars()
|
|
1869
1880
|
if match:
|
|
1870
1881
|
ctx.variables[out_var] = match.group(0)
|
|
@@ -1886,7 +1897,10 @@ def handle_string(
|
|
|
1886
1897
|
out_var = args[3]
|
|
1887
1898
|
inputs = args[4:]
|
|
1888
1899
|
full_input = "".join(inputs)
|
|
1889
|
-
matches =
|
|
1900
|
+
matches = [
|
|
1901
|
+
m.group(0)
|
|
1902
|
+
for m in re.finditer(cmake_regex_to_python(pattern), full_input)
|
|
1903
|
+
]
|
|
1890
1904
|
ctx.variables[out_var] = ";".join(matches)
|
|
1891
1905
|
elif regex_sub == "REPLACE":
|
|
1892
1906
|
# string(REGEX REPLACE <regex> <replace_string> <out_var> <input> [<input>...])
|
|
@@ -1900,7 +1914,7 @@ def handle_string(
|
|
|
1900
1914
|
# CMake uses \1, \2 etc for backreferences, Python uses \1, \2
|
|
1901
1915
|
# but also supports \g<1> which is safer.
|
|
1902
1916
|
# Actually CMake's REGEX REPLACE is a bit different.
|
|
1903
|
-
ctx.variables[out_var] = re.sub(pattern, replace_str, full_input)
|
|
1917
|
+
ctx.variables[out_var] = re.sub(cmake_regex_to_python(pattern), replace_str, full_input)
|
|
1904
1918
|
|
|
1905
1919
|
elif subcommand == "SUBSTRING":
|
|
1906
1920
|
# string(SUBSTRING <string> <begin> <length> <out_var>)
|
|
@@ -1990,6 +2004,16 @@ def handle_string(
|
|
|
1990
2004
|
result = s1 > s2
|
|
1991
2005
|
ctx.variables[out_var] = "1" if result else "0"
|
|
1992
2006
|
|
|
2007
|
+
elif subcommand == "MAKE_C_IDENTIFIER":
|
|
2008
|
+
# string(MAKE_C_IDENTIFIER <string> <output_variable>)
|
|
2009
|
+
if len(args) >= 3:
|
|
2010
|
+
string_val = args[1]
|
|
2011
|
+
out_var = args[2]
|
|
2012
|
+
result = re.sub(r"[^a-zA-Z0-9_]", "_", string_val)
|
|
2013
|
+
if result and result[0].isdigit():
|
|
2014
|
+
result = "_" + result
|
|
2015
|
+
ctx.variables[out_var] = result
|
|
2016
|
+
|
|
1993
2017
|
|
|
1994
2018
|
def handle_file(
|
|
1995
2019
|
ctx: BuildContext,
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from .parser import Command
|
|
3
|
+
from .build_context import (
|
|
4
|
+
BuildContext,
|
|
5
|
+
find_matching_endforeach,
|
|
6
|
+
find_matching_endif,
|
|
7
|
+
)
|
|
8
|
+
from .syntax import evaluate_condition, find_else_or_elseif
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def select_if_block(
|
|
12
|
+
ctx: BuildContext,
|
|
13
|
+
commands: list[Command],
|
|
14
|
+
pc: int,
|
|
15
|
+
strict: bool,
|
|
16
|
+
) -> tuple[int, tuple[int, int] | None]:
|
|
17
|
+
"""Select the if/elseif/else block to execute."""
|
|
18
|
+
cmd = commands[pc]
|
|
19
|
+
# Find matching endif
|
|
20
|
+
endif_idx = find_matching_endif(commands, pc, ctx)
|
|
21
|
+
# Find elseif/else blocks
|
|
22
|
+
blocks = find_else_or_elseif(commands, pc, endif_idx)
|
|
23
|
+
|
|
24
|
+
block_start = pc + 1
|
|
25
|
+
|
|
26
|
+
def target_exists(name: str) -> bool:
|
|
27
|
+
return (
|
|
28
|
+
ctx.get_library(name) is not None
|
|
29
|
+
or ctx.get_executable(name) is not None
|
|
30
|
+
or name in ctx.imported_targets
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def _is_empty_string_token(token: str) -> bool:
|
|
34
|
+
return token == "" or token in ('""', "''")
|
|
35
|
+
|
|
36
|
+
def _is_exact_var_token(token: str) -> bool:
|
|
37
|
+
return (
|
|
38
|
+
(token.startswith("${") and token.endswith("}"))
|
|
39
|
+
or (token.startswith('"${') and token.endswith('}"'))
|
|
40
|
+
or (token.startswith("'${") and token.endswith("}'"))
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Check the if condition
|
|
44
|
+
if_args = []
|
|
45
|
+
for i, arg in enumerate(cmd.args):
|
|
46
|
+
allow_undefined = (
|
|
47
|
+
i + 2 < len(cmd.args)
|
|
48
|
+
and cmd.args[i + 1] == "STREQUAL"
|
|
49
|
+
and _is_empty_string_token(cmd.args[i + 2])
|
|
50
|
+
and _is_exact_var_token(arg)
|
|
51
|
+
)
|
|
52
|
+
if_args.append(
|
|
53
|
+
ctx.expand_variables(
|
|
54
|
+
arg,
|
|
55
|
+
strict,
|
|
56
|
+
cmd.line,
|
|
57
|
+
allow_undefined_empty=allow_undefined,
|
|
58
|
+
allow_undefined_warning="${${" in arg,
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
if evaluate_condition(if_args, ctx.variables, target_exists=target_exists):
|
|
62
|
+
# Execute commands from if to first elseif/else or endif
|
|
63
|
+
block_end = blocks[0][1] if blocks else endif_idx
|
|
64
|
+
return endif_idx, (block_start, block_end)
|
|
65
|
+
|
|
66
|
+
# Check elseif/else blocks
|
|
67
|
+
for j, (block_type, block_idx, block_args) in enumerate(blocks):
|
|
68
|
+
if block_type == "elseif":
|
|
69
|
+
elseif_args = []
|
|
70
|
+
for i, arg in enumerate(block_args):
|
|
71
|
+
allow_undefined = (
|
|
72
|
+
i + 2 < len(block_args)
|
|
73
|
+
and block_args[i + 1] == "STREQUAL"
|
|
74
|
+
and _is_empty_string_token(block_args[i + 2])
|
|
75
|
+
and _is_exact_var_token(arg)
|
|
76
|
+
)
|
|
77
|
+
elseif_args.append(
|
|
78
|
+
ctx.expand_variables(
|
|
79
|
+
arg,
|
|
80
|
+
strict,
|
|
81
|
+
commands[block_idx].line,
|
|
82
|
+
allow_undefined_empty=allow_undefined,
|
|
83
|
+
allow_undefined_warning="${${" in arg,
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
if evaluate_condition(
|
|
87
|
+
elseif_args, ctx.variables, target_exists=target_exists
|
|
88
|
+
):
|
|
89
|
+
block_start = block_idx + 1
|
|
90
|
+
block_end = blocks[j + 1][1] if j + 1 < len(blocks) else endif_idx
|
|
91
|
+
return endif_idx, (block_start, block_end)
|
|
92
|
+
elif block_type == "else":
|
|
93
|
+
block_start = block_idx + 1
|
|
94
|
+
return endif_idx, (block_start, endif_idx)
|
|
95
|
+
|
|
96
|
+
return endif_idx, None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def build_foreach_info(
|
|
100
|
+
ctx: BuildContext,
|
|
101
|
+
commands: list[Command],
|
|
102
|
+
pc: int,
|
|
103
|
+
args: list[str],
|
|
104
|
+
) -> tuple[int, str, list[str], list[Command]]:
|
|
105
|
+
"""Build foreach() iteration info."""
|
|
106
|
+
cmd = commands[pc]
|
|
107
|
+
if not args:
|
|
108
|
+
ctx.raise_syntax_error("foreach() requires at least a loop variable", cmd.line)
|
|
109
|
+
|
|
110
|
+
# Find matching endforeach
|
|
111
|
+
endforeach_idx = find_matching_endforeach(commands, pc, ctx)
|
|
112
|
+
body = commands[pc + 1 : endforeach_idx]
|
|
113
|
+
|
|
114
|
+
loop_var = cmd.args[0] # Use unexpanded for variable name
|
|
115
|
+
remaining = args[1:] # Use expanded args for values
|
|
116
|
+
|
|
117
|
+
# Determine iteration items
|
|
118
|
+
items: list[str] = []
|
|
119
|
+
if remaining and remaining[0] == "RANGE":
|
|
120
|
+
# foreach(var RANGE stop) or foreach(var RANGE start stop [step])
|
|
121
|
+
range_args = remaining[1:]
|
|
122
|
+
if len(range_args) == 1:
|
|
123
|
+
stop = int(range_args[0])
|
|
124
|
+
items = [str(x) for x in range(stop + 1)]
|
|
125
|
+
elif len(range_args) == 2:
|
|
126
|
+
start, stop = int(range_args[0]), int(range_args[1])
|
|
127
|
+
items = [str(x) for x in range(start, stop + 1)]
|
|
128
|
+
elif len(range_args) >= 3:
|
|
129
|
+
start, stop, step = (
|
|
130
|
+
int(range_args[0]),
|
|
131
|
+
int(range_args[1]),
|
|
132
|
+
int(range_args[2]),
|
|
133
|
+
)
|
|
134
|
+
items = [str(x) for x in range(start, stop + 1, step)]
|
|
135
|
+
elif remaining and remaining[0] == "IN":
|
|
136
|
+
# foreach(var IN LISTS list1 ... | ITEMS item1 ...)
|
|
137
|
+
mode = remaining[1] if len(remaining) > 1 else ""
|
|
138
|
+
values = remaining[2:]
|
|
139
|
+
if mode == "LISTS":
|
|
140
|
+
for list_name in values:
|
|
141
|
+
list_val = ctx.variables.get(list_name, "")
|
|
142
|
+
if list_val:
|
|
143
|
+
items.extend(list_val.split())
|
|
144
|
+
elif mode == "ITEMS":
|
|
145
|
+
items = values
|
|
146
|
+
else:
|
|
147
|
+
# foreach(var item1 item2 ...)
|
|
148
|
+
items = remaining
|
|
149
|
+
|
|
150
|
+
return endforeach_idx, loop_var, items, body
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
_VERSION_RE = re.compile(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?")
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _version_components(version: str) -> tuple[str, str, str]:
|
|
157
|
+
match = _VERSION_RE.match(version.strip())
|
|
158
|
+
if not match:
|
|
159
|
+
return "0", "0", "0"
|
|
160
|
+
major = match.group(1) or "0"
|
|
161
|
+
minor = match.group(2) or "0"
|
|
162
|
+
patch = match.group(3) or "0"
|
|
163
|
+
return major, minor, patch
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _render_basic_package_version_file(
|
|
167
|
+
version: str,
|
|
168
|
+
compatibility: str,
|
|
169
|
+
arch_independent: bool,
|
|
170
|
+
ctx: BuildContext,
|
|
171
|
+
) -> str:
|
|
172
|
+
major, minor, _ = _version_components(version)
|
|
173
|
+
arch_block = ""
|
|
174
|
+
if arch_independent:
|
|
175
|
+
arch_block = "set(PACKAGE_VERSION_UNSUITABLE FALSE)\n"
|
|
176
|
+
else:
|
|
177
|
+
sizeof_void_p = ctx.variables.get(
|
|
178
|
+
"CMAKE_SIZEOF_VOID_P", "${CMAKE_SIZEOF_VOID_P}"
|
|
179
|
+
)
|
|
180
|
+
arch_block = (
|
|
181
|
+
f'set(PACKAGE_VERSION_SIZEOF_VOID_P "{sizeof_void_p}")\n'
|
|
182
|
+
"if(NOT CMAKE_SIZEOF_VOID_P STREQUAL PACKAGE_VERSION_SIZEOF_VOID_P)\n"
|
|
183
|
+
" set(PACKAGE_VERSION_UNSUITABLE TRUE)\n"
|
|
184
|
+
"endif()\n"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
f'set(PACKAGE_VERSION "{version}")\n'
|
|
189
|
+
"set(PACKAGE_VERSION_COMPATIBLE FALSE)\n"
|
|
190
|
+
"set(PACKAGE_VERSION_EXACT FALSE)\n"
|
|
191
|
+
f"{arch_block}"
|
|
192
|
+
"if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)\n"
|
|
193
|
+
" set(PACKAGE_VERSION_COMPATIBLE FALSE)\n"
|
|
194
|
+
"else()\n"
|
|
195
|
+
f' if("{compatibility}" STREQUAL "AnyNewerVersion")\n'
|
|
196
|
+
" set(PACKAGE_VERSION_COMPATIBLE TRUE)\n"
|
|
197
|
+
f' elseif("{compatibility}" STREQUAL "SameMajorVersion")\n'
|
|
198
|
+
f' if(PACKAGE_FIND_VERSION_MAJOR STREQUAL "{major}")\n'
|
|
199
|
+
" set(PACKAGE_VERSION_COMPATIBLE TRUE)\n"
|
|
200
|
+
" endif()\n"
|
|
201
|
+
f' elseif("{compatibility}" STREQUAL "SameMinorVersion")\n'
|
|
202
|
+
f' if(PACKAGE_FIND_VERSION_MAJOR STREQUAL "{major}" AND '
|
|
203
|
+
f'PACKAGE_FIND_VERSION_MINOR STREQUAL "{minor}")\n'
|
|
204
|
+
" set(PACKAGE_VERSION_COMPATIBLE TRUE)\n"
|
|
205
|
+
" endif()\n"
|
|
206
|
+
f' elseif("{compatibility}" STREQUAL "ExactVersion")\n'
|
|
207
|
+
" if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)\n"
|
|
208
|
+
" set(PACKAGE_VERSION_COMPATIBLE TRUE)\n"
|
|
209
|
+
" endif()\n"
|
|
210
|
+
" endif()\n"
|
|
211
|
+
"endif()\n"
|
|
212
|
+
"if(PACKAGE_VERSION_COMPATIBLE AND PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)\n"
|
|
213
|
+
" set(PACKAGE_VERSION_EXACT TRUE)\n"
|
|
214
|
+
"endif()\n"
|
|
215
|
+
"if(NOT DEFINED PACKAGE_VERSION_UNSUITABLE)\n"
|
|
216
|
+
" set(PACKAGE_VERSION_UNSUITABLE FALSE)\n"
|
|
217
|
+
"endif()\n"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _render_package_init_block(
|
|
222
|
+
install_destination: str,
|
|
223
|
+
*,
|
|
224
|
+
no_set_and_check_macro: bool,
|
|
225
|
+
no_check_required_components_macro: bool,
|
|
226
|
+
) -> str:
|
|
227
|
+
install_destination = install_destination.replace("\\", "/").strip()
|
|
228
|
+
if install_destination.startswith("/"):
|
|
229
|
+
prefix_expr = install_destination
|
|
230
|
+
else:
|
|
231
|
+
parts = [p for p in install_destination.split("/") if p and p != "."]
|
|
232
|
+
up = "/".join([".."] * len(parts))
|
|
233
|
+
prefix_expr = (
|
|
234
|
+
"${CMAKE_CURRENT_LIST_DIR}"
|
|
235
|
+
if not up
|
|
236
|
+
else f"${{CMAKE_CURRENT_LIST_DIR}}/{up}"
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
lines = [
|
|
240
|
+
"# Generated by cja: configure_package_config_file()",
|
|
241
|
+
f'get_filename_component(PACKAGE_PREFIX_DIR "{prefix_expr}" ABSOLUTE)',
|
|
242
|
+
"",
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
if not no_set_and_check_macro:
|
|
246
|
+
lines.extend(
|
|
247
|
+
[
|
|
248
|
+
"macro(set_and_check _var _file)",
|
|
249
|
+
' set(${_var} "${_file}")',
|
|
250
|
+
' if(NOT EXISTS "${_file}")',
|
|
251
|
+
' message(FATAL_ERROR "File or directory ${_file} referenced by ${_var} does not exist")',
|
|
252
|
+
" endif()",
|
|
253
|
+
"endmacro()",
|
|
254
|
+
"",
|
|
255
|
+
]
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if not no_check_required_components_macro:
|
|
259
|
+
lines.extend(
|
|
260
|
+
[
|
|
261
|
+
"macro(check_required_components _NAME)",
|
|
262
|
+
" foreach(comp ${${_NAME}_FIND_COMPONENTS})",
|
|
263
|
+
" if(NOT ${_NAME}_${comp}_FOUND)",
|
|
264
|
+
" if(${_NAME}_FIND_REQUIRED_${comp})",
|
|
265
|
+
" set(${_NAME}_FOUND FALSE)",
|
|
266
|
+
" endif()",
|
|
267
|
+
" endif()",
|
|
268
|
+
" endforeach()",
|
|
269
|
+
"endmacro()",
|
|
270
|
+
"",
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
return "\n".join(lines)
|