#!/usr/bin/env bash # # Py_BUILD_CORE compile probe for the Windows 9x port. # # scripts/vc6-probe.sh only ever compiles a public-header translation unit # (Programs/python.c). CPython's internal (`Include/internal/pycore_*.h`) # headers are a different, stricter surface: every one of them requires # Py_BUILD_CORE to be defined and Include/internal on the include path, and # they use compiler features the public headers avoid. This script probes # that surface directly by compiling Modules/main.c, the first internal # translation unit CPython's own build reaches, the same way # scripts/vc6-probe.sh probes the public one: run the external MSVC600 # `cl.exe` under Wine against the CPython 3.11.16 baseline in ./cpython, # using the project-local compatibility headers in ./compat/msvc600. # Compile-only (/c): this measures how far the VC6 front end gets, it does # not attempt to link. # # The MSVC600 bundle is an external, local-only prerequisite; nothing under # MSVC600/ is part of this project's source. # # Usage: # scripts/vc6-probe-core.sh # probe Modules/main.c # scripts/vc6-probe-core.sh path/to/other.c # probe another core TU # # 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_core() { MSVC600_ROOT="${MSVC600_ROOT:-$REPO_ROOT/MSVC600}" BUILD_DIR="$REPO_ROOT/build/vc6-probe-core" SOURCE_REL="${1:-cpython/Modules/main.c}" SOURCE_ABS="$REPO_ROOT/$SOURCE_REL" CL="$MSVC600_ROOT/VC98/Bin/CL.EXE" VCVARS="$MSVC600_ROOT/VC98/Bin/VCVARS32.BAT" for required in "$CL" "$VCVARS" "$MSVC600_ROOT/VC98/Include" \ "$MSVC600_ROOT/Common/MSDev98/Bin" "$SOURCE_ABS"; do if [ ! -e "$required" ]; then echo "vc6-probe-core: missing prerequisite: $required" >&2 return 2 fi done if ! command -v wine >/dev/null 2>&1; then echo "vc6-probe-core: 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. export WINEPATH="$(winpath "$MSVC600_ROOT/VC98/Bin");$(winpath "$MSVC600_ROOT/Common/MSDev98/Bin")" mkdir -p "$BUILD_DIR" # Include/internal must come before Include so pycore_*.h headers can # find each other with their own bare #include "pycore_foo.h" style, # same order CPython's own PC build uses. 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 Py_BUILD_CORE compile probe ==" echo "source : $SOURCE_REL" echo "prefix : $WINEPREFIX" echo CMD="call $(winpath "$VCVARS") && cd /d $(winpath "$REPO_ROOT/cpython") && cl /nologo /D Py_BUILD_CORE" for include_arg in "${INCLUDE_ARGS[@]}"; do CMD+=" /I $include_arg" done CMD+=" /c $(winpath "$SOURCE_ABS") /Fo$(winpath "$BUILD_DIR")\\" wine cmd /c "$CMD" 2>&1 | grep -v '^[0-9a-f]\{4\}:err:' | strip_prefix "$(winpath "$REPO_ROOT")\\" status="${PIPESTATUS[0]}" echo echo "== cl.exe exit status: $status ==" return "$status" } if [ "${BASH_SOURCE[0]}" = "${0}" ]; then run_probe_core "$@" exit "$?" fi