From a015fa0744119fb1122f7ccf4977e8f06b709cbd Mon Sep 17 00:00:00 2001 From: helly25 Date: Sun, 18 Aug 2024 17:52:17 +0000 Subject: [PATCH 1/3] Add pre-processed header support. This is a expanded version of https://github.com/hedronvision/bazel-compile-commands-extractor/pull/205 It adds more header file extensions. --- refresh.template.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/refresh.template.py b/refresh.template.py index 194f365e..063a21d0 100644 --- a/refresh.template.py +++ b/refresh.template.py @@ -173,7 +173,7 @@ def _parse_headers_from_makefile_deps(d_file_content: str, source_path_for_sanit # For example, `d_file_content` might be: `"foo.o : foo.cc bar.h \\\n baz.hpp"`. target, dependencies = d_file_content.split(': ', 1) # Needs to handle absolute Windows paths, like C:\ target = target.strip() # Remove the optional trailing space. - assert target.endswith(('.o', '.obj')), "Something went wrong in makefile parsing to get headers. The target should be an object file. Output:\n" + d_file_content + assert target.endswith(('.o', '.obj', '.processed')), "Something went wrong in makefile parsing to get headers. The target should be an object file. Output:\n" + d_file_content # Undo shell-like line wrapping because the newlines aren't eaten by shlex.join. Note also that it's the line wrapping is inconsistently generated across compilers and depends on the lengths of the filenames, so you can't just split on the escaped newlines. dependencies = dependencies.replace('\\\n', '') # On Windows, swap out (single) backslash path directory separators for forward slash. Shlex otherwise eats the separators...and Windows gcc intermixes backslash separators with backslash escaped spaces. For a real example of gcc run from Windows, see https://github.com/hedronvision/bazel-compile-commands-extractor/issues/81 @@ -691,8 +691,8 @@ def _get_files(compile_action): _get_files.has_logged_missing_file_error = False # Setup extensions and flags for the whole C-language family. # Clang has a list: https://github.com/llvm/llvm-project/blob/b9f3b7f89a4cb4cf541b7116d9389c73690f78fa/clang/lib/Driver/Types.cpp#L293 -_get_files.c_source_extensions = ('.c', '.i') -_get_files.cpp_source_extensions = ('.cc', '.cpp', '.cxx', '.c++', '.C', '.CC', '.cp', '.CPP', '.C++', '.CXX', '.ii') +_get_files.c_source_extensions = ('.c', '.i', '.h') +_get_files.cpp_source_extensions = ('.cc', '.cpp', '.cxx', '.c++', '.C', '.CC', '.cp', '.CPP', '.C++', '.CXX', '.ii', '.hh', '.hpp', '.hxx') _get_files.objc_source_extensions = ('.m',) _get_files.objcpp_source_extensions = ('.mm', '.M') _get_files.cuda_source_extensions = ('.cu', '.cui') From 74e98046085d19a00059beab64dfd18b1758b58d Mon Sep 17 00:00:00 2001 From: helly25 Date: Tue, 27 Aug 2024 05:45:41 +0000 Subject: [PATCH 2/3] Add '.inl' as possible c source. There is an issue with those as they are typically not meant as stand alone sources. Nonetheless, the tool should just gracefully warn on failure. --- refresh.template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refresh.template.py b/refresh.template.py index 063a21d0..7b80eab2 100644 --- a/refresh.template.py +++ b/refresh.template.py @@ -691,7 +691,7 @@ def _get_files(compile_action): _get_files.has_logged_missing_file_error = False # Setup extensions and flags for the whole C-language family. # Clang has a list: https://github.com/llvm/llvm-project/blob/b9f3b7f89a4cb4cf541b7116d9389c73690f78fa/clang/lib/Driver/Types.cpp#L293 -_get_files.c_source_extensions = ('.c', '.i', '.h') +_get_files.c_source_extensions = ('.c', '.i', '.h', '.inl') _get_files.cpp_source_extensions = ('.cc', '.cpp', '.cxx', '.c++', '.C', '.CC', '.cp', '.CPP', '.C++', '.CXX', '.ii', '.hh', '.hpp', '.hxx') _get_files.objc_source_extensions = ('.m',) _get_files.objcpp_source_extensions = ('.mm', '.M') From 6f0f6e4f8c6722316e2e48ba50c157a6a3c3404b Mon Sep 17 00:00:00 2001 From: helly25 Date: Fri, 18 Apr 2025 12:01:13 +0000 Subject: [PATCH 3/3] Update patch to include `.ipp` and use configs instead of repeating them. Ignore MODULE.bazel.lock --- .gitignore | 2 ++ refresh.template.py | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index dfc30b91..eb2014ff 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ # Ignore links to Bazel's output. The pattern needs the `*` because people can change the name of the directory into which the repository is cloned (changing the `bazel-` symlink), and must not end with a trailing `/` because it's a symlink on macOS/Linux. /bazel-* + +MODULE.bazel.lock diff --git a/refresh.template.py b/refresh.template.py index 7b80eab2..c43f319c 100644 --- a/refresh.template.py +++ b/refresh.template.py @@ -173,7 +173,7 @@ def _parse_headers_from_makefile_deps(d_file_content: str, source_path_for_sanit # For example, `d_file_content` might be: `"foo.o : foo.cc bar.h \\\n baz.hpp"`. target, dependencies = d_file_content.split(': ', 1) # Needs to handle absolute Windows paths, like C:\ target = target.strip() # Remove the optional trailing space. - assert target.endswith(('.o', '.obj', '.processed')), "Something went wrong in makefile parsing to get headers. The target should be an object file. Output:\n" + d_file_content + assert target.endswith(_get_headers.output_extensions), "Something went wrong in makefile parsing to get headers. The target should be an object file. Output:\n" + d_file_content # Undo shell-like line wrapping because the newlines aren't eaten by shlex.join. Note also that it's the line wrapping is inconsistently generated across compilers and depends on the lengths of the filenames, so you can't just split on the escaped newlines. dependencies = dependencies.replace('\\\n', '') # On Windows, swap out (single) backslash path directory separators for forward slash. Shlex otherwise eats the separators...and Windows gcc intermixes backslash separators with backslash escaped spaces. For a real example of gcc run from Windows, see https://github.com/hedronvision/bazel-compile-commands-extractor/issues/81 @@ -267,13 +267,17 @@ def _get_headers_gcc(compile_action, source_path: str, action_key: str): # Strip output flags. Apple clang tries to do a full compile if you don't. header_cmd = (arg for arg in header_cmd - if arg != '-o' and not arg.endswith('.o')) + if arg != '-o' and not arg.endswith(_get_headers.output_extensions)) # Strip sanitizer ignore lists...so they don't show up in the dependency list. # See https://clang.llvm.org/docs/SanitizerSpecialCaseList.html and https://github.com/hedronvision/bazel-compile-commands-extractor/issues/34 for more context. header_cmd = (arg for arg in header_cmd if not arg.startswith('-fsanitize')) + # Strip syntax-only option since it is ignored when running pre-processor only, and will create noisy warnings. + header_cmd = (arg for arg in header_cmd + if not arg.startswith('-fsyntax-only')) + # Dump system and user headers to stdout...in makefile format. # Relies on our having made the workspace directory simulate a complete version of the execroot with //external symlink header_cmd = list(header_cmd) @@ -422,6 +426,9 @@ def _get_headers_msvc(compile_action, source_path: str): '/EP', # Preprocess (only, no compilation for speed), writing to stdout where we can easily ignore it instead of a file. https://docs.microsoft.com/en-us/cpp/build/reference/ep-preprocess-to-stdout-without-hash-line-directives ] + # Strip syntax-only (/Zs) option since it is ignored when running pre-processor only, and will create noisy warnings. + header_cmd = (arg for arg in header_cmd if arg != '/Zs') + # cl.exe needs the `INCLUDE` environment variable to find the system headers, since they aren't specified in the action command # Bazel neglects to include INCLUDE per action, so we'll do the best we can and infer them from the default (host) cc toolchain. # These are set in https://github.com/bazelbuild/bazel/bloc/master/tools/cpp/windows_cc_configure.bzl. Search INCLUDE. @@ -608,6 +615,7 @@ def _get_headers(compile_action, source_path: str): return headers _get_headers.has_logged = False +_get_headers.output_extensions = ('.o', '.obj', '.processed') def _get_files(compile_action): @@ -692,7 +700,7 @@ def _get_files(compile_action): # Setup extensions and flags for the whole C-language family. # Clang has a list: https://github.com/llvm/llvm-project/blob/b9f3b7f89a4cb4cf541b7116d9389c73690f78fa/clang/lib/Driver/Types.cpp#L293 _get_files.c_source_extensions = ('.c', '.i', '.h', '.inl') -_get_files.cpp_source_extensions = ('.cc', '.cpp', '.cxx', '.c++', '.C', '.CC', '.cp', '.CPP', '.C++', '.CXX', '.ii', '.hh', '.hpp', '.hxx') +_get_files.cpp_source_extensions = ('.cc', '.cpp', '.cxx', '.c++', '.C', '.CC', '.cp', '.CPP', '.C++', '.CXX', '.ii', '.ipp', '.hh', '.hpp', '.hxx') _get_files.objc_source_extensions = ('.m',) _get_files.objcpp_source_extensions = ('.mm', '.M') _get_files.cuda_source_extensions = ('.cu', '.cui')