-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathcommands.py
More file actions
140 lines (110 loc) · 4.48 KB
/
Copy pathcommands.py
File metadata and controls
140 lines (110 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
from __future__ import annotations
import os
import re
import sys
DIR = os.path.abspath(os.path.dirname(__file__))
# shlex/sysconfig are imported lazily below to keep `import pybind11` light
# This is the conditional used for os.path being posixpath
if "posix" in sys.builtin_module_names:
def _quote(s: str) -> str:
import shlex
return shlex.quote(s)
elif "nt" in sys.builtin_module_names:
# See https://github.com/mesonbuild/meson/blob/db22551ed9d2dd7889abea01cc1c7bba02bf1c75/mesonbuild/utils/universal.py#L1092-L1121
# and the original documents:
# https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and
# https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
_UNSAFE = re.compile("[ \t\n\r]")
def _quote(s: str) -> str:
if s and not _UNSAFE.search(s):
return s
# Paths cannot contain a '"' on Windows, so we don't need to worry
# about nuanced counting here.
return f'"{s}\\"' if s.endswith("\\") else f'"{s}"'
else:
def _quote(s: str) -> str:
return s
def _config(name: str) -> str:
"""A stripped sysconfig variable, or "" if unset."""
import sysconfig
return str(sysconfig.get_config_var(name) or "").strip()
def get_include(user: bool = False) -> str: # noqa: ARG001
"""
Return the path to the pybind11 include directory. The historical "user"
argument is unused, and may be removed.
"""
installed_path = os.path.join(DIR, "include")
source_path = os.path.join(os.path.dirname(DIR), "include")
return installed_path if os.path.exists(installed_path) else source_path
def get_cmake_dir() -> str:
"""
Return the path to the pybind11 CMake module directory.
"""
cmake_installed_path = os.path.join(DIR, "share", "cmake", "pybind11")
if os.path.exists(cmake_installed_path):
return cmake_installed_path
msg = "pybind11 not installed, installation required to access the CMake files"
raise ImportError(msg)
def get_pkgconfig_dir() -> str:
"""
Return the path to the pybind11 pkgconfig directory.
"""
pkgconfig_installed_path = os.path.join(DIR, "share", "pkgconfig")
if os.path.exists(pkgconfig_installed_path):
return pkgconfig_installed_path
msg = "pybind11 not installed, installation required to access the pkgconfig files"
raise ImportError(msg)
def get_include_dirs() -> list[str]:
"""
Return the unique include directories for Python and pybind11.
"""
import sysconfig
dirs = [
sysconfig.get_path("include"),
sysconfig.get_path("platinclude"),
get_include(),
]
# Make unique but preserve order
unique_dirs = []
for d in dirs:
if d and d not in unique_dirs:
unique_dirs.append(d)
return unique_dirs
def get_cflags() -> str:
"""
Return the compile flags for building a simple extension with a
Unix-style command-line compiler (GCC/Clang). Based on python-config.
"""
flags = [_quote(f"-I{d}") for d in get_include_dirs()]
# CFLAGS is a pre-composed multi-flag string, passed through as-is (like
# python-config does)
if cflags := _config("CFLAGS"):
flags.append(cflags)
flags.append("-std=c++17")
return " ".join(flags)
def get_ldflags(embed: bool = False) -> str:
"""
Return the link flags for building a simple extension (or, with
embed=True, an embedding program) with a Unix-style command-line
compiler (GCC/Clang). Based on python-config.
"""
# LDFLAGS/LIBS/SYSLIBS are pre-composed multi-flag strings, passed
# through as-is (like python-config does)
flags = [ldflags] if (ldflags := _config("LDFLAGS")) else []
if embed:
if libdir := _config("LIBDIR"):
flags.append(_quote(f"-L{libdir}"))
if not _config("Py_ENABLE_SHARED") and (libpl := _config("LIBPL")):
flags.append(_quote(f"-L{libpl}"))
abiflags = getattr(sys, "abiflags", "") or ""
flags.append(f"-lpython{_config('VERSION')}{abiflags}")
if libs := _config("LIBS"):
flags.append(libs)
if syslibs := _config("SYSLIBS"):
flags.append(syslibs)
elif sys.platform.startswith("darwin"):
flags += ["-undefined", "dynamic_lookup", "-shared"]
elif os.name == "posix":
# Linux and other Unix platforms (FreeBSD, Solaris, AIX, ...)
flags += ["-fPIC", "-shared"]
return " ".join(flags)