1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# This file is part of the openHiTLS project. 4# 5# openHiTLS is licensed under the Mulan PSL v2. 6# You can use this software according to the terms and conditions of the Mulan PSL v2. 7# You may obtain a copy of Mulan PSL v2 at: 8# 9# http://license.coscl.org.cn/MulanPSL2 10# 11# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14# See the Mulan PSL v2 for more details. 15""" 16Customize the openHiTLS build. 17Generate the modules.cmake file based on command line arguments and configuration files. 18 19Options usage and examples: 201 Enable the feature on demand and specify the implementation type of the feature, c or assembly. 21 # Use 'enable' to specify the features to be constructed. 22 # Compile C code if there is no other parameter. 23 ./configure.py --enable all # Build all features of openHiTLS. 24 ./configure.py --enable hitls_crypto # Build all features in the lib hitls_crypto. 25 ./configure.py --enable md # Build all sub features of md. 26 ./configure.py --enable sha2 sha3 hmac # Specifies to build certain features. 27 28 # Use 'enable' to specify the features to be constructed. 29 # Use 'asm_type' to specify the assembly type. 30 # If there are features in enable list that supports assembly, compile its assembly implementation. 31 ./configure.py --enable sm3 aes ... --asm_type armv8 32 33 # Use 'enable' to specify the features to be constructed. 34 # Use 'asm_type' to specify the assembly type. 35 # Use 'asm' to specify the assembly feature(s), which is(are) based on the enabled features. 36 # Compile the assembly code of the features in the asm, and the C code of other features in the enable list. 37 ./configure.py --enable sm3 aes ... --asm_type armv8 --asm sm3 38 392 Compile options: Add or delete compilation options based on the default compilation options (compile.json). 40 ./configure.py --add_options "-O0 -g" --del_options "-O2 -D_FORTIFY_SOURCE=2" 41 423 Link options: Add or delete link options based on the default link options (compile.json). 43 ./configure.py --add_link_flags "xxx xxx" --del_link_flags "xxx xxx" 44 454 Set the endian mode of the system. Set the endian mode of the system. The default value is little endian. 46 ./configure.py --endian big 47 485 Specifies the system type. 49 ./configure.py --system linux 50 516 Specifies the number of system bits. 52 ./configure.py --bits 32 53 547 Generating modules.cmake 55 ./configure.py -m 56 578 Specifies the directory where the compilation middleware is generated. The default directory is ./output. 58 ./configure.py --build_dir build 59 609 Specifies the lib type. 61 ./configure.py --lib_type static 62 ./configure.py --lib_type static shared object 63 6410 You can directly specify the compilation configuration files, omitting the above 1~9 command line parameters. 65 For the file format, please refer to the compile_config.json and feature_config.json files generated after executing 66 the above 1~9 commands. 67 ./configure.py --feature_config path/to/xxx.json --compile_config path/to/xxx.json 68 69Note: 70 Options for different functions can be combined. 71""" 72 73import sys 74sys.dont_write_bytecode = True 75import os 76import argparse 77import traceback 78import glob 79from script.methods import copy_file, save_json_file, trans2list 80from script.config_parser import (FeatureParser, CompileParser, FeatureConfigParser, 81 CompileConfigParser, CompleteOptionParser) 82 83srcdir = os.path.dirname(os.path.realpath(sys.argv[0])) 84work_dir = os.path.abspath(os.getcwd()) 85 86def get_cfg_args(): 87 parser = argparse.ArgumentParser(prog='openHiTLS', description='parser configure arguments') 88 try: 89 # Version/Release Build Configuration Parameters 90 parser.add_argument('-m', '--module_cmake', action='store_true', help='generate moudules.cmake file') 91 parser.add_argument('--build_dir', metavar='dir', type=str, default=os.path.join(srcdir, 'build'), 92 help='compile temp directory') 93 parser.add_argument('--output_dir', metavar='dir', type=str, default=os.path.join(srcdir, 'output'), 94 help='compile output directory') 95 # Configuration file 96 parser.add_argument('--feature_config', metavar='file_path', type=str, default='', 97 help='Configuration file of the compilation features.') 98 parser.add_argument('--compile_config', metavar='file_path', type=str, default='', 99 help='Configuration file of compilation parameters.') 100 # Compilation Feature Configuration 101 parser.add_argument('--enable', metavar='feature', nargs='+', default=[], 102 help='enable some libs or features, such as --enable sha256 aes gcm_asm, default is "all"') 103 parser.add_argument('--disable', metavar='feature', nargs='+', default=['uio_sctp'], 104 help='disable some libs or features, such as --disable aes gcm_asm, default is disable "uio_sctp" ') 105 parser.add_argument('--enable-sctp', action="store_true", help='enable sctp which is used in DTLS') 106 parser.add_argument('--asm_type', type=str, help='Assembly Type, default is "no_asm".') 107 parser.add_argument('--asm', metavar='feature', default=[], nargs='+', help='config asm, such as --asm sha2') 108 # System Configuration 109 parser.add_argument('--system', type=str, 110 help='To enable feature "sal_xxx", should specify the system.') 111 parser.add_argument('--endian', metavar='little|big', type=str, choices=['little', 'big'], 112 help='Specify the platform endianness as little or big, default is "little".') 113 parser.add_argument('--bits', metavar='32|64', type=int, choices=[32, 64], 114 help='To enable feature "bn", should specify the number of OS bits, default is "64".') 115 # Compiler Options, Link Options 116 parser.add_argument('--lib_type', choices=['static', 'shared', 'object'], nargs='+', 117 help='set lib type, such as --lib_type staic shared, default is "staic shared object"') 118 parser.add_argument('--add_options', default='', type=str, 119 help='add some compile options, such as --add_options="-O0 -g"') 120 parser.add_argument('--del_options', default='', type=str, 121 help='delete some compile options such as --del_options="-O2 -Werror"') 122 parser.add_argument('--add_link_flags', default='', type=str, 123 help='add some link flags such as --add_link_flags="-pie"') 124 parser.add_argument('--del_link_flags', default='', type=str, 125 help='delete some link flags such as --del_link_flags="-shared -Wl,-z,relro"') 126 127 parser.add_argument('--hitls_version', default='openHiTLS 0.2.1 20 May 2025', help='%(prog)s version str') 128 parser.add_argument('--hitls_version_num', default=0x0020001f, help='%(prog)s version num') 129 parser.add_argument('--bundle_libs', action='store_true', help='Indicates that multiple libraries are bundled together. By default, it is not bound.\ 130 It need to be used together with "-m"') 131 132 args = vars(parser.parse_args()) 133 134 args['tmp_feature_config'] = os.path.join(args['build_dir'], 'feature_config.json') 135 args['tmp_compile_config'] = os.path.join(args['build_dir'], 'compile_config.json') 136 137 # disable uio_sctp by default 138 if args['enable_sctp'] or args['module_cmake']: 139 if 'uio_sctp' in args['disable']: 140 args['disable'].remove('uio_sctp') 141 142 except argparse.ArgumentError as e: 143 parser.print_help() 144 raise ValueError("Error: Failed to obtain parameters.") from e 145 146 return argparse.Namespace(**args) 147 148class Configure: 149 """Provides operations related to configuration and input parameter parsing: 150 1 Parse input parameters. 151 2 Read configuration files and input parameters. 152 3 Update the final configuration files in the build directory. 153 """ 154 config_json_file = 'config.json' 155 feature_json_file = 'config/json/feature.json' 156 complete_options_json_file = 'config/json/complete_options.json' 157 default_compile_json_file = 'config/json/compile.json' 158 159 def __init__(self, features: FeatureParser): 160 self._features = features 161 self._args = get_cfg_args() 162 self._preprocess_args() 163 164 @property 165 def args(self): 166 return self._args 167 168 def _preprocess_args(self): 169 if self._args.feature_config and not os.path.exists(self._args.feature_config): 170 raise FileNotFoundError('File not found: %s' % self._args.feature_config) 171 if self._args.compile_config and not os.path.exists(self._args.compile_config): 172 raise FileNotFoundError('File not found: %s' % self._args.compile_config) 173 174 if 'all' in self._args.enable: 175 if len(self._args.enable) > 1: 176 raise ValueError("Error: 'all' and other features cannot be set at the same time.") 177 else: 178 for fea in self._args.enable: 179 if fea in self._features.libs or fea in self._features.feas_info: 180 continue 181 raise ValueError("unrecognized fea '%s'" % fea) 182 183 if self._args.asm_type: 184 if self._args.asm_type not in self._features.asm_types: 185 raise ValueError("Unsupported asm_type: asm_type should be one of [%s]" % self._features.asm_types) 186 else: 187 if self._args.asm and not self._args.asm_type: 188 raise ValueError("Error: 'asm_type' and 'asm' must be set at the same time.") 189 # The value of 'asm' will be verified later. 190 191 @staticmethod 192 def _load_config(is_fea_cfg, src_file, dest_file): 193 if os.path.exists(dest_file): 194 if src_file != '': 195 raise FileExistsError('{} already exists'.format(dest_file)) 196 else: 197 if src_file == '': 198 # No custom configuration file is specified, create a default config file. 199 cfg = FeatureConfigParser.default_cfg() if is_fea_cfg else CompileConfigParser.default_cfg() 200 save_json_file(cfg, dest_file) 201 else: 202 copy_file(src_file, dest_file) 203 204 def load_config_to_build(self): 205 """Load the compilation feature and compilation option configuration files to the build directory: 206 build/feature_config.json 207 build/compile_config.json 208 """ 209 if not os.path.exists(self._args.build_dir): 210 os.makedirs(self._args.build_dir) 211 self._load_config(True, self._args.feature_config, self._args.tmp_feature_config) 212 self._load_config(False, self._args.compile_config, self._args.tmp_compile_config) 213 214 def update_feature_config(self, gen_cmake): 215 """Update the feature configuration file in the build based on the input parameters.""" 216 conf_custom_feature = FeatureConfigParser(self._features, self._args.tmp_feature_config) 217 218 # If no feature is enabled before modules.cmake is generated, set enable to "all". 219 if not conf_custom_feature.libs and not self._args.enable and gen_cmake: 220 self._args.enable = ['all'] 221 222 # Set parameters by referring to "FeatureConfigParser.key_value". 223 conf_custom_feature.set_param('libType', self._args.lib_type) 224 conf_custom_feature.set_param('endian', self._args.endian) 225 conf_custom_feature.set_param('system', self._args.system, False) 226 conf_custom_feature.set_param('bits', self._args.bits, False) 227 if self._args.bundle_libs: 228 conf_custom_feature.set_param('bundleLibs', self._args.bundle_libs) 229 enable_feas, asm_feas = conf_custom_feature.get_enable_feas(self._args.enable, self._args.asm) 230 231 asm_type = self._args.asm_type if self._args.asm_type else '' 232 if not asm_type and conf_custom_feature.asm_type != 'no_asm': 233 asm_type = conf_custom_feature.asm_type 234 235 if asm_type: 236 conf_custom_feature.set_asm_type(asm_type) 237 conf_custom_feature.set_asm_features(enable_feas, asm_feas, asm_type) 238 if enable_feas: 239 conf_custom_feature.set_c_features(enable_feas) 240 241 self._args.securec_lib = conf_custom_feature.securec_lib 242 # update feature and resave file. 243 conf_custom_feature.update_feature(self._args.enable, self._args.disable, gen_cmake) 244 conf_custom_feature.save(self._args.tmp_feature_config) 245 self._args.bundle_libs = conf_custom_feature.bundle_libs 246 247 def update_compile_config(self, all_options: CompleteOptionParser): 248 """Update the compilation configuration file in the build based on the input parameters.""" 249 conf_custom_compile = CompileConfigParser(all_options, self._args.tmp_compile_config) 250 251 if self._args.add_options: 252 conf_custom_compile.change_options(self._args.add_options.strip().split(' '), True) 253 if self._args.del_options: 254 conf_custom_compile.change_options(self._args.del_options.strip().split(' '), False) 255 256 if self._args.add_link_flags: 257 conf_custom_compile.change_link_flags(self._args.add_link_flags.strip().split(' '), True) 258 if self._args.del_link_flags: 259 conf_custom_compile.change_link_flags(self._args.del_link_flags.strip().split(' '), False) 260 261 conf_custom_compile.save(self._args.tmp_compile_config) 262 263class CMakeGenerator: 264 """ Generating CMake Commands and Scripts Based on Configuration Files """ 265 def __init__(self, args, features: FeatureParser, all_options: CompleteOptionParser): 266 self._args = args 267 self._cfg_feature = features 268 self._cfg_compile = CompileParser(all_options, Configure.default_compile_json_file) 269 self._cfg_custom_feature = FeatureConfigParser(features, args.tmp_feature_config) 270 self._cfg_custom_feature.check_fea_opts() 271 self._cfg_custom_compile = CompileConfigParser(all_options, args.tmp_compile_config) 272 273 self._asm_type = self._cfg_custom_feature.asm_type 274 275 self._platform = 'linux' 276 277 @staticmethod 278 def _get_common_include(modules: list): 279 """ modules: ['::','::']""" 280 inc_dirs = set() 281 top_modules = set(x.split('::')[0] for x in modules) 282 top_modules.add('bsl/log') 283 top_modules.add('bsl/err') 284 for module in top_modules: 285 path = module + '/include' 286 if os.path.exists(path): 287 inc_dirs.add(path) 288 path = 'include/' + module 289 if os.path.exists(path): 290 inc_dirs.add(path) 291 292 if os.path.exists('config/macro_config'): 293 inc_dirs.add('config/macro_config') 294 if os.path.exists('../../../../Secure_C/include'): 295 inc_dirs.add('../../../../Secure_C/include') 296 if os.path.exists('../../../platform/Secure_C/include'): 297 inc_dirs.add('../../../platform/Secure_C/include') 298 return inc_dirs 299 300 def _get_module_include(self, mod: str, dep_mods: list): 301 inc_dirs = set() 302 dep_mods.append(mod) 303 for dep in dep_mods: 304 top_dir, sub_dir = dep.split('::') 305 path = "{}/{}/include".format(top_dir, sub_dir) 306 if os.path.exists(path): 307 inc_dirs.add(path) 308 top_mod, sub_mod = dep.split('::') 309 310 cfg_inc = self._cfg_feature.modules[top_mod][sub_mod].get('.include', []) 311 for inc_dir in cfg_inc: 312 if os.path.exists(inc_dir): 313 inc_dirs.add(inc_dir) 314 return inc_dirs 315 316 @staticmethod 317 def _expand_srcs(srcs): 318 if not srcs: 319 return [] 320 321 ret = [] 322 for x in srcs: 323 ret += glob.glob(x, recursive=True) 324 if len(ret) == 0: 325 raise SystemError("The .c file does not exist in the {} directory.".format(srcs)) 326 ret.sort() 327 return ret 328 329 @classmethod 330 def _gen_cmd_cmake(cls, cmd: str, title, content_obj=None): 331 if not content_obj: 332 return '{}({})\n'.format(cmd, title) 333 334 items = None 335 if isinstance(content_obj, list) or isinstance(content_obj, set): 336 items = content_obj 337 elif isinstance(content_obj, dict): 338 items = content_obj.values() 339 elif isinstance(content_obj, str): 340 items = [content_obj] 341 else: 342 raise ValueError('Unsupported type "%s"' % type(content_obj)) 343 344 content = '' 345 for item in items: 346 content += ' {}\n'.format(item) 347 348 if len(items) == 1: 349 return '{}({} {})\n'.format(cmd, title, item) 350 else: 351 return '{}({}\n{})\n'.format(cmd, title, content) 352 353 def _get_module_src_set(self, lib, top_mod, sub_mod, mod_obj): 354 srcs = self._cfg_feature.get_mod_srcs(top_mod, sub_mod, mod_obj) 355 return self._expand_srcs(srcs) 356 357 def _gen_module_cmake(self, lib, mod, mod_obj, mods_cmake): 358 top_mod, module_name = mod.split('::') 359 inc_set = self._get_module_include(mod, mod_obj.get('deps', [])) 360 src_list = self._get_module_src_set(lib, top_mod, module_name, mod_obj) 361 362 tgt_name = module_name + '-objs' 363 cmake = '\n# Add module {} \n'.format(module_name) 364 cmake += self._gen_cmd_cmake('add_library', '{} OBJECT'.format(tgt_name)) 365 cmake += self._gen_cmd_cmake('target_include_directories', '{} PRIVATE'.format(tgt_name), inc_set) 366 cmake += self._gen_cmd_cmake('target_sources', '{} PRIVATE'.format(tgt_name), src_list) 367 mods_cmake[tgt_name] = cmake 368 369 def _gen_shared_lib_cmake(self, lib_name, tgt_obj_list, tgt_list, macros): 370 tgt_name = lib_name + '-shared' 371 properties = 'OUTPUT_NAME {}'.format(lib_name) 372 373 cmake = '\n' 374 cmake += self._gen_cmd_cmake('add_library', '{} SHARED'.format(tgt_name), tgt_obj_list) 375 cmake += self._gen_cmd_cmake('target_link_options', '{} PRIVATE'.format(tgt_name), '${SHARED_LNK_FLAGS}') 376 if os.path.exists('{}/platform/Secure_C/lib'.format(srcdir)): 377 cmake += self._gen_cmd_cmake('target_link_directories', '{} PRIVATE'.format(tgt_name), '{}/platform/Secure_C/lib'.format(srcdir)) 378 cmake += self._gen_cmd_cmake('set_target_properties', '{} PROPERTIES'.format(tgt_name), properties) 379 cmake += 'install(TARGETS %s DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)\n' % tgt_name 380 381 if lib_name == 'hitls_bsl': 382 for item in macros: 383 if item == '-DHITLS_BSL_UIO' or item == '-DHITLS_BSL_UIO_SCTP': 384 cmake += self._gen_cmd_cmake("target_link_directories", "hitls_bsl-shared PRIVATE " + "${CMAKE_SOURCE_DIR}/platform/Secure_C/lib") 385 cmake += self._gen_cmd_cmake("target_link_libraries", "hitls_bsl-shared " + str(self._args.securec_lib)) 386 if item == '-DHITLS_BSL_SAL_DL': 387 cmake += self._gen_cmd_cmake("target_link_directories", "hitls_bsl-shared PRIVATE " + "${CMAKE_SOURCE_DIR}/platform/Secure_C/lib") 388 cmake += self._gen_cmd_cmake("target_link_libraries", "hitls_bsl-shared dl " + str(self._args.securec_lib)) 389 if lib_name == 'hitls_crypto': 390 cmake += self._gen_cmd_cmake("target_link_directories", "hitls_crypto-shared PRIVATE " + "${CMAKE_SOURCE_DIR}/platform/Secure_C/lib") 391 cmake += self._gen_cmd_cmake("target_link_libraries", "hitls_crypto-shared hitls_bsl-shared " + str(self._args.securec_lib)) 392 if lib_name == 'hitls_tls': 393 cmake += self._gen_cmd_cmake("target_link_directories", "hitls_tls-shared PRIVATE " + "${CMAKE_SOURCE_DIR}/platform/Secure_C/lib") 394 cmake += self._gen_cmd_cmake("target_link_libraries", "hitls_tls-shared hitls_pki-shared hitls_crypto-shared hitls_bsl-shared " + str(self._args.securec_lib)) 395 if lib_name == 'hitls_pki': 396 cmake += self._gen_cmd_cmake("target_link_directories", "hitls_pki-shared PRIVATE " + "${CMAKE_SOURCE_DIR}/platform/Secure_C/lib") 397 cmake += self._gen_cmd_cmake( 398 "target_link_libraries", "hitls_pki-shared hitls_crypto-shared hitls_bsl-shared " + str(self._args.securec_lib)) 399 if lib_name == 'hitls_auth': 400 cmake += self._gen_cmd_cmake("target_link_directories", "hitls_auth-shared PRIVATE " + "${CMAKE_SOURCE_DIR}/platform/Secure_C/lib") 401 cmake += self._gen_cmd_cmake( 402 "target_link_libraries", "hitls_auth-shared hitls_crypto-shared hitls_bsl-shared " + str(self._args.securec_lib)) 403 tgt_list.append(tgt_name) 404 return cmake 405 406 def _gen_static_lib_cmake(self, lib_name, tgt_obj_list, tgt_list): 407 tgt_name = lib_name + '-static' 408 properties = 'OUTPUT_NAME {}'.format(lib_name) 409 410 cmake = '\n' 411 cmake += self._gen_cmd_cmake('add_library', '{} STATIC'.format(tgt_name), tgt_obj_list) 412 cmake += self._gen_cmd_cmake('set_target_properties', '{} PROPERTIES'.format(tgt_name), properties) 413 cmake += 'install(TARGETS %s DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)\n' % tgt_name 414 415 tgt_list.append(tgt_name) 416 return cmake 417 418 def _gen_obejct_lib_cmake(self, lib_name, tgt_obj_list, tgt_list): 419 tgt_name = lib_name + '-object' 420 properties = 'OUTPUT_NAME lib{}.o'.format(lib_name) 421 422 cmake = '\n' 423 cmake += self._gen_cmd_cmake('add_executable', tgt_name, tgt_obj_list) 424 cmake += self._gen_cmd_cmake('target_link_options', '{} PRIVATE'.format(tgt_name), '${PIE_EXE_LNK_FLAGS}') 425 cmake += self._gen_cmd_cmake('set_target_properties', '{} PROPERTIES'.format(tgt_name), properties) 426 cmake += 'install(TARGETS %s DESTINATION ${CMAKE_INSTALL_PREFIX}/obj)\n' % tgt_name 427 428 tgt_list.append(tgt_name) 429 return cmake 430 431 def _get_definitions(self): 432 return '"${CMAKE_C_FLAGS} -DOPENHITLS_VERSION_S=\'\\"%s\\"\' -DOPENHITLS_VERSION_I=%lu %s"' % ( 433 self._args.hitls_version, self._args.hitls_version_num, '-D__FILENAME__=\'\\"$(notdir $(subst .o,,$@))\\"\'') 434 435 def _gen_lib_cmake(self, lib_name, inc_dirs, lib_obj, macros): 436 lang = self._cfg_feature.libs[lib_name].get('lang', 'C') 437 438 cmake = 'project({} {})\n\n'.format(lib_name, lang) 439 cmake += self._gen_cmd_cmake('set', 'CMAKE_ASM_NASM_OBJECT_FORMAT elf64') 440 cmake += self._gen_cmd_cmake('set', 'CMAKE_C_FLAGS', '${CC_ALL_OPTIONS}') 441 cmake += self._gen_cmd_cmake('set', 'CMAKE_ASM_FLAGS', '${CC_ALL_OPTIONS}') 442 cmake += self._gen_cmd_cmake('set', 'CMAKE_C_FLAGS', self._get_definitions()) 443 cmake += self._gen_cmd_cmake('include_directories', '', inc_dirs) 444 for _, mod_cmake in lib_obj['mods_cmake'].items(): 445 cmake += mod_cmake 446 447 tgt_obj_list = list('$<TARGET_OBJECTS:{}>'.format(x) for x in lib_obj['mods_cmake'].keys()) 448 449 tgt_list = [] 450 lib_type = self._cfg_custom_feature.lib_type 451 if 'shared' in lib_type: 452 cmake += self._gen_shared_lib_cmake(lib_name, tgt_obj_list, tgt_list, macros) 453 if 'static' in lib_type: 454 cmake += self._gen_static_lib_cmake(lib_name, tgt_obj_list, tgt_list) 455 if 'object' in lib_type: 456 cmake += self._gen_obejct_lib_cmake(lib_name, tgt_obj_list, tgt_list) 457 lib_obj['cmake'] = cmake 458 lib_obj['targets'] = tgt_list 459 460 def _gen_bundled_lib_cmake(self, lib_name, inc_dirs, projects, macros): 461 lang = 'C ASM' 462 if 'mpa' in projects.keys(): 463 lang += 'ASM_NASM' 464 465 cmake = 'project({} {})\n\n'.format(lib_name, lang) 466 cmake += self._gen_cmd_cmake('set', 'CMAKE_ASM_NASM_OBJECT_FORMAT elf64') 467 cmake += self._gen_cmd_cmake('set', 'CMAKE_C_FLAGS', '${CC_ALL_OPTIONS}') 468 cmake += self._gen_cmd_cmake('set', 'CMAKE_ASM_FLAGS', '${CC_ALL_OPTIONS}') 469 cmake += self._gen_cmd_cmake('set', 'CMAKE_C_FLAGS', self._get_definitions()) 470 cmake += self._gen_cmd_cmake('include_directories', '', inc_dirs) 471 472 tgt_obj_list = [] 473 for _, lib_obj in projects.items(): 474 tgt_obj_list.extend(list('$<TARGET_OBJECTS:{}>'.format(x) for x in lib_obj['mods_cmake'].keys())) 475 for _, mod_cmake in lib_obj['mods_cmake'].items(): 476 cmake += mod_cmake 477 478 tgt_list = [] 479 lib_type = self._cfg_custom_feature.lib_type 480 if 'shared' in lib_type: 481 cmake += self._gen_shared_lib_cmake(lib_name, tgt_obj_list, tgt_list, macros) 482 if 'static' in lib_type: 483 cmake += self._gen_static_lib_cmake(lib_name, tgt_obj_list, tgt_list) 484 if 'object' in lib_type: 485 cmake += self._gen_obejct_lib_cmake(lib_name, tgt_obj_list, tgt_list) 486 487 return {lib_name:{'cmake':cmake, 'targets':tgt_list}} 488 489 def _gen_projects_cmake(self, macros): 490 lib_enable_modules = self._cfg_custom_feature.get_enable_modules() 491 492 projects = {} 493 all_inc_dirs = set() 494 for lib, lib_obj in lib_enable_modules.items(): 495 projects[lib] = {} 496 projects[lib]['mods_cmake'] = {} 497 inc_dirs = self._get_common_include(lib_obj.keys()) 498 for mod, mod_obj in lib_obj.items(): 499 self._gen_module_cmake(lib, mod, mod_obj, projects[lib]['mods_cmake']) 500 if self._args.bundle_libs: 501 all_inc_dirs = all_inc_dirs.union(inc_dirs) 502 continue 503 self._gen_lib_cmake(lib, inc_dirs, projects[lib], macros) 504 505 if self._args.bundle_libs: 506 # update projects 507 projects = self._gen_bundled_lib_cmake('hitls', all_inc_dirs, projects, macros) 508 return projects 509 510 def _gen_target_cmake(self, lib_tgts): 511 cmake = 'add_custom_target(openHiTLS)\n' 512 cmake += self._gen_cmd_cmake('add_dependencies', 'openHiTLS', lib_tgts) 513 return cmake 514 515 def _gen_set_param_cmake(self, macro_file): 516 compile_flags, link_flags = self._cfg_compile.union_options(self._cfg_custom_compile) 517 macros = self._cfg_custom_feature.get_fea_macros() 518 macros.sort() 519 520 if '-DHITLS_CRYPTO_CMVP' in macros: 521 self._hmac = True 522 523 compile_flags.extend(macros) 524 hitls_macros = list(filter(lambda x: '-DHITLS' in x, compile_flags)) 525 with open(macro_file, "w") as f: 526 f.write(" ".join(hitls_macros)) 527 f.close() 528 529 compile_flags_str = '"{}"'.format(" ".join(compile_flags)) 530 shared_link_flags = '{}'.format(" ".join(link_flags['SHARED']) + " " + " ".join(link_flags['PUBLIC'])) 531 exe_link_flags = '{}'.format(" ".join(link_flags['EXE']) + " " + " ".join(link_flags['PUBLIC'])) 532 533 cmake = self._gen_cmd_cmake('set', 'CC_ALL_OPTIONS', compile_flags_str) + "\n" 534 cmake += self._gen_cmd_cmake('set', 'SHARED_LNK_FLAGS', shared_link_flags) + "\n" 535 cmake += self._gen_cmd_cmake('set', 'PIE_EXE_LNK_FLAGS', exe_link_flags) + "\n" 536 537 return cmake, macros 538 539 def out_cmake(self, cmake_path, macro_file): 540 self._cfg_custom_feature.check_bn_config() 541 542 set_param_cmake, macros = self._gen_set_param_cmake(macro_file) 543 544 projects = self._gen_projects_cmake(macros) 545 546 lib_tgts = list(tgt for lib_obj in projects.values() for tgt in lib_obj['targets']) 547 bottom_cmake = self._gen_target_cmake(lib_tgts) 548 549 with open(cmake_path, "w") as f: 550 f.write(set_param_cmake) 551 for lib_obj in projects.values(): 552 f.write(lib_obj['cmake']) 553 f.write('\n\n') 554 f.write(bottom_cmake) 555 556def main(): 557 os.chdir(srcdir) 558 559 # The Python version cannot be earlier than 3.5. 560 if sys.version_info < (3, 5): 561 print("your python version %d.%d should not be lower than 3.5" % tuple(sys.version_info[:2])) 562 raise Exception("your python version %d.%d should not be lower than 3.5" % tuple(sys.version_info[:2])) 563 564 conf_feature = FeatureParser(Configure.feature_json_file) 565 complete_options = CompleteOptionParser(Configure.complete_options_json_file) 566 567 cfg = Configure(conf_feature) 568 cfg.load_config_to_build() 569 cfg.update_feature_config(cfg.args.module_cmake) 570 cfg.update_compile_config(complete_options) 571 572 if cfg.args.module_cmake: 573 tmp_cmake = os.path.join(cfg.args.build_dir, 'modules.cmake') 574 macro_file = os.path.join(cfg.args.build_dir, 'macro.txt') 575 if (os.path.exists(macro_file)): 576 os.remove(macro_file) 577 CMakeGenerator(cfg.args, conf_feature, complete_options).out_cmake(tmp_cmake, macro_file) 578 579if __name__ == '__main__': 580 try: 581 main() 582 except SystemExit: 583 exit(0) 584 except: 585 traceback.print_exc() 586 exit(2) 587