Skip to content

Support using system llhttp library #10760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES/10759.packaging.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Added support for building against system ``llhttp`` library -- by :user:`mgorny`.

This change adds support for :envvar:`AIOHTTP_USE_SYSTEM_DEPS` environment variable that
can be used to build aiohttp against the system install of the ``llhttp`` library rather
than the vendored one.
2 changes: 1 addition & 1 deletion aiohttp/_cparser.pxd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from libc.stdint cimport int32_t, uint8_t, uint16_t, uint64_t


cdef extern from "../vendor/llhttp/build/llhttp.h":
cdef extern from "llhttp.h":

struct llhttp__internal_s:
int32_t _index
Expand Down
11 changes: 11 additions & 0 deletions docs/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@
Environment Variables
=====================

.. envvar:: AIOHTTP_NO_EXTENSIONS

If set to a non-empty value while building from source, aiohttp will be built without speedups
written as C extensions. This option is primarily useful for debugging.

.. envvar:: AIOHTTP_USE_SYSTEM_DEPS

If set to a non-empty value while building from source, aiohttp will be built against
the system installation of llhttp rather than the vendored library. This option is primarily
meant to be used by downstream redistributors.

.. envvar:: NETRC

If set, HTTP Basic Auth will be read from the file pointed to by this environment variable,
Expand Down
1 change: 1 addition & 0 deletions docs/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ kwargs
latin
lifecycle
linux
llhttp
localhost
Locator
login
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[build-system]
requires = [
"pkgconfig",
"setuptools >= 46.4.0",
]
build-backend = "setuptools.build_meta"
Expand Down
1 change: 1 addition & 0 deletions requirements/test.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ coverage
freezegun
isal
mypy; implementation_name == "cpython"
pkgconfig
proxy.py >= 2.4.4rc5
pytest
pytest-cov
Expand Down
37 changes: 31 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
raise RuntimeError("aiohttp 4.x requires Python 3.9+")


USE_SYSTEM_DEPS = bool(
os.environ.get("AIOHTTP_USE_SYSTEM_DEPS", os.environ.get("USE_SYSTEM_DEPS"))
)
NO_EXTENSIONS: bool = bool(os.environ.get("AIOHTTP_NO_EXTENSIONS"))
HERE = pathlib.Path(__file__).parent
IS_GIT_REPO = (HERE / ".git").exists()
Expand All @@ -17,7 +20,11 @@
NO_EXTENSIONS = True


if IS_GIT_REPO and not (HERE / "vendor/llhttp/README.md").exists():
if (
not USE_SYSTEM_DEPS
and IS_GIT_REPO
and not (HERE / "vendor/llhttp/README.md").exists()
):
print("Install submodules when building from git clone", file=sys.stderr)
print("Hint:", file=sys.stderr)
print(" git submodule update --init", file=sys.stderr)
Expand All @@ -26,19 +33,37 @@

# NOTE: makefile cythonizes all Cython modules

if USE_SYSTEM_DEPS:
import shlex

import pkgconfig

llhttp_sources = []
llhttp_kwargs = {
"extra_compile_args": shlex.split(pkgconfig.cflags("libllhttp")),
"extra_link_args": shlex.split(pkgconfig.libs("libllhttp")),
}
else:
llhttp_sources = [
"vendor/llhttp/build/c/llhttp.c",
"vendor/llhttp/src/native/api.c",
"vendor/llhttp/src/native/http.c",
]
llhttp_kwargs = {
"define_macros": [("LLHTTP_STRICT_MODE", 0)],
"include_dirs": ["vendor/llhttp/build"],
}

extensions = [
Extension("aiohttp._websocket.mask", ["aiohttp/_websocket/mask.c"]),
Extension(
"aiohttp._http_parser",
[
"aiohttp/_http_parser.c",
"aiohttp/_find_header.c",
"vendor/llhttp/build/c/llhttp.c",
"vendor/llhttp/src/native/api.c",
"vendor/llhttp/src/native/http.c",
*llhttp_sources,
],
define_macros=[("LLHTTP_STRICT_MODE", 0)],
include_dirs=["vendor/llhttp/build"],
**llhttp_kwargs,
),
Extension("aiohttp._http_writer", ["aiohttp/_http_writer.c"]),
Extension("aiohttp._websocket.reader_c", ["aiohttp/_websocket/reader_c.c"]),
Expand Down
Loading