Skip to content

Commit

Permalink
ci(windows): build binary packages using the vcpkg package
Browse files Browse the repository at this point in the history
  • Loading branch information
dvarrazzo committed Jan 4, 2025
1 parent 2ffe822 commit 5559d64
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 0 deletions.
68 changes: 68 additions & 0 deletions .github/workflows/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,71 @@ jobs:
with:
name: macos-${{matrix.pyver}}-macos-${{matrix.macver}}_${{matrix.arch}}
path: ./wheelhouse/*.whl


build-windows:
runs-on: windows-latest
if: true

strategy:
fail-fast: false
matrix:
arch: [win_amd64]
pyver: [cp38, cp39, cp310, cp311, cp312, cp313]

defaults:
run:
shell: bash

steps:
# there are some other libpq in PATH
- name: Drop spurious libpq in the path
run: rm -rf c:/tools/php C:/Strawberry/c/bin

- name: Checkout repo
uses: actions/checkout@v4

- name: Start PostgreSQL service for test
run: |
$PgSvc = Get-Service "postgresql*"
Set-Service $PgSvc.Name -StartupType manual
$PgSvc.Start()
shell: powershell

- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v7
with:
script: |
const path = require('path')
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.addPath(path.join(process.env.VCPKG_INSTALLATION_ROOT, 'installed/x64-windows-release/lib'));
core.addPath(path.join(process.env.VCPKG_INSTALLATION_ROOT, 'installed/x64-windows-release/bin'));
# TODO: patch to psycopg2-binary
# - name: Create the binary package source tree
# run: python3 ./tools/build/copy_to_binary.py

- name: Build wheels
uses: pypa/[email protected]
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" # cache vcpkg
CIBW_BUILD: ${{matrix.pyver}}-${{matrix.arch}}
CIBW_ARCHS_WINDOWS: AMD64 x86
CIBW_BEFORE_BUILD_WINDOWS: '.\scripts\build\wheel_win32_before_build.bat'
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >-
delvewheel repair -w {dest_dir}
--no-mangle "libiconv-2.dll;libwinpthread-1.dll" {wheel}
CIBW_TEST_REQUIRES: ./psycopg[test] ./psycopg_pool
CIBW_TEST_COMMAND: >-
export PYTHONPATH={project} &&
python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')"
# Note: no fast test because we don't run Windows tests
CIBW_ENVIRONMENT_WINDOWS: >-
PSYCOPG2_TESTDB=postgres
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: windows-${{matrix.pyver}}-${{matrix.arch}}
path: ./wheelhouse/*.whl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python
"""
We use vcpkg in github actions to build psycopg-binary.
This is a stub to work as `pg_config --libdir` or `pg_config --includedir` to
make it work with vcpkg.
You will need install vcpkg and set `VCPKG_ROOT `env
and run `vcpkg install libpq:x64-windows-release` before you use this script
"""

import os
import sys
import logging
import platform
from pathlib import Path
from argparse import ArgumentParser, Namespace, RawDescriptionHelpFormatter

logger = logging.getLogger()
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")


class ScriptError(Exception):
"""Controlled exception raised by the script."""


def _main() -> None:
# only x64-windows
if not (sys.platform == "win32" and platform.machine() == "AMD64"):
raise ScriptError("this script should only be used in x64-windows")

args = parse_cmdline()

# on github actions it's `VCPKG_INSTALLATION_ROOT`
if "VCPKG_ROOT" not in os.environ:
raise ScriptError("failed to find VCPKG ROOT path")

vcpkg_root = Path(os.environ["VCPKG_ROOT"])
vcpkg_platform_root = (vcpkg_root / "installed/x64-windows-release").resolve()

if args.libdir:
f = vcpkg_platform_root / "lib/libpq.lib"
if not f.exists():
raise ScriptError(f"libpq library not found: {f}")
print(vcpkg_platform_root.joinpath("lib"))

elif args.includedir:
d = vcpkg_platform_root / "include/libpq"
if not d.is_dir():
raise ScriptError(f"libpq include directory not found: {d}")
print(vcpkg_platform_root.joinpath("include"))

else:
raise ScriptError("command not handled")


def parse_cmdline() -> Namespace:
parser = ArgumentParser(
description=__doc__, formatter_class=RawDescriptionHelpFormatter
)
g = parser.add_mutually_exclusive_group(required=True)
g.add_argument("--libdir", action="store_true")
g.add_argument("--includedir", action="store_true")
opt = parser.parse_args()
return opt


def main() -> None:
try:
_main()
except ScriptError as e:
logger.error("%s", e)
sys.exit(1)


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python
"""
We use vcpkg in github actions to build psycopg-binary.
This is a stub to work as `pg_config --libdir` or `pg_config --includedir` to
make it work with vcpkg.
You will need install `vcpkg`, set `VCPKG_ROOT` env, and run `vcpkg install
libpq:x64-windows-release` before using this script.
"""

import os
import sys
import platform
from pathlib import Path
from argparse import ArgumentParser, Namespace, RawDescriptionHelpFormatter


class ScriptError(Exception):
"""Controlled exception raised by the script."""


def _main() -> None:
# only x64-windows
if not (sys.platform == "win32" and platform.machine() == "AMD64"):
raise ScriptError("this script should only be used in x64-windows")

vcpkg_root = os.environ.get(
"VCPKG_ROOT", os.environ.get("VCPKG_INSTALLATION_ROOT", "")
)
if not vcpkg_root:
raise ScriptError("VCPKG_ROOT/VCPKG_INSTALLATION_ROOT env var not specified")
vcpkg_platform_root = (Path(vcpkg_root) / "installed/x64-windows-release").resolve()

args = parse_cmdline()

if args.libdir:
if not (f := vcpkg_platform_root / "lib/libpq.lib").exists():
raise ScriptError(f"libpq library not found: {f}")
print(vcpkg_platform_root.joinpath("lib"))

elif args.includedir:
if not (d := vcpkg_platform_root / "include/libpq").is_dir():
raise ScriptError(f"libpq include directory not found: {d}")
print(vcpkg_platform_root.joinpath("include"))

else:
raise ScriptError("command not handled")


def parse_cmdline() -> Namespace:
parser = ArgumentParser(
description=__doc__, formatter_class=RawDescriptionHelpFormatter
)
g = parser.add_mutually_exclusive_group(required=True)
g.add_argument(
"--libdir",
action="store_true",
help="show location of object code libraries",
)
g.add_argument(
"--includedir",
action="store_true",
help="show location of C header files of the client interfaces",
)
opt = parser.parse_args()
return opt


def main() -> None:
try:
_main()
except ScriptError as e:
print(f"ERROR: {e}.", file=sys.stderr)
sys.exit(1)


if __name__ == "__main__":
main()
11 changes: 11 additions & 0 deletions scripts/build/pg_config_vcpkg_stub/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = 'pg_config_vcpkg_stub'
version = "0"
description = "see docs string in pg_config_vcpkg_stub for more details"

[project.scripts]
pg_config = 'pg_config_vcpkg_stub:main'
7 changes: 7 additions & 0 deletions scripts/build/wheel_win32_before_build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@echo on

pip install delvewheel wheel

vcpkg install libpq:x64-windows-release

pipx install .\scripts\build\pg_config_vcpkg_stub\

0 comments on commit 5559d64

Please sign in to comment.