#!/usr/bin/env bash # # Minimal VC6 link-frontier probe for the Windows 9x port. # # This is deliberately smaller than CPython's full PCbuild/pythoncore.vcxproj: # it compiles only the translation units already proven by the core compile # probes plus the tiny Programs/python.c executable entry point, then invokes # LINK.EXE under Wine. A successful executable link is not expected yet; the # purpose of this milestone is to verify that the build can get past CL.EXE # for the current frontier and reach a real VC6 linker diagnostic with a # reproducible command line. # # The MSVC600 bundle is an external, local-only prerequisite; nothing under # MSVC600/ is part of this project's source. # # Usage: # scripts/vc6-probe-minlink.sh # # Environment: # MSVC600_ROOT override the MSVC600 location (default: /MSVC600) # WINEPREFIX override the Wine prefix (default: ~/.wine-win9xport) set -u REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # Reuse winpath()/strip_prefix() from vc6-probe.sh instead of duplicating # them; sourcing it does not run the probe itself (see its own guard). # shellcheck source=scripts/vc6-probe.sh source "$REPO_ROOT/scripts/vc6-probe.sh" run_probe_minlink() { MSVC600_ROOT="${MSVC600_ROOT:-$REPO_ROOT/MSVC600}" BUILD_DIR="$REPO_ROOT/build/vc6-probe-minlink" CL="$MSVC600_ROOT/VC98/Bin/CL.EXE" LINK="$MSVC600_ROOT/VC98/Bin/LINK.EXE" VCVARS="$MSVC600_ROOT/VC98/Bin/VCVARS32.BAT" # Keep this list intentionally tiny and aligned with the post-core-probe # milestone: python.vcxproj's single executable TU plus the three core TUs # that are currently known to compile under scripts/vc6-probe-core.sh. SOURCES=( "cpython/Programs/python.c" "cpython/Modules/main.c" "cpython/Python/pylifecycle.c" "cpython/Python/pystate.c" ) for required in "$CL" "$LINK" "$VCVARS" "$MSVC600_ROOT/VC98/Include" \ "$MSVC600_ROOT/VC98/Lib" "$MSVC600_ROOT/Common/MSDev98/Bin"; do if [ ! -e "$required" ]; then echo "vc6-probe-minlink: missing prerequisite: $required" >&2 return 2 fi done local source_rel for source_rel in "${SOURCES[@]}"; do if [ ! -e "$REPO_ROOT/$source_rel" ]; then echo "vc6-probe-minlink: missing source: $REPO_ROOT/$source_rel" >&2 return 2 fi done if ! command -v wine >/dev/null 2>&1; then echo "vc6-probe-minlink: wine is not installed" >&2 return 2 fi export WINEPREFIX="${WINEPREFIX:-$HOME/.wine-win9xport}" export WINEDEBUG="${WINEDEBUG:--all}" # CL.EXE loads C1/C2 from VC98/Bin and MSPDB60.DLL from Common/MSDev98/Bin; # LINK.EXE also needs the VC98 tools and default libraries. export WINEPATH="$(winpath "$MSVC600_ROOT/VC98/Bin");$(winpath "$MSVC600_ROOT/Common/MSDev98/Bin")" rm -rf "$BUILD_DIR" mkdir -p "$BUILD_DIR" INCLUDE_ARGS=( "$(winpath "$REPO_ROOT/compat/msvc600")" "$(winpath "$REPO_ROOT/cpython/Include/internal")" "$(winpath "$REPO_ROOT/cpython/Include")" "$(winpath "$REPO_ROOT/cpython/PC")" "$(winpath "$MSVC600_ROOT/VC98/Include")" ) echo "== MSVC600 minimal link-frontier probe ==" echo "sources:" for source_rel in "${SOURCES[@]}"; do echo " - $source_rel" done echo "prefix : $WINEPREFIX" echo local obj_args="" local source_abs obj_name obj_abs cmd status for source_rel in "${SOURCES[@]}"; do source_abs="$REPO_ROOT/$source_rel" obj_name="${source_rel#cpython/}" obj_name="${obj_name//\//_}" obj_name="${obj_name%.c}.obj" obj_abs="$BUILD_DIR/$obj_name" obj_args+=" $(winpath "$obj_abs")" cmd="call $(winpath "$VCVARS") && cd /d $(winpath "$REPO_ROOT/cpython") && cl /nologo /D Py_BUILD_CORE /D Py_BUILD_CORE_BUILTIN /D Py_ENABLE_SHARED /D _USRDLL" for include_arg in "${INCLUDE_ARGS[@]}"; do cmd+=" /I $include_arg" done cmd+=" /c $(winpath "$source_abs") /Fo$(winpath "$obj_abs")" wine cmd /c "$cmd" 2>&1 | grep -v '^[0-9a-f]\{4\}:err:' | strip_prefix "$(winpath "$REPO_ROOT")\\" status="${PIPESTATUS[0]}" if [ "$status" -ne 0 ]; then echo echo "== cl.exe exit status: $status ==" echo "vc6-probe-minlink: compile failed before link at $source_rel" >&2 return "$status" fi done echo echo "== LINK.EXE attempt ==" cmd="call $(winpath "$VCVARS") && cd /d $(winpath "$REPO_ROOT/cpython") && link /nologo /subsystem:console /out:$(winpath "$BUILD_DIR/python-min.exe") /libpath:$(winpath "$MSVC600_ROOT/VC98/Lib")$obj_args kernel32.lib user32.lib advapi32.lib shell32.lib version.lib ws2_32.lib" wine cmd /c "$cmd" 2>&1 | grep -v '^[0-9a-f]\{4\}:err:' | strip_prefix "$(winpath "$REPO_ROOT")\\" status="${PIPESTATUS[0]}" echo echo "== link.exe exit status: $status ==" return "$status" } if [ "${BASH_SOURCE[0]}" = "${0}" ]; then run_probe_minlink "$@" exit "$?" fi