def _clang_tidy_impl(ctx, src, output_filename):
    """Clang-tidy a file.

    Creates an action that performs clang-tidy on a file and writes the output
    to a separate file.

    If `src` ends in '.exp', then a temp file with '.exp' removed will be
    created, otherwise the temp file will have the same base filename.

    Args:
      ctx: The current rule's context object.
      src: The source file.
      output_filename: The name of the output file.

    Returns:
      The output file.
    """
    src_no_exp = src.path[:-4] if src.path.endswith(".exp") else src.path
    clang_tidy_src = ctx.actions.declare_file(src_no_exp)
    clang_tidy_file = ctx.actions.declare_file(output_filename)
    ctx.actions.run_shell(
        outputs = [clang_tidy_src, clang_tidy_file],
        inputs = [
            src,
            ctx.executable._stable_clang_format_tool,
        ],
        tools = [ctx.executable._stable_clang_format_tool],
        command = "cat {} > {} && {} --sort-includes={} --style=Google {} > {}".format(
            src.path,
            clang_tidy_src.path,
            ctx.executable._stable_clang_format_tool.path,
            "1" if ctx.attr.sort_includes else "0",
            clang_tidy_src.path,
            clang_tidy_file.path,
        ),
        mnemonic = "ClangTidy",
        progress_message = "Clang Tidy on file: %s." % (src.path),
    )
    return clang_tidy_file