pw_build: CMake library name check improvements

- Do not check names for libraries not under PW_ROOT.
- Enforce checks from the beginning of the string. Previously, names
  with extra prefixes would pass the check.
- Support remapping prefixes in checks to support third_party names
  starting with pw_third_party.

Change-Id: I52d0323bb4ad30994e64c87e7197007733cc5aec
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/95463
Reviewed-by: Armando Montanez <amontanez@google.com>
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/pw_build/pigweed.cmake b/pw_build/pigweed.cmake
index e40bac9..8849442 100644
--- a/pw_build/pigweed.cmake
+++ b/pw_build/pigweed.cmake
@@ -284,6 +284,45 @@
   endif(NOT "${arg_PUBLIC_LINK_OPTIONS}" STREQUAL "")
 endfunction(pw_add_library)
 
+# Checks that the library's name is prefixed by the relative path with dot
+# separators instead of forward slashes. Ignores paths not under the root
+# directory.
+#
+# Optional Args:
+#
+#   REMAP_PREFIXES - support remapping a prefix for checks
+#
+function(_pw_check_name_is_relative_to_root NAME ROOT)
+  pw_parse_arguments_strict(_pw_check_name_is_relative_to_root
+      2 "" "" "REMAP_PREFIXES")
+
+  file(RELATIVE_PATH rel_path "${ROOT}" "${CMAKE_CURRENT_SOURCE_DIR}")
+  if("${rel_path}" MATCHES "^\\.\\.")
+    return()  # Ignore paths not under ROOT
+  endif()
+
+  list(LENGTH arg_REMAP_PREFIXES remap_arg_count)
+  if("${remap_arg_count}" EQUAL 2)
+    list(GET arg_REMAP_PREFIXES 0 from_prefix)
+    list(GET arg_REMAP_PREFIXES 1 to_prefix)
+    string(REGEX REPLACE "^${from_prefix}" "${to_prefix}" rel_path "${rel_path}")
+  elseif(NOT "${remap_arg_count}" EQUAL 0)
+    message(FATAL_ERROR
+        "If REMAP_PREFIXES is specified, exactly two arguments must be given.")
+  endif()
+
+  if(NOT "${rel_path}" MATCHES "^\\.\\..*")
+    string(REPLACE "/" "." dot_rel_path "${rel_path}")
+    if(NOT "${NAME}" MATCHES "^${dot_rel_path}(\\.[^\\.]+)?(\\.facade)?$")
+      message(FATAL_ERROR
+          "Module libraries under ${ROOT} must match the module name or be in "
+          "the form 'PATH_TO.THE_TARGET.NAME'. The library '${NAME}' does not "
+          "match. Expected ${dot_rel_path}.LIBRARY_NAME"
+      )
+    endif()
+  endif()
+endfunction(_pw_check_name_is_relative_to_root)
+
 # Creates a pw module library.
 #
 # Required Args:
@@ -310,17 +349,10 @@
   _pw_add_library_multi_value_args(multi_value_args IMPLEMENTS_FACADES)
   pw_parse_arguments_strict(pw_add_module_library 1 "" "" "${multi_value_args}")
 
-  # Check that the library's name is prefixed by the relative PW path with dot
-  # separators instead of forward slashes.
-  file(RELATIVE_PATH rel_path $ENV{PW_ROOT} ${CMAKE_CURRENT_SOURCE_DIR})
-  string(REPLACE "/" "." dot_rel_path ${rel_path})
-  if(NOT "${NAME}" MATCHES "${dot_rel_path}(\\.[^\\.]+)?(\\.facade)?$")
-    message(FATAL_ERROR
-        "Module libraries must match the module name or be in the form "
-        "'PATH_TO.THE_TARGET.NAME'. The library '${NAME}' does not match. "
-        "Expected ${dot_rel_path}.LIBRARY_NAME"
-    )
-  endif()
+  _pw_check_name_is_relative_to_root("${NAME}" "$ENV{PW_ROOT}"
+    REMAP_PREFIXES
+      third_party pw_third_party
+  )
 
   # Use STATIC libraries if sources are provided, else instantiate an INTERFACE
   # library. Also conditionally select PUBLIC vs INTERFACE depending on this