import logging
import os
import platform
import sys
from tools.shared import PIPE, run_process, CLANG_CC, CLANG_CXX
from tools.utils import MACOS, WINDOWS, path_from_root
logger = logging.getLogger('clang_native')
def get_native_triple():
native_compilation_triple = os.getenv('EMTEST_NATIVE_COMPILATION_TRIPLE')
if native_compilation_triple:
return native_compilation_triple
arch = {
'aarch64': 'arm64',
'arm64': 'arm64',
'x86_64': 'x86_64',
'AMD64': 'x86_64',
}[platform.machine()]
OS = {
'linux': 'linux',
'darwin': 'darwin',
'win32': 'windows-msvc',
}[sys.platform]
return f'{arch}-{OS}'
def get_clang_native_args():
triple = ['--target=' + get_native_triple()]
if MACOS:
sysroot = run_process(['xcrun', '--show-sdk-path'], stdout=PIPE).stdout.strip()
return triple + ['-isystem', path_from_root('system/include/libcxx'), f'--sysroot={sysroot}']
elif os.name == 'nt':
return triple + ['-DWIN32']
else:
return triple
CACHED_CLANG_NATIVE_ENV = None
def get_clang_native_env():
global CACHED_CLANG_NATIVE_ENV
if CACHED_CLANG_NATIVE_ENV is not None:
return CACHED_CLANG_NATIVE_ENV
env = os.environ.copy()
env['CC'] = CLANG_CC
env['CXX'] = CLANG_CXX
env['LD'] = CLANG_CXX
if MACOS:
path = run_process(['xcrun', '--show-sdk-path'], stdout=PIPE).stdout.strip()
logger.debug('Using MacOS SDKROOT: ' + path)
env['SDKROOT'] = path
elif WINDOWS:
if 'VSINSTALLDIR' in env and 'INCLUDE' in env and 'LIB' in env:
CACHED_CLANG_NATIVE_ENV = env
return env
if 'VSINSTALLDIR' in env:
visual_studio_path = env['VSINSTALLDIR']
elif 'VS170COMNTOOLS' in env:
visual_studio_path = os.path.normpath(os.path.join(env['VS170COMNTOOLS'], '../..'))
elif 'ProgramFiles(x86)' in env:
visual_studio_path = os.path.normpath(os.path.join(env['ProgramFiles(x86)'], 'Microsoft Visual Studio', '2022', 'Community'))
elif 'ProgramFiles' in env:
visual_studio_path = os.path.normpath(os.path.join(env['ProgramFiles'], 'Microsoft Visual Studio', '2022', 'Community'))
else:
visual_studio_path = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community'
if not os.path.isdir(visual_studio_path):
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).')
if 'ProgramFiles(x86)' in env:
prog_files_x86 = env['ProgramFiles(x86)']
elif 'ProgramFiles' in env:
prog_files_x86 = env['ProgramFiles']
elif os.path.isdir('C:\\Program Files (x86)'):
prog_files_x86 = 'C:\\Program Files (x86)'
elif os.path.isdir('C:\\Program Files'):
prog_files_x86 = 'C:\\Program Files'
else:
raise Exception('Unable to detect Program files directory for native Visual Studio build!')
def highest_version_subdir(path):
candidates = []
for entry in os.listdir(path):
full = os.path.join(path, entry)
if os.path.isdir(full):
try:
candidates.append((tuple(int(p) for p in entry.split('.')), full))
except ValueError:
continue
if len(candidates) == 0:
return None
return max(candidates, key=lambda x: x[0])[1]
vc_root = os.path.join(visual_studio_path, 'VC')
vc_code_root = highest_version_subdir(os.path.join(vc_root, 'Tools', 'MSVC'))
if not vc_code_root:
raise Exception ('Unable to find Visual Studio INCLUDE root directory. Run in Visual Studio command prompt to avoid the need to autoguess this location.')
windows_sdk_dir = highest_version_subdir(os.path.join(prog_files_x86, 'Windows Kits'))
if not windows_sdk_dir:
raise Exception ('Unable to find Windows SDK root directory. Run in Visual Studio command prompt to avoid the need to autoguess this location.')
env.setdefault('VSINSTALLDIR', visual_studio_path)
env.setdefault('VCINSTALLDIR', os.path.join(visual_studio_path, 'VC'))
windows_sdk_include_dir = highest_version_subdir(os.path.join(windows_sdk_dir, 'include'))
windows_sdk_lib_dir = highest_version_subdir(os.path.join(windows_sdk_dir, 'lib'))
def append_path_item(key, path):
if not os.path.isdir(path):
logger.warning(f'VS path {path} does not exist')
return
if key not in env or len(env[key].strip()) == 0:
env[key] = path
else:
env[key] = env[key] + ';' + path
append_path_item('INCLUDE', os.path.join(vc_code_root, 'include'))
append_path_item('INCLUDE', os.path.join(vc_code_root, 'ATLMFC', 'include'))
append_path_item('INCLUDE', os.path.join(vc_root, 'Auxiliary', 'VS', 'include'))
for d in ['ucrt', 'um', 'shared', 'winrt', 'cppwinrt']:
append_path_item('INCLUDE', os.path.join(windows_sdk_include_dir, d))
logger.debug('Visual Studio native build INCLUDE: ' + env['INCLUDE'])
append_path_item('LIB', os.path.join(vc_code_root, 'ATLMFC', 'lib', 'x64'))
append_path_item('LIB', os.path.join(vc_code_root, 'lib', 'x64'))
append_path_item('LIB', os.path.join(windows_sdk_lib_dir, 'ucrt', 'x64'))
append_path_item('LIB', os.path.join(windows_sdk_lib_dir, 'um', 'x64'))
logger.debug('Visual Studio native build LIB: ' + env['LIB'])
env['PATH'] = env['PATH'] + ';' + os.path.join(env['VCINSTALLDIR'], 'BIN')
logger.debug('Visual Studio native build PATH: ' + env['PATH'])
CACHED_CLANG_NATIVE_ENV = env
return env