pw_build: Fall back to copying if linking fails

Fall back to copying in mirror_tree if hard linking fails.

Change-Id: I2023f29a7576141a93fdebea81042b259e06d05f
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/42440
Pigweed-Auto-Submit: Rob Mohr <mohrr@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Reviewed-by: (☞゚∀゚)☞ Tennessee Carmel-Veilleux  <tennessee@google.com>
diff --git a/pw_build/py/pw_build/mirror_tree.py b/pw_build/py/pw_build/mirror_tree.py
index ef7e455..a1a74b2 100644
--- a/pw_build/py/pw_build/mirror_tree.py
+++ b/pw_build/py/pw_build/mirror_tree.py
@@ -16,6 +16,7 @@
 import argparse
 import os
 from pathlib import Path
+import shutil
 from typing import Iterable, Iterator, List
 
 
@@ -54,9 +55,20 @@
 
         # Use a hard link to avoid unnecessary copies. Resolve the source before
         # linking in case it is a symlink.
-        os.link(source.resolve(), dest)
+        source = source.resolve()
+        try:
+            os.link(source, dest)
+            yield dest
 
-        yield dest
+        # If the link failed try copying. If copying fails re-raise the
+        # original exception.
+        except OSError:
+            try:
+                shutil.copy(source, dest)
+                yield dest
+            except OSError:
+                pass
+            raise
 
 
 def _link_files_or_dirs(paths: Iterable[Path],