[llvm] [llvm][support] Refactor symlink handling and add readlink (PR #184256)

Michael Spencer via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 10 20:17:06 PDT 2026


================
@@ -338,8 +338,52 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting,
   return std::error_code();
 }
 
-// We can't use symbolic links for windows.
+std::error_code create_symlink(const Twine &to, const Twine &from) {
+  SmallVector<wchar_t, 128> wide_from;
+  SmallVector<wchar_t, 128> wide_to;
+  if (std::error_code ec = widenPath(from, wide_from))
+    return ec;
+  if (std::error_code ec = widenPath(to, wide_to))
+    return ec;
+
+  // The Win32 API normally allows forward slashes, but under some cases it does
+  // not correctly handle them in the target of a symlink.
+  for (wchar_t &C : wide_to)
+    if (C == L'/')
+      C = L'\\';
+
+  // Windows requires SYMBOLIC_LINK_FLAG_DIRECTORY for directory symlinks.
+  DWORD Flags = 0;
+  DWORD Attr = ::GetFileAttributesW(wide_to.begin());
+  if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY))
+    Flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
+
+  // Try with SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE first, which works
+  // when Developer Mode is enabled on Windows 10+.
+  if (::CreateSymbolicLinkW(wide_from.begin(), wide_to.begin(),
+                            Flags |
+                                SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE))
+    return std::error_code();
+
+  // If the flag is not recognized (older Windows), retry without it.
+  DWORD Err = ::GetLastError();
+  if (Err == ERROR_INVALID_PARAMETER) {
----------------
Bigcheese wrote:

Hmm, I'm not sure `SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE` would fail in that case? It should only fail for UWP programs when you're no in developer mode.

https://github.com/llvm/llvm-project/pull/184256


More information about the llvm-commits mailing list