Skip to content

Commit cbbfc3e

Browse files
committed
v3: suggest a Windows target for MSVC C generated off Windows
Off Windows, the missing-`cl` diagnostic suggested `-cc msvc -o file.c`, which still generates C for the host target. Suggest `-os windows` (and `-arch amd64` when the architecture would follow a non-x64 host) unless the build already targets Windows.
1 parent e66bda1 commit cbbfc3e

3 files changed

Lines changed: 49 additions & 7 deletions

File tree

‎vlib/v/driver/driver.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12654,7 +12654,7 @@ pub fn run(args []string) {
1265412654
b.step('MSVC C compatibility')
1265512655
}
1265612656
if effective_c_compiler == 'msvc' && !c_only {
12657-
msvc_require_cl(c_compiler, host_os)
12657+
msvc_require_cl(c_compiler, host_os, prefs.target)
1265812658
}
1265912659
pic_flag := shared_pic_flag(is_shared || use_cached_dev_dylib, prefs.normalized_target_os())
1266012660
mut linux_cross_sysroot := ''

‎vlib/v/driver/msvc.v‎

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,13 +302,29 @@ fn msvc_lower_c_file(path string) ! {
302302
}
303303

304304
// msvc_require_cl exits with an explanation when MSVC's compiler cannot be run.
305-
fn msvc_require_cl(c_compiler string, host_os string) {
305+
fn msvc_require_cl(c_compiler string, host_os string, target pref.Target) {
306306
os.find_abs_path_of_executable(c_compiler) or {
307-
if host_os == 'windows' {
308-
eprintln('`-cc msvc` could not find `${c_compiler}`. Run V from a Visual Studio Developer Command Prompt (or after `vcvars64.bat`), so that `cl` and its INCLUDE/LIB environment are available.')
309-
} else {
310-
eprintln('`-cc msvc` can only compile on Windows; use `-o file.c` to generate C for MSVC on ${host_os}.')
311-
}
307+
eprintln(msvc_missing_cl_message(c_compiler, host_os, target))
312308
exit(1)
313309
}
314310
}
311+
312+
// msvc_missing_cl_message explains why `cl` cannot run. Off Windows, it suggests generating
313+
// the C file instead, for a Windows target: C generated for the host target contains the
314+
// host's platform code, which MSVC cannot compile.
315+
fn msvc_missing_cl_message(c_compiler string, host_os string, target pref.Target) string {
316+
if host_os == 'windows' {
317+
return '`-cc msvc` could not find `${c_compiler}`. Run V from a Visual Studio Developer Command Prompt (or after `vcvars64.bat`), so that `cl` and its INCLUDE/LIB environment are available.'
318+
}
319+
mut flags := []string{}
320+
if target.os != 'windows' {
321+
flags << '-os windows'
322+
// The target architecture follows the host otherwise. V's MSVC code paths (for
323+
// example the `math.bits` intrinsics) target x64.
324+
if target.arch != 'amd64' {
325+
flags << '-arch amd64'
326+
}
327+
}
328+
flags << ['-cc msvc', '-o file.c']
329+
return '`-cc msvc` can only compile on Windows. To generate C for MSVC on ${host_os}, use `${flags.join(' ')}`, and compile `file.c` with `cl` on Windows.'
330+
}

‎vlib/v/driver/msvc_test.v‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module driver
22

3+
import v.pref
4+
35
fn test_msvc_cl_args_translate_an_executable_build() {
46
args := msvc_cl_args(['-std=gnu11', '-w', '-fwrapv', '-Wno-int-conversion', '-O3', '-I',
57
'C:/v/thirdparty/include', '-DGC_THREADS=1', '-Wl,/STACK:33554432', '-o', 'out.exe', 'src.c',
@@ -53,3 +55,27 @@ fn test_c_compiler_is_msvc() {
5355
assert !c_compiler_is_msvc('clang')
5456
assert !c_compiler_is_msvc('cc')
5557
}
58+
59+
fn test_msvc_missing_cl_message_targets_windows_off_windows() {
60+
macos_arm := pref.Target{
61+
os: 'macos'
62+
arch: 'arm64'
63+
}
64+
assert msvc_missing_cl_message('msvc', 'macos', macos_arm).contains('use `-os windows -arch amd64 -cc msvc -o file.c`')
65+
linux_x64 := pref.Target{
66+
os: 'linux'
67+
arch: 'amd64'
68+
}
69+
assert msvc_missing_cl_message('msvc', 'linux', linux_x64).contains('use `-os windows -cc msvc -o file.c`')
70+
// An explicit Windows target, including its architecture, is kept.
71+
windows_arm := pref.Target{
72+
os: 'windows'
73+
arch: 'arm64'
74+
}
75+
assert msvc_missing_cl_message('msvc', 'linux', windows_arm).contains('use `-cc msvc -o file.c`')
76+
windows_x64 := pref.Target{
77+
os: 'windows'
78+
arch: 'amd64'
79+
}
80+
assert msvc_missing_cl_message('cl', 'windows', windows_x64).contains('Developer Command Prompt')
81+
}

0 commit comments

Comments
 (0)