Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/clang_native.py
6170 views
1
# Copyright 2020 The Emscripten Authors. All rights reserved.
2
# Emscripten is available under two separate licenses, the MIT license and the
3
# University of Illinois/NCSA Open Source License. Both these licenses can be
4
# found in the LICENSE file.
5
6
import logging
7
import os
8
import platform
9
import sys
10
11
from tools.shared import CLANG_CC, CLANG_CXX, PIPE
12
from tools.utils import MACOS, WINDOWS, path_from_root, run_process
13
14
logger = logging.getLogger('clang_native')
15
16
17
def get_native_triple():
18
# On Raspberry Pi 5, the target triple for native compilation must exactly
19
# match 'aarch64-linux-gnu', or clang will not find the native sysroot.
20
# Users on a Pi 5 can set environment variable
21
# EMTEST_NATIVE_COMPILATION_TRIPLE=aarch64-linux-gnu
22
# to be able to override the native triple for Pi 5 compilation.
23
native_compilation_triple = os.getenv('EMTEST_NATIVE_COMPILATION_TRIPLE')
24
if native_compilation_triple:
25
return native_compilation_triple
26
27
arch = {
28
'aarch64': 'arm64',
29
'arm64': 'arm64', # Python on Apple Silicon ARM64 reports lowercase arm64
30
'ARM64': 'arm64', # Python on Windows-on-ARM reports uppercase ARM64
31
'x86_64': 'x86_64',
32
'AMD64': 'x86_64',
33
}[platform.machine()]
34
OS = {
35
'linux': 'linux',
36
'darwin': 'darwin',
37
'win32': 'windows-msvc',
38
}[sys.platform]
39
return f'{arch}-{OS}'
40
41
42
# These extra args need to be passed to Clang when targeting a native host system executable
43
def get_clang_native_args():
44
triple = ['--target=' + get_native_triple()]
45
if MACOS:
46
sysroot = run_process(['xcrun', '--show-sdk-path'], stdout=PIPE).stdout.strip()
47
return triple + ['-isystem', path_from_root('system/include/libcxx'), f'--sysroot={sysroot}']
48
elif os.name == 'nt':
49
# TODO: If Windows.h et al. are needed, will need to add something like '-isystemC:/Program
50
# Files (x86)/Microsoft SDKs/Windows/v7.1A/Include'.
51
return triple + ['-DWIN32']
52
else:
53
return triple
54
55
56
# This environment needs to be present when targeting a native host system executable
57
CACHED_CLANG_NATIVE_ENV = None
58
59
60
def get_clang_native_env():
61
global CACHED_CLANG_NATIVE_ENV
62
if CACHED_CLANG_NATIVE_ENV is not None:
63
return CACHED_CLANG_NATIVE_ENV
64
env = os.environ.copy()
65
66
env['CC'] = CLANG_CC
67
env['CXX'] = CLANG_CXX
68
env['LD'] = CLANG_CXX
69
70
if MACOS:
71
path = run_process(['xcrun', '--show-sdk-path'], stdout=PIPE).stdout.strip()
72
logger.debug('Using MacOS SDKROOT: ' + path)
73
env['SDKROOT'] = path
74
elif WINDOWS:
75
# If already running in Visual Studio Command Prompt manually, no need to
76
# add anything here, so just return.
77
if 'VSINSTALLDIR' in env and 'INCLUDE' in env and 'LIB' in env:
78
CACHED_CLANG_NATIVE_ENV = env
79
return env
80
81
# VSINSTALLDIR is not in environment, so the user is not running in Visual Studio
82
# Command Prompt. Attempt to autopopulate INCLUDE and LIB directives.
83
84
# Guess where Visual Studio is installed (VSINSTALLDIR env. var in VS X64 Command Prompt)
85
if 'VSINSTALLDIR' in env:
86
visual_studio_path = env['VSINSTALLDIR']
87
elif 'VS170COMNTOOLS' in env:
88
visual_studio_path = os.path.normpath(os.path.join(env['VS170COMNTOOLS'], '../..'))
89
elif 'ProgramFiles(x86)' in env:
90
visual_studio_path = os.path.normpath(os.path.join(env['ProgramFiles(x86)'], 'Microsoft Visual Studio', '2022', 'Community'))
91
elif 'ProgramFiles' in env:
92
visual_studio_path = os.path.normpath(os.path.join(env['ProgramFiles'], 'Microsoft Visual Studio', '2022', 'Community'))
93
else:
94
visual_studio_path = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community'
95
if not os.path.isdir(visual_studio_path):
96
raise Exception('Visual Studio was not found in "' + visual_studio_path + '"! Run in Visual Studio X64 command prompt to avoid the need to autoguess this location (or set VSINSTALLDIR env var).')
97
98
# Guess where Program Files (x86) is located
99
if 'ProgramFiles(x86)' in env:
100
prog_files_x86 = env['ProgramFiles(x86)']
101
elif 'ProgramFiles' in env:
102
prog_files_x86 = env['ProgramFiles']
103
elif os.path.isdir('C:\\Program Files (x86)'):
104
prog_files_x86 = 'C:\\Program Files (x86)'
105
elif os.path.isdir('C:\\Program Files'):
106
prog_files_x86 = 'C:\\Program Files'
107
else:
108
raise Exception('Unable to detect Program files directory for native Visual Studio build!')
109
110
# Find include directory root
111
def highest_version_subdir(path):
112
candidates = []
113
for entry in os.listdir(path):
114
full = os.path.join(path, entry)
115
if os.path.isdir(full):
116
try:
117
candidates.append((tuple(int(p) for p in entry.split('.')), full))
118
except ValueError:
119
continue
120
if len(candidates) == 0:
121
return None
122
return max(candidates, key=lambda x: x[0])[1]
123
124
vc_root = os.path.join(visual_studio_path, 'VC')
125
vc_code_root = highest_version_subdir(os.path.join(vc_root, 'Tools', 'MSVC'))
126
if not vc_code_root:
127
raise Exception('Unable to find Visual Studio INCLUDE root directory. Run in Visual Studio command prompt to avoid the need to autoguess this location.')
128
129
windows_sdk_dir = highest_version_subdir(os.path.join(prog_files_x86, 'Windows Kits'))
130
if not windows_sdk_dir:
131
raise Exception('Unable to find Windows SDK root directory. Run in Visual Studio command prompt to avoid the need to autoguess this location.')
132
133
env.setdefault('VSINSTALLDIR', visual_studio_path)
134
env.setdefault('VCINSTALLDIR', os.path.join(visual_studio_path, 'VC'))
135
136
windows_sdk_include_dir = highest_version_subdir(os.path.join(windows_sdk_dir, 'include'))
137
windows_sdk_lib_dir = highest_version_subdir(os.path.join(windows_sdk_dir, 'lib'))
138
139
def append_path_item(key, path):
140
if not os.path.isdir(path):
141
logger.warning(f'VS path {path} does not exist')
142
return
143
144
if key not in env or len(env[key].strip()) == 0:
145
env[key] = path
146
else:
147
env[key] = env[key] + ';' + path
148
149
append_path_item('INCLUDE', os.path.join(vc_code_root, 'include'))
150
append_path_item('INCLUDE', os.path.join(vc_code_root, 'ATLMFC', 'include'))
151
append_path_item('INCLUDE', os.path.join(vc_root, 'Auxiliary', 'VS', 'include'))
152
for d in ['ucrt', 'um', 'shared', 'winrt', 'cppwinrt']:
153
append_path_item('INCLUDE', os.path.join(windows_sdk_include_dir, d))
154
logger.debug('Visual Studio native build INCLUDE: ' + env['INCLUDE'])
155
156
append_path_item('LIB', os.path.join(vc_code_root, 'ATLMFC', 'lib', 'x64'))
157
append_path_item('LIB', os.path.join(vc_code_root, 'lib', 'x64'))
158
append_path_item('LIB', os.path.join(windows_sdk_lib_dir, 'ucrt', 'x64'))
159
append_path_item('LIB', os.path.join(windows_sdk_lib_dir, 'um', 'x64'))
160
logger.debug('Visual Studio native build LIB: ' + env['LIB'])
161
162
env['PATH'] = env['PATH'] + ';' + os.path.join(env['VCINSTALLDIR'], 'BIN')
163
logger.debug('Visual Studio native build PATH: ' + env['PATH'])
164
165
CACHED_CLANG_NATIVE_ENV = env
166
return env
167
168