Skip to content

Commit c421c66

Browse files
authored
bpo-36231: Support building on macOS without /usr/include (GH-13773) (GH-14256)
1 parent 598c756 commit c421c66

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Support building Python on macOS without /usr/include installed. As of macOS
2+
10.14, system header files are only available within an SDK provided by
3+
either the Command Line Tools or the Xcode app.

setup.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,57 @@ def add_dir_to_list(dirlist, dir):
4242
if dir is not None and os.path.isdir(dir) and dir not in dirlist:
4343
dirlist.insert(0, dir)
4444

45+
MACOS_SDK_ROOT = None
46+
4547
def macosx_sdk_root():
48+
"""Return the directory of the current macOS SDK.
49+
50+
If no SDK was explicitly configured, call the compiler to find which
51+
include files paths are being searched by default. Use '/' if the
52+
compiler is searching /usr/include (meaning system header files are
53+
installed) or use the root of an SDK if that is being searched.
54+
(The SDK may be supplied via Xcode or via the Command Line Tools).
55+
The SDK paths used by Apple-supplied tool chains depend on the
56+
setting of various variables; see the xcrun man page for more info.
4657
"""
47-
Return the directory of the current OSX SDK,
48-
or '/' if no SDK was specified.
49-
"""
58+
global MACOS_SDK_ROOT
59+
60+
# If already called, return cached result.
61+
if MACOS_SDK_ROOT:
62+
return MACOS_SDK_ROOT
63+
5064
cflags = sysconfig.get_config_var('CFLAGS')
5165
m = re.search(r'-isysroot\s+(\S+)', cflags)
52-
if m is None:
53-
sysroot = '/'
66+
if m is not None:
67+
MACOS_SDK_ROOT = m.group(1)
5468
else:
55-
sysroot = m.group(1)
56-
return sysroot
69+
MACOS_SDK_ROOT = '/'
70+
cc = sysconfig.get_config_var('CC')
71+
tmpfile = '/tmp/setup_sdk_root.%d' % os.getpid()
72+
try:
73+
os.unlink(tmpfile)
74+
except:
75+
pass
76+
ret = os.system('%s -E -v - </dev/null 2>%s 1>/dev/null' % (cc, tmpfile))
77+
in_incdirs = False
78+
try:
79+
if ret >> 8 == 0:
80+
with open(tmpfile) as fp:
81+
for line in fp.readlines():
82+
if line.startswith("#include <...>"):
83+
in_incdirs = True
84+
elif line.startswith("End of search list"):
85+
in_incdirs = False
86+
elif in_incdirs:
87+
line = line.strip()
88+
if line == '/usr/include':
89+
MACOS_SDK_ROOT = '/'
90+
elif line.endswith(".sdk/usr/include"):
91+
MACOS_SDK_ROOT = line[:-12]
92+
finally:
93+
os.unlink(tmpfile)
94+
95+
return MACOS_SDK_ROOT
5796

5897
def is_macosx_sdk_path(path):
5998
"""

0 commit comments

Comments
 (0)