Skip to content

Commit ecb4585

Browse files
committed
[temp] probe: Windows SDK outside C:, Termux first run, cl.exe module roles
1 parent b165218 commit ecb4585

29 files changed

Lines changed: 416 additions & 8050 deletions
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# O5 probe: which cl.exe options compile each C++20 module role, in .cpp and
2+
# .cppm/.ixx files, and whether each writes the BMI an importer needs.
3+
# Prints; asserts nothing.
4+
$ErrorActionPreference = 'Continue'
5+
$PSNativeCommandUseErrorActionPreference = $false
6+
$summary = $env:GITHUB_STEP_SUMMARY
7+
function Say($t) { Write-Host $t; Add-Content -Path $summary -Value $t }
8+
$d = 'C:\roles'
9+
New-Item -ItemType Directory -Force $d | Out-Null
10+
Set-Location $d
11+
12+
Set-Content m.ixx "export module m;`nexport import :api;`nexport int twice(int);`n"
13+
Set-Content api.cppm "export module m:api;`nexport int answer();`n"
14+
Set-Content api_cpp.cpp "export module m2:api;`nexport int answer2();`n"
15+
Set-Content impl_part.cpp "module m:impl;`nimport :api;`nint helper() { return answer(); }`n"
16+
Set-Content impl_part.cppm "module m:impl2;`nimport :api;`nint helper2() { return answer(); }`n"
17+
Set-Content iface.cpp "export module solo;`nexport int solo_value() { return 7; }`n"
18+
Set-Content impl.cpp "module m;`nint twice(int x) { return 2 * x; }`n"
19+
20+
Say "## cl.exe module roles"
21+
Say '```'
22+
& cl 2>&1 | Select-Object -First 1 | ForEach-Object { Say $_ }
23+
Say '```'
24+
25+
function Try-Cl($label, [string[]]$a) {
26+
Remove-Item *.obj -ErrorAction SilentlyContinue
27+
$t0 = Get-Date
28+
Start-Sleep -Milliseconds 1100
29+
$out = & cl /nologo /std:c++latest /EHsc /c @a 2>&1
30+
$rc = $LASTEXITCODE
31+
$ifc = (Get-ChildItem *.ifc -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -gt $t0 } | ForEach-Object Name) -join ' '
32+
Say "### $label (exit $rc)"
33+
Say "command: ``cl /std:c++latest /c $($a -join ' ')`` — .ifc written: ``$ifc``"
34+
Say '```'
35+
$out | Select-Object -First 8 | ForEach-Object { Say "$_" }
36+
Say '```'
37+
}
38+
39+
# Interface partition in .cppm: needs /interface (cl does not know .cppm).
40+
Try-Cl 'interface partition, .cppm, no option' @('api.cppm')
41+
Try-Cl 'interface partition, .cppm, /interface /TP' @('/interface', '/TP', 'api.cppm')
42+
# Primary interface in .ixx.
43+
Try-Cl 'primary interface, .ixx' @('m.ixx')
44+
# Implementation partition in .cpp: plain, /internalPartition, /interface.
45+
Try-Cl 'implementation partition, .cpp, no option' @('impl_part.cpp')
46+
Try-Cl 'implementation partition, .cpp, /internalPartition' @('/internalPartition', 'impl_part.cpp')
47+
Try-Cl 'implementation partition, .cpp, /interface' @('/interface', 'impl_part.cpp')
48+
# Implementation partition in .cppm.
49+
Try-Cl 'implementation partition, .cppm, /internalPartition /TP' @('/internalPartition', '/TP', 'impl_part.cppm')
50+
Try-Cl 'implementation partition, .cppm, /interface /TP' @('/interface', '/TP', 'impl_part.cppm')
51+
# Interface unit in .cpp.
52+
Try-Cl 'interface unit, .cpp, no option' @('iface.cpp')
53+
Try-Cl 'interface unit, .cpp, /interface' @('/interface', 'iface.cpp')
54+
Try-Cl 'interface partition, .cpp, /interface' @('/interface', 'api_cpp.cpp')
55+
# Implementation unit (`module m;`) in .cpp, with m.ifc present.
56+
Try-Cl 'implementation unit, .cpp, no option' @('impl.cpp')
57+
exit 0

‎.github/probe/termux_docker.sh‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env bash
2+
# O7 / O8 probe: the published aarch64 mcpp, first run, inside a Termux userland
3+
# (termux/termux-docker on a native arm64 runner). The container has Termux's
4+
# bionic userland and paths but not Android's SELinux, so it shows host
5+
# recognition, the default toolchain and where Planning spends its time, not
6+
# the app-sandbox hard-link rule (see termux_emulator.sh). Prints only.
7+
set -u
8+
V="${MCPP_VERSION}"
9+
DL="$RUNNER_TEMP/termux-dl"
10+
LOGS="$RUNNER_TEMP/termux-logs"
11+
mkdir -p "$DL" "$LOGS"; chmod 777 "$LOGS"
12+
S="$GITHUB_STEP_SUMMARY"
13+
say() { echo "$*"; echo "$*" >> "$S"; }
14+
15+
curl -fsSL -o "$DL/mcpp.tar.gz" \
16+
"https://github.com/mcpp-community/mcpp/releases/download/v$V/mcpp-$V-linux-aarch64.tar.gz"
17+
cp "$GITHUB_WORKSPACE/.github/probe/termux_inner.sh" "$DL/"
18+
chmod -R a+rX "$DL"
19+
20+
say "## termux-docker aarch64 (mcpp $V)"
21+
docker pull -q termux/termux-docker:aarch64 2>&1 | tail -1
22+
docker image inspect termux/termux-docker:aarch64 --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}} {{json .Config.User}}' | tee -a "$S"
23+
24+
start=$(date +%s)
25+
docker run --rm --privileged \
26+
-v "$DL:/mnt/dl:ro" -v "$LOGS:/mnt/logs" \
27+
termux/termux-docker:aarch64 bash /mnt/dl/termux_inner.sh 2>&1 | tee "$LOGS/container.log"
28+
say "- container exit: ${PIPESTATUS[0]}, wall: $(( $(date +%s) - start )) s"
29+
30+
say '### environment'
31+
say '```'
32+
grep -E '^(ENV|UNAME|ID|HARDLINK)' "$LOGS/container.log" | head -40 >> "$S"
33+
say '```'
34+
say '### first run: key lines'
35+
say '```'
36+
grep -E 'First run|Resolving|Installing|Downloading|Planning|error|warning|hint|Finished|TIMING|glibc|llvm|musl' \
37+
"$LOGS/container.log" | grep -v '^\s*$' | head -60 >> "$S"
38+
say '```'
39+
say '### plan stage timings'
40+
say '```'
41+
grep -h 'build/stage' "$LOGS"/mcpp-log/*.log 2>/dev/null | tail -40 >> "$S"
42+
say '```'
43+
exit 0

‎.github/probe/termux_emulator.sh‎

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env bash
2+
# O8 / D19 probe: the Android app sandbox on an x86_64 emulator. The debuggable
3+
# Termux APK gives an app uid and SELinux app domain that `run-as` can enter,
4+
# which is where the hard-link rule the Termux report hit applies. The published
5+
# x86_64 mcpp is static, so it runs there without Termux's own bootstrap.
6+
# Prints only.
7+
set -u
8+
V="${MCPP_VERSION}"
9+
EMU="$RUNNER_TEMP/termux-emu"
10+
LOGS="$RUNNER_TEMP/termux-emu-logs"
11+
mkdir -p "$EMU" "$LOGS"
12+
S="$GITHUB_STEP_SUMMARY"
13+
say() { echo "$*"; echo "$*" >> "$S"; }
14+
15+
case "${1:-}" in
16+
download)
17+
apk_url=$(curl -fsSL -H "Authorization: Bearer ${GITHUB_TOKEN:-}" \
18+
https://api.github.com/repos/termux/termux-app/releases/latest \
19+
| python3 -c 'import json,sys; a=[x["browser_download_url"] for x in json.load(sys.stdin)["assets"] if x["name"].endswith("github-debug_x86_64.apk")]; print(a[0] if a else "")')
20+
echo "apk: $apk_url"
21+
curl -fsSL -o "$EMU/termux.apk" "$apk_url"
22+
curl -fsSL -o "$EMU/mcpp.tar.gz" \
23+
"https://github.com/mcpp-community/mcpp/releases/download/v$V/mcpp-$V-linux-x86_64.tar.gz"
24+
cp /etc/ssl/certs/ca-certificates.crt "$EMU/cacert.pem"
25+
cp "$GITHUB_WORKSPACE/.github/probe/termux_inner.sh" "$EMU/"
26+
ls -la "$EMU"
27+
;;
28+
run)
29+
say "## Termux app sandbox on an API 34 x86_64 emulator (mcpp $V)"
30+
adb wait-for-device
31+
say "- getenforce: $(adb shell getenforce | tr -d '\r')"
32+
adb install -r "$EMU/termux.apk" 2>&1 | tail -1
33+
for f in mcpp.tar.gz cacert.pem termux_inner.sh; do adb push "$EMU/$f" /data/local/tmp/ >/dev/null; done
34+
adb shell chmod 644 /data/local/tmp/mcpp.tar.gz /data/local/tmp/cacert.pem /data/local/tmp/termux_inner.sh
35+
A=/data/data/com.termux/files
36+
adb shell run-as com.termux sh -c "'mkdir -p $A/home $A/probe && cp /data/local/tmp/mcpp.tar.gz /data/local/tmp/cacert.pem /data/local/tmp/termux_inner.sh $A/probe/'" 2>&1
37+
adb shell run-as com.termux sh -c "'id; cat /proc/self/attr/current; echo; ls -la $A'" 2>&1 | tee -a "$LOGS/sandbox.txt"
38+
# The bash in termux_inner.sh is not there without Termux's bootstrap; run it
39+
# with the system sh, which handles everything the script uses.
40+
start=$(date +%s)
41+
timeout 5400 adb shell run-as com.termux sh -c \
42+
"'PROBE_OUT=$A/probe/out PROBE_TARBALL=$A/probe/mcpp.tar.gz PROBE_HOME=$A/home SSL_CERT_FILE=$A/probe/cacert.pem sh $A/probe/termux_inner.sh'" \
43+
2>&1 | tee "$LOGS/inner.log"
44+
say "- wall: $(( $(date +%s) - start )) s"
45+
for f in first-build.log; do
46+
adb shell run-as com.termux cat "$A/probe/out/$f" > "$LOGS/$f" 2>/dev/null
47+
done
48+
adb shell run-as com.termux sh -c "'cat $A/probe/out/mcpp-log/*.log'" > "$LOGS/mcpp.log" 2>/dev/null
49+
say '### sandbox'
50+
say '```'
51+
cat "$LOGS/sandbox.txt" >> "$S"
52+
grep -E '^(ENV|UNAME|ID|HARDLINK|MCPP|TIMING)' "$LOGS/inner.log" >> "$S"
53+
say '```'
54+
say '### first run: key lines'
55+
say '```'
56+
grep -E 'First run|Resolving|Installing|Downloading|error|warning|hint|Finished|glibc|Can.t create' \
57+
"$LOGS/inner.log" | head -60 >> "$S"
58+
say '```'
59+
say '### plan stage timings'
60+
say '```'
61+
grep 'build/stage' "$LOGS/mcpp.log" | tail -30 >> "$S"
62+
say '```'
63+
;;
64+
esac
65+
exit 0

‎.github/probe/termux_inner.sh‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/sh
2+
# POSIX sh: under run-as there is only the system shell.
3+
# Runs inside a Termux userland (termux-docker, or an app sandbox through
4+
# run-as). Prints what it sees; asserts nothing.
5+
set -u
6+
OUT="${PROBE_OUT:-/mnt/logs}"
7+
TARBALL="${PROBE_TARBALL:-/mnt/dl/mcpp.tar.gz}"
8+
export HOME="${PROBE_HOME:-${HOME:-/data/data/com.termux/files/home}}"
9+
mkdir -p "$HOME" "$OUT"
10+
export TMPDIR="${TMPDIR:-$HOME/tmp}"; mkdir -p "$TMPDIR"
11+
12+
echo "ENV ANDROID_ROOT=${ANDROID_ROOT-<unset>} ANDROID_DATA=${ANDROID_DATA-<unset>} PREFIX=${PREFIX-<unset>} TERMUX_VERSION=${TERMUX_VERSION-<unset>}"
13+
echo "ENV HOME=$HOME TMPDIR=$TMPDIR SSL_CERT_FILE=${SSL_CERT_FILE-<unset>}"
14+
echo "ENV linker64: $(ls -l /system/bin/linker64 2>&1 | head -1)"
15+
echo "UNAME $(uname -a 2>&1)"
16+
echo "ID $(id 2>&1)"
17+
echo "ID selinux: $(cat /proc/self/attr/current 2>&1 | tr -d '\0')"
18+
19+
cd "$HOME"
20+
rm -f hl_a hl_b
21+
echo a > hl_a
22+
if ln hl_a hl_b 2>"$TMPDIR/ln.err"; then echo "HARDLINK ok"; else echo "HARDLINK refused: $(cat "$TMPDIR/ln.err")"; fi
23+
rm -f hl_a hl_b
24+
25+
mkdir -p "$HOME/dist"
26+
tar -xzf "$TARBALL" -C "$HOME/dist" 2>&1 | tail -3
27+
MCPP=$(find "$HOME/dist" -path '*/bin/mcpp' -type f | head -1)
28+
echo "MCPP $MCPP"
29+
"$MCPP" --version 2>&1
30+
"$MCPP" self env 2>&1 | head -40
31+
32+
mkdir -p "$HOME/hello/src"
33+
cd "$HOME/hello"
34+
cat > mcpp.toml <<'EOF'
35+
[package]
36+
name = "hello"
37+
version = "0.1.0"
38+
39+
[targets.hello]
40+
kind = "bin"
41+
main = "src/main.cpp"
42+
EOF
43+
printf 'import std;\nint main() { std::println("hello from termux"); }\n' > src/main.cpp
44+
45+
t0=$(date +%s)
46+
MCPP_LOG_LEVEL=info timeout 3600 "$MCPP" build --verbose > "$OUT/first-build.log" 2>&1
47+
rc=$?
48+
cat "$OUT/first-build.log"
49+
echo "TIMING first build: exit $rc, $(( $(date +%s) - t0 )) s"
50+
t0=$(date +%s)
51+
timeout 600 "$MCPP" run 2>&1 | tail -5
52+
echo "TIMING run: $(( $(date +%s) - t0 )) s"
53+
54+
mkdir -p "$OUT/mcpp-log"
55+
cp -r "$HOME"/.mcpp/log/. "$OUT/mcpp-log/" 2>/dev/null
56+
cp "$TMPDIR"/mcpp-xlings-*.stderr "$OUT/" 2>/dev/null
57+
ls "$HOME"/.mcpp/registry/logs/hooks/ 2>/dev/null | head
58+
cp -r "$HOME"/.mcpp/registry/logs "$OUT/registry-logs" 2>/dev/null
59+
cat "$HOME"/.mcpp/config.toml 2>/dev/null | grep -E 'toolchain|target'
60+
exit 0

‎.github/probe/windows_sdk.ps1‎

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# O6 / D17 / D18 probe: what the published mcpp does when the Windows SDK is not
2+
# under the conventional "C:\Program Files (x86)\Windows Kits\10" path, as on a
3+
# machine whose SDK was installed to another drive. Prints; asserts nothing.
4+
$ErrorActionPreference = 'Continue'
5+
$PSNativeCommandUseErrorActionPreference = $false
6+
$v = $env:MCPP_VERSION
7+
$root = 'C:\probe'
8+
$logs = "$root\logs"
9+
New-Item -ItemType Directory -Force $logs | Out-Null
10+
$summary = $env:GITHUB_STEP_SUMMARY
11+
function Say($t) { Write-Host $t; Add-Content -Path $summary -Value $t }
12+
13+
Say "## windows sdk probe (mcpp $v)"
14+
$zip = "$root\mcpp.zip"
15+
Invoke-WebRequest "https://github.com/mcpp-community/mcpp/releases/download/v$v/mcpp-$v-windows-x86_64.zip" -OutFile $zip
16+
Expand-Archive $zip -DestinationPath "$root\dist" -Force
17+
$mcpp = (Get-ChildItem "$root\dist" -Recurse -Filter mcpp.exe | Select-Object -First 1).FullName
18+
Say "- mcpp: ``$mcpp``"
19+
Say "- WindowsSdkDir in env: ``$env:WindowsSdkDir`` VSINSTALLDIR: ``$env:VSINSTALLDIR``"
20+
21+
function Run-Case($name, $mcppHome, $dir, [string[]]$cmdArgs) {
22+
$env:MCPP_HOME = $mcppHome
23+
New-Item -ItemType Directory -Force $mcppHome | Out-Null
24+
Push-Location $dir
25+
$log = "$logs\$name.log"
26+
& $mcpp @cmdArgs *>&1 | Tee-Object -FilePath $log | Out-Host
27+
$rc = $LASTEXITCODE
28+
Pop-Location
29+
Say "### $name (exit $rc)"
30+
Say '```'
31+
Get-Content $log | Select-String -Pattern 'First run|Default|Resolved|warning|error|note|hint|Visual Studio|SDK|MinGW|mingw|Finished|toolchain' |
32+
Select-Object -First 40 | ForEach-Object { Say $_.Line }
33+
Say '```'
34+
$cfg = Join-Path $mcppHome 'config.toml'
35+
if (Test-Path $cfg) {
36+
Say "config.toml after ${name}:"
37+
Say '```'
38+
Get-Content $cfg | Select-String -Pattern 'toolchain|target' | ForEach-Object { Say $_.Line }
39+
Say '```'
40+
}
41+
return $rc
42+
}
43+
44+
function New-Hello($name, [string]$toolchainLine) {
45+
$dir = "$root\$name"
46+
New-Item -ItemType Directory -Force "$dir\src" | Out-Null
47+
$toml = "[package]`nname = `"$name`"`nversion = `"0.1.0`"`n"
48+
if ($toolchainLine) { $toml += "`n[toolchain]`n$toolchainLine`n" }
49+
$toml += "`n[targets.$name]`nkind = `"bin`"`nmain = `"src/main.cpp`"`n"
50+
Set-Content -Path "$dir\mcpp.toml" -Value $toml -NoNewline
51+
Set-Content -Path "$dir\src\main.cpp" -Value "import std;`nint main() { std::println(`"hello from {}`", `"$name`"); }`n"
52+
return $dir
53+
}
54+
55+
$home1 = "$root\home-first-run"
56+
$home2 = "$root\home-llvm"
57+
58+
# B0: control, SDK in its conventional place, llvm declared.
59+
$b0 = New-Hello 'b0_control_llvm' 'windows = "llvm@23.1.3"'
60+
Run-Case 'B0_control_llvm_declared' $home2 $b0 @('build') | Out-Null
61+
62+
# Move the SDK and record its new place where an installer would.
63+
$kits = Join-Path ${env:ProgramFiles(x86)} 'Windows Kits\10'
64+
$moved = 'C:\MovedKits\10'
65+
New-Item -ItemType Directory -Force 'C:\MovedKits' | Out-Null
66+
Say "### moving ``$kits`` -> ``$moved``"
67+
try { Move-Item -Path $kits -Destination $moved -ErrorAction Stop; Say '- moved' }
68+
catch { Say "- Move-Item failed: $($_.Exception.Message)"; cmd /c "move `"$kits`" `"$moved`"" | Out-Host }
69+
Say "- conventional path exists now: $(Test-Path $kits); moved path exists: $(Test-Path $moved)"
70+
foreach ($k in @('HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots',
71+
'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots')) {
72+
if (Test-Path $k) {
73+
$old = (Get-ItemProperty $k -ErrorAction SilentlyContinue).KitsRoot10
74+
Set-ItemProperty -Path $k -Name KitsRoot10 -Value "$moved\"
75+
Say "- ``$k`` KitsRoot10: ``$old`` -> ``$moved\``"
76+
}
77+
}
78+
foreach ($k in @('HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0',
79+
'HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0')) {
80+
if (Test-Path $k) {
81+
$old = (Get-ItemProperty $k -ErrorAction SilentlyContinue).InstallationFolder
82+
Set-ItemProperty -Path $k -Name InstallationFolder -Value "$moved\"
83+
Say "- ``$k`` InstallationFolder: ``$old`` -> ``$moved\``"
84+
}
85+
}
86+
87+
# S1: nothing configured anywhere (fresh home, no [toolchain]).
88+
$s1 = New-Hello 's1_nothing_configured' ''
89+
Run-Case 'S1_first_run_nothing_configured' $home1 $s1 @('build') | Out-Null
90+
Run-Case 'S1_self_env' $home1 $s1 @('self', 'env') | Out-Null
91+
92+
# S2: [toolchain] windows = llvm in mcpp.toml (llvm already installed by B0).
93+
$s2 = New-Hello 's2_llvm_declared' 'windows = "llvm@23.1.3"'
94+
$rc = Run-Case 'S2_llvm_declared_in_manifest' $home2 $s2 @('build')
95+
if ($rc -eq 0) {
96+
$exe = Get-ChildItem "$s2\target" -Recurse -Filter 's2_llvm_declared.exe' | Select-Object -First 1
97+
if ($exe) { Say "S2 program output: $(& $exe.FullName)" }
98+
}
99+
100+
# S3: nothing in mcpp.toml, --toolchain on the command line.
101+
$s3 = New-Hello 's3_toolchain_flag' ''
102+
Run-Case 'S3_toolchain_flag' $home2 $s3 @('build', '--toolchain', 'llvm@23.1.3') | Out-Null
103+
104+
# S4: S2 again with --verbose, for the SDK lines the plain run hides.
105+
Run-Case 'S4_llvm_declared_verbose' $home2 $s2 @('build', '--verbose') | Out-Null
106+
exit 0

0 commit comments

Comments
 (0)