Skip to content

feat: small command line helpers for quick tests #4272

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

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
44 changes: 42 additions & 2 deletions pybind11/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
import argparse
import sys
import sysconfig
from pathlib import Path

from .commands import get_cmake_dir, get_include, get_pkgconfig_dir
from .commands import (
get_cflags,
get_cmake_dir,
get_extension,
get_include,
get_ldflags,
get_pkgconfig_dir,
)


def print_includes() -> None:
Expand Down Expand Up @@ -41,11 +49,43 @@ def main() -> None:
action="store_true",
help="Print the pkgconfig directory, ideal for setting $PKG_CONFIG_PATH.",
)
parser.add_argument(
"--cflags",
action="store_true",
help="Print the simple compile flags",
)
parser.add_argument(
"--ldflags",
action="store_true",
help="Print the simple link flags",
)
parser.add_argument(
"--embed",
action="store_true",
help="Show embed version instead of extension",
)
parser.add_argument(
"--file",
type=Path,
help="Print the suggested compile line for a given file",
)
args = parser.parse_args()
if not sys.argv[1:]:
parser.print_help()
if args.includes:
if args.cflags or args.file:
print(get_cflags(), end=" " if args.file else "\n")
elif args.includes and not args.file:
print_includes()
if args.file:
print(args.file.name, end=" ")
if args.ldflags or args.file:
print(get_ldflags(args.embed), end=" " if args.file else "\n")
if args.file:
if args.embed:
print("-o", args.file.with_suffix(""))
else:
print("-o", args.file.with_suffix(get_extension()))

if args.cmakedir:
print(get_cmake_dir())
if args.pkgconfigdir:
Expand Down
55 changes: 55 additions & 0 deletions pybind11/commands.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import os
import sys
import sysconfig
from typing import List

DIR = os.path.abspath(os.path.dirname(__file__))


def _getvar(varname: str, fmt: str = "{}") -> List[str]:
var = sysconfig.get_config_var(varname)
return [fmt.format(var.strip())] if var else []


def get_include(user: bool = False) -> str: # pylint: disable=unused-argument
"""
Return the path to the pybind11 include directory. The historical "user"
Expand Down Expand Up @@ -35,3 +43,50 @@ def get_pkgconfig_dir() -> str:

msg = "pybind11 not installed, installation required to access the pkgconfig files"
raise ImportError(msg)


def get_cflags() -> str:
"""
Gets the compile flags needed for a simple module.
"""

flags = f"-I{sysconfig.get_path('include')} -I{sysconfig.get_path('platinclude')} -I{get_include()}"
cflags = sysconfig.get_config_var("CFLAGS")
if cflags:
flags += " " + cflags
flags += " -std=c++11"
return flags


def get_ldflags(embed: bool) -> str:
"""
Get the linker flags needed for a simple module.
"""

flags = _getvar("LDFLAGS")

if embed:
flags += _getvar("LIBIDR", "-L{}")
shared = sysconfig.get_config_var("Py_ENABLE_SHARED")
if shared and shared != "0":
flags += _getvar("LIBPL", "-L{}")
pyver = sysconfig.get_config_var("VERSION") or ""
flags += [f"-lpython{pyver}{sys.abiflags}"]

flags += _getvar("LIBS")
flags += _getvar("SYSLIBS")
else:
if sys.platform.startswith("darwin"):
flags += ["-undefined dynamic_lookup", "-shared"]
elif sys.platform.startswith("linux"):
flags += ["-fPIC", "-shared"]

return " ".join(flags)


def get_extension() -> str:
"""
Get the extension suffix on this platform
"""

return sysconfig.get_config_var("EXT_SUFFIX") or ""