Skip to content

Commit 0288dd6

Browse files
authored
bpo-36231: Support building on macOS without /usr/include (GH-13773)
1 parent 8565f6b commit 0288dd6

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-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: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,57 @@ def sysroot_paths(make_vars, subdirs):
125125
break
126126
return dirs
127127

128+
MACOS_SDK_ROOT = None
128129

129130
def macosx_sdk_root():
131+
"""Return the directory of the current macOS SDK.
132+
133+
If no SDK was explicitly configured, call the compiler to find which
134+
include files paths are being searched by default. Use '/' if the
135+
compiler is searching /usr/include (meaning system header files are
136+
installed) or use the root of an SDK if that is being searched.
137+
(The SDK may be supplied via Xcode or via the Command Line Tools).
138+
The SDK paths used by Apple-supplied tool chains depend on the
139+
setting of various variables; see the xcrun man page for more info.
130140
"""
131-
Return the directory of the current OSX SDK,
132-
or '/' if no SDK was specified.
133-
"""
141+
global MACOS_SDK_ROOT
142+
143+
# If already called, return cached result.
144+
if MACOS_SDK_ROOT:
145+
return MACOS_SDK_ROOT
146+
134147
cflags = sysconfig.get_config_var('CFLAGS')
135148
m = re.search(r'-isysroot\s+(\S+)', cflags)
136-
if m is None:
137-
sysroot = '/'
149+
if m is not None:
150+
MACOS_SDK_ROOT = m.group(1)
138151
else:
139-
sysroot = m.group(1)
140-
return sysroot
152+
MACOS_SDK_ROOT = '/'
153+
cc = sysconfig.get_config_var('CC')
154+
tmpfile = '/tmp/setup_sdk_root.%d' % os.getpid()
155+
try:
156+
os.unlink(tmpfile)
157+
except:
158+
pass
159+
ret = os.system('%s -E -v - </dev/null 2>%s 1>/dev/null' % (cc, tmpfile))
160+
in_incdirs = False
161+
try:
162+
if ret >> 8 == 0:
163+
with open(tmpfile) as fp:
164+
for line in fp.readlines():
165+
if line.startswith("#include <...>"):
166+
in_incdirs = True
167+
elif line.startswith("End of search list"):
168+
in_incdirs = False
169+
elif in_incdirs:
170+
line = line.strip()
171+
if line == '/usr/include':
172+
MACOS_SDK_ROOT = '/'
173+
elif line.endswith(".sdk/usr/include"):
174+
MACOS_SDK_ROOT = line[:-12]
175+
finally:
176+
os.unlink(tmpfile)
177+
178+
return MACOS_SDK_ROOT
141179

142180

143181
def is_macosx_sdk_path(path):

0 commit comments

Comments
 (0)