openubmc-bingo 0.5.277__py3-none-any.whl → 0.6.2__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.

Potentially problematic release.


This version of openubmc-bingo might be problematic. Click here for more details.

Files changed (53) hide show
  1. bmcgo/__init__.py +1 -1
  2. bmcgo/bmcgo_config.py +22 -10
  3. bmcgo/cli/cli.py +95 -39
  4. bmcgo/cli/config.conan2.yaml +9 -0
  5. bmcgo/codegen/lua/codegen.py +2 -2
  6. bmcgo/codegen/lua/script/gen_intf_rpc_json.py +15 -14
  7. bmcgo/component/analysis/analysis.py +8 -8
  8. bmcgo/component/analysis/intf_validation.py +23 -12
  9. bmcgo/component/build.py +76 -14
  10. bmcgo/component/component_dt_version_parse.py +3 -2
  11. bmcgo/component/component_helper.py +43 -15
  12. bmcgo/component/coverage/incremental_cov.py +2 -2
  13. bmcgo/component/deploy.py +68 -14
  14. bmcgo/component/gen.py +1 -1
  15. bmcgo/component/package_info.py +128 -38
  16. bmcgo/component/template/conanbase.py.mako +1 -0
  17. bmcgo/component/template_v2/conanbase.py.mako +383 -0
  18. bmcgo/component/template_v2/conanfile.deploy.py.mako +26 -0
  19. bmcgo/component/test.py +53 -20
  20. bmcgo/frame.py +7 -3
  21. bmcgo/functional/analysis.py +3 -2
  22. bmcgo/functional/check.py +10 -6
  23. bmcgo/functional/conan_index_build.py +96 -20
  24. bmcgo/functional/csr_build.py +1 -1
  25. bmcgo/functional/diff.py +1 -1
  26. bmcgo/functional/fetch.py +1 -1
  27. bmcgo/functional/full_component.py +32 -24
  28. bmcgo/functional/git_history.py +220 -0
  29. bmcgo/functional/maintain.py +55 -12
  30. bmcgo/functional/new.py +1 -1
  31. bmcgo/functional/schema_valid.py +2 -2
  32. bmcgo/logger.py +2 -3
  33. bmcgo/misc.py +130 -9
  34. bmcgo/tasks/conan/__init__.py +10 -0
  35. bmcgo/tasks/conan/conanfile.py +45 -0
  36. bmcgo/tasks/task.py +27 -4
  37. bmcgo/tasks/task_build_conan.py +425 -53
  38. bmcgo/tasks/task_buildgppbin.py +8 -2
  39. bmcgo/tasks/task_download_buildtools.py +76 -0
  40. bmcgo/tasks/task_download_dependency.py +1 -0
  41. bmcgo/tasks/task_hpm_envir_prepare.py +1 -1
  42. bmcgo/utils/build_conans.py +231 -0
  43. bmcgo/utils/component_post.py +6 -4
  44. bmcgo/utils/component_version_check.py +75 -16
  45. bmcgo/utils/config.py +76 -40
  46. bmcgo/utils/fetch_component_code.py +44 -25
  47. bmcgo/utils/tools.py +239 -117
  48. bmcgo/worker.py +2 -2
  49. {openubmc_bingo-0.5.277.dist-info → openubmc_bingo-0.6.2.dist-info}/METADATA +4 -2
  50. {openubmc_bingo-0.5.277.dist-info → openubmc_bingo-0.6.2.dist-info}/RECORD +53 -46
  51. {openubmc_bingo-0.5.277.dist-info → openubmc_bingo-0.6.2.dist-info}/WHEEL +0 -0
  52. {openubmc_bingo-0.5.277.dist-info → openubmc_bingo-0.6.2.dist-info}/entry_points.txt +0 -0
  53. {openubmc_bingo-0.5.277.dist-info → openubmc_bingo-0.6.2.dist-info}/top_level.txt +0 -0
@@ -22,9 +22,11 @@ from bmcgo.codegen import __version__ as codegen_version
22
22
  from bmcgo.logger import Logger
23
23
  from bmcgo.utils.tools import Tools
24
24
  from bmcgo import misc
25
+ from bmcgo import errors
25
26
  from bmcgo.component.component_helper import ComponentHelper
26
27
 
27
28
  global log
29
+ tools = Tools()
28
30
  log = Logger()
29
31
 
30
32
  cwd = os.getcwd()
@@ -40,22 +42,28 @@ class CodegenPolicyError(OSError):
40
42
 
41
43
 
42
44
  class InfoComp():
43
- def __init__(self, args=None, service_json="mds/service.json", partner_mode=False):
44
- parser = self.arg_parser(True, partner_mode)
45
+ def __init__(self, args=None, service_json="mds/service.json", partner_mode=False, enable_upload=True):
46
+ self.enable_upload = enable_upload
47
+ self.package = ""
48
+ self.setting = ""
49
+ self.full_profile = ""
50
+ self.cmd_base = ""
51
+ parser = self.arg_parser(True, partner_mode, enable_upload)
45
52
  self.parse_args(parser, args, service_json)
46
53
 
47
54
  @staticmethod
48
- def arg_parser(add_help=False, partner_mode=False):
55
+ def arg_parser(add_help=False, partner_mode=False, enable_upload=True):
49
56
  stage_values = [member.value for member in misc.StageEnum]
50
- parser = argparse.ArgumentParser(prog="bingo build", description="Build conan", add_help=add_help,
57
+ parser = argparse.ArgumentParser(prog=f"{misc.tool_name()} build", description="Build conan", add_help=add_help,
51
58
  formatter_class=argparse.RawTextHelpFormatter)
52
- parser.add_argument("-bt", "--build_type", default="debug", help="构建类型,可选:dt,debug,release\n默认:debug")
59
+ parser.add_argument("-bt", "--build_type", default="debug", help=f"构建类型,可选:{misc.build_type_str()}\n默认:debug")
53
60
  parser.add_argument(
54
- "--stage",
55
- help=f"组件包发布阶段, 可选: {stage_values}\n默认:{misc.StageEnum.STAGE_DEV.value}",
61
+ "--stage",
62
+ help=f"组件包发布阶段, 可选: {stage_values}\n默认:{misc.StageEnum.STAGE_DEV.value}",
56
63
  default=misc.StageEnum.STAGE_DEV.value
57
64
  )
58
- parser.add_argument("-u", "--upload", action=misc.STORE_TRUE, help="上传组件包到conan仓")
65
+ if enable_upload:
66
+ parser.add_argument("-u", "--upload", action=misc.STORE_TRUE, help="上传组件包到conan仓")
59
67
  parser.add_argument(
60
68
  "-r", "--remote", help=f"conan仓别名,请检查conan remote list查看已配置的conan仓"
61
69
  )
@@ -71,14 +79,19 @@ class InfoComp():
71
79
  )
72
80
  parser.add_argument("-nc", "--no_cache",
73
81
  help="不使用~/.conan/data目录下的缓存包(构建前删除缓存)", action=misc.STORE_FALSE)
74
- parser.add_argument("-o", "--options", help="Define options values (host machine), e.g.: -o Pkg:with_qt=true",
75
- action='append', default=[])
82
+ if misc.conan_v2():
83
+ parser.add_argument("-o", "--options", action='append', default=[],
84
+ help="Define options values (host machine), e.g.: -o Pkg/*:with_qt=True")
85
+ else:
86
+ parser.add_argument("-o", "--options", action='append', default=[],
87
+ help="Define options values (host machine), e.g.: -o Pkg:with_qt=True")
76
88
  parser.add_argument(
77
89
  "--user",
78
- help=f"指定conan包的user字段,尝试从{misc.GLOBAL_CFG_FILE}文件读取conan.user字段,否则由程序管理",
90
+ help=f"指定conan包的user字段,未指定时依次尝试读取mds/service.json的user字段,都未指定时使用'{misc.conan_user()}'",
79
91
  default=None
80
92
  )
81
93
  parser.add_argument("-cov", "--coverage", help=argparse.SUPPRESS, action=misc.STORE_TRUE)
94
+ parser.add_argument("-test", "--test", help=argparse.SUPPRESS, action=misc.STORE_TRUE)
82
95
  parser.add_argument(
83
96
  "-as",
84
97
  "--asan",
@@ -92,11 +105,14 @@ class InfoComp():
92
105
  help=argparse.SUPPRESS if partner_mode else Tools.get_profile_arg_help(),
93
106
  default="",
94
107
  )
108
+ profile_name = tools.get_conan_profile("", "", True)
109
+ profile_file = os.path.join(tools.conan_profiles_dir, profile_name)
110
+ default_enable_luajit = partner_mode and os.path.isfile(profile_file)
95
111
  parser.add_argument(
96
112
  "-jit",
97
113
  "--enable_luajit",
98
- help=argparse.SUPPRESS if partner_mode else "Enable luajit",
99
- action=misc.STORE_FALSE if partner_mode else misc.STORE_TRUE,
114
+ help=argparse.SUPPRESS if default_enable_luajit else "Enable luajit",
115
+ action=misc.STORE_FALSE if default_enable_luajit else misc.STORE_TRUE,
100
116
  )
101
117
  return parser
102
118
 
@@ -104,7 +120,9 @@ class InfoComp():
104
120
  def get_codegen_policy(service_data) -> Tuple[str, int]:
105
121
  # 代码自动生成工具版本号检查
106
122
  policy = ComponentHelper.get_config_value(service_data, "codegen_policy", {})
107
- code_version = policy.get("version", ">=0")
123
+ if "codeGenPolicy" in service_data:
124
+ policy = ComponentHelper.get_config_value(service_data, "codeGenPolicy", {})
125
+ code_version = policy.get("version", "3")
108
126
  if not isinstance(code_version, str):
109
127
  code_version = str(code_version)
110
128
  code_language = policy.get("language", "c")
@@ -116,54 +134,80 @@ class InfoComp():
116
134
  if code_version.startswith(">="):
117
135
  codegen_base_version = int(code_version[2:])
118
136
  if codegen_base_version > codegen_version:
119
- raise CodegenVersionNotMatchError("代码自动生成要求的版本号大于当前bmcgo工具提供的版本号,建议升级到最新版本")
137
+ raise CodegenVersionNotMatchError(f"代码自动生成要求的版本号大于当前{misc.tool_name()}工具提供的版本号,建议升级到最新版本")
120
138
  codegen_base_version = codegen_version
121
139
  else:
122
140
  codegen_base_version = int(code_version)
123
141
  return code_language, codegen_base_version
124
142
 
143
+ @staticmethod
144
+ def get_dependencies_v2(service_data, key):
145
+ dependencies = []
146
+ user_channel = f"@{misc.conan_user()}/stable"
147
+ deps = ComponentHelper.get_config_value(service_data, key, [])
148
+ for dep in deps:
149
+ conan = dep.get(misc.CONAN)
150
+ if conan is None:
151
+ log.info("获取 conan 依赖失败, 跳过未知组件")
152
+ continue
153
+ if conan.find("@") < 0:
154
+ conan += user_channel
155
+ if not misc.conan_package_match(conan, True):
156
+ raise errors.BmcGoException(f"未正确定义依赖组件的名称: {conan}")
157
+ dependencies.append(conan)
158
+
159
+ return dependencies
160
+
125
161
  def parse_args(self, parser, args, service_json):
126
162
  self.args, _ = parser.parse_known_args(args)
127
163
  self.build_type = self.args.build_type
128
164
  self.stage = self.args.stage
129
- self.upload = self.args.upload
165
+ if self.enable_upload:
166
+ self.upload = self.args.upload
167
+ else:
168
+ self.upload = False
130
169
  self.from_source = self.args.from_source
131
170
  self.options = self.args.options
132
171
  self.coverage = self.args.coverage
133
172
  self.asan = self.args.asan
134
173
  self.remote = self.args.remote
174
+ self.user = self.args.user
175
+ self.test = self.args.test
135
176
  self.no_cache = self.args.no_cache and (not os.getenv('NOT_CLEAN_CONAN_CACHE') == 'True')
136
177
  # 是否是维护模式
137
178
  self.is_maintain = self.args.maintain
138
179
  self.enable_luajit = self.args.enable_luajit
139
- self.profile = Tools.get_conan_profile(self.args.profile, self.build_type, self.enable_luajit)
180
+ self.profile = Tools.get_conan_profile(self.args.profile, self.build_type, self.enable_luajit, self.test)
181
+ if self.profile == "profile.luajit.ini":
182
+ self.enable_luajit = True
140
183
 
141
184
  os.environ["ROOTFS_DIR"] = os.path.join(cwd, "temp")
142
185
  stage_values = [member.value for member in misc.StageEnum]
143
186
  if self.stage not in stage_values:
144
187
  raise OSError(f"参数 stage 错误, 请从 {stage_values} 中选择")
145
188
  # 构建阶段检查
146
- build_types = ["dt", "debug", "release"]
147
- if self.build_type not in build_types:
148
- raise OSError("参数 build_type 错误, 请从 [debug, release, dt] 中选择")
189
+ if self.build_type not in misc.build_type():
190
+ raise OSError(f"参数 build_type 错误, 请从 {misc.build_type_str()} 中选择")
149
191
  if self.upload and not self.remote:
150
192
  raise OSError("参数 remote 必填")
151
193
 
152
- # 只有指定为pre时才增加prerelease编码
153
- pre = ""
154
- if self.stage == misc.StageEnum.STAGE_PRE:
155
- self.stage = misc.StageEnum.STAGE_DEV
156
- now = datetime.datetime.utcnow()
157
- pre = "-pre." + now.strftime("%Y%m%d%H%M%S")
194
+ if misc.conan_v1():
195
+ # 只有指定为pre时才增加prerelease编码
196
+ pre = ""
197
+ if self.stage == misc.StageEnum.STAGE_PRE:
198
+ self.stage = misc.StageEnum.STAGE_DEV
199
+ now = datetime.datetime.utcnow()
200
+ pre = "-pre." + now.strftime("%Y%m%d%H%M%S")
158
201
 
159
- # 尝试从/etc/bmcgo.conf读取user配置
160
- user = self._get_package_user()
161
- self.channel = f"@{user}/{self.stage}"
162
-
163
- self._parse_service_json(service_json, pre)
202
+ # 尝试从/etc/bmcgo.conf读取user配置
203
+ user = self._get_package_user()
204
+ self.channel = f"@{user}/{self.stage}"
205
+ self._parse_service_json(service_json, pre)
206
+ else:
207
+ self._parse_service_json(service_json)
164
208
  self._conan_define()
165
209
 
166
- def get_dependencies(self, service_data, key):
210
+ def get_dependencies_v1(self, service_data, key):
167
211
  dependencies = []
168
212
  user_channel = ComponentHelper.get_user_channel(self.stage)
169
213
  deps = ComponentHelper.get_config_value(service_data, key, [])
@@ -178,14 +222,51 @@ class InfoComp():
178
222
  dependencies.append(conan + user_channel)
179
223
  return dependencies
180
224
 
225
+ def get_dependencies(self, service_data, key):
226
+ if misc.conan_v1():
227
+ return self.get_dependencies_v1(service_data, key)
228
+ else:
229
+ return self.get_dependencies_v2(service_data, key)
230
+
181
231
  def _conan_define(self):
232
+ if misc.conan_v1():
233
+ self._conan_define_v1()
234
+ else:
235
+ self._conan_define_v2()
236
+
237
+ def _conan_define_v2(self):
238
+ self.package = "%s/%s@%s/%s" % (self.name, self.version, self.user, self.stage)
239
+ profiles = [f"-pr:h {self.profile}"]
240
+ profiles.append("-pr:b default")
241
+ if self.enable_luajit:
242
+ self.options.append("*/*:enable_luajit=True")
243
+ if self.build_type == "debug":
244
+ self.setting = "-s:a build_type=Debug"
245
+ else:
246
+ self.setting = "-s:a build_type=Release"
247
+ self.full_profile = " ".join(profiles)
248
+ self.cmd_base = ". %s %s " % (self.full_profile, self.setting)
249
+ self.cmd_base += "%s %s " % (f"--user {self.user}", f"--channel {self.stage}")
250
+ if self.remote:
251
+ self.cmd_base += "-r %s " % self.remote
252
+ if self.options:
253
+ for option in self.options:
254
+ self.cmd_base += " -o " + option
255
+ if self.coverage:
256
+ self.cmd_base += f" -o {self.name}/*:gcov=True"
257
+ if self.asan:
258
+ self.cmd_base += f" -o {self.name}/*:asan=True"
259
+ if self.test:
260
+ self.cmd_base += f" -o */*:test=True"
261
+
262
+ def _conan_define_v1(self):
182
263
  self.package = "%s/%s%s" % (self.name, self.version, self.channel)
183
264
  profiles = [f"-pr:h {self.profile}"]
184
265
  if self.build_type == "dt":
185
266
  self.setting = "-s build_type=Dt"
186
267
  else:
187
268
  profiles.append("-pr:b profile.dt.ini")
188
- if self.enable_luajit:
269
+ if self.enable_luajit or misc.community_name() == "openubmc":
189
270
  self.options.append("skynet:enable_luajit=True")
190
271
  if self.build_type == "debug":
191
272
  self.setting = "-s build_type=Debug"
@@ -215,17 +296,26 @@ class InfoComp():
215
296
  user = None
216
297
  if user is None:
217
298
  if self.stage == misc.StageEnum.STAGE_DEV.value:
218
- user = misc.ConanUserEnum.CONAN_USER_DEV.value
299
+ user = misc.conan_user_dev()
219
300
  else:
220
- user = misc.ConanUserEnum.CONAN_USER_RELEASE.value
301
+ user = misc.conan_user()
221
302
  return user
222
303
 
223
- def _parse_service_json(self, service_json: str, pre: str):
304
+ def _parse_service_json(self, service_json: str, pre: str = ""):
224
305
  self.language = ComponentHelper.get_language(service_json=service_json)
225
306
  with open(service_json, "r", encoding="UTF-8") as file_handler:
226
307
  data = json.load(file_handler)
227
- self.version = ComponentHelper.get_config_value(data, "version") + pre
228
- self.name = data.get("name")
308
+ if misc.conan_v2():
309
+ self.language = data.get("language", "lua")
310
+ if not self.user:
311
+ self.user = data.get("user", misc.conan_user()).lower()
312
+ if self.stage == "dev":
313
+ self.user += ".dev"
314
+ self.version = ComponentHelper.get_config_value(data, "version").lower()
315
+ self.name = data.get("name").lower()
316
+ else:
317
+ self.version = ComponentHelper.get_config_value(data, "version") + pre
318
+ self.name = data.get("name")
229
319
  # 编译依赖
230
320
  self.build_dependencies = self.get_dependencies(data, "dependencies/build")
231
321
  # 开发者测试依赖
@@ -5,6 +5,7 @@ import urllib3
5
5
  import shutil
6
6
  % endif
7
7
  from conans import ConanFile, CMake
8
+ from conan.tools.files import copy
8
9
  % if pkg.is_maintain:
9
10
  from conans import tools
10
11
  from conans.util.files import mkdir
@@ -0,0 +1,383 @@
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
4
+ # openUBMC is licensed under Mulan PSL v2.
5
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
6
+ # You may obtain a copy of Mulan PSL v2 at:
7
+ # http://license.coscl.org.cn/MulanPSL2
8
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
+ # See the Mulan PSL v2 for more details.
12
+ import os
13
+ import concurrent.futures
14
+ import urllib3
15
+ % if pkg.is_maintain:
16
+ import time
17
+ % endif
18
+ % if pkg.is_maintain:
19
+ import stat
20
+ import shutil
21
+ % endif
22
+ from conan import ConanFile
23
+ from conan.tools.scm import Git
24
+ from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
25
+ from conan.tools.files import copy, update_conandata, chdir, rm
26
+ from conan.errors import ConanInvalidConfiguration
27
+ % if language == "c":
28
+ from bmcgo.component.gen import GenComp
29
+ % endif
30
+ % if pkg.is_maintain:
31
+ from conans import tools
32
+ from conans.util.files import mkdir
33
+ from conan.tools.files import patch as apply_patch
34
+ from conans.errors import ConanException
35
+ % endif
36
+
37
+ urllib3.disable_warnings()
38
+
39
+ # 构建时由工具自动生成到业务仓,做为conanfile.py的基类参与组件构建
40
+ # 如需要调试,请修改模板文件(目录中存在python版本号、bingo集成开发环境应用名称,请适配):
41
+ # ~/.local/lib/python3.8/site-packages/bingo/component/template/conanbase.py.mako
42
+
43
+
44
+ class ConanBase(ConanFile):
45
+ name = "${pkg.name}"
46
+ % if not pkg.is_maintain:
47
+ version = "${pkg.version}"
48
+ % endif
49
+ settings = "os", "compiler", "build_type", "arch"
50
+ license = "Mulan PSL v2"
51
+ generators = "CMakeDeps", "VirtualBuildEnv", "PkgConfigDeps"
52
+ language = "${language}"
53
+ _cmake = None
54
+ _codegen_version = ${codegen_version}
55
+ options = {
56
+ "asan": [True, False],
57
+ "gcov": [True, False],
58
+ "test": [True, False],
59
+ "manufacture": [True, False],
60
+ % if language == "lua":
61
+ "enable_luajit": [True, False],
62
+ % endif
63
+ % for op, ctx in pkg.design_options.items():
64
+ "${op}": [${", ".join(("\"" + i + "\"") if isinstance(i, str) else str(i) for i in ctx["option"])}],
65
+ % endfor
66
+ }
67
+ default_options = {
68
+ "asan": False,
69
+ "gcov": False,
70
+ "test": False,
71
+ "manufacture": False,
72
+ % if language == "lua":
73
+ "enable_luajit": False,
74
+ % endif
75
+ % for op, ctx in pkg.design_options.items():
76
+ "${op}": ${("\"" + ctx["default"] + "\"") if isinstance(ctx["default"], str) else str(ctx["default"])},
77
+ % endfor
78
+ }
79
+
80
+ def layout(self):
81
+ cmake_layout(self, build_folder=".build")
82
+
83
+ def requirements(self):
84
+ % if len(pkg.build_dependencies) > 0:
85
+ # 编译依赖
86
+ % for build_dep in pkg.build_dependencies:
87
+ self.requires("${build_dep}")
88
+ % endfor
89
+ % endif
90
+ %if language == "lua":
91
+ skynet = self.conf.get("user.tools:skynet")
92
+ if skynet:
93
+ self.tool_requires(skynet, options={"tools_only": True})
94
+ luajit = self.conf.get("user.tools:luajit")
95
+ if luajit:
96
+ self.tool_requires(luajit, options={"tools_only": True})
97
+ % endif
98
+ pass
99
+
100
+ def export(self):
101
+ copy(self, "conanbase.py", self.recipe_folder, self.export_folder)
102
+ % if not pkg.is_maintain:
103
+ git = Git(self, self.recipe_folder)
104
+ if git.is_dirty():
105
+ update_conandata(self, {"sources": {self.version: {"branch": None, "url": None, "pwd": os.getcwd(), "timestamp": int(time.time())}}})
106
+ return
107
+ url = None
108
+ commit = git.get_commit()
109
+ branches = git.run("branch -r --contains {}".format(commit))
110
+ remotes = git.run("remote")
111
+ for remote in remotes.splitlines():
112
+ if "{}/".format(remote) in branches:
113
+ url = git.get_remote_url(remote)
114
+ break
115
+ if not url:
116
+ update_conandata(self, {"sources": {self.version: {"branch": None, "url": None, "pwd": os.getcwd(), "timestamp": int(time.time())}}})
117
+ return
118
+ tag = git.run("tag --points-at HEAD")
119
+ update_conandata(self, {"sources": {self.version: {"branch": f"refs/tags/{tag}" if tag else commit, "url": url}}})
120
+ % endif
121
+
122
+ % if pkg.is_maintain:
123
+ def export_sources(self):
124
+ patches = self.conan_data.get("patches", {}).get(self.version, [])
125
+ for patch in patches:
126
+ patch_file = patch.get("patch_file")
127
+ if patch_file is None:
128
+ continue
129
+ # 与export_conandata_patches方法不同点:所有patches将从recipes_folder/../pacthes读取
130
+ src = os.path.join(self.recipe_folder, "..", patch_file)
131
+ dst = os.path.join(self.export_sources_folder, patch_file)
132
+ mkdir(os.path.dirname(dst))
133
+ shutil.copy2(src, dst)
134
+
135
+ % endif
136
+ def source(self):
137
+ git = Git(self)
138
+ sources = self.conan_data["sources"][self.version]
139
+ % if pkg.is_maintain:
140
+ if sources["url"] and sources["branch"]:
141
+ git.fetch_commit(url=sources["url"], commit=sources["branch"].split("/")[-1])
142
+ else:
143
+ copy(self, "*", src=sources["pwd"], dst=".")
144
+ % else:
145
+ git.fetch_commit(url=sources["url"], commit=sources["branch"].split("/")[-1])
146
+ % endif
147
+ % if language == "c":
148
+ self._codegen()
149
+ % endif
150
+
151
+ def generate(self):
152
+ tc = self._pre_generate()
153
+ tc.generate()
154
+
155
+ % if pkg.is_maintain:
156
+ @staticmethod
157
+ def _get_patch_changed_files(patch_file):
158
+ files = {}
159
+ for line in open(patch_file):
160
+ if not line.startswith("diff --git"):
161
+ continue
162
+ line = line.strip()
163
+ chunk = line.split()
164
+ a_file = chunk[-2][2:]
165
+ b_file = chunk[-1][2:]
166
+ files[a_file] = b_file
167
+ return files
168
+
169
+ %endif
170
+ def build(self):
171
+ % if pkg.is_maintain:
172
+ for patch in self.conan_data.get("patches", {}).get(self.version, []):
173
+ patch_file = patch.get("patch_file")
174
+ if not patch_file:
175
+ continue
176
+ real_path = os.path.join(self.folders.base_source, patch_file)
177
+ print(f"Start patch file {patch_file}")
178
+ changed_files = self._get_patch_changed_files(real_path)
179
+ try:
180
+ apply_patch(self, patch_file=real_path)
181
+ self._revise_renamed_files(changed_files)
182
+ cmd = f"git commit -m \"{patch_file}\""
183
+ self.run(cmd)
184
+ except ConanException:
185
+ # 尝试还原文件修改
186
+ for a_file, b_file in changed_files.items():
187
+ cmd = f"git checkout -- {a_file}"
188
+ self.run(cmd, ignore_errors=True)
189
+ cmd = f"git checkout -- {b_file}"
190
+ self.run(cmd, ignore_errors=True)
191
+ cmd = "git am " + real_path
192
+ self.run(cmd)
193
+ % endif
194
+ cmake = self._configure_cmake()
195
+ cmake.build()
196
+
197
+ def package(self):
198
+ cmake = self._configure_cmake()
199
+ cmake.install()
200
+ files_to_copy = [
201
+ ("permissions.ini", self.source_folder, self.package_folder),
202
+ ("model.json", os.path.join(self.source_folder, "mds"),
203
+ os.path.join(self.package_folder, "include/mds")),
204
+ ("service.json", os.path.join(self.source_folder, "mds"),
205
+ os.path.join(self.package_folder, "include/mds")),
206
+ ("*", os.path.join(self.source_folder, "customization"),
207
+ os.path.join(self.package_folder, "include")),
208
+ ("*", os.path.join(self.source_folder, "mds"),
209
+ os.path.join(self.package_folder, "usr/share/doc/openubmc/${pkg.name}/mds")),
210
+ ("*", os.path.join(self.source_folder, "docs"),
211
+ os.path.join(self.package_folder, "usr/share/doc/openubmc/${pkg.name}/docs")),
212
+ ("*", os.path.join(self.source_folder, "build"),
213
+ os.path.join(self.package_folder, "include")),
214
+ ("permissions.ini", os.path.join(self.source_folder, "dist"), self.package_folder),
215
+ ("*.md", self.source_folder, os.path.join(self.package_folder,
216
+ "usr/share/doc/openubmc/${pkg.name}/docs")),
217
+ ("*.MD", self.source_folder, os.path.join(self.package_folder,
218
+ "usr/share/doc/openubmc/${pkg.name}/docs"))
219
+ ]
220
+ for pattern, src, dst in files_to_copy:
221
+ copy(self, pattern, src=src, dst=dst, keep_path=True)
222
+
223
+ # 只有当需要统计覆盖率且TRANSTOBIN环境变量未设置时才不处理lua文件
224
+ if self.options.gcov and os.getenv("TRANSTOBIN") is None:
225
+ return
226
+
227
+ os.chdir(self.package_folder)
228
+ with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
229
+ for root, _, files in os.walk("."):
230
+ self.compile_files(root, files, executor)
231
+ rm(self, "luac.out", self.package_folder)
232
+
233
+ def compile_files(self, root, files, executor):
234
+ for file in files:
235
+ if file.endswith(".lua") and not os.path.islink(os.path.join(root, file)):
236
+ file_path = os.path.join(root, file)
237
+ if self.options.enable_luajit:
238
+ executor.submit(self.compile_file, file_path, True)
239
+ else:
240
+ executor.submit(self.compile_file, file_path, False)
241
+
242
+ def compile_file(self, file_path, enable_luajit):
243
+ if enable_luajit:
244
+ self.run(f"luajit -b -g {file_path} {file_path}")
245
+ else:
246
+ self.run(f"luac -o {file_path} {file_path}")
247
+ self.run(f"luac -s {file_path}")
248
+
249
+ def package_info(self):
250
+ app_dir = os.path.join(self.package_folder, "opt/bmc/apps/${pkg.name}")
251
+ if os.path.isdir(app_dir):
252
+ self.runenv_info.append("PATH", ':' + app_dir)
253
+ self.buildenv_info.append("PATH", ':' + app_dir)
254
+ % if "application" in pkg.package_type and pkg.package_info is not None:
255
+ % if len(pkg.package_info.get("bindirs", [])) > 0:
256
+ self.cpp_info.bindirs = [${", ".join("\"" + i + "\"" for i in pkg.package_info["bindirs"])}]
257
+ % for dir in pkg.package_info["bindirs"]:
258
+ self.env_info.PATH.append(os.path.join(self.package_folder, "${dir}"))
259
+ % endfor
260
+ % endif
261
+ % endif
262
+ libs = []
263
+ dirs = []
264
+ for root, _, files in os.walk("."):
265
+ for file in files:
266
+ dirname, libname = self.find_libraries(root, file)
267
+ if dirname and dirname not in dirs:
268
+ dirs.append(dirname)
269
+ if libname:
270
+ libs.append(libname)
271
+
272
+ if dirs:
273
+ self.cpp_info.components["${pkg.name}"].set_property("cmake_target_name", "${pkg.name}::${pkg.name}")
274
+ self.cpp_info.components["${pkg.name}"].set_property("cmake_target_aliass", ["${pkg.name}::${pkg.name}"])
275
+ self.cpp_info.components["${pkg.name}"].set_property("pkg_config_name", "${pkg.name}")
276
+ self.cpp_info.components["${pkg.name}"].libs = libs
277
+ self.cpp_info.components["${pkg.name}"].libdirs = dirs
278
+ for dir in dirs:
279
+ self.runenv_info.append("LD_LIBRARY_PATH", os.path.join(self.package_folder, dir))
280
+ self.buildenv_info.append("LD_LIBRARY_PATH", os.path.join(self.package_folder, dir))
281
+
282
+ def find_libraries(self, root, file):
283
+ if file.endswith(".so") and file.startswith("lib"):
284
+ if root.startswith("./"):
285
+ dirname = root[2:]
286
+ else:
287
+ dirname = root
288
+ libname = file[3:-3]
289
+ return (dirname, libname)
290
+ if file.endswith(".a") and file.startswith("lib"):
291
+ if root.startswith("./"):
292
+ dirname = root[2:]
293
+ else:
294
+ dirname = root
295
+ return (dirname, file)
296
+ return (None, None)
297
+
298
+ % if pkg.is_maintain:
299
+ def _revise_renamed_files(self, changed_files):
300
+ for a_file, b_file in changed_files.items():
301
+ if a_file != b_file:
302
+ if a_file != "/dev/null" and b_file != "/dev/null":
303
+ os.rename(a_file, b_file)
304
+ cmd = f"git rm -f {a_file}"
305
+ self.run(cmd)
306
+ elif a_file != "/dev/null":
307
+ cmd = f"git rm -f {a_file}"
308
+ self.run(cmd)
309
+ continue
310
+ cmd = f"git add {b_file}"
311
+ self.run(cmd)
312
+
313
+ %endif
314
+ def _configure_cmake(self):
315
+ if self._cmake is not None:
316
+ return self._cmake
317
+ self._cmake = CMake(self)
318
+ self._cmake.configure()
319
+ return self._cmake
320
+
321
+ % if language == "c":
322
+ def _codegen(self):
323
+ args = ["-s", "mds/service.json"]
324
+ gen = GenComp(args)
325
+ gen.run(self._codegen_version)
326
+
327
+ % endif
328
+ def _pre_generate(self):
329
+ tc = CMakeToolchain(self)
330
+ tc.preprocessor_definitions["_FORTIFY_SOURCE"] = "2"
331
+
332
+ tc.variables["BUILD_MANUFACTURE"] = self.options.manufacture
333
+ % if len(pkg.design_options) > 0:
334
+ % for op, _ in pkg.design_options.items():
335
+ tc.variables["CONAN_DEFS_${op.upper()}"] = self.options.${op}
336
+ % endfor
337
+ % endif
338
+ % if language == "lua":
339
+ if self.options.enable_luajit:
340
+ tc.variables["CONAN_DEFS_ENABLE_LUAJIT"] = True
341
+ % endif
342
+ if self.options.test:
343
+ tc.variables["ENABLE_TEST"] = True
344
+ tc.preprocessor_definitions["ENABLE_TEST"] = True
345
+ # 向CMAKE传递版本号信息
346
+ version = self.version.split(".")
347
+ if len(version) >= 1:
348
+ tc.variables["PACKAGE_VERSION_MAJOR"] = version[0]
349
+ if len(version) >= 2:
350
+ tc.variables["PACKAGE_VERSION_MINOR"] = version[1]
351
+ if len(version) >= 3:
352
+ tc.variables["PACKAGE_VERSION_REVISION"] = version[2]
353
+ # 设置额外编译选项或者重定义CFLAGS CXXFLAGS,也可以设置其他开关
354
+ # 示例: os.environ['CFLAGS'] = f"{os.getenv('CFLAGS')} -fPIE"
355
+
356
+ if self.settings.arch in ["armv8", "x86_64"]:
357
+ tc.variables["CMAKE_INSTALL_LIBDIR"] = "usr/lib64"
358
+ else:
359
+ tc.variables["CMAKE_INSTALL_LIBDIR"] = "usr/lib"
360
+
361
+ if self.options.get_safe("asan", False):
362
+ print("Enable asan flags")
363
+ asan_flags = "-fsanitize=address -fsanitize-recover=address,all -fno-omit-frame-pointer -fno-stack-protector -O0"
364
+ tc.extra_cflags.append(asan_flags)
365
+ tc.extra_cxxflags.append(asan_flags)
366
+ tc.extra_sharedlinkflag.append("LDFLAGS", "-fsanitize=address")
367
+ tc.extra_exelinkflag.append("LDFLAGS", "-fsanitize=address")
368
+
369
+ # GCOV 标志设置
370
+ if self.options.get_safe("gcov", False):
371
+ print("Enable gcov flags")
372
+ gcov_flags = "-ftest-coverage -fprofile-arcs -fprofile-update=atomic"
373
+ tc.extra_cflags.append(gcov_flags)
374
+ tc.extra_cxxflags.append(gcov_flags)
375
+ # 配合generate添加宏定义
376
+ tc.variables["CMAKE_TOOLCHAIN_FILE"] = "conan_toolchain.cmake"
377
+ # rpath配置
378
+ tc.variables["CMAKE_SKIP_BUILD_RPATH"] = True
379
+ tc.variables["CMAKE_SKIP_RPATH"] = True
380
+ tc.variables["CMAKE_SKIP_INSTALL_RPATH"] = True
381
+ tc.variables["CMAKE_BUILD_WITH_INSTALL_RPATH"] = False
382
+ tc.variables["CMAKE_INSTALL_RPATH_USE_LINK_PATH"] = False
383
+ return tc