# SPDX-FileCopyrightText: Copyright (c) 2022-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import platform import re import subprocess import sys from pathlib import Path from setuptools import find_namespace_packages, find_packages, setup from setuptools.dist import Distribution def parse_requirements(filename: os.PathLike): with open(filename) as f: requirements = f.read().splitlines() def extract_url(line): return next(filter(lambda x: x[0] != '-', line.split())) extra_URLs = [] deps = [] for line in requirements: if line.startswith("#") or line.startswith("-r") or line.startswith( "-c"): continue # handle -i and --extra-index-url options if "-i " in line or "--extra-index-url" in line: extra_URLs.append(extract_url(line)) # handle URLs such as git+https://github.com/flashinfer-ai/flashinfer.git@e3853dd#egg=flashinfer-python elif line.startswith("git+https"): idx = line.find("egg=") dep = line[idx + 4:] deps.append(dep) else: deps.append(line) return deps, extra_URLs def sanity_check(): tensorrt_llm_path = Path(__file__).resolve().parent / "tensorrt_llm" for config_kind in ("config", "disagg-config", "visual-gen-config"): schema = tensorrt_llm_path / "schemas" / f"trtllm-serve-{config_kind}.schema.json" if not schema.is_file(): raise ImportError( f"Missing configuration schema: {schema}. Restore the checked-in " "schema files, or regenerate them with " "python3 scripts/generate_trtllm_serve_schemas.py " "using a matching TensorRT-LLM build before packaging.") if not (tensorrt_llm_path / "bindings").exists(): raise ImportError( 'The `bindings` module does not exist. Please check the package integrity. ' 'If you are attempting to use the pip development mode (editable installation), ' 'please execute `scripts/build_wheel.py` first, and then run `pip install -e .`.' ) if not (Path(__file__).resolve().parent / "3rdparty" / "fmha_sm100").is_dir(): raise ImportError( 'The `fmha_sm100` package is missing. Please execute ' '`scripts/build_wheel.py` first (CMake FetchContent stages it under ' '3rdparty/fmha_sm100), or use TRTLLM_USE_PRECOMPILED to extract it ' 'from a published wheel.') if not (tensorrt_llm_path / "grpc" / "openengine" / "_generated" / "openengine_pb2.py").is_file(): raise ImportError( 'The checked-in private OpenEngine bindings are missing. Please check the package integrity.' ) def get_version(): version_file = Path( __file__).resolve().parent / "tensorrt_llm" / "version.py" version = None with open(version_file) as f: for line in f: if not line.startswith("__version__"): continue version = line.split('"')[1] if version is None: raise RuntimeError(f"Could not set version from {version_file}") # For develop / editable installs (`pip install -e .` or # `python setup.py develop`), append the git commit hash as a PEP 440 # local version segment so the installed package is identifiable, # e.g. "1.3.0rc21+58d8964d13". is_develop = any(arg in sys.argv for arg in ("develop", "editable_wheel")) if is_develop: try: commit = subprocess.check_output( ["git", "rev-parse", "--short=10", "HEAD"], cwd=Path(__file__).resolve().parent, stderr=subprocess.DEVNULL).decode().strip() except (subprocess.CalledProcessError, FileNotFoundError, OSError): commit = "" commit = re.sub(r"[^A-Za-z0-9.]", "", commit) if commit: version = f"{version}+{commit}" return version def get_project_urls() -> dict[str, str]: source_commit = os.getenv("TRTLLM_BUILD_SOURCE_COMMIT") if not source_commit: return {} return { "Source Commit": f"https://github.com/NVIDIA/TensorRT-LLM/commit/{source_commit}", } def get_license(): """Get license files for the wheel package. Prefers auto-generated ATTRIBUTIONS.md (copied to project root by build_wheel.py) when available, falling back to hard-coded platform-specific attribution files. """ import sysconfig # Check for auto-generated attributions (copied to project root by build_wheel.py) auto_generated_attributions = Path("ATTRIBUTIONS.md") if auto_generated_attributions.exists(): return ["LICENSE", "ATTRIBUTIONS.md"] # Fall back to hard-coded platform-specific attribution files platform_tag = sysconfig.get_platform() if "x86_64" in platform_tag: return ["LICENSE", "ATTRIBUTIONS-CPP-x86_64.md"] elif "arm64" in platform_tag or "aarch64" in platform_tag: return ["LICENSE", "ATTRIBUTIONS-CPP-aarch64.md"] else: raise RuntimeError(f"Unrecognized CPU architecture: {platform_tag}") class BinaryDistribution(Distribution): """Distribution which always forces a binary package with platform name""" def has_ext_modules(self): return True on_windows = platform.system() == "Windows" required_deps, extra_URLs = parse_requirements( Path("requirements-windows.txt" if on_windows else "requirements.txt")) devel_deps, _ = parse_requirements( Path("requirements-dev-windows.txt" if on_windows else "requirements-dev.txt")) mx_deps = ["modelexpress>=0.5.1,<0.6.0"] # OpenEngine's private schema bindings ship in this wheel and use the base # grpcio dependency; its empty extra remains an install-compatible feature # marker. SMG still consumes its external generated package. grpc_smg_deps, _ = parse_requirements(Path("requirements-grpc-smg.txt")) constraints_file = Path("constraints.txt") if constraints_file.exists(): constraints, _ = parse_requirements(constraints_file) required_deps.extend(constraints) if on_windows: package_data = [ 'libs/th_common.dll', 'libs/tensorrt_llm.dll', 'bindings.*.pyd', "include/**/*" ] else: package_data = [ 'libs/libtensorrt_llm.so', 'libs/libth_common.so', 'libs/libtensorrt_llm_ucx_wrapper.so', 'libs/libdecoder_attention_0.so', 'libs/libtensorrt_llm_nixl_wrapper.so', 'libs/nixl/**/*', 'tensorrt_llm_transfer_agent_binding*.so', 'tensorrt_llm_transfer_agent_binding.pyi', 'libs/libtensorrt_llm_mooncake_wrapper.so', 'libs/ucx/**/*', 'libs/libpg_utils.so', 'libs/libdecoder_attention_1.so', 'libs/nvshmem/License.txt', 'libs/nvshmem/nvshmem_bootstrap_uid.so.3', 'libs/nvshmem/nvshmem_transport_ibgda.so.103', 'bindings.*.so', 'deep_ep/LICENSE', 'deep_ep/*.py', 'deep_ep_cpp_tllm.*.so', "include/**/*", 'deep_gemm/LICENSE', 'deep_gemm/include/**/*', 'deep_gemm/*.py', 'deep_gemm_cpp_tllm.*.so', 'flash_mla/LICENSE', 'flash_mla/*.py', 'flash_mla_cpp_tllm.*.so', ] package_data += [ 'bindings/*.pyi', 'bindings/**/*.pyi', 'evaluate/lm_eval_tasks/**/*', 'schemas/*.json', 'usage/schemas/*.json', 'grpc/openengine/_generated/*.pyi', 'grpc/openengine/proto/manifest.json', 'grpc/openengine/proto/openengine/v1/*.proto', ] def download_precompiled(workspace: str, version: str) -> str: import glob import subprocess from setuptools.errors import SetupError cmd = [ "python3", "-m", "pip", "download", f"tensorrt_llm=={version}", f"--dest={workspace}", "--no-deps", "--extra-index-url=https://pypi.nvidia.com" ] try: subprocess.check_call(cmd) wheel_path = glob.glob(f"{workspace}/tensorrt_llm-*.whl")[0] except Exception as e: raise SetupError( "Failed to download the automatically resolved wheel, please try specifying TRTLLM_USE_PRECOMPILED with a link or local path to a valid wheel." ) from e else: return wheel_path def should_skip_precompiled_package_data(filename: str) -> bool: """Return True for source-owned package data kept from local checkout. Precompiled wheels own native bits. Source owns configuration/telemetry schemas and the OpenEngine contract. Skip those wheel files so Python-only edits layer over old wheels and tracked bindings from the current checkout remain authoritative. """ filename = filename.replace("\\", "/") if filename.startswith( ("tensorrt_llm/schemas/", "tensorrt_llm/usage/schemas/")): return filename.endswith(".json") return filename.startswith(( "tensorrt_llm/grpc/openengine/_generated/", "tensorrt_llm/grpc/openengine/proto/", )) def warn_on_build_skew(precompiled_location: str) -> None: """Warn when the source checkout differs from this one where it matters. The precompiled artifacts are reused as they are, never rebuilt, so any difference in what feeds the native build makes them stale. This is advisory: it never fails the install, since the two checkouts are often meant to differ (that is the point of reusing a build) and only some of those differences matter. """ import subprocess NATIVE_BUILD_INPUTS = [ "cpp/", "3rdparty/", "setup.py", "scripts/build_wheel.py", "requirements.txt" ] def head_of(checkout: str) -> str | None: try: done = subprocess.run(["git", "-C", checkout, "rev-parse", "HEAD"], capture_output=True, text=True, check=True) except (OSError, subprocess.SubprocessError): return None return done.stdout.strip() or None source_head = head_of(precompiled_location) current_head = head_of(".") if source_head is None or current_head is None: print("Cannot check for build skew: one of the two checkouts is not a " "git repository. Make sure the precompiled artifacts were built " "from these sources.") return if source_head == current_head: return stale = ("Import errors mentioning 'rebuild and install' after this may be " "ABI skew; rebuild, or pick a precompiled source that matches.") try: # Both revisions are reachable here when the two checkouts are # worktrees of one clone, which is the case this is meant to catch. done = subprocess.run( ["git", "diff", "--name-only", source_head, current_head, "--"] + NATIVE_BUILD_INPUTS, capture_output=True, text=True, check=True) except (OSError, subprocess.SubprocessError): print( f"WARNING: the precompiled artifacts come from {source_head[:12]} " f"but this checkout is {current_head[:12]}, and the difference " f"could not be inspected from here. {stale}") return changed = done.stdout.split() if not changed: return shown = ", ".join(changed[:3]) if len(changed) > 3: shown += ", ..." count = f"{len(changed)} file" + ("s" if len(changed) > 1 else "") print( f"WARNING: the precompiled artifacts come from {source_head[:12]} but " f"this checkout is {current_head[:12]}; {count} feeding the " f"native build changed ({shown}). {stale}") def extract_from_precompiled(precompiled_location: str, package_data: list[str], workspace: str) -> None: """Extract package data (binaries and other materials) from a precompiled wheel or local directory to the working directory. This allows skipping the compilation, and repackaging the binaries and Python files in the working directory to a new wheel. Supports three source types: - Local directory (git clone structure): e.g., /home/dev/TensorRT-LLM - Local wheel file: e.g., /path/to/tensorrt_llm-*.whl - Remote URL: Downloads and extracts from URL (wheel or tar.gz) With TRTLLM_PRECOMPILED_LINK=1 a local directory is symlinked instead of copied, so several checkouts can share one build tree. """ import fnmatch import shutil import tarfile import zipfile from urllib.request import urlretrieve from setuptools.errors import SetupError # Only a local directory can be linked; a wheel or a URL has no build tree # to point at. link_artifacts = os.getenv("TRTLLM_PRECOMPILED_LINK", "0") not in ("", "0") if link_artifacts and not os.path.isdir(precompiled_location): raise SetupError( "TRTLLM_PRECOMPILED_LINK=1 requires TRTLLM_PRECOMPILED_LOCATION to " "be a local directory in git-clone layout, but got " f"{precompiled_location}.") # Linking a checkout onto itself would unlink the real artifacts and # replace them with symlinks that point to themselves, destroying the # build tree this mode is meant to share. if link_artifacts and os.path.realpath( precompiled_location) == os.path.realpath("."): raise SetupError( "TRTLLM_PRECOMPILED_LINK=1 needs a source checkout separate from " "this one, but TRTLLM_PRECOMPILED_LOCATION resolves to the current " "directory.") # Handle local directory (assuming repo structure) if os.path.isdir(precompiled_location): precompiled_location = os.path.abspath(precompiled_location) print( f"Using local directory as precompiled source: {precompiled_location}" ) warn_on_build_skew(precompiled_location) source_tensorrt_llm = os.path.join(precompiled_location, "tensorrt_llm") if not os.path.isdir(source_tensorrt_llm): raise SetupError( f"Directory {precompiled_location} does not contain a tensorrt_llm folder." ) # Walk through all files and match using fnmatch (consistent with wheel extraction) for root, dirs, files in os.walk(source_tensorrt_llm): for filename in files: src_file = os.path.join(root, filename) # Get path relative to precompiled_location (e.g., "tensorrt_llm/libs/libtensorrt_llm.so") rel_path = os.path.relpath(src_file, precompiled_location) dst_file = rel_path # Skip yaml files if dst_file.endswith(".yaml"): continue # Keep source-owned package data local so Python-only schema edits # layer over precompiled wheels. if should_skip_precompiled_package_data(dst_file): continue # Skip .py files EXCEPT for generated C++ extension wrappers # (deep_gemm, deep_ep, flash_mla Python files are generated during build) if dst_file.endswith(".py"): allowed_dirs = ("tensorrt_llm/deep_gemm/", "tensorrt_llm/deep_ep/", "tensorrt_llm/flash_mla/") if not any(dst_file.startswith(d) for d in allowed_dirs): continue # Check if file matches any pattern using fnmatch (same as wheel extraction) for filename_pattern in package_data: if fnmatch.fnmatchcase(rel_path, f"tensorrt_llm/{filename_pattern}"): break else: continue dst_dir = os.path.dirname(dst_file) if dst_dir: os.makedirs(dst_dir, exist_ok=True) if link_artifacts: if os.path.lexists(dst_file): os.unlink(dst_file) print(f"Linking {rel_path} from local directory.") os.symlink(os.path.abspath(src_file), dst_file) else: print(f"Copying {rel_path} from local directory.") # Drop a stale symlink from a prior link-mode run so # copy2 writes a real file instead of following the link # into the shared build tree. if os.path.islink(dst_file): os.unlink(dst_file) shutil.copy2(src_file, dst_file) source_fmha = os.path.join(precompiled_location, "3rdparty", "fmha_sm100") if not os.path.isdir(source_fmha): raise SetupError( f"Precompiled directory {precompiled_location} predates MSA " "packaging and does not contain 3rdparty/fmha_sm100. Use a " "precompiled source built with MSA packaging support.") dst_fmha = os.path.join("3rdparty", "fmha_sm100") if link_artifacts: if os.path.islink(dst_fmha) and os.path.realpath( dst_fmha) == os.path.realpath(source_fmha): # Already points at this source; leave the shared link alone. print(f"Keeping existing fmha_sm100 symlink: {dst_fmha}") else: # A stale link (pointing at a different source) or a real # directory: replace it so fmha_sm100 tracks the same source # as the other linked artifacts. if os.path.islink(dst_fmha): os.unlink(dst_fmha) elif os.path.isdir(dst_fmha): shutil.rmtree(dst_fmha) # copytree() creates the parent below; os.symlink() does not. os.makedirs(os.path.dirname(dst_fmha), exist_ok=True) print(f"Linking fmha_sm100 from local directory: {source_fmha}") os.symlink(source_fmha, dst_fmha) else: print(f"Copying fmha_sm100 from local directory: {source_fmha}") if os.path.islink(dst_fmha): os.unlink(dst_fmha) elif os.path.isdir(dst_fmha): shutil.rmtree(dst_fmha) shutil.copytree(source_fmha, dst_fmha) source_nccl_extensions = os.path.join(precompiled_location, "3rdparty", "nccl_extensions") if os.path.isdir(source_nccl_extensions): dst_nccl_extensions = os.path.join("3rdparty", "nccl_extensions") if link_artifacts: if os.path.islink(dst_nccl_extensions) and os.path.realpath( dst_nccl_extensions) == os.path.realpath( source_nccl_extensions): print("Keeping existing NCCL-EP symlink: " f"{dst_nccl_extensions}") else: if os.path.islink(dst_nccl_extensions): os.unlink(dst_nccl_extensions) elif os.path.isdir(dst_nccl_extensions): shutil.rmtree(dst_nccl_extensions) os.makedirs(os.path.dirname(dst_nccl_extensions), exist_ok=True) print("Linking embedded NCCL-EP packages from local " f"directory: {source_nccl_extensions}") os.symlink(source_nccl_extensions, dst_nccl_extensions) else: print("Copying embedded NCCL-EP packages from local directory: " f"{source_nccl_extensions}") if os.path.islink(dst_nccl_extensions): os.unlink(dst_nccl_extensions) elif os.path.isdir(dst_nccl_extensions): shutil.rmtree(dst_nccl_extensions) shutil.copytree(source_nccl_extensions, dst_nccl_extensions) else: print("Precompiled directory does not contain embedded NCCL-EP " "packages; continuing without NCCL-EP.") return # Handle local file or remote URL if os.path.isfile(precompiled_location): precompiled_path = precompiled_location print(f"Using local precompiled file: {precompiled_path}.") else: precompiled_filename = precompiled_location.split("/")[-1] precompiled_path = os.path.join(workspace, precompiled_filename) print( f"Downloading precompiled file from {precompiled_location} to {precompiled_path}." ) try: urlretrieve(precompiled_location, filename=precompiled_path) except Exception as e: raise SetupError( f"Failed to get precompiled file from {precompiled_location}." ) from e if precompiled_path.endswith("tar.gz"): with tarfile.open(precompiled_path, "r:gz") as tar: for member in tar.getmembers(): if fnmatch.fnmatchcase(member.name, "TensorRT-LLM/tensorrt_llm-*.whl"): break else: raise SetupError( f"Failed to get wheel file from {precompiled_path}.") wheel_path = os.path.join(workspace, member.name) tar.extract(member, path=workspace, filter=tarfile.data_filter) else: wheel_path = precompiled_path with zipfile.ZipFile(wheel_path) as wheel: dst_fmha = os.path.join("3rdparty", "fmha_sm100") wheel_has_fmha = any( file.filename.startswith("fmha_sm100/") for file in wheel.filelist) if not wheel_has_fmha: raise SetupError( f"Precompiled wheel {wheel_path} predates MSA packaging and " "does not contain fmha_sm100. Use a precompiled wheel built " "with MSA packaging support.") if os.path.islink(dst_fmha): os.unlink(dst_fmha) elif os.path.isdir(dst_fmha): shutil.rmtree(dst_fmha) dst_nccl_extensions = os.path.join("3rdparty", "nccl_extensions") if os.path.islink(dst_nccl_extensions): os.unlink(dst_nccl_extensions) elif os.path.isdir(dst_nccl_extensions): shutil.rmtree(dst_nccl_extensions) for file in wheel.filelist: # Skip yaml files if file.filename.endswith(".yaml"): continue # Keep source-owned package data local so Python-only schema edits # layer over precompiled wheels. if should_skip_precompiled_package_data(file.filename): continue # Top-level MSA package in the wheel; stage under 3rdparty for # setuptools package_dir, matching scripts/build_wheel.py. if file.filename.startswith("fmha_sm100/"): print( f"Extracting and including {file.filename} from precompiled wheel." ) wheel.extract(file, path="3rdparty") continue # NCCL-EP is a top-level namespace package in the wheel. Stage it # beneath 3rdparty for package_dir, matching build_wheel.py. if file.filename.startswith(("nccl/ep/", "nccl/_extensions/")): print( f"Extracting and including {file.filename} from precompiled wheel." ) wheel.extract(file, path=dst_nccl_extensions) continue # Skip .py files EXCEPT for generated C++ extension wrappers # (deep_gemm, deep_ep, flash_mla Python files are generated during build) if file.filename.endswith(".py"): allowed_dirs = ( "tensorrt_llm/deep_gemm/", "tensorrt_llm/deep_ep/", "tensorrt_llm/flash_mla/", ) if not any(file.filename.startswith(d) for d in allowed_dirs): continue for filename_pattern in package_data: if fnmatch.fnmatchcase(file.filename, f"tensorrt_llm/{filename_pattern}"): break else: continue print( f"Extracting and including {file.filename} from precompiled wheel." ) wheel.extract(file) precompiled: str | None = os.getenv("TRTLLM_USE_PRECOMPILED") precompiled_location: str | None = os.getenv("TRTLLM_PRECOMPILED_LOCATION") use_precompiled: bool = (precompiled is not None and precompiled != "0") or (precompiled_location is not None) if use_precompiled: from tempfile import TemporaryDirectory with TemporaryDirectory() as tempdir: if not precompiled_location: version = precompiled if precompiled != "1" else get_version() precompiled_location = download_precompiled(tempdir, version) extract_from_precompiled(precompiled_location, package_data, tempdir) sanity_check() with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() packages = find_packages() exclude_package_data = {} # Add vendored triton_kernels as an explicit top-level package. # This is vendored from the Triton project and kept at repo root so its # internal absolute imports (e.g., "from triton_kernels.foo import bar") work. packages += find_packages(include=["triton_kernels", "triton_kernels.*"]) # fmha_sm100 is staged under 3rdparty/ by scripts/build_wheel.py from the # CMake FetchContent tree (same packaging role as tensorrt_llm/deep_ep). package_dirs = {"fmha_sm100": "3rdparty/fmha_sm100"} packages += ["fmha_sm100"] # NCCL-EP is staged from the source-built nccl-extensions wheel under # 3rdparty/. Its ``nccl`` package is a namespace shared with nccl4py, so # register only its staged namespace subpackages and preserve nccl4py core. nccl_extensions_root = Path("3rdparty/nccl_extensions") nccl_extensions_package_data = {} if (nccl_extensions_root / "nccl").is_dir(): packages += find_namespace_packages( where=str(nccl_extensions_root), include=("nccl.ep", "nccl.ep.*", "nccl._extensions", "nccl._extensions.*"), ) package_dirs["nccl"] = str(nccl_extensions_root / "nccl") nccl_extensions_package_data = { "nccl.ep": ["lib/*.so", "include/**/*"], "nccl._extensions.bindings": ["*.so", "_internal/*.so"], "nccl._extensions.bindings._internal": ["*.so"], } def get_build_state_options(): """Optionally redirect setuptools build state out of the source tree. When TRTLLM_WHEEL_STAGING_DIR is set (e.g. by scripts/build_wheel.py --build_root), the setuptools staging tree (build/) and *.egg-info are written there instead of into the checkout. This keeps metadata-heavy churn off slow network filesystems; behavior is unchanged when unset. """ staging_dir = os.environ.get("TRTLLM_WHEEL_STAGING_DIR") if not staging_dir: return {} staging = Path(staging_dir) egg_base = staging / "egg-info" egg_base.mkdir(parents=True, exist_ok=True) return { "build": { "build_base": str(staging / "build") }, "egg_info": { "egg_base": str(egg_base) }, } # https://setuptools.pypa.io/en/latest/references/keywords.html setup( name='tensorrt_llm', version=get_version(), description= ('TensorRT LLM provides users with an easy-to-use Python API to define Large Language Models (LLMs) and supports ' 'state-of-the-art optimizations to perform inference efficiently on NVIDIA GPUs.' ), long_description=long_description, long_description_content_type="text/markdown", author="NVIDIA Corporation", url="https://github.com/NVIDIA/TensorRT-LLM", download_url="https://github.com/NVIDIA/TensorRT-LLM/tags", packages=packages, package_dir=package_dirs, exclude_package_data=exclude_package_data, # TODO Add windows support for python bindings. classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.12", ], distclass=BinaryDistribution, options=get_build_state_options(), license="Apache License 2.0", keywords="nvidia tensorrt deeplearning inference", package_data={ 'tensorrt_llm': package_data, 'triton_kernels': ['LICENSE', 'VERSION', 'README.md'], 'fmha_sm100': [ '*.py', 'csrc/**/*', 'cute/**/*', 'cutlass/include/**/*', 'cutlass/tools/util/include/**/*', 'cutlass/LICENSE.txt', ], **nccl_extensions_package_data, }, license_files=get_license(), entry_points={ 'console_scripts': [ 'trtllm-bench=tensorrt_llm.commands.bench:main', 'trtllm-serve=tensorrt_llm.commands.serve:main', 'trtllm-eval=tensorrt_llm.commands.eval:main', 'trtllm-render=tensorrt_llm.serve.render.__main__:main' ], }, scripts=[ 'tensorrt_llm/llmapi/trtllm-llmapi-launch', 'tensorrt_llm/llmapi/_llmapi_process_guard.py', ], extras_require={ "devel": devel_deps + grpc_smg_deps, "openengine": [], "mx": mx_deps, "grpc-smg": grpc_smg_deps, }, zip_safe=True, install_requires=required_deps, dependency_links= extra_URLs, # Warning: Dependency links support has been dropped by pip 19.0 python_requires=">=3.10, <4", project_urls=get_project_urls())