Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 1 | # Copyright 2021 The Pigweed Authors |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 4 | # use this file except in compliance with the License. You may obtain a copy of |
| 5 | # the License at |
| 6 | # |
| 7 | # https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations under |
| 13 | # the License. |
| 14 | |
| 15 | import("//build_overrides/pigweed.gni") |
| 16 | |
| 17 | import("$dir_pw_toolchain/universal_tools.gni") |
| 18 | |
| 19 | declare_args() { |
Ted Pudlik | 73d948c | 2021-10-26 19:44:17 +0000 | [diff] [blame] | 20 | # Regular expressions matching the paths of the source files to be excluded |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 21 | # from the analysis. clang-tidy provides no alternative option. |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 22 | # |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 23 | # For example, the following disables clang-tidy on all source files in the |
| 24 | # third_party directory: |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 25 | # |
Ted Pudlik | 73d948c | 2021-10-26 19:44:17 +0000 | [diff] [blame] | 26 | # pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES = ["third_party/.*"] |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 27 | # |
Ted Pudlik | 73d948c | 2021-10-26 19:44:17 +0000 | [diff] [blame] | 28 | pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES = [] |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 29 | |
| 30 | # Disable clang-tidy for specific include paths. In the clang-tidy command, |
Scott James Remnant | 4d28e22 | 2022-02-16 12:01:25 -0800 | [diff] [blame] | 31 | # include paths that end with one of these, or match as a regular expression, |
| 32 | # are switched from -I to -isystem, which causes clang-tidy to ignore them. |
| 33 | # Unfortunately, clang-tidy provides no other way to filter header files. |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 34 | # |
| 35 | # For example, the following ignores header files in "mbedtls/include": |
| 36 | # |
| 37 | # pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS = ["mbedtls/include"] |
| 38 | # |
Scott James Remnant | 4d28e22 | 2022-02-16 12:01:25 -0800 | [diff] [blame] | 39 | # While the following ignores all third-party header files: |
| 40 | # |
| 41 | # pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS = [".*/third_party/.*"] |
| 42 | # |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 43 | pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS = [] |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 44 | } |
| 45 | |
| 46 | # Creates a toolchain target for static analysis. |
Ted Pudlik | 17d5e71 | 2021-10-25 20:43:54 +0000 | [diff] [blame] | 47 | # |
| 48 | # The generated toolchain runs clang-tidy on all source files that are not |
Ted Pudlik | 73d948c | 2021-10-26 19:44:17 +0000 | [diff] [blame] | 49 | # excluded by pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES or |
Ted Pudlik | 17d5e71 | 2021-10-25 20:43:54 +0000 | [diff] [blame] | 50 | # pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS. |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 51 | # |
| 52 | # Args: |
| 53 | # cc: (required) String indicating the C compiler to use. |
| 54 | # cxx: (required) String indicating the C++ compiler to use. |
| 55 | template("pw_static_analysis_toolchain") { |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 56 | invoker_toolchain_args = invoker.defaults |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 57 | |
| 58 | # Clang tidy is invoked by a wrapper script which implements the missing |
| 59 | # option --source-filter. |
| 60 | _clang_tidy_py_path = |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 61 | rebase_path("$dir_pw_toolchain/py/pw_toolchain/clang_tidy.py", |
| 62 | root_build_dir) |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 63 | _clang_tidy_py = "${python_path} ${_clang_tidy_py_path}" |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 64 | _source_root = rebase_path("//", root_build_dir) |
| 65 | _source_exclude = "" |
Ted Pudlik | 73d948c | 2021-10-26 19:44:17 +0000 | [diff] [blame] | 66 | foreach(pattern, pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES) { |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 67 | _source_exclude = _source_exclude + " --source-exclude '${pattern}'" |
| 68 | } |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 69 | |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 70 | _skip_include_path = |
| 71 | "--skip-include-path " + |
| 72 | string_join(" ", pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS) |
| 73 | |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 74 | toolchain(target_name) { |
| 75 | # Uncomment this line to see which toolchains generate other toolchains. |
| 76 | # print("Generating toolchain: ${target_name} by ${current_toolchain}") |
| 77 | |
| 78 | tool("asm") { |
| 79 | depfile = "{{output}}.d" |
| 80 | command = pw_universal_stamp.command |
| 81 | depsformat = "gcc" |
| 82 | description = "as {{output}}" |
| 83 | outputs = [ |
| 84 | # Use {{source_file_part}}, which includes the extension, instead of |
| 85 | # {{source_name_part}} so that object files created from <file_name>.c |
| 86 | # and <file_name>.cc sources are unique. |
| 87 | "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o", |
| 88 | ] |
| 89 | } |
| 90 | |
| 91 | assert(defined(invoker.cc), "toolchain is missing 'cc'") |
| 92 | tool("cc") { |
| 93 | depfile = "{{output}}.d" |
| 94 | command = string_join(" ", |
| 95 | [ |
| 96 | _clang_tidy_py, |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 97 | _source_exclude, |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 98 | _skip_include_path, |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 99 | "--source-file {{source}}", |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 100 | "--source-root '${_source_root}'", |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 101 | "--export-fixes {{output}}.yaml", |
| 102 | "--", |
| 103 | invoker.cc, |
| 104 | "-MMD -MF $depfile", # Write out dependencies. |
| 105 | "{{cflags}}", |
| 106 | "{{cflags_c}}", # Must come after {{cflags}}. |
| 107 | "{{defines}}", |
| 108 | "{{include_dirs}}", |
| 109 | "-c {{source}}", |
| 110 | "-o {{output}}", |
| 111 | ]) + " && touch {{output}}" |
| 112 | depsformat = "gcc" |
| 113 | description = "clang-tidy {{source}}" |
| 114 | outputs = |
| 115 | [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ] |
| 116 | } |
| 117 | |
| 118 | assert(defined(invoker.cxx), "toolchain is missing 'cxx'") |
| 119 | tool("cxx") { |
| 120 | depfile = "{{output}}.d" |
| 121 | command = string_join(" ", |
| 122 | [ |
| 123 | _clang_tidy_py, |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 124 | _source_exclude, |
Wyatt Hepler | 5e9f7a6 | 2021-10-08 21:04:10 -0700 | [diff] [blame] | 125 | _skip_include_path, |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 126 | "--source-file {{source}}", |
Henri Chataing | dd46587 | 2021-09-01 15:41:21 +0000 | [diff] [blame] | 127 | "--source-root '${_source_root}'", |
Henri Chataing | 19e41f0 | 2021-08-10 11:04:30 +0200 | [diff] [blame] | 128 | "--export-fixes {{output}}.yaml", |
| 129 | "--", |
| 130 | invoker.cxx, |
| 131 | "-MMD -MF $depfile", # Write out dependencies. |
| 132 | "{{cflags}}", |
| 133 | "{{cflags_cc}}", # Must come after {{cflags}}. |
| 134 | "{{defines}}", |
| 135 | "{{include_dirs}}", |
| 136 | "-c {{source}}", |
| 137 | "-o {{output}}", |
| 138 | ]) + " && touch {{output}}" |
| 139 | depsformat = "gcc" |
| 140 | description = "clang-tidy {{source}}" |
| 141 | outputs = |
| 142 | [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ] |
| 143 | } |
| 144 | |
| 145 | tool("objc") { |
| 146 | depfile = "{{output}}.d" |
| 147 | command = pw_universal_stamp.command |
| 148 | depsformat = "gcc" |
| 149 | description = "objc {{source}}" |
| 150 | outputs = |
| 151 | [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ] |
| 152 | } |
| 153 | |
| 154 | tool("objcxx") { |
| 155 | depfile = "{{output}}.d" |
| 156 | command = pw_universal_stamp.command |
| 157 | depsformat = "gcc" |
| 158 | description = "objc++ {{output}}" |
| 159 | outputs = |
| 160 | [ "{{source_out_dir}}/{{target_output_name}}.{{source_file_part}}.o" ] |
| 161 | } |
| 162 | |
| 163 | tool("alink") { |
| 164 | command = "rm -f {{output}} && touch {{output}}" |
| 165 | description = "ar {{target_output_name}}{{output_extension}}" |
| 166 | outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ] |
| 167 | default_output_extension = ".a" |
| 168 | default_output_dir = "{{target_out_dir}}/lib" |
| 169 | } |
| 170 | |
| 171 | tool("link") { |
| 172 | if (host_os == "win") { |
| 173 | # Force the extension to '.bat', empty bat scripts are still |
| 174 | # executable and will not raise errors. |
| 175 | _output = "{{output_dir}}/{{target_output_name}}.bat" |
| 176 | command = pw_universal_stamp.command |
| 177 | default_output_extension = ".bat" |
| 178 | } else { |
| 179 | default_output_extension = "" |
| 180 | _output = "{{output_dir}}/{{target_output_name}}{{output_extension}}" |
| 181 | command = "touch {{output}} && chmod +x {{output}}" |
| 182 | } |
| 183 | description = "ld $_output" |
| 184 | outputs = [ _output ] |
| 185 | default_output_dir = "{{target_out_dir}}/bin" |
| 186 | } |
| 187 | |
| 188 | tool("solink") { |
| 189 | _output = "{{output_dir}}/{{target_output_name}}{{output_extension}}" |
| 190 | command = pw_universal_stamp.command |
| 191 | description = "ld -shared $_output" |
| 192 | outputs = [ _output ] |
| 193 | default_output_dir = "{{target_out_dir}}/lib" |
| 194 | default_output_extension = ".so" |
| 195 | } |
| 196 | |
| 197 | tool("stamp") { |
| 198 | # GN-ism: GN gets mad if you directly forward the contents of |
| 199 | # pw_universal_stamp. |
| 200 | _stamp = pw_universal_stamp |
| 201 | forward_variables_from(_stamp, "*") |
| 202 | } |
| 203 | |
| 204 | tool("copy") { |
| 205 | # GN-ism: GN gets mad if you directly forward the contents of |
| 206 | # pw_universal_copy. |
| 207 | _copy = pw_universal_copy |
| 208 | forward_variables_from(_copy, "*") |
| 209 | } |
| 210 | |
| 211 | # Build arguments to be overridden when compiling cross-toolchain: |
| 212 | # |
| 213 | # pw_toolchain_defaults: A scope setting defaults to apply to GN targets |
| 214 | # in this toolchain. It is analogous to $pw_target_defaults in |
| 215 | # $dir_pigweed/pw_vars_default.gni. |
| 216 | # |
| 217 | # pw_toolchain_SCOPE: A copy of the invoker scope that defines the |
| 218 | # toolchain. Used for generating derivative toolchains. |
| 219 | # |
| 220 | toolchain_args = { |
| 221 | pw_toolchain_SCOPE = { |
| 222 | } |
| 223 | pw_toolchain_SCOPE = { |
| 224 | forward_variables_from(invoker, "*") |
| 225 | name = target_name |
| 226 | } |
| 227 | forward_variables_from(invoker_toolchain_args, "*") |
| 228 | } |
| 229 | } |
| 230 | } |