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