Skip to content

Commit 329261e

Browse files
committed
v3: address fallback review feedback
1 parent 887cacd commit 329261e

10 files changed

Lines changed: 253 additions & 115 deletions

File tree

.github/workflows/linux_ci.yml

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,17 @@ jobs:
3636
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
3737
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
3838
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
39-
# V3 is the default compiler on Linux; disable the V3->V1 fallback for the
40-
# whole job so a V3 regression fails CI directly — including when it stops
41-
# ci/linux_ci.vsh itself (compiled by `v run`) from building.
39+
# V3 is the default compiler on Linux; disable the V3->V1 fallback for every
40+
# eligible V3 build so a regression fails CI directly. The `.vsh` runner is
41+
# intentionally compiled by V1; the canary below verifies V3 dispatch itself.
4242
V_MACOS_V3_NO_FALLBACK: 1
4343
steps:
4444
- uses: actions/checkout@v7
4545
- uses: ./.github/actions/cache-apt-packages-action
4646
- name: Build v
47-
# `make`'s post-bootstrap `v run` helpers (cmd/tools/detect_tcc.v and
48-
# .github/problem-matchers/register_all.vsh) are not buildable by V3 yet and
49-
# legitimately fall back to V1; without clearing the job-wide no-fallback guard for
50-
# this bootstrap step that fallback would become a hard build failure. The canary
51-
# and the self-test steps below keep the guard, so V3 is still enforced where it
52-
# must build the program.
47+
# `make` runs bootstrap helpers before the V3 canary: detect_tcc.v may need the
48+
# compatibility fallback, while register_all.vsh intentionally uses V1. Clear the
49+
# guard for this bootstrap step; later eligible builds and the canary retain it.
5350
env:
5451
V_MACOS_V3_NO_FALLBACK: 0
5552
run: make -j4 && ./v symlink
@@ -122,20 +119,17 @@ jobs:
122119
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
123120
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
124121
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
125-
# V3 is the default compiler on Linux; disable the V3->V1 fallback for the
126-
# whole job so a V3 regression fails CI directly — including when it stops
127-
# ci/linux_ci.vsh itself (compiled by `v run`) from building.
122+
# V3 is the default compiler on Linux; disable the V3->V1 fallback for every
123+
# eligible V3 build so a regression fails CI directly. The `.vsh` runner is
124+
# intentionally compiled by V1; the canary below verifies V3 dispatch itself.
128125
V_MACOS_V3_NO_FALLBACK: 1
129126
steps:
130127
- uses: actions/checkout@v7
131128
- uses: ./.github/actions/cache-apt-packages-action
132129
- name: Build V
133-
# `make`'s post-bootstrap `v run` helpers (cmd/tools/detect_tcc.v and
134-
# .github/problem-matchers/register_all.vsh) are not buildable by V3 yet and
135-
# legitimately fall back to V1; without clearing the job-wide no-fallback guard for
136-
# this bootstrap step that fallback would become a hard build failure. The canary
137-
# and the self-test steps below keep the guard, so V3 is still enforced where it
138-
# must build the program.
130+
# `make` runs bootstrap helpers before the V3 canary: detect_tcc.v may need the
131+
# compatibility fallback, while register_all.vsh intentionally uses V1. Clear the
132+
# guard for this bootstrap step; later eligible builds and the canary retain it.
139133
env:
140134
V_MACOS_V3_NO_FALLBACK: 0
141135
run: make -j4 && ./v symlink
@@ -670,20 +664,17 @@ jobs:
670664
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
671665
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
672666
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
673-
# V3 is the default compiler on Linux; disable the V3->V1 fallback for the
674-
# whole job so a V3 regression fails CI directly — including when it stops
675-
# ci/linux_ci.vsh itself (compiled by `v run`) from building.
667+
# V3 is the default compiler on Linux; disable the V3->V1 fallback for every
668+
# eligible V3 build so a regression fails CI directly. The `.vsh` runner is
669+
# intentionally compiled by V1; the canary below verifies V3 dispatch itself.
676670
V_MACOS_V3_NO_FALLBACK: 1
677671
steps:
678672
- uses: actions/checkout@v7
679673
- uses: ./.github/actions/cache-apt-packages-action
680674
- name: Build V
681-
# `make`'s post-bootstrap `v run` helpers (cmd/tools/detect_tcc.v and
682-
# .github/problem-matchers/register_all.vsh) are not buildable by V3 yet and
683-
# legitimately fall back to V1; without clearing the job-wide no-fallback guard for
684-
# this bootstrap step that fallback would become a hard build failure. The canary
685-
# and the self-test steps below keep the guard, so V3 is still enforced where it
686-
# must build the program.
675+
# `make` runs bootstrap helpers before the V3 canary: detect_tcc.v may need the
676+
# compatibility fallback, while register_all.vsh intentionally uses V1. Clear the
677+
# guard for this bootstrap step; later eligible builds and the canary retain it.
687678
env:
688679
V_MACOS_V3_NO_FALLBACK: 0
689680
run: make -j4 && ./v symlink

ci/qemu_linux_tests.sh

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Environment overrides:
2626
V_QEMU_NO_FALLBACK Set V_MACOS_V3_NO_FALLBACK (default: 1)
2727
V_QEMU_STOP_AFTER Power off the guest after the run when set to 1
2828
V_QEMU_FIRMWARE AArch64 UEFI firmware path
29+
V_QEMU_RSYNC Host rsync executable (only needed when syncing)
2930
3031
Examples:
3132
ci/qemu_linux_tests.sh
@@ -73,14 +74,18 @@ no_fallback=${V_QEMU_NO_FALLBACK:-1}
7374
stop_after=${V_QEMU_STOP_AFTER:-0}
7475

7576
qemu_bin=${V_QEMU_BIN:-$(command -v qemu-system-aarch64 || true)}
76-
rsync_bin=${V_QEMU_RSYNC:-$(command -v rsync || true)}
7777
if [[ -z "$qemu_bin" ]]; then
7878
echo 'qemu-system-aarch64 is required (on macOS: brew install qemu).' >&2
7979
exit 1
8080
fi
81-
if [[ -z "$rsync_bin" ]]; then
82-
echo 'rsync is required.' >&2
83-
exit 1
81+
rsync_bin=
82+
if ((sync_checkout)); then
83+
rsync_candidate=${V_QEMU_RSYNC:-rsync}
84+
rsync_bin=$(command -v "$rsync_candidate" || true)
85+
if [[ -z "$rsync_bin" ]]; then
86+
echo 'rsync is required unless --no-sync is used.' >&2
87+
exit 1
88+
fi
8489
fi
8590

8691
key_file="${vm_dir}/id_ed25519"
@@ -176,6 +181,12 @@ trap power_off EXIT
176181
start_vm
177182
wait_for_ssh
178183

184+
if ((provision)); then
185+
# A fresh Debian guest does not necessarily have the remote half of rsync yet.
186+
# Install it before attempting to transfer the checkout.
187+
ssh "${ssh_options[@]}" "$guest" "sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential clang git lld rsync pkg-config libssl-dev sqlite3 libsqlite3-dev valgrind libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev libwayland-dev libxkbcommon-dev libwayland-egl1 libxkbcommon-x11-dev wayland-protocols libx11-dev libgl1-mesa-dri xauth xvfb"
188+
fi
189+
179190
host_head=$(git -C "$repo_root" rev-parse HEAD)
180191
guest_head=$(ssh "${ssh_options[@]}" "$guest" "git -C '${guest_repo}' rev-parse HEAD")
181192
if [[ "$host_head" != "$guest_head" ]]; then
@@ -185,18 +196,28 @@ if [[ "$host_head" != "$guest_head" ]]; then
185196
fi
186197

187198
if ((sync_checkout)); then
188-
git -C "$repo_root" ls-files -z --cached --others --exclude-standard | "$rsync_bin" -az \
199+
printf -v guest_repo_q '%q' "$guest_repo"
200+
# Remove tracked paths deleted or renamed in the local worktree. The NUL-delimited
201+
# protocol keeps arbitrary Git filenames safe, and every removal is scoped beneath
202+
# the already-validated guest checkout.
203+
git -C "$repo_root" diff --no-renames --name-only --diff-filter=D -z HEAD -- \
204+
| ssh "${ssh_options[@]}" "$guest" "cd ${guest_repo_q} && xargs -0 -r rm -f --"
205+
# Staged deletions are absent from `git ls-files --cached`, while unstaged
206+
# deletions are still listed. Send only paths that currently exist locally.
207+
git -C "$repo_root" ls-files -z --cached --others --exclude-standard \
208+
| while IFS= read -r -d '' path; do
209+
if [[ -e "${repo_root}/${path}" || -L "${repo_root}/${path}" ]]; then
210+
printf '%s\0' "$path"
211+
fi
212+
done \
213+
| "$rsync_bin" -az \
189214
--from0 \
190215
--files-from=- \
191216
--exclude '.detect_tcc*' \
192217
-e "ssh -i ${key_file} -p ${ssh_port} -o UserKnownHostsFile=${known_hosts_file} -o StrictHostKeyChecking=yes" \
193218
"${repo_root}/" "${guest}:${guest_repo}/"
194219
fi
195220

196-
if ((provision)); then
197-
ssh "${ssh_options[@]}" "$guest" "sudo apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential clang git lld rsync pkg-config libssl-dev sqlite3 libsqlite3-dev valgrind libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev libwayland-dev libxkbcommon-dev libwayland-egl1 libxkbcommon-x11-dev wayland-protocols libx11-dev libgl1-mesa-dri xauth xvfb"
198-
fi
199-
200221
if (($# == 0)); then
201222
set -- test-all
202223
fi

cmd/v/macos_v3_dispatch.c.v

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const macos_v3_caller_vexe_env = 'V_MACOS_V3_CALLER_VEXE'
2424
const macos_v3_caller_vexe_present_env = 'V_MACOS_V3_CALLER_VEXE_PRESENT'
2525
const macos_v3_caller_vchild_env = 'V_MACOS_V3_CALLER_VCHILD'
2626
const macos_v3_caller_vchild_present_env = 'V_MACOS_V3_CALLER_VCHILD_PRESENT'
27+
const macos_v3_caller_no_fallback_env = 'V_MACOS_V3_CALLER_NO_FALLBACK'
28+
const macos_v3_caller_no_fallback_present_env = 'V_MACOS_V3_CALLER_NO_FALLBACK_PRESENT'
2729
const macos_v3_embedded_env = 'V_MACOS_V3_EMBEDDED'
2830
const macos_v3_retry_env = 'V_MACOS_V3_RETRY'
2931
const macos_v3_no_fallback_env = 'V_MACOS_V3_NO_FALLBACK'
@@ -143,9 +145,8 @@ fn is_macos_v3_relevant_command(command string, prefs &pref.Preferences) bool {
143145
normalized_path := prefs.path.replace('\\', '/').trim_right('/')
144146
// cmd/v remains the command dispatcher. All other user compilation and test
145147
// modes use V3 by default.
146-
if normalized_path == 'cmd/v' || normalized_path.starts_with('cmd/v/')
147-
|| normalized_path.contains('/cmd/v/') || normalized_path.ends_with('/cmd/v')
148-
|| normalized_path == 'vlib/v3/v3.v' || normalized_path.ends_with('/vlib/v3/v3.v')
148+
if is_macos_v3_vroot_path(normalized_path, 'cmd/v', true)
149+
|| is_macos_v3_vroot_path(normalized_path, 'vlib/v3/v3.v', false)
149150
|| is_macos_v3_v1_compiler_source(normalized_path)
150151
|| is_macos_v3_internal_tool_bootstrap(normalized_path, os.getenv('VCHILD') == 'true') {
151152
return false
@@ -161,26 +162,35 @@ fn is_macos_v3_relevant_command(command string, prefs &pref.Preferences) bool {
161162
}
162163

163164
fn is_macos_v3_v1_compiler_source(normalized_path string) bool {
164-
is_compiler_source := normalized_path.starts_with('vlib/v/')
165-
|| normalized_path.contains('/vlib/v/')
166-
if !is_compiler_source {
165+
compiler_dir := macos_v3_vroot_path_value('vlib/v')
166+
path := os.real_path(normalized_path).replace('\\', '/').trim_right('/')
167+
if path != compiler_dir && !path.starts_with(compiler_dir + '/') {
167168
return false
168169
}
169-
if normalized_path.starts_with('vlib/v3/') || normalized_path.contains('/vlib/v3/') {
170+
relative := path[compiler_dir.len..].trim_left('/')
171+
if relative == 'v3' || relative.starts_with('v3/') {
170172
return false
171173
}
172174
// The established compiler's implementation modules still require V1 to compile.
173175
// Keep the language-level regression suites on V3: their files are ordinary user
174176
// programs even though they live below the compiler tree.
175-
return !normalized_path.starts_with('vlib/v/tests/')
176-
&& !normalized_path.contains('/vlib/v/tests/')
177-
&& !normalized_path.starts_with('vlib/v/slow_tests/')
178-
&& !normalized_path.contains('/vlib/v/slow_tests/')
177+
return relative != 'tests' && !relative.starts_with('tests/') && relative != 'slow_tests'
178+
&& !relative.starts_with('slow_tests/')
179+
}
180+
181+
fn macos_v3_vroot_path_value(relative string) string {
182+
vroot := os.real_path(os.dir(pref.vexe_path()))
183+
return os.real_path(os.join_path(vroot, relative)).replace('\\', '/').trim_right('/')
184+
}
185+
186+
fn is_macos_v3_vroot_path(normalized_path string, relative string, include_children bool) bool {
187+
path := os.real_path(normalized_path).replace('\\', '/').trim_right('/')
188+
target := macos_v3_vroot_path_value(relative)
189+
return path == target || (include_children && path.starts_with(target + '/'))
179190
}
180191

181192
fn is_macos_v3_internal_tool_bootstrap(normalized_path string, is_vchild bool) bool {
182-
return is_vchild
183-
&& (normalized_path.starts_with('cmd/tools/') || normalized_path.contains('/cmd/tools/'))
193+
return is_vchild && is_macos_v3_vroot_path(normalized_path, 'cmd/tools', true)
184194
}
185195

186196
fn launch_macos_v3_compiler(prefs &pref.Preferences, raw_args []string) ?MacosV3CErrorReport {
@@ -420,6 +430,9 @@ fn macos_v3_child_environment(vexe string, fallback_file string, caller_environm
420430
macos_v3_caller_vexe_env, macos_v3_caller_vexe_present_env)
421431
preserve_macos_v3_caller_environment_value(mut environment, caller_environment, 'VCHILD',
422432
macos_v3_caller_vchild_env, macos_v3_caller_vchild_present_env)
433+
preserve_macos_v3_caller_environment_value(mut environment, caller_environment,
434+
macos_v3_no_fallback_env, macos_v3_caller_no_fallback_env,
435+
macos_v3_caller_no_fallback_present_env)
423436
for private_name in ['V_MACOS_V3_FALLBACK_FILE', 'V_MACOS_V3_C_ERROR_DIR', 'V_MACOS_V3_RETRY'] {
424437
environment.delete(private_name)
425438
}
@@ -463,11 +476,18 @@ fn macos_v3_original_caller_environment(dispatch_environment map[string]string)
463476
restore_macos_v3_caller_environment_value(mut caller_environment, dispatch_environment,
464477
'VCHILD', macos_v3_caller_vchild_env, macos_v3_caller_vchild_present_env)
465478
}
479+
no_fallback_present := dispatch_environment[macos_v3_caller_no_fallback_present_env] or { '' }
480+
if no_fallback_present in ['0', '1'] {
481+
restore_macos_v3_caller_environment_value(mut caller_environment, dispatch_environment,
482+
macos_v3_no_fallback_env, macos_v3_caller_no_fallback_env,
483+
macos_v3_caller_no_fallback_present_env)
484+
}
466485
for private_name in [macos_v3_fallback_file_env, macos_v3_c_error_dir_env, macos_v3_vhash_env,
467486
macos_v3_vcurrent_hash_env, macos_v3_embedded_env, macos_v3_retry_env,
468487
'V3_CRUN_BUILD_IDENTITY', 'V3_INTERNAL_RESTART', macos_v3_caller_vexe_env,
469488
macos_v3_caller_vexe_present_env, macos_v3_caller_vchild_env,
470-
macos_v3_caller_vchild_present_env] {
489+
macos_v3_caller_vchild_present_env, macos_v3_caller_no_fallback_env,
490+
macos_v3_caller_no_fallback_present_env] {
471491
caller_environment.delete(private_name)
472492
}
473493
return caller_environment

0 commit comments

Comments
 (0)