Skip to content

Instantly share code, notes, and snippets.

@dllud
Last active May 19, 2025 17:16
Show Gist options
  • Save dllud/d301640a88abf7d736344243c45ecfcc to your computer and use it in GitHub Desktop.
Save dllud/d301640a88abf7d736344243c45ecfcc to your computer and use it in GitHub Desktop.
python-curl-cffi PKGBUILD
# Maintainer: Neurognostic <[email protected]>
# Contributor: dllud <dllud riseup net>
_pipname=curl_cffi
pkgname=python-${_pipname//_/-}
pkgver=0.11.1
pkgrel=1
pkgdesc='Python FFI binding for curl-impersonate'
arch=(x86_64)
url='https://github.com/lexiforest/curl_cffi'
license=(MIT)
depends=(
libcurl-impersonate
python
python-certifi
python-cffi
python-eventlet
python-gevent
python-typing_extensions
)
optdepends=('python-orjson: for speed and memory optimized JSON parsing')
makedepends=(
gcc13
python-build
python-installer
python-setuptools
python-wheel
python-python-multipart
unzip
)
source=(
$pkgname-$pkgver.tar.gz::$url/releases/download/v$pkgver/$_pipname-$pkgver.tar.gz
use-system-libs.patch
)
sha256sums=(
'e6d7aefd659a614bebaafd8a895d160b65429ce49a7460c99014424a04ac30f3'
'e631a03ae6bb8830b5f79f46aef2d72781f19ac8dde175f4e3c068fbdd520318'
)
prepare() {
patch -d $_pipname-$pkgver -p1 -i ../use-system-libs.patch
cd $_pipname-$pkgver
make preprocess
}
build() {
cd $_pipname-$pkgver
# TODO: remove gcc13 from makedepends when upstream gets resolved
# https://github.com/lexiforest/curl_cffi/issues/473
export CC=gcc-13 CXX=g++-13
python -m build --wheel --no-isolation
}
package() {
cd $_pipname-$pkgver
python -m installer --destdir="$pkgdir" dist/*.whl
# Symlink license file
local site_packages=$(python -c 'import site;print(site.getsitepackages()[0])')
install -d "$pkgdir/usr/share/licenses/$pkgname"
ln -s "$site_packages/$_pipname-$pkgver.dist-info/LICENSE" \
"$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
diff --git a/scripts/build.py b/scripts/build.py
index e21085c..1336176 100644
--- a/scripts/build.py
+++ b/scripts/build.py
@@ -1,152 +1,21 @@
-import json
-import os
-import platform
-import shutil
-import struct
-import tempfile
-from glob import glob
from pathlib import Path
-from urllib.request import urlretrieve
from cffi import FFI
# this is the upstream libcurl-impersonate version
__version__ = "1.0.0"
-
-def detect_arch():
- with open(Path(__file__).parent.parent / "libs.json") as f:
- archs = json.loads(f.read())
-
- uname = platform.uname()
- glibc_flavor = "gnueabihf" if uname.machine in ["armv7l", "armv6l"] else "gnu"
-
- libc, _ = platform.libc_ver()
- # https://github.com/python/cpython/issues/87414
- libc = glibc_flavor if libc == "glibc" else "musl"
- pointer_size = struct.calcsize("P") * 8
-
- for arch in archs:
- if (
- arch["system"] == uname.system
- and arch["machine"] == uname.machine
- and arch["pointer_size"] == pointer_size
- and ("libc" not in arch or arch.get("libc") == libc)
- ):
- if arch["libdir"]:
- arch["libdir"] = os.path.expanduser(arch["libdir"])
- else:
- global tmpdir
- if "CI" in os.environ:
- tmpdir = "./tmplibdir"
- os.makedirs(tmpdir, exist_ok=True)
- arch["libdir"] = tmpdir
- else:
- tmpdir = tempfile.TemporaryDirectory()
- arch["libdir"] = tmpdir.name
- return arch
- raise Exception(f"Unsupported arch: {uname}")
-
-
-arch = detect_arch()
-print(f"Using {arch['libdir']} to store libcurl-impersonate")
-
-
-def download_libcurl():
- if (Path(arch["libdir"]) / arch["so_name"]).exists():
- print(".so files already downloaded.")
- return
-
- file = "libcurl-impersonate.tar.gz"
- sysname = "linux-" + arch["libc"] if arch["system"] == "Linux" else arch["sysname"]
-
- url = (
- f"https://github.com/lexiforest/curl-impersonate/releases/download/"
- f"v{__version__}/libcurl-impersonate-v{__version__}"
- f".{arch['so_arch']}-{sysname}.tar.gz"
- )
-
- print(f"Downloading libcurl-impersonate from {url}...")
- urlretrieve(url, file)
-
- print("Unpacking downloaded files...")
- os.makedirs(arch["libdir"], exist_ok=True)
- shutil.unpack_archive(file, arch["libdir"])
-
- if arch["system"] == "Windows":
- for file in glob(os.path.join(arch["libdir"], "lib/*.lib")):
- shutil.move(file, arch["libdir"])
- for file in glob(os.path.join(arch["libdir"], "bin/*.dll")):
- shutil.move(file, arch["libdir"])
-
- print("Files after unpacking")
- print(os.listdir(arch["libdir"]))
-
-
-def get_curl_archives():
- print("Files for linking")
- print(os.listdir(arch["libdir"]))
- if arch["system"] == "Linux" and arch.get("link_type") == "static":
- # note that the order of libraries matters
- # https://stackoverflow.com/a/36581865
- return [
- f"{arch['libdir']}/libcurl-impersonate.a",
- f"{arch['libdir']}/libssl.a",
- f"{arch['libdir']}/libcrypto.a",
- f"{arch['libdir']}/libz.a",
- f"{arch['libdir']}/libzstd.a",
- f"{arch['libdir']}/libnghttp2.a",
- f"{arch['libdir']}/libngtcp2.a",
- f"{arch['libdir']}/libngtcp2_crypto_boringssl.a",
- f"{arch['libdir']}/libnghttp3.a",
- f"{arch['libdir']}/libbrotlidec.a",
- f"{arch['libdir']}/libbrotlienc.a",
- f"{arch['libdir']}/libbrotlicommon.a",
- ]
- else:
- return []
-
-
-def get_curl_libraries():
- if arch["system"] == "Windows":
- return [
- "Crypt32",
- "Secur32",
- "wldap32",
- "Normaliz",
- "libcurl",
- "zstd",
- "zlib",
- "ssl",
- "nghttp2",
- "crypto",
- "brotlienc",
- "brotlidec",
- "brotlicommon",
- ]
- elif arch["system"] == "Darwin" or (
- arch["system"] == "Linux" and arch.get("link_type") == "dynamic"
- ):
- return ["curl-impersonate"]
- else:
- return []
-
-
ffibuilder = FFI()
-system = platform.system()
root_dir = Path(__file__).parent.parent
-download_libcurl()
-
ffibuilder.set_source(
"curl_cffi._wrapper",
"""
#include "shim.h"
""",
- # FIXME from `curl-impersonate`
- libraries=get_curl_libraries(),
- extra_objects=get_curl_archives(),
- library_dirs=[arch["libdir"]],
+ libraries=["curl-impersonate"],
+ extra_objects=[],
+ library_dirs=["/usr/lib"],
source_extension=".c",
include_dirs=[
str(root_dir / "include"),
@@ -155,10 +24,8 @@ ffibuilder.set_source(
sources=[
str(root_dir / "ffi/shim.c"),
],
- extra_compile_args=(
- ["-Wno-implicit-function-declaration"] if system == "Darwin" else []
- ),
- extra_link_args=(["-lstdc++"] if system != "Windows" else []),
+ extra_compile_args=[],
+ extra_link_args=["-lstdc++"],
)
with open(root_dir / "ffi/cdef.c") as f:
@@ -167,4 +34,4 @@ with open(root_dir / "ffi/cdef.c") as f:
if __name__ == "__main__":
- ffibuilder.compile(verbose=False)
+ ffibuilder.compile(verbose=True)
@Samy879
Copy link

Samy879 commented Aug 3, 2024

Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment