Fix absolute file paths checking for Windows

Copybara Import from https://github.com/bazelbuild/rules_cc/pull/477

BEGIN_PUBLIC
Fix absolute file paths checking for Windows (#477)

This is a fix for #476 and uses `bazel_skylib`'s `is_absolute` function. I looked for other places that would need a similar fix but found only one more, so I may have missed some.

Closes #477
END_PUBLIC

COPYBARA_INTEGRATE_REVIEW=https://github.com/bazelbuild/rules_cc/pull/477 from stevenlr:fix_absolute_include_paths_check_windows ba54fcece2edbfd2535d39d3e69c81ddf7062f4a
PiperOrigin-RevId: 811375155
Change-Id: Ie1626dd16dd9a100f55ffcadfcfc2eedf93e646b
diff --git a/cc/common/BUILD b/cc/common/BUILD
index 25dea6e..23296ed 100644
--- a/cc/common/BUILD
+++ b/cc/common/BUILD
@@ -19,6 +19,7 @@
     srcs = glob(["*.bzl"]),
     visibility = ["//visibility:public"],
     deps = [
+        "//cc/private:paths_bzl",
         "//cc/private/rules_impl:native_bzl",
     ],
 )
@@ -29,6 +30,7 @@
     visibility = ["//visibility:public"],
     deps = [
         ":visibility_bzl",
+        "//cc/private:paths_bzl",
         "//cc/private/rules_impl:objc_common",
     ],
 )
diff --git a/cc/common/cc_helper.bzl b/cc/common/cc_helper.bzl
index 970a0b4..1847f60 100644
--- a/cc/common/cc_helper.bzl
+++ b/cc/common/cc_helper.bzl
@@ -14,6 +14,7 @@
 """Utility functions for C++ rules."""
 
 load("//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_TYPE")
+load("//cc/private:paths.bzl", "is_path_absolute")
 load("//cc/private/rules_impl:objc_common.bzl", "objc_common")
 load(":cc_common.bzl", "cc_common")
 load(
@@ -808,7 +809,7 @@
     package_source_root = _package_source_root(ctx.label.workspace_name, package, sibling_repository_layout)
     for include in ctx.attr.includes:
         includes_attr = _expand(ctx, include, additional_make_variable_substitutions)
-        if includes_attr.startswith("/"):
+        if is_path_absolute(includes_attr):
             continue
         includes_path = get_relative_path(package_exec_path, includes_attr)
         if not sibling_repository_layout and path_contains_up_level_references(includes_path):
diff --git a/cc/common/cc_helper_internal.bzl b/cc/common/cc_helper_internal.bzl
index 3b2cc5d..674ee66 100644
--- a/cc/common/cc_helper_internal.bzl
+++ b/cc/common/cc_helper_internal.bzl
@@ -19,6 +19,7 @@
 """
 
 load("@bazel_skylib//lib:paths.bzl", "paths")
+load("//cc/private:paths.bzl", "is_path_absolute")
 
 # LINT.IfChange(forked_exports)
 
@@ -239,7 +240,7 @@
 # LINT.ThenChange(https://github.com/bazelbuild/bazel/blob/master/src/main/starlark/builtins_bzl/common/cc/cc_helper_internal.bzl:forked_exports)
 
 def get_relative_path(path_a, path_b):
-    if paths.is_absolute(path_b):
+    if is_path_absolute(path_b):
         return path_b
     return paths.normalize(paths.join(path_a, path_b))
 
diff --git a/cc/private/BUILD b/cc/private/BUILD
index 15361bb..8be8271 100644
--- a/cc/private/BUILD
+++ b/cc/private/BUILD
@@ -12,13 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
 filegroup(
     name = "srcs",
     srcs = glob([
         "**/BUILD",
+        "*.bzl",
     ]) + [
         "//cc/private/rules_impl:srcs",
         "//cc/private/toolchain:srcs",
     ],
     visibility = ["//visibility:public"],
 )
+
+bzl_library(
+    name = "paths_bzl",
+    srcs = ["paths.bzl"],
+    visibility = ["//cc:__subpackages__"],
+)
diff --git a/cc/private/paths.bzl b/cc/private/paths.bzl
new file mode 100644
index 0000000..8b430b5
--- /dev/null
+++ b/cc/private/paths.bzl
@@ -0,0 +1,40 @@
+# Copyright 2025 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Paths utility functions."""
+
+def is_path_absolute(path):
+    """Checks whether a path is absolute or not.
+
+    Note that is does not take the execution platform into account.
+
+    This was implemented to replace skylib's paths.is_absolute, which
+    only checks for the presence of a colon character in the second position
+    of the paths
+
+    Args:
+      path: A path (as a string).
+
+    Returns:
+      `True` if `path` is an absolute path.
+    """
+
+    if path.startswith("/"):
+        return True
+
+    # Check for DOS-style absolute paths for Windows
+    return len(path) >= 3 and \
+           path[0].isalpha() and \
+           path[1] == ":" and \
+           path[2] in ("/", "\\")
diff --git a/cc/toolchains/BUILD b/cc/toolchains/BUILD
index e2e1af0..00c17e3 100644
--- a/cc/toolchains/BUILD
+++ b/cc/toolchains/BUILD
@@ -22,6 +22,7 @@
         "//cc:action_names_bzl",
         "//cc:cc_toolchain_config_lib_bzl",
         "//cc:find_cc_toolchain_bzl",
+        "//cc/private:paths_bzl",
         "//cc/private/rules_impl:cc_flags_supplier_lib_bzl",
         "//cc/private/rules_impl:native_bzl",
         "//cc/toolchains/impl:toolchain_impl_rules",
diff --git a/cc/toolchains/args.bzl b/cc/toolchains/args.bzl
index 6a0133d..a852292 100644
--- a/cc/toolchains/args.bzl
+++ b/cc/toolchains/args.bzl
@@ -14,6 +14,7 @@
 """All providers for rule-based bazel toolchain config."""
 
 load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo")
+load("//cc/private:paths.bzl", "is_path_absolute")
 load("//cc/toolchains/impl:args_utils.bzl", "validate_env_variables", "validate_nested_args")
 load(
     "//cc/toolchains/impl:collect.bzl",
@@ -50,7 +51,7 @@
     )
 
     for path in ctx.attr.allowlist_absolute_include_directories:
-        if not path.startswith("/"):
+        if not is_path_absolute(path):
             fail("`{}` is not an absolute paths".format(path))
 
     nested = None