diff --git a/src/blade/backend.py b/src/blade/backend.py index 6c26f44c..4e252ade 100644 --- a/src/blade/backend.py +++ b/src/blade/backend.py @@ -256,12 +256,7 @@ def _generate_cc_inclusion_check_rule(self): description='CC INCLUSION CHECK ${in}') def _generate_cc_ar_rules(self): - arflags = ''.join(config.get_item('cc_library_config', 'arflags')) - ar = self.build_accelerator.get_ar_command() - if self.cc_toolchain.is_kind_of('msvc'): - command = '%s %s /OUT:$out $in' % (ar, arflags) - else: - command = 'rm -f $out; %s %s $out $in' % (ar, arflags) + command = self.cc_toolchain.get_static_library_command() self.generate_rule(name='ar', command=command, description='AR ${out}') def _generate_cc_link_rules(self, ld, linkflags): @@ -660,25 +655,26 @@ def _builtin_tools_prefix(self): python = os.environ.get('BLADE_PYTHON_INTERPRETER') or sys.executable if not self.__builtin_tools_prefix: # we need to set the PYTHONPATH to the path of the blade directory before run python. + python_args = '-m blade.builtin_tools' if os.name == 'nt': # On Windows, we generate a batch file to set the PYTHONPATH. builtin_tools_file = os.path.join(self.build_dir, 'builtin_tools.bat') with open(builtin_tools_file, 'w') as f: print('@echo off', file=f) print('set "PYTHONPATH={};%PYTHONPATH%"'.format(self.blade_path), file=f) - print('"{}" %*'.format(python), file=f) + print('"{}" {} %*'.format(python, python_args), file=f) self.__builtin_tools_prefix = builtin_tools_file else: # On posix system, a simply environment prefix is enough to do it. - self.__builtin_tools_prefix = 'PYTHONPATH="%s":$$PYTHONPATH %s' % (self.blade_path, python) + self.__builtin_tools_prefix = 'PYTHONPATH="%s":$$PYTHONPATH "%s" %s' % ( + self.blade_path, python, python_args) return self.__builtin_tools_prefix def _builtin_command(self, builder, args=''): """ Generate blade builtin command line """ - cmd = [self._builtin_tools_prefix()] - cmd.append('-m blade.builtin_tools %s' % builder) + cmd = [self._builtin_tools_prefix(), builder] if args: cmd.append(args) else: diff --git a/src/blade/inclusion_check.py b/src/blade/inclusion_check.py index 4ba7caa1..ae680a61 100644 --- a/src/blade/inclusion_check.py +++ b/src/blade/inclusion_check.py @@ -61,6 +61,23 @@ def is_allowed_undeclared_hdr(self, hdr): return hdr in self._allowed_undeclared_hdrs +_MSVC_INCUSION_PREFIX = 'Note: including file:' + + +def _is_inclusion_line(line): + """Return True if the line is a header inclusion line.""" + return _is_msvc_inclusion_line(line) + + +def _is_msvc_inclusion_line(line): + return line.startswith(_MSVC_INCUSION_PREFIX) + + +def _is_gcc_inclusion_line(line): + """Return True if the line is a header inclusion line.""" + return line.startswith('#include') + + def _parse_inclusion_stacks(path, build_dir): """Parae headers inclusion stacks from file. @@ -118,7 +135,7 @@ def _process_hdr(level, hdr, current_level): with open(path) as f: for index, line in enumerate(f): line = line.rstrip() # Strip `\n` - if not line.startswith('.'): + if not _is_inclusion_line(line): # The remaining lines are useless for us break level, hdr = _parse_hdr_level_line(line) @@ -159,6 +176,10 @@ def _parse_hdr_level_line(line): Example: . ./common/rpc/rpc_client.h """ + return _parse_msvc_hdr_level_line(line) + + +def _parse_gcc_hdr_level_line(line): pos = line.find(' ') if pos == -1: return -1, '' @@ -169,6 +190,13 @@ def _parse_hdr_level_line(line): return level, hdr +def _parse_msvc_hdr_level_line(line): + line = line.removeprefix(_MSVC_INCUSION_PREFIX) + hdr = line.lstrip() + level = len(line) - len(hdr) + return level, hdr + + def _remove_build_dir_prefix(path, build_dir): """Remove the build dir prefix of path (e.g. build64_release/) Args: @@ -362,6 +390,7 @@ def check_file(src, full_src, is_header): if not path: console.warning('No inclusion file found for %s' % full_src) return + console.debug('Find inclusuon file %s for %s' % (path, full_src)) direct_hdrs, stacks = _parse_inclusion_stacks(path, self.build_dir) all_direct_hdrs.update(direct_hdrs) missing_dep_hdrs = set() diff --git a/src/blade/toolchain.py b/src/blade/toolchain.py index 66cfe40b..25c12df1 100644 --- a/src/blade/toolchain.py +++ b/src/blade/toolchain.py @@ -183,6 +183,30 @@ def executable_file_name(self, name): Get the executable file name from the name. """ raise NotImplementedError + + def get_compile_commands(self, build_dir, cppflags, is_dump): + """ + Get the compile commands for the specified source file. + """ + raise NotImplementedError + + def get_link_command(self): + """ + Get the link command. + """ + raise NotImplementedError + + def get_shared_link_command(self): + """ + Get the link command for dynamic library. + """ + raise NotImplementedError + + def get_static_library_command(self): + """ + Get the static library command. + """ + raise NotImplementedError # To verify whether a header file is included without depends on the library it belongs to, # we use the gcc's `-H` option to generate the inclusion stack information, see @@ -270,6 +294,7 @@ def _cc_compile_command_wrapper_template(self, inclusion_stack_file, cuda=False) return template + @override def get_compile_commands(self, build_dir, cppflags, is_dump): cc_config = config.get_section('cc_config') cflags, cxxflags = cc_config['cflags'], cc_config['cxxflags'] @@ -315,15 +340,23 @@ def _hdrs_command(self, flags, cppflags, includes): return ('export LC_ALL=C; %s || %s; ec=$$?; %s ${out}.err > ${out}; ' 'rm -f ${out}.err; exit $$ec') % (cmd1, cmd2, _INCLUSION_STACK_SPLITTER) + @override def get_link_command(self): return self.ld + self._get_link_args() + @override def get_shared_link_command(self): return self.ld + '-shared ' + self._get_link_args() + @override + def get_static_library_command(self): + flags = ''.join(config.get_item('cc_library_config', 'arflags')) + return 'rm -f $out; %s %s $out $in' % (self.ar, flags) + def _get_link_args(self): return ' -o ${out} ${intrinsic_linkflags} ${linkflags} ${target_linkflags} @${out}.rsp ${extra_linkflags}' + @override def filter_cc_flags(self, flag_list, language='c'): """Filter out the unrecognized compilation flags.""" flag_list = var_to_list(flag_list) @@ -439,6 +472,7 @@ def filter_cc_flags(self, flag_list, language='c'): return valid_flags + @override def get_compile_commands(self, build_dir, cppflags, is_dump): cc_config = config.get_section('cc_config') cflags, cxxflags = cc_config['cflags'], cc_config['cxxflags'] @@ -480,12 +514,19 @@ def _hdrs_command(self, flags, cppflags, includes): # The error message of the first command should be completely ignored. return cmd + @override def get_link_command(self): return self.ld + self._get_link_args() + @override def get_shared_link_command(self): return self.ld + ' /DLL ' + self._get_link_args() + @override + def get_static_library_command(self): + flags = ''.join(config.get_item('cc_library_config', 'arflags')) + return '%s /nologo %s /OUT:$out $in' % (self.ar, flags) + def _get_link_args(self): return ' /nologo /OUT:${out} ${intrinsic_linkflags} ${linkflags} ${target_linkflags} @${out}.rsp ${extra_linkflags}'