Ctrl K
ComunidadGuías…

windows/python-gtk3-install.ps1

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<#
Install Python and GTK development and build environment for BleachBit on Windows.
This is a special version built for BleachBit.
It installs in a portable style.
This script may be run in an empty directory like `c:\projects`.

Afterwards, launch the application like this:
  c:\projects\x86-windows\tools\python3\python.exe c:\projects\bleachbit\bleachbit.py

This assumes that the BleachBit source code is in `c:\projects\bleachbit` and PyGTK
is installed in `c:\projects\pygtk`, but either directory can be relocated.

Copyright (C) 2008-2025 Andrew Ziem

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
#>

# CI's pwsh wrapper already does this, but `powershell -File` does not
$ErrorActionPreference = 'Stop'

$root_dir = Join-Path (Get-Location).Path "vcpkg_installed\x86-windows"
$python_home = Join-Path $root_dir "tools\python3"
$themes_dir = Join-Path $python_home "share\themes"
# When the tree is restored from cache python.exe already exists, so the pip
# bootstrap and installs below can be skipped. A dependency change busts the
# cache key, forcing a fresh unpack where this is false.
$python_exists = Test-Path "$python_home\python.exe"
# location of this .ps1 script
$script_dir = Split-Path -Parent $MyInvocation.MyCommand.Path
$base_download_url = "https://github.com/bleachbit/pygtkwin/releases/download/v2026-10-13/"

function Assert-FileHash($Path, $Expected) {
    $actual = (Get-FileHash -Path $Path -Algorithm SHA256).Hash
    if ($actual -ine $Expected) {
        throw "SHA256 mismatch for ${Path}: expected $Expected, got $actual"
    }
}

function Expand-7z($Path) {
    $seven_zip = (Get-Command 7z.exe -ErrorAction SilentlyContinue).Source
    if (-not $seven_zip) {
        $seven_zip = Join-Path $env:ProgramFiles "7-Zip\7z.exe"
    }
    if (-not (Test-Path $seven_zip)) {
        Write-Error "7-Zip is needed to unpack $Path"
        exit 1
    }
    & $seven_zip x -bso0 -bsp0 -y $Path
    if ($LASTEXITCODE -ne 0) {
        Write-Error "7-Zip failed to unpack ${Path}: exit code $LASTEXITCODE"
        exit $LASTEXITCODE
    }
}

# Visual C++ Redistributable 2015 x86
$VC_REDIST_FN = "VC_redist.x86.exe"
$VC_REDIST_URL = "https://aka.ms/vs/17/release/vc_redist.x86.exe"
if (-not $env:GITHUB_ACTIONS) {
    if (-not (Test-Path $VC_REDIST_FN)) {
        Write-Host "Downloading Visual C++ Redistributable..."
        Invoke-WebRequest -Uri $VC_REDIST_URL -OutFile $VC_REDIST_FN
        Get-FileHash -Path $VC_REDIST_FN -Algorithm SHA256 | Format-List
        $fileSizeMB = (Get-Item $VC_REDIST_FN).Length / 1MB
        if ($fileSizeMB -lt 5) {
            Write-Warning "The downloaded Visual C++ Redistributable file is smaller than expected (< 5MB). Please verify its integrity."
        }
    } else {
        Write-Host "Visual C++ Redistributable is already downloaded."
    }
    if (-not (Test-Path "C:\Windows\SysWOW64\vcruntime140.dll")) {
        Write-Host "Installing Visual C++ Redistributable..."
        Write-Host "Tip: If this step seems to freeze, press ALT+TAB to check for the UAC dialog."
        Start-Process -FilePath $VC_REDIST_FN -ArgumentList "/install", "/quiet", "/norestart" -Wait
    } else {
        Write-Host "Visual C++ Redistributable is already installed."
    }
} else {
    Write-Host "Skipping Visual C++ Redistributable installation in CI."
}

# Python and GTK+
$GTK_ARCHIVE_FN = "gtk3.24-x86-windows.7z"
if (-not (Test-Path $GTK_ARCHIVE_FN)) {
    Write-Host "Downloading Python and GTK+..."
    Invoke-WebRequest -Uri "$base_download_url/$GTK_ARCHIVE_FN" -OutFile $GTK_ARCHIVE_FN
} else {
    Write-Host "Python and GTK+ are already downloaded."
}
Assert-FileHash $GTK_ARCHIVE_FN "d3fd28959ab69ceb185a3f22cfe03bd6f00ab4f7e896621b850e377913a992f3"

if (-not (Test-Path $python_home\python.exe)) {
    Write-Host "Unpacking Python and GTK+..."
    Expand-7z $GTK_ARCHIVE_FN
} else {
    Write-Host "Python and GTK+ are already unpacked."
}

if (-not (Test-Path "$root_dir\tools\gtk3\gtk-launch.exe")) {
    Write-Error "GTK+ is not installed correctly."
    exit 1
}

$schema_compiler = Join-Path $root_dir "tools\glib\glib-compile-schemas.exe"
$schema_dir = Join-Path $root_dir "share\glib-2.0\schemas"
if (-not (Test-Path "$schema_dir\gschemas.compiled")) {
    Write-Host "Compiling GLib schemas..."
    & $schema_compiler $schema_dir
    if ($LASTEXITCODE -ne 0) {
        Write-Error "Failed to compile GLib schemas: exit code $LASTEXITCODE"
        exit $LASTEXITCODE
    }
    if (-not (Test-Path "$schema_dir\gschemas.compiled")) {
        Write-Error "Failed to compile GLib schemas: $schema_dir\gschemas.compiled does not exist"
        exit 1
    }
}

# This fixes the chaff dialog when running on Windows from source.
New-Item -ItemType Directory -Path "$python_home\share\glib-2.0\schemas" -Force
Copy-Item -Path "$schema_dir\gschemas.compiled" -Destination "$python_home\share\glib-2.0\schemas" -Force

Write-Host "Checking Python version"
& "$python_home\python.exe" -V  # show Python version
if ($LASTEXITCODE -ne 0) {
    Write-Error "python.exe -V failed"
    exit $LASTEXITCODE
}

# Add Python home and scripts to PATH.
if ($env:PATH -notlike "*$python_home*") {
    Write-Host "Adding Python home and scripts to PATH..."
    $env:PATH += ";$python_home;$python_home\Scripts"
    Write-Host "Updated PATH: $env:PATH"
}

if (-not $python_exists) {
    Write-Host "ensurepip"
    & "$python_home\python.exe" -m ensurepip

    Write-Host "Checking pip version"
    & "$python_home\Scripts\pip3.exe" --version  # show pip version

    Write-Host "Updating pip..."
    & "$python_home\python.exe" -m pip install --disable-pip-version-check --upgrade pip
    if ($LASTEXITCODE -ne 0) {
        Write-Error "Failed to update pip: exit code $LASTEXITCODE"
        exit $LASTEXITCODE
    }
} else {
    Write-Host "Python is already unpacked; skipping pip bootstrap."
}

if (-not (Test-Path gtk-themes.zip)) {
    Write-Host "Downloading GTK themes..."
    #Invoke-WebRequest -Uri "$base_download_url/gtk-themes.zip" -OutFile "gtk-themes.zip"
    #FIXME: use new themes
    Invoke-WebRequest -Uri "https://github.com/mkhon/vcpkg/releases/download/gtk3-introspection-v1/gtk-themes.zip" -OutFile "gtk-themes.zip"
} else {
    Write-Host "GTK themes are already downloaded."
}
Assert-FileHash gtk-themes.zip "6BD572256773175C0139FCA9AD0D28A0EF23B4E087901D04198FF907FC096624"

if (-not (Test-Path "$themes_dir")) {
    Write-Host "Unpacking GTK themes..."
    Expand-Archive -Path gtk-themes.zip -DestinationPath .
    Copy-Item -Path "gtk-themes\*" -Destination $python_home -Recurse -ErrorAction SilentlyContinue
} else {
    Write-Host "GTK themes are already unpacked."
}

if (-not (Test-Path "$themes_dir\Adwaita\index.theme")) {
    Write-Error "GTK themes are not installed correctly."
    exit 1
}

if (Test-Path "gtk-themes") {
    Write-Host "Removing temporary directory gtk-themes..."
    Remove-Item -Path "gtk-themes" -Recurse
}

# psutil 7.1.2 stopped providing 32-bit wheels.
# It needs MSVC++ with the python3.lib.
Write-Host "Copying python312.lib..."
New-Item -ItemType Directory -Path "$python_home\libs" -Force
$pylibdest = "$python_home\libs\python3.lib"
Copy-Item -Path "$root_dir\lib\python312.lib" -Destination $pylibdest
Get-ChildItem -Path $pylibdest | Format-List -Property Name, Length

# Install pip packages
if (-not $python_exists) {
    Write-Host "pip install -r requirements.txt..."
    & "$python_home\Scripts\pip3.exe" install --disable-pip-version-check -r "$script_dir\requirements.txt"
    if ($LASTEXITCODE -ne 0) {
        Write-Error "Failed to update pip: exit code $LASTEXITCODE"
        exit $LASTEXITCODE
    }
}

$PYGOBJECT_FN = "pygobject-3.58.0-cp312-cp312-win32.whl"
if (-not (Test-Path $PYGOBJECT_FN)) {
    Write-Host "Downloading PyGObject..."
    Invoke-WebRequest -Uri "$base_download_url/$PYGOBJECT_FN" -OutFile "$PYGOBJECT_FN"
} else {
    Write-Host "PyGObject is already downloaded."
}
Assert-FileHash $PYGOBJECT_FN "a51a6fa9b1cbe55485d63c08e953538c72007a3798fc2285ca369625a0265f29"

if (-not $python_exists) {
    Write-Host "pip install $PYGOBJECT_FN..."
    & "$python_home\Scripts\pip3.exe" install --disable-pip-version-check $PYGOBJECT_FN
    if ($LASTEXITCODE -ne 0) {
        Write-Error "Failed to install PyGObject: exit code $LASTEXITCODE"
        exit $LASTEXITCODE
    }
}

# By default, pygobject installs to `x86-windows\lib\girepository-1.0`.
# Copy it to `x86-windows\tools\python3\lib\girepository-1.0`.
$girepo_dir = "$python_home\lib\girepository-1.0"
if (-not (Test-Path $girepo_dir)) {
    New-Item -Path "$girepo_dir" -ItemType Directory -Force
    Copy-Item -Path "$root_dir\lib\girepository-1.0\*" -Destination "$girepo_dir" -Recurse -Force -ErrorAction Stop
}

# Copy GTK dependencies to Python home.
Get-Content "$script_dir\python-gtk3-deps.lst" | ForEach-Object {
    Write-Host "Copying $_..."
    if (-not (Test-Path "$python_home\$_")) {
        Copy-Item -Path "$root_dir\$_" -Destination "$python_home" -Recurse -Force
    }
}

Write-Host "Copying gdk-pixbuf-2.0..."
$GDK_PIXBUF_DIR = "$python_home\lib\gdk-pixbuf-2.0\2.10.0"
if (-not (Test-Path $GDK_PIXBUF_DIR)) {
    Write-Host "Creating $GDK_PIXBUF_DIR..."
    New-Item -Path $GDK_PIXBUF_DIR -ItemType Directory -Force
}

$GDK_PIXBUF_LOADER_DIR = Join-Path $GDK_PIXBUF_DIR "loaders"
if (-not (Test-Path $GDK_PIXBUF_LOADER_DIR)) {
    New-Item -Path $GDK_PIXBUF_LOADER_DIR -ItemType Directory -Force | Out-Null
}
$svg_loader_src = Join-Path $root_dir "lib\gdk-pixbuf-2.0\2.10.0\loaders\pixbufloader-svg.dll"
if (Test-Path $svg_loader_src) {
    Copy-Item -Path $svg_loader_src -Destination $GDK_PIXBUF_LOADER_DIR -Force
}
Get-ChildItem -Path $GDK_PIXBUF_LOADER_DIR | Format-List -Property Name, Length

# Update cache file for GDK pixbuf.
$env:GDK_PIXBUF_MODULE_FILE = "$GDK_PIXBUF_DIR\loaders.cache"
if (-not (Test-Path $env:GDK_PIXBUF_MODULE_FILE)) {
    Write-Host "Creating $env:GDK_PIXBUF_MODULE_FILE..."
    $prevPath = $env:PATH
    try {
        $env:GDK_PIXBUF_MODULEDIR = $GDK_PIXBUF_LOADER_DIR
        $env:PATH = "$python_home\bin;$python_home;$python_home\Scripts;$root_dir\tools\gtk3;$prevPath"
        & "$root_dir\tools\gdk-pixbuf\gdk-pixbuf-query-loaders.exe" --update-cache
        if ($LASTEXITCODE -ne 0) {
            Write-Error "gdk-pixbuf-query-loaders.exe failed with exit code $LASTEXITCODE"
            exit $LASTEXITCODE
        }
    } finally {
        $env:PATH = $prevPath
    }
}