l0n0lc 0.8.4__py3-none-any.whl → 1.0.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.
- l0n0lc/Py/350/275/254Cpp/350/275/254/350/257/221/345/231/250.py +579 -0
- l0n0lc/__init__.py +75 -6
- l0n0lc/aot/347/274/226/350/257/221.py +679 -0
- l0n0lc/ast/350/256/277/351/227/256/350/200/205.py +599 -0
- l0n0lc/cpp/347/261/273/345/236/213.py +330 -0
- l0n0lc/cpp/347/274/226/350/257/221/345/231/250.py +317 -0
- l0n0lc/simd/344/274/230/345/214/226.py +260 -0
- l0n0lc/std_map.py +153 -0
- l0n0lc/std_set.py +185 -0
- l0n0lc/std_vector.py +96 -0
- l0n0lc//344/273/243/347/240/201/344/274/230/345/214/226.py +302 -0
- l0n0lc//344/273/243/347/240/201/347/224/237/346/210/220.py +546 -0
- l0n0lc//344/276/235/350/265/226/346/263/250/345/205/245.py +155 -0
- l0n0lc//345/215/263/346/227/266/347/274/226/350/257/221.py +192 -0
- l0n0lc//345/217/230/351/207/217/347/256/241/347/220/206/345/231/250.py +123 -0
- l0n0lc//345/237/272/347/241/200/346/230/240/345/260/204.py +103 -0
- l0n0lc//345/237/272/347/241/200/346/267/267/345/205/245.py +147 -0
- l0n0lc//345/256/271/345/231/250/346/236/204/345/273/272/345/231/250.py +214 -0
- l0n0lc//345/267/245/345/205/267.py +285 -0
- l0n0lc//345/271/266/350/241/214/347/274/226/350/257/221/345/231/250.py +412 -0
- l0n0lc//345/274/202/345/270/270.py +474 -0
- l0n0lc//346/225/260/347/273/204/345/257/271/350/261/241/346/261/240.py +248 -0
- l0n0lc//346/226/207/344/273/266/347/256/241/347/220/206/345/231/250.py +286 -0
- l0n0lc//346/227/245/345/277/227/345/267/245/345/205/267.py +152 -0
- l0n0lc//347/261/273/345/236/213/346/216/250/346/226/255/345/267/245/345/205/267.py +352 -0
- l0n0lc//347/261/273/345/236/213/350/275/254/346/215/242.py +210 -0
- l0n0lc//347/261/273/346/224/257/346/214/201.py +372 -0
- l0n0lc//347/274/226/350/257/221/344/270/212/344/270/213/346/226/207.py +132 -0
- l0n0lc//347/274/226/350/257/221/347/256/241/347/220/206/345/231/250.py +171 -0
- l0n0lc//350/241/250/350/276/276/345/274/217/345/244/204/347/220/206.py +462 -0
- l0n0lc//350/275/254/350/257/221/345/231/250/345/267/245/345/205/267.py +49 -0
- l0n0lc//350/277/220/350/241/214/346/227/266/345/212/240/350/275/275.py +217 -0
- l0n0lc//351/200/232/347/224/250/345/267/245/345/205/267.py +149 -0
- l0n0lc-1.0.0.dist-info/METADATA +363 -0
- l0n0lc-1.0.0.dist-info/RECORD +39 -0
- {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/WHEEL +1 -1
- l0n0lc-1.0.0.dist-info/entry_points.txt +2 -0
- {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/licenses/LICENSE +0 -0
- l0n0lc/StdList.py +0 -24
- l0n0lc/StdMap.py +0 -21
- l0n0lc/c/345/237/272/347/241/200/345/244/204/347/220/206.py +0 -207
- l0n0lc/jit.py +0 -604
- l0n0lc//347/274/226/350/257/221.py +0 -58
- l0n0lc//351/200/232/347/224/250.py +0 -134
- l0n0lc-0.8.4.dist-info/METADATA +0 -241
- l0n0lc-0.8.4.dist-info/RECORD +0 -12
- {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from .工具 import 生成变量ID
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cpp类型:
|
|
6
|
+
"""
|
|
7
|
+
预定义的 C++ 类型字符串常量。
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
INT8_T = "int8_t"
|
|
11
|
+
INT16_T = "int16_t"
|
|
12
|
+
INT32_T = "int32_t"
|
|
13
|
+
INT64_T = "int64_t"
|
|
14
|
+
UINT8_T = "uint8_t"
|
|
15
|
+
UINT16_T = "uint16_t"
|
|
16
|
+
UINT32_T = "uint32_t"
|
|
17
|
+
UINT64_T = "uint64_t"
|
|
18
|
+
HALF = "half"
|
|
19
|
+
FLOAT32 = "float"
|
|
20
|
+
FLOAT64 = "double"
|
|
21
|
+
字符串 = "char*"
|
|
22
|
+
静态字符串 = "const char*"
|
|
23
|
+
StdString = "std::string"
|
|
24
|
+
布尔 = "bool"
|
|
25
|
+
任意 = "std::any"
|
|
26
|
+
自动 = "auto"
|
|
27
|
+
空指针 = "void*"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class 代码块:
|
|
31
|
+
"""
|
|
32
|
+
用于生成 C++ 代码块的上下文管理器(包含大括号)。
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, 编译器) -> None:
|
|
36
|
+
self.编译器 = 编译器
|
|
37
|
+
|
|
38
|
+
def __enter__(self, *args, **kwargs):
|
|
39
|
+
self.编译器.添加代码("{")
|
|
40
|
+
self.编译器.进入作用域()
|
|
41
|
+
|
|
42
|
+
def __exit__(self, *args, **kwargs):
|
|
43
|
+
self.编译器.退出作用域()
|
|
44
|
+
self.编译器.添加代码("}\n")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class C代码:
|
|
48
|
+
"""
|
|
49
|
+
表示单行 C++ 代码,主要负责缩进处理。
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, 代码: str, 层级: int, lineno: Optional[int] = None) -> None:
|
|
53
|
+
self.代码 = 代码
|
|
54
|
+
self.层级 = 层级
|
|
55
|
+
self.lineno = lineno # 对应的Python源码行号
|
|
56
|
+
|
|
57
|
+
def __str__(self) -> str:
|
|
58
|
+
return " " * self.层级 + self.代码
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class C获取下标:
|
|
62
|
+
"""
|
|
63
|
+
表示 C++ 数组或 Vector 的下标访问表达式。
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, 变量, 下标) -> None:
|
|
67
|
+
self.变量 = 变量
|
|
68
|
+
self.下标 = 下标
|
|
69
|
+
|
|
70
|
+
def __str__(self) -> str:
|
|
71
|
+
return f"{self.变量}[{self.下标}]"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class C获取属性:
|
|
75
|
+
"""
|
|
76
|
+
表示 C++ 对象属性或成员函数访问表达式。
|
|
77
|
+
自动处理指针 ->、引用 . 以及对象 . 的访问差异。
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(self, 变量, 属性) -> None:
|
|
81
|
+
self.变量 = 变量
|
|
82
|
+
self.属性 = 属性
|
|
83
|
+
|
|
84
|
+
def __str__(self) -> str:
|
|
85
|
+
# 如果是C变量,根据类型决定访问方式
|
|
86
|
+
if isinstance(self.变量, C变量):
|
|
87
|
+
类型名 = self.变量.类型名
|
|
88
|
+
|
|
89
|
+
# 指针类型使用 -> 访问
|
|
90
|
+
if 类型名.endswith("*"):
|
|
91
|
+
return f"{self.变量}->{self.属性}"
|
|
92
|
+
# 引用类型使用 . 访问
|
|
93
|
+
elif 类型名.endswith("&"):
|
|
94
|
+
return f"{self.变量}.{self.属性}"
|
|
95
|
+
# 对象类型使用 . 访问
|
|
96
|
+
else:
|
|
97
|
+
return f"{self.变量}.{self.属性}"
|
|
98
|
+
|
|
99
|
+
# 如果是字符串表达式,需要解析类型
|
|
100
|
+
elif isinstance(self.变量, str):
|
|
101
|
+
# 简单的指针检测(以*结尾)
|
|
102
|
+
if self.变量.endswith("*"):
|
|
103
|
+
return f"{self.变量}->{self.属性}"
|
|
104
|
+
# 简单的引用检测(以&结尾)
|
|
105
|
+
elif self.变量.endswith("&"):
|
|
106
|
+
return f"{self.变量}.{self.属性}"
|
|
107
|
+
else:
|
|
108
|
+
return f"{self.变量}.{self.属性}"
|
|
109
|
+
|
|
110
|
+
# 如果是C函数调用(临时对象),需要用括号包围
|
|
111
|
+
elif isinstance(self.变量, C函数调用):
|
|
112
|
+
return f"({self.变量}).{self.属性}"
|
|
113
|
+
|
|
114
|
+
# 默认使用 . 访问
|
|
115
|
+
return f"{self.变量}.{self.属性}"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class C函数调用:
|
|
119
|
+
"""
|
|
120
|
+
表示 C++ 函数调用表达式。
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
def __init__(self, 函数名, 参数字符串, 返回C类型=None) -> None:
|
|
124
|
+
self.函数名 = 函数名
|
|
125
|
+
self.参数字符串 = 参数字符串
|
|
126
|
+
self.返回C类型 = 返回C类型
|
|
127
|
+
|
|
128
|
+
def __str__(self) -> str:
|
|
129
|
+
return f"{self.函数名}({self.参数字符串})"
|
|
130
|
+
|
|
131
|
+
def __getattr__(self, name):
|
|
132
|
+
"""
|
|
133
|
+
支持对函数调用返回对象的属性访问。
|
|
134
|
+
当访问 C函数调用 对象的属性时,返回一个 C获取属性 表达式。
|
|
135
|
+
"""
|
|
136
|
+
return C获取属性(self, name)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class C布尔:
|
|
140
|
+
"""
|
|
141
|
+
表示 C++ 布尔值 (true/false)。
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
def __init__(self, v) -> None:
|
|
145
|
+
self.v = v
|
|
146
|
+
|
|
147
|
+
def __str__(self) -> str:
|
|
148
|
+
return "true" if self.v else "false"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class C静态调用:
|
|
152
|
+
"""
|
|
153
|
+
表示 C++ 静态方法调用表达式。
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
def __init__(self, class_name, method_name) -> None:
|
|
157
|
+
self.class_name = class_name
|
|
158
|
+
self.method_name = method_name
|
|
159
|
+
|
|
160
|
+
def __str__(self) -> str:
|
|
161
|
+
return f"{self.class_name}::{self.method_name}"
|
|
162
|
+
|
|
163
|
+
class CInt常量:
|
|
164
|
+
def __init__(self, v:int) -> None:
|
|
165
|
+
self.v = v
|
|
166
|
+
|
|
167
|
+
def __str__(self) -> str:
|
|
168
|
+
from .基础映射 import int映射目标
|
|
169
|
+
return f'{int映射目标}({self.v})'
|
|
170
|
+
|
|
171
|
+
class CFloat常量:
|
|
172
|
+
def __init__(self, v:float) -> None:
|
|
173
|
+
self.v = v
|
|
174
|
+
|
|
175
|
+
def __str__(self) -> str:
|
|
176
|
+
from .基础映射 import float映射目标
|
|
177
|
+
return f'{float映射目标}({self.v})'
|
|
178
|
+
|
|
179
|
+
class CString常量:
|
|
180
|
+
def __init__(self, v:str) -> None:
|
|
181
|
+
self.v = v
|
|
182
|
+
|
|
183
|
+
def __str__(self) -> str:
|
|
184
|
+
return f'u8"{self.v}"'
|
|
185
|
+
|
|
186
|
+
class CBytes常量:
|
|
187
|
+
def __init__(self, v:bytes) -> None:
|
|
188
|
+
self.v = v
|
|
189
|
+
|
|
190
|
+
def __str__(self) -> str:
|
|
191
|
+
return f'"{self.v}"'
|
|
192
|
+
|
|
193
|
+
class SuperCallWrapper:
|
|
194
|
+
"""包装super()调用,用于处理基类方法访问"""
|
|
195
|
+
|
|
196
|
+
def __init__(self, base_class_name: str, transpiler):
|
|
197
|
+
self.base_class_name = base_class_name
|
|
198
|
+
self.transpiler = transpiler
|
|
199
|
+
|
|
200
|
+
def __getattribute__(self, name):
|
|
201
|
+
"""拦截所有属性访问,包括特殊方法"""
|
|
202
|
+
# Call object's __getattribute__ first to avoid infinite recursion
|
|
203
|
+
obj = super().__getattribute__(name)
|
|
204
|
+
|
|
205
|
+
# For special method names like __init__, return SuperMethodCall
|
|
206
|
+
if name.startswith("__") and name.endswith("__") and name != "__getattribute__":
|
|
207
|
+
transpiler = super().__getattribute__("transpiler")
|
|
208
|
+
return SuperMethodCall(self.base_class_name, name, transpiler)
|
|
209
|
+
|
|
210
|
+
# For other attributes, return normally
|
|
211
|
+
return obj
|
|
212
|
+
|
|
213
|
+
def __getattr__(self, method_name: str):
|
|
214
|
+
"""当访问super().method时返回基类方法调用"""
|
|
215
|
+
transpiler = super().__getattribute__("transpiler")
|
|
216
|
+
return SuperMethodCall(self.base_class_name, method_name, transpiler)
|
|
217
|
+
|
|
218
|
+
def __call__(self, *args, **kwargs):
|
|
219
|
+
"""当直接调用super()时(构造函数)"""
|
|
220
|
+
args_str = ", ".join(str(arg) for arg in args)
|
|
221
|
+
return f"{self.base_class_name}({args_str})"
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class SuperMethodCall:
|
|
225
|
+
"""表示super().method()调用"""
|
|
226
|
+
|
|
227
|
+
def __init__(self, base_class_name: str, method_name: str, transpiler=None):
|
|
228
|
+
self.base_class_name = base_class_name
|
|
229
|
+
self.method_name = method_name
|
|
230
|
+
self.transpiler = transpiler
|
|
231
|
+
|
|
232
|
+
def __call__(self, *args):
|
|
233
|
+
"""生成基类方法调用的C++代码"""
|
|
234
|
+
# Special handling: if this is super().__init__() in a constructor,
|
|
235
|
+
# don't generate any code since the parent constructor is already called
|
|
236
|
+
# in the initialization list
|
|
237
|
+
if (
|
|
238
|
+
self.method_name == "__init__"
|
|
239
|
+
and self.transpiler
|
|
240
|
+
and hasattr(self.transpiler, "当前方法名")
|
|
241
|
+
and self.transpiler.当前方法名 == "__init__"
|
|
242
|
+
):
|
|
243
|
+
return "" # No code needed for super().__init__() in constructors
|
|
244
|
+
|
|
245
|
+
args_str = ", ".join(str(arg) for arg in args)
|
|
246
|
+
# C++中调用基类方法:BaseClass::method(args...)
|
|
247
|
+
return f"{self.base_class_name}::{self.method_name}({args_str})"
|
|
248
|
+
|
|
249
|
+
def __str__(self):
|
|
250
|
+
"""用于表达式上下文"""
|
|
251
|
+
return f"{self.base_class_name}::{self.method_name}"
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# 导入统一的类型转换器
|
|
255
|
+
from .类型转换 import 类型转换器
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class 列表初始化列表:
|
|
259
|
+
"""
|
|
260
|
+
表示 C++ 的初始化列表 {e1, e2, ...},用于 std::vector 初始化。
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
def __init__(self, 代码: str, 类型名: str, 长度: int) -> None:
|
|
264
|
+
self.代码 = 代码
|
|
265
|
+
self.类型名 = 类型名
|
|
266
|
+
self.长度 = 长度
|
|
267
|
+
|
|
268
|
+
def __str__(self) -> str:
|
|
269
|
+
return self.代码
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class 字典初始化列表:
|
|
275
|
+
"""
|
|
276
|
+
表示 C++ 的字典初始化列表 {{k1, v1}, {k2, v2}, ...},用于 std::unordered_map。
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
def __init__(self, 代码: str, 键类型名: str, 值类型名: str) -> None:
|
|
280
|
+
self.代码 = 代码
|
|
281
|
+
self.键类型名 = 键类型名
|
|
282
|
+
self.值类型名 = 值类型名
|
|
283
|
+
|
|
284
|
+
def __str__(self) -> str:
|
|
285
|
+
return self.代码
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class 集合初始化列表:
|
|
291
|
+
"""
|
|
292
|
+
表示 C++ 的集合初始化列表 {e1, e2, ...},用于 std::unordered_set。
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
def __init__(self, 代码: str, 类型名: str) -> None:
|
|
296
|
+
self.代码 = 代码
|
|
297
|
+
self.类型名 = 类型名
|
|
298
|
+
|
|
299
|
+
def __str__(self) -> str:
|
|
300
|
+
return self.代码
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class C变量:
|
|
306
|
+
"""
|
|
307
|
+
表示一个 C++ 变量。
|
|
308
|
+
包含变量类型、名称、生成的 C 变量名以及初始化代码生成逻辑。
|
|
309
|
+
"""
|
|
310
|
+
|
|
311
|
+
def __init__(self, 类型名: str, 名称: str, 是否参数: bool, 默认值=None) -> None:
|
|
312
|
+
self.类型名 = 类型名
|
|
313
|
+
self.名称 = 名称
|
|
314
|
+
self.C名称 = 生成变量ID(名称)
|
|
315
|
+
self.是否参数 = 是否参数
|
|
316
|
+
self.默认值 = 默认值
|
|
317
|
+
|
|
318
|
+
def __str__(self):
|
|
319
|
+
return self.C名称
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def decltype(self):
|
|
323
|
+
return f"decltype({self})"
|
|
324
|
+
|
|
325
|
+
def 初始化代码(self, initial_value, cast_type: str | None = None):
|
|
326
|
+
"""生成变量声明和初始化代码"""
|
|
327
|
+
if cast_type:
|
|
328
|
+
return f"{self.类型名} {self.C名称} = (({cast_type})({initial_value}));"
|
|
329
|
+
else:
|
|
330
|
+
return f"{self.类型名} {self.C名称} = {initial_value};"
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import Union, List, Optional
|
|
3
|
+
import subprocess
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Cpp编译器:
|
|
9
|
+
"""
|
|
10
|
+
C++ 编译器包装类,负责检测编译器、设置参数并执行编译命令。
|
|
11
|
+
"""
|
|
12
|
+
# 支持的优化级别
|
|
13
|
+
_支持的优化级别 = {
|
|
14
|
+
'O0': '-O0', # 无优化,编译最快
|
|
15
|
+
'O1': '-O1', # 基础优化
|
|
16
|
+
'O2': '-O2', # 标准优化(默认)
|
|
17
|
+
'O3': '-O3', # 最大优化
|
|
18
|
+
'Os': '-Os', # 优化代码大小
|
|
19
|
+
'Ofast': '-Ofast', # 激进优化(可能破坏标准合规)
|
|
20
|
+
'Og': '-Og', # 调试优化
|
|
21
|
+
'Oz': '-Oz', # 最小代码大小(类似于 Os 但更激进)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
优化级别: str = 'O2',
|
|
27
|
+
启用LTO: bool = False,
|
|
28
|
+
启用向量化: bool = False,
|
|
29
|
+
SIMD指令集: Optional[str] = None
|
|
30
|
+
) -> None:
|
|
31
|
+
"""
|
|
32
|
+
初始化 C++ 编译器
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
优化级别: 优化级别,默认为 'O2'
|
|
36
|
+
- O0: 无优化,编译最快,运行最慢
|
|
37
|
+
- O1: 基础优化
|
|
38
|
+
- O2: 标准优化(默认)
|
|
39
|
+
- O3: 最大优化,编译较慢,运行最快
|
|
40
|
+
- Os: 优化代码大小
|
|
41
|
+
- Ofast: 激进优化(可能破坏标准合规)
|
|
42
|
+
- Og: 调试优化
|
|
43
|
+
- Oz: 最小代码大小
|
|
44
|
+
启用LTO: 是否启用链接时优化(LTO),默认为 False
|
|
45
|
+
启用向量化: 是否启用 SIMD 向量化优化,默认为 False
|
|
46
|
+
SIMD指令集: 指定 SIMD 指令集(None 表示自动检测)
|
|
47
|
+
可选值: SSE2, SSE4_2, AVX, AVX2, AVX512F, NEON
|
|
48
|
+
"""
|
|
49
|
+
self.编译器 = self._检测编译器()
|
|
50
|
+
self.包含目录: List[str] = []
|
|
51
|
+
self.库目录: List[str] = []
|
|
52
|
+
self.库: List[str] = []
|
|
53
|
+
self.编译选项: List[str] = []
|
|
54
|
+
self.详细模式 = False
|
|
55
|
+
self._启用LTO = 启用LTO
|
|
56
|
+
self._启用向量化 = 启用向量化
|
|
57
|
+
self._SIMD指令集 = SIMD指令集
|
|
58
|
+
|
|
59
|
+
# 设置优化级别
|
|
60
|
+
self.设置优化级别(优化级别)
|
|
61
|
+
|
|
62
|
+
# 如果启用 LTO,添加 LTO 标志
|
|
63
|
+
if 启用LTO:
|
|
64
|
+
self.启用LTO()
|
|
65
|
+
|
|
66
|
+
# 如果启用向量化,添加向量化标志
|
|
67
|
+
if 启用向量化:
|
|
68
|
+
self.启用向量化(SIMD指令集)
|
|
69
|
+
|
|
70
|
+
def _检测编译器(self) -> str:
|
|
71
|
+
"""
|
|
72
|
+
自动检测可用的 C++ 编译器。
|
|
73
|
+
优先检查 'CXX' 环境变量,然后检查常见的编译器命令。
|
|
74
|
+
"""
|
|
75
|
+
# 1. 检查环境变量
|
|
76
|
+
cxx = os.environ.get('CXX')
|
|
77
|
+
if cxx:
|
|
78
|
+
return cxx
|
|
79
|
+
|
|
80
|
+
# 2. 检查系统路径中的标准编译器
|
|
81
|
+
for compiler in ['c++', 'g++', 'clang++']:
|
|
82
|
+
if shutil.which(compiler):
|
|
83
|
+
return compiler
|
|
84
|
+
|
|
85
|
+
# 3. 没有找到编译器,抛出明确错误
|
|
86
|
+
raise RuntimeError(
|
|
87
|
+
"未找到可用的C++编译器。请安装以下编译器之一:\n"
|
|
88
|
+
"- Ubuntu/Debian: sudo apt install g++ clang++\n"
|
|
89
|
+
"- CentOS/RHEL: sudo yum install gcc-c++ clang\n"
|
|
90
|
+
"- macOS: xcode-select --install\n"
|
|
91
|
+
"- Windows: 安装 Visual Studio 或 MinGW\n"
|
|
92
|
+
"或者设置 CXX 环境变量指定编译器路径。"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def 设置编译器(self, compiler_path: str):
|
|
96
|
+
"""手动设置编译器路径"""
|
|
97
|
+
self.编译器 = compiler_path
|
|
98
|
+
|
|
99
|
+
def 设置优化级别(self, 优化级别: str):
|
|
100
|
+
"""
|
|
101
|
+
设置编译优化级别
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
优化级别: 优化级别字符串(如 'O0', 'O1', 'O2', 'O3', 'Os', 'Ofast')
|
|
105
|
+
不区分大小写,'os' 和 'Os' 等效
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
ValueError: 如果优化级别不支持
|
|
109
|
+
"""
|
|
110
|
+
# 不区分大小写,但保持原始形式
|
|
111
|
+
优化级别_lower = 优化级别.lower()
|
|
112
|
+
|
|
113
|
+
# 查找匹配的键(不区分大小写)
|
|
114
|
+
匹配键 = None
|
|
115
|
+
for key in self._支持的优化级别:
|
|
116
|
+
if key.lower() == 优化级别_lower:
|
|
117
|
+
匹配键 = key
|
|
118
|
+
break
|
|
119
|
+
|
|
120
|
+
if 匹配键 is None:
|
|
121
|
+
支持的级别 = ', '.join(self._支持的优化级别.keys())
|
|
122
|
+
raise ValueError(
|
|
123
|
+
f"不支持的优化级别: {优化级别}\n"
|
|
124
|
+
f"支持的优化级别: {支持的级别}"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
self._当前优化级别 = 匹配键
|
|
128
|
+
# 添加到编译选项(如果还没有)
|
|
129
|
+
优化选项 = self._支持的优化级别[匹配键]
|
|
130
|
+
if not any(opt.startswith('-O') or opt.startswith('--optimize') for opt in self.编译选项):
|
|
131
|
+
self.编译选项.append(优化选项)
|
|
132
|
+
|
|
133
|
+
def 获取优化级别(self) -> str:
|
|
134
|
+
"""获取当前优化级别"""
|
|
135
|
+
return getattr(self, '_当前优化级别', 'O2')
|
|
136
|
+
|
|
137
|
+
def 启用LTO(self):
|
|
138
|
+
"""
|
|
139
|
+
启用链接时优化 (LTO)
|
|
140
|
+
|
|
141
|
+
LTO 允许编译器在链接阶段进行跨编译单元的优化,
|
|
142
|
+
可以显著提升运行时性能(10-30%),但会增加编译时间。
|
|
143
|
+
"""
|
|
144
|
+
if not self._启用LTO:
|
|
145
|
+
self._启用LTO = True
|
|
146
|
+
# 添加 LTO 编译标志
|
|
147
|
+
if '-flto' not in self.编译选项:
|
|
148
|
+
self.添加编译选项('-flto')
|
|
149
|
+
|
|
150
|
+
def 禁用LTO(self):
|
|
151
|
+
"""禁用链接时优化 (LTO)"""
|
|
152
|
+
if self._启用LTO:
|
|
153
|
+
self._启用LTO = False
|
|
154
|
+
# 移除 LTO 编译标志
|
|
155
|
+
self.编译选项 = [opt for opt in self.编译选项 if opt != '-flto']
|
|
156
|
+
|
|
157
|
+
def 是否启用LTO(self) -> bool:
|
|
158
|
+
"""检查是否启用了 LTO"""
|
|
159
|
+
return self._启用LTO
|
|
160
|
+
|
|
161
|
+
def 设置LTO(self, 启用: bool):
|
|
162
|
+
"""
|
|
163
|
+
设置是否启用 LTO
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
启用: True 启用 LTO,False 禁用 LTO
|
|
167
|
+
"""
|
|
168
|
+
if 启用:
|
|
169
|
+
self.启用LTO()
|
|
170
|
+
else:
|
|
171
|
+
self.禁用LTO()
|
|
172
|
+
|
|
173
|
+
def 启用向量化(self, SIMD指令集: Optional[str] = None):
|
|
174
|
+
"""
|
|
175
|
+
启用 SIMD 向量化优化
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
SIMD指令集: 指定 SIMD 指令集,None 表示自动检测
|
|
179
|
+
可选值: SSE2, SSE4_2, AVX, AVX2, AVX512F, NEON
|
|
180
|
+
"""
|
|
181
|
+
if not self._启用向量化:
|
|
182
|
+
self._启用向量化 = True
|
|
183
|
+
self._SIMD指令集 = SIMD指令集
|
|
184
|
+
|
|
185
|
+
# 延迟导入避免循环依赖
|
|
186
|
+
from .simd优化 import 获取SIMD编译标志, 启用自动向量化标志
|
|
187
|
+
|
|
188
|
+
# 添加 SIMD 编译标志
|
|
189
|
+
SIMD标志 = 获取SIMD编译标志(SIMD指令集)
|
|
190
|
+
for 标志 in SIMD标志:
|
|
191
|
+
if 标志 not in self.编译选项:
|
|
192
|
+
self.添加编译选项(标志)
|
|
193
|
+
|
|
194
|
+
# 添加自动向量化标志
|
|
195
|
+
向量化标志 = 启用自动向量化标志()
|
|
196
|
+
for 标志 in 向量化标志:
|
|
197
|
+
if 标志 not in self.编译选项:
|
|
198
|
+
self.添加编译选项(标志)
|
|
199
|
+
|
|
200
|
+
def 禁用向量化(self):
|
|
201
|
+
"""禁用 SIMD 向量化优化"""
|
|
202
|
+
if self._启用向量化:
|
|
203
|
+
self._启用向量化 = False
|
|
204
|
+
self._SIMD指令集 = None
|
|
205
|
+
|
|
206
|
+
# 移除 SIMD 相关标志
|
|
207
|
+
SIMD标志前缀 = ['-m', '-ftree-vectorize', '-ffast-math']
|
|
208
|
+
self.编译选项 = [
|
|
209
|
+
opt for opt in self.编译选项
|
|
210
|
+
if not any(opt.startswith(prefix) for prefix in SIMD标志前缀)
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
def 是否启用向量化(self) -> bool:
|
|
214
|
+
"""检查是否启用了向量化"""
|
|
215
|
+
return self._启用向量化
|
|
216
|
+
|
|
217
|
+
def 设置向量化(self, 启用: bool, SIMD指令集: Optional[str] = None):
|
|
218
|
+
"""
|
|
219
|
+
设置是否启用向量化
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
启用: True 启用向量化,False 禁用向量化
|
|
223
|
+
SIMD指令集: 指定 SIMD 指令集,None 表示自动检测
|
|
224
|
+
"""
|
|
225
|
+
if 启用:
|
|
226
|
+
self.启用向量化(SIMD指令集)
|
|
227
|
+
else:
|
|
228
|
+
self.禁用向量化()
|
|
229
|
+
|
|
230
|
+
def 添加头文件目录(self, directory: Union[str, List[str]]):
|
|
231
|
+
"""添加头文件搜索目录 (-I)"""
|
|
232
|
+
if isinstance(directory, str):
|
|
233
|
+
self.包含目录.append(directory)
|
|
234
|
+
return
|
|
235
|
+
self.包含目录.extend(directory)
|
|
236
|
+
|
|
237
|
+
def 添加库目录(self, directory: Union[str, List[str]]):
|
|
238
|
+
"""添加库文件搜索目录 (-L)"""
|
|
239
|
+
if isinstance(directory, str):
|
|
240
|
+
self.库目录.append(directory)
|
|
241
|
+
return
|
|
242
|
+
self.库目录.extend(directory)
|
|
243
|
+
|
|
244
|
+
def 添加库(self, library_name: Union[str, List[str]]):
|
|
245
|
+
"""添加需要链接的库 (-l)"""
|
|
246
|
+
if isinstance(library_name, str):
|
|
247
|
+
self.库.append(library_name)
|
|
248
|
+
return
|
|
249
|
+
self.库.extend(library_name)
|
|
250
|
+
|
|
251
|
+
def 添加编译选项(self, option: Union[str, List[str]]):
|
|
252
|
+
"""添加其他编译选项"""
|
|
253
|
+
if isinstance(option, str):
|
|
254
|
+
self.编译选项.append(option)
|
|
255
|
+
return
|
|
256
|
+
self.编译选项.extend(option)
|
|
257
|
+
|
|
258
|
+
def 编译文件(self, file_path: Union[str, List[str]], output_path: str):
|
|
259
|
+
"""
|
|
260
|
+
编译源文件到指定输出路径。
|
|
261
|
+
构建并执行完整的编译器命令。
|
|
262
|
+
"""
|
|
263
|
+
cmd = [self.编译器]
|
|
264
|
+
|
|
265
|
+
# 添加头文件目录
|
|
266
|
+
cmd.extend([f'-I{d}' for d in self.包含目录])
|
|
267
|
+
|
|
268
|
+
# 添加库目录
|
|
269
|
+
cmd.extend([f'-L{d}' for d in self.库目录])
|
|
270
|
+
|
|
271
|
+
# 添加链接库
|
|
272
|
+
cmd.extend([f'-l{lib}' for lib in self.库])
|
|
273
|
+
|
|
274
|
+
# 添加编译选项
|
|
275
|
+
cmd.extend(self.编译选项)
|
|
276
|
+
|
|
277
|
+
# 添加源文件
|
|
278
|
+
if isinstance(file_path, list):
|
|
279
|
+
cmd.extend(file_path)
|
|
280
|
+
else:
|
|
281
|
+
cmd.append(file_path)
|
|
282
|
+
|
|
283
|
+
# 添加输出路径
|
|
284
|
+
cmd.extend(['-o', output_path])
|
|
285
|
+
|
|
286
|
+
if self.详细模式:
|
|
287
|
+
print(f"Compiling with command: {' '.join(cmd)}")
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
subprocess.check_call(cmd)
|
|
291
|
+
except subprocess.CalledProcessError as e:
|
|
292
|
+
raise RuntimeError(f"Compilation failed with exit code {e.returncode}") from e
|
|
293
|
+
except FileNotFoundError:
|
|
294
|
+
raise RuntimeError(f"Compiler '{self.编译器}' not found. Please install a C++ compiler.")
|
|
295
|
+
|
|
296
|
+
def 编译共享库(self, file_path: Union[str, List[str]], output_path: str):
|
|
297
|
+
"""
|
|
298
|
+
编译为共享/动态库 (.so)。
|
|
299
|
+
自动添加 -fPIC、--shared 和 RPATH 选项。
|
|
300
|
+
使用初始化时设置的优化级别。
|
|
301
|
+
"""
|
|
302
|
+
# 临时保存当前选项,避免重复添加
|
|
303
|
+
原始选项 = self.编译选项.copy()
|
|
304
|
+
|
|
305
|
+
# 确保必要选项存在(避免重复)
|
|
306
|
+
if '-fPIC' not in self.编译选项:
|
|
307
|
+
self.添加编译选项('-fPIC')
|
|
308
|
+
if '--shared' not in self.编译选项:
|
|
309
|
+
self.添加编译选项('--shared')
|
|
310
|
+
|
|
311
|
+
# 注意:优化级别已在 __init__ 中通过 设置优化级别() 添加
|
|
312
|
+
|
|
313
|
+
try:
|
|
314
|
+
self.编译文件(file_path, output_path)
|
|
315
|
+
finally:
|
|
316
|
+
# 恢复原始选项
|
|
317
|
+
self.编译选项 = 原始选项
|