[clang] [Driver][SYCL][Windows] Add SYCL windows runtime library linking (PR #194744)

Srividya Sundaram via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 28 15:52:04 PDT 2026


https://github.com/srividya-sundaram updated https://github.com/llvm/llvm-project/pull/194744

>From c83935594b5bcdd2a7744fcd0d4527b7e8734e4f Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Tue, 28 Apr 2026 15:01:38 -0700
Subject: [PATCH 1/3] [Driver][SYCL][Windows] Add runtime library linking with
 CRT validation, phase1

---
 .../clang/Basic/DiagnosticDriverKinds.td      |   5 +
 clang/include/clang/Options/Options.td        |   2 +
 clang/lib/Driver/ToolChains/MSVC.cpp          | 108 +++++++++++++++++-
 3 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 469045948a47c..690228317e2be 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -93,6 +93,11 @@ def err_drv_hipspv_no_hip_path : Error<
   "'--hip-path' must be specified when offloading to SPIR-V unless '-nogpuinc' "
   "is given">;
 
+// SYCL Windows-specific diagnostics
+def err_drv_sycl_requires_dynamic_crt : Error<
+  "SYCL requires dynamic C++ runtime (/MD or /MDd); "
+  "static C++ runtime (/MT or /MTd) is not supported">;
+
 def err_drv_no_spv_tools : Error<"cannot find SPIR-V Tools binary '%0', which "
                                  "is required for SPIR-V compilation. "
                                  "It can be obtained from your system package "
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index c16c41ad4057d..9bc8c981cb014 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -7566,6 +7566,8 @@ def fsycl : Flag<["-"], "fsycl">,
   HelpText<"Enable SYCL C++ extensions">;
 def fno_sycl : Flag<["-"], "fno-sycl">,
   HelpText<"Disable SYCL C++ extensions">;
+def nolibsycl : Flag<["-"], "nolibsycl">,
+  HelpText<"Do not link the SYCL runtime library">;
 def fsycl_device_only : Flag<["-"], "fsycl-device-only">,
   Alias<offload_device_only>, HelpText<"Compile SYCL code for device only">;
 def fsycl_host_only : Flag<["-"], "fsycl-host-only">,
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index f57440855fce4..2e052f6e282b1 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -85,9 +85,109 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back(Args.MakeArgString("--dependent-lib=amath"));
   }
 
+  // ==========================================================================
+  // SYCL: Auto-add /MD if no C++ runtime specified
+  // SYCL requires dynamic C++ runtime because STL objects cross DLL boundaries
+  // This must happen BEFORE other CRT handling logic
+  // ==========================================================================
+  if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) &&
+      !Args.hasArg(options::OPT_nolibsycl) &&
+      !Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+
+    bool HasExplicitCRT = false;
+
+    // Check if user already specified a CRT flag
+    if (Args.hasArg(options::OPT__SLASH_MT) ||
+        Args.hasArg(options::OPT__SLASH_MTd) ||
+        Args.hasArg(options::OPT__SLASH_MD) ||
+        Args.hasArg(options::OPT__SLASH_MDd) ||
+        Args.hasArg(options::OPT_fms_runtime_lib_EQ))
+      HasExplicitCRT = true;
+
+    // Auto-add /MD if no CRT specified (makes dynamic CRT the default for SYCL)
+    if (!HasExplicitCRT) {
+      CmdArgs.push_back("/MD");
+    }
+  }
+
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
       !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
-    CmdArgs.push_back("-defaultlib:libcmt");
+
+    // ========================================================================
+    // SYCL: Validate CRT compatibility and add SYCL runtime libraries
+    // ========================================================================
+    if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) &&
+        !Args.hasArg(options::OPT_nolibsycl)) {
+
+      // ----------------------------------------------------------------------
+      // STEP 1: Validate that static CRT is not being used
+      // ----------------------------------------------------------------------
+      bool HasStaticCRT = false;
+
+      // Check for explicit /MT or /MTd flags
+      if (Args.hasArg(options::OPT__SLASH_MT) ||
+          Args.hasArg(options::OPT__SLASH_MTd)) {
+        HasStaticCRT = true;
+      }
+
+      // Check -fms-runtime-lib flag
+      if (const Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+        StringRef RuntimeLib = A->getValue();
+        if (RuntimeLib == "static" || RuntimeLib == "static_dbg") {
+          HasStaticCRT = true;
+        }
+      }
+
+      // Reject static CRT with SYCL
+      if (HasStaticCRT) {
+        TC.getDriver().Diag(diag::err_drv_sycl_requires_dynamic_crt);
+        // Continue to show other potential errors, but skip SYCL library
+        // linking
+      } else {
+        // --------------------------------------------------------------------
+        // STEP 2: Add SYCL library search path
+        // --------------------------------------------------------------------
+        CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
+                                             TC.getDriver().Dir + "/../lib"));
+
+        // --------------------------------------------------------------------
+        // STEP 3: Determine if this is a debug build
+        // Only check DYNAMIC CRT flags (/MDd), never static (/MTd)
+        // --------------------------------------------------------------------
+        bool IsDebugBuild = false;
+
+        // Method 1: Check -fms-runtime-lib=dll_dbg
+        if (const Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+          StringRef RuntimeVal = A->getValue();
+          if (RuntimeVal == "dll_dbg")
+            IsDebugBuild = true;
+        }
+
+        // Method 2: Check for /MDd flag (dynamic debug CRT)
+        if (Args.hasArg(options::OPT__SLASH_MDd))
+          IsDebugBuild = true;
+
+        // --------------------------------------------------------------------
+        // STEP 4: Add appropriate SYCL runtime library
+        // Using LLVMSYCL for LLVM naming convention
+        // --------------------------------------------------------------------
+        if (IsDebugBuild) {
+          // Debug build: link debug SYCL runtime
+          CmdArgs.push_back("-defaultlib:LLVMSYCLd.lib");
+        } else {
+          // Release build: link release SYCL runtime
+          CmdArgs.push_back("-defaultlib:LLVMSYCL.lib");
+        }
+
+        // Add msvcrt for SYCL (dynamic CRT)
+        CmdArgs.push_back("-defaultlib:msvcrt");
+      }
+    } else {
+      // Original logic for non-SYCL builds
+      CmdArgs.push_back("-defaultlib:libcmt");
+    }
+
     CmdArgs.push_back("-defaultlib:oldnames");
   }
 
@@ -162,6 +262,12 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   if (TC.getVFS().exists(CRTPath))
     CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
 
+  // ==========================================================================
+  // SYCL: Suppress LNK4078 warning (multiple .llvm.offloading sections)
+  // ==========================================================================
+  if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false))
+    CmdArgs.push_back("/IGNORE:4078");
+
   CmdArgs.push_back("-nologo");
 
   if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))

>From 0e6636be0f146b5f0eaa09823b4cd8592235b97c Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Tue, 28 Apr 2026 15:28:43 -0700
Subject: [PATCH 2/3] Add SYCL RT lib path for windows and test.

---
 clang/lib/Driver/ToolChains/SYCL.cpp | 65 ++++++++++++++++++++--------
 clang/test/Driver/sycl-windows.cpp   | 65 ++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/Driver/sycl-windows.cpp

diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp
index 55a697df5081e..7e7c1d6a31d6a 100644
--- a/clang/lib/Driver/ToolChains/SYCL.cpp
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -23,25 +23,52 @@ SYCLInstallationDetector::SYCLInstallationDetector(
   // directory in SYCLRTLibPath for use by the linker.
   StringRef SysRoot = D.SysRoot;
   SmallString<128> DriverDir(D.Dir);
-  SmallString<128> LibPath(DriverDir);
-  llvm::sys::path::append(LibPath, "..", "lib", HostTriple.str(),
-                          "libLLVMSYCL.so");
-  // Flat lib path for LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF builds,
-  // where the library is installed directly in lib/ with no triple subdir.
-  SmallString<128> FlatLibPath(DriverDir);
-  llvm::sys::path::append(FlatLibPath, "..", "lib", "libLLVMSYCL.so");
-
-  if (DriverDir.starts_with(SysRoot) &&
-      Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
-    // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON: library is in lib/<triple>/
-    if (D.getVFS().exists(LibPath))
-      llvm::sys::path::append(DriverDir, "..", "lib", HostTriple.str());
-    // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF: library is in lib/
-    else if (D.getVFS().exists(FlatLibPath))
-      llvm::sys::path::append(DriverDir, "..", "lib");
-    else
-      return; // Neither path exists : broken install, leave SYCLRTLibPath unset
-    SYCLRTLibPath = DriverDir;
+
+  if (HostTriple.isOSWindows()) {
+    // ========================================================================
+    // Windows: Check for LLVMSYCL.lib
+    // NOTE: Only checks for release library; debug variant is selected via
+    //       CRT flags in MSVC.cpp, not filesystem detection
+    // ========================================================================
+    if (DriverDir.starts_with(SysRoot) &&
+        Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
+      SmallString<128> LibDir(DriverDir);
+      llvm::sys::path::append(LibDir, "..", "lib");
+
+      // Verify SYCL runtime library exists
+      SmallString<256> SYCLLibPath(LibDir);
+      llvm::sys::path::append(SYCLLibPath, "LLVMSYCL.lib");
+
+      if (D.getVFS().exists(SYCLLibPath)) {
+        SYCLRTLibPath = LibDir;
+      }
+    }
+  } else {
+    // ========================================================================
+    // Linux/Unix: Check for libLLVMSYCL.so (existing logic)
+    // ========================================================================
+    SmallString<128> LibPath(DriverDir);
+    llvm::sys::path::append(LibPath, "..", "lib", HostTriple.str(),
+                            "libLLVMSYCL.so");
+    // Flat lib path for LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF builds,
+    // where the library is installed directly in lib/ with no triple subdir.
+    SmallString<128> FlatLibPath(DriverDir);
+    llvm::sys::path::append(FlatLibPath, "..", "lib", "libLLVMSYCL.so");
+
+    if (DriverDir.starts_with(SysRoot) &&
+        Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
+      // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON: library is in lib/<triple>/
+      if (D.getVFS().exists(LibPath))
+        llvm::sys::path::append(DriverDir, "..", "lib", HostTriple.str());
+      // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF: library is in lib/
+      else if (D.getVFS().exists(FlatLibPath))
+        llvm::sys::path::append(DriverDir, "..", "lib");
+      else
+        return; // Neither path exists : broken install, leave SYCLRTLibPath
+                // unset
+
+      SYCLRTLibPath = DriverDir;
+    }
   }
 }
 
diff --git a/clang/test/Driver/sycl-windows.cpp b/clang/test/Driver/sycl-windows.cpp
new file mode 100644
index 0000000000000..4fae8da6d0f37
--- /dev/null
+++ b/clang/test/Driver/sycl-windows.cpp
@@ -0,0 +1,65 @@
+/// Windows SYCL runtime library linking tests
+
+
+/// Test 1: Auto-/MD is added when no CRT specified
+// RUN: %clang_cl -### -fsycl --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-AUTO-MD %s
+// CHECK-AUTO-MD: "/MD"
+// CHECK-AUTO-MD: "-defaultlib:LLVMSYCL.lib"
+
+/// Test 2: /MT is rejected with clear error
+// RUN: not %clang_cl -fsycl /MT --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-MT-ERROR %s
+// CHECK-MT-ERROR: error: SYCL requires dynamic C++ runtime
+
+/// Test 3: /MTd is also rejected
+// RUN: not %clang_cl -fsycl /MTd --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-MTD-ERROR %s
+// CHECK-MTD-ERROR: error: SYCL requires dynamic C++ runtime
+
+/// Test 4: /MD uses release library
+// RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-RELEASE %s
+// CHECK-RELEASE: "-defaultlib:LLVMSYCL.lib"
+// CHECK-RELEASE-NOT: LLVMSYCLd.lib
+
+/// Test 5: /MDd uses debug library
+// RUN: %clang_cl -### -fsycl /MDd --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-DEBUG %s
+// CHECK-DEBUG: "-defaultlib:LLVMSYCLd.lib"
+// CHECK-DEBUG-NOT: "-defaultlib:LLVMSYCL.lib"
+
+/// Test 6: -fms-runtime-lib=static is rejected
+// RUN: not %clang_cl -fsycl -fms-runtime-lib=static \
+// RUN:   --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-STATIC-ERROR %s
+// CHECK-STATIC-ERROR: error: SYCL requires dynamic C++ runtime
+
+/// Test 7: -fms-runtime-lib=dll_dbg uses debug library
+// RUN: %clang_cl -### -fsycl -fms-runtime-lib=dll_dbg \
+// RUN:   --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-FLAG-DEBUG %s
+// CHECK-FLAG-DEBUG: "-defaultlib:LLVMSYCLd.lib"
+
+/// Test 8: LNK4078 warning is suppressed
+// RUN: %clang_cl -### -fsycl --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-IGNORE %s
+// CHECK-IGNORE: "/IGNORE:4078"
+
+/// Test 9: -nolibsycl skips library linking and CRT check
+// RUN: %clang_cl -### -fsycl -nolibsycl /MT \
+// RUN:   --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-NOLIBSYCL %s
+// CHECK-NOLIBSYCL-NOT: error:
+// CHECK-NOLIBSYCL-NOT: "-defaultlib:LLVMSYCL
+
+/// Test 10: Explicit /MD doesn't cause duplicate flag
+// RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-NO-DUP %s
+// CHECK-NO-DUP: "/MD"
+// CHECK-NO-DUP-NOT: "/MD"{{.*}}"/MD"
+
+/// Test 11: Library search path is added
+// RUN: %clang_cl -### -fsycl --target=x86_64-pc-windows-msvc %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-LIBPATH %s
+// CHECK-LIBPATH: "-libpath:{{.*}}{{[/\\]+}}lib"

>From 4479f02c843373eb3dc7c11f1215124dec3328d4 Mon Sep 17 00:00:00 2001
From: srividya sundaram <srividya.sundaram at intel.com>
Date: Tue, 28 Apr 2026 15:51:35 -0700
Subject: [PATCH 3/3] Update test.

---
 clang/lib/Driver/ToolChains/MSVC.cpp | 124 +++++++++++++--------------
 clang/test/Driver/sycl-windows.cpp   |   9 +-
 2 files changed, 66 insertions(+), 67 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 2e052f6e282b1..4b0fa4627980f 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -111,83 +111,81 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
-      !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
+  // ==========================================================================
+  // SYCL: Validate CRT compatibility and add SYCL runtime libraries
+  // This needs to run for both CL mode and regular mode
+  // ==========================================================================
+  if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) &&
+      !Args.hasArg(options::OPT_nolibsycl) &&
+      !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
 
-    // ========================================================================
-    // SYCL: Validate CRT compatibility and add SYCL runtime libraries
-    // ========================================================================
-    if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) &&
-        !Args.hasArg(options::OPT_nolibsycl)) {
+    // ------------------------------------------------------------------------
+    // STEP 1: Validate that static CRT is not being used
+    // ------------------------------------------------------------------------
+    bool HasStaticCRT = false;
 
-      // ----------------------------------------------------------------------
-      // STEP 1: Validate that static CRT is not being used
-      // ----------------------------------------------------------------------
-      bool HasStaticCRT = false;
+    // Check for explicit /MT or /MTd flags
+    if (Args.hasArg(options::OPT__SLASH_MT) ||
+        Args.hasArg(options::OPT__SLASH_MTd)) {
+      HasStaticCRT = true;
+    }
 
-      // Check for explicit /MT or /MTd flags
-      if (Args.hasArg(options::OPT__SLASH_MT) ||
-          Args.hasArg(options::OPT__SLASH_MTd)) {
+    // Check -fms-runtime-lib flag
+    if (const Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+      StringRef RuntimeLib = A->getValue();
+      if (RuntimeLib == "static" || RuntimeLib == "static_dbg") {
         HasStaticCRT = true;
       }
+    }
 
-      // Check -fms-runtime-lib flag
-      if (const Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
-        StringRef RuntimeLib = A->getValue();
-        if (RuntimeLib == "static" || RuntimeLib == "static_dbg") {
-          HasStaticCRT = true;
-        }
-      }
+    // Reject static CRT with SYCL
+    if (HasStaticCRT) {
+      TC.getDriver().Diag(diag::err_drv_sycl_requires_dynamic_crt);
+      // Continue to show other potential errors, but skip SYCL library linking
+    } else {
+      // ----------------------------------------------------------------------
+      // STEP 2: Add SYCL library search path
+      // ----------------------------------------------------------------------
+      CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
+                                           TC.getDriver().Dir + "/../lib"));
 
-      // Reject static CRT with SYCL
-      if (HasStaticCRT) {
-        TC.getDriver().Diag(diag::err_drv_sycl_requires_dynamic_crt);
-        // Continue to show other potential errors, but skip SYCL library
-        // linking
-      } else {
-        // --------------------------------------------------------------------
-        // STEP 2: Add SYCL library search path
-        // --------------------------------------------------------------------
-        CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
-                                             TC.getDriver().Dir + "/../lib"));
-
-        // --------------------------------------------------------------------
-        // STEP 3: Determine if this is a debug build
-        // Only check DYNAMIC CRT flags (/MDd), never static (/MTd)
-        // --------------------------------------------------------------------
-        bool IsDebugBuild = false;
-
-        // Method 1: Check -fms-runtime-lib=dll_dbg
-        if (const Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
-          StringRef RuntimeVal = A->getValue();
-          if (RuntimeVal == "dll_dbg")
-            IsDebugBuild = true;
-        }
+      // ----------------------------------------------------------------------
+      // STEP 3: Determine if this is a debug build
+      // Only check DYNAMIC CRT flags (/MDd), never static (/MTd)
+      // ----------------------------------------------------------------------
+      bool IsDebugBuild = false;
 
-        // Method 2: Check for /MDd flag (dynamic debug CRT)
-        if (Args.hasArg(options::OPT__SLASH_MDd))
+      // Method 1: Check -fms-runtime-lib=dll_dbg
+      if (const Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+        StringRef RuntimeVal = A->getValue();
+        if (RuntimeVal == "dll_dbg")
           IsDebugBuild = true;
+      }
 
-        // --------------------------------------------------------------------
-        // STEP 4: Add appropriate SYCL runtime library
-        // Using LLVMSYCL for LLVM naming convention
-        // --------------------------------------------------------------------
-        if (IsDebugBuild) {
-          // Debug build: link debug SYCL runtime
-          CmdArgs.push_back("-defaultlib:LLVMSYCLd.lib");
-        } else {
-          // Release build: link release SYCL runtime
-          CmdArgs.push_back("-defaultlib:LLVMSYCL.lib");
-        }
+      // Method 2: Check for /MDd flag (dynamic debug CRT)
+      if (Args.hasArg(options::OPT__SLASH_MDd))
+        IsDebugBuild = true;
 
-        // Add msvcrt for SYCL (dynamic CRT)
-        CmdArgs.push_back("-defaultlib:msvcrt");
+      // ----------------------------------------------------------------------
+      // STEP 4: Add appropriate SYCL runtime library
+      // Using LLVMSYCL for LLVM naming convention
+      // ----------------------------------------------------------------------
+      if (IsDebugBuild) {
+        // Debug build: link debug SYCL runtime
+        CmdArgs.push_back("-defaultlib:LLVMSYCLd.lib");
+      } else {
+        // Release build: link release SYCL runtime
+        CmdArgs.push_back("-defaultlib:LLVMSYCL.lib");
       }
-    } else {
-      // Original logic for non-SYCL builds
-      CmdArgs.push_back("-defaultlib:libcmt");
+
+      // Add msvcrt for SYCL (dynamic CRT)
+      CmdArgs.push_back("-defaultlib:msvcrt");
     }
+  }
 
+  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
+      !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
+    CmdArgs.push_back("-defaultlib:libcmt");
     CmdArgs.push_back("-defaultlib:oldnames");
   }
 
diff --git a/clang/test/Driver/sycl-windows.cpp b/clang/test/Driver/sycl-windows.cpp
index 4fae8da6d0f37..86c09c4014cff 100644
--- a/clang/test/Driver/sycl-windows.cpp
+++ b/clang/test/Driver/sycl-windows.cpp
@@ -53,11 +53,12 @@
 // CHECK-NOLIBSYCL-NOT: error:
 // CHECK-NOLIBSYCL-NOT: "-defaultlib:LLVMSYCL
 
-/// Test 10: Explicit /MD doesn't cause duplicate flag
+/// Test 10: Explicit /MD results in correct libraries
 // RUN: %clang_cl -### -fsycl /MD --target=x86_64-pc-windows-msvc %s 2>&1 \
-// RUN:   | FileCheck -check-prefix=CHECK-NO-DUP %s
-// CHECK-NO-DUP: "/MD"
-// CHECK-NO-DUP-NOT: "/MD"{{.*}}"/MD"
+// RUN:   | FileCheck -check-prefix=CHECK-EXPLICIT-MD %s
+// CHECK-EXPLICIT-MD: clang-linker-wrapper"
+// CHECK-EXPLICIT-MD-SAME: "-defaultlib:LLVMSYCL.lib"
+// CHECK-EXPLICIT-MD-SAME: "-defaultlib:msvcrt"
 
 /// Test 11: Library search path is added
 // RUN: %clang_cl -### -fsycl --target=x86_64-pc-windows-msvc %s 2>&1 \



More information about the cfe-commits mailing list