Merge branch 'clang_cl2' into 'waf-2.1'

Clang-cl support

See merge request ita1024/waf!2273
This commit is contained in:
ita1024 2019-12-10 06:29:06 +00:00
commit 73d432eb0a
7 changed files with 230 additions and 2 deletions

8
.gitignore vendored
View File

@ -8,7 +8,9 @@ build
demos/*/build*
playground/*/build*
.waf-*
waf-*
.waf3-*
waf3-*
*.log
.DS_Store
.AppleDouble
@ -37,3 +39,9 @@ Temporary Items
# Windows build output
waf.bat
# Vim temporary files
*.swp
# YouCompleteMe configuration
.ycm_extra_conf.py

View File

@ -0,0 +1,27 @@
# Clang-CL
Clang-CL is a drop-in MSVC compatible driver replacing CL.exe
The clang compiler offers high compatibility with MSVC, but also offers more up to date C++ support.
It features better code generation, but still adheres to the MSVC ABI, letting you link with link.exe, offering you superior performance but also PDB debug info.
On Windows this waf module should just work, on Linux it tries to find the LLVM replacements and requires an environment containing the paths defined by the vsvars batch files (Visual Studio C++ Developer command prompt).
# Cross compilation
To cross compile for Windows from Linux, you will require the following:
* A partition with Windows installed (NTFS).
* Visual Studio (Tested with 2017).
* The Windows SDK.
* lowntfs-3g file system driver.
Make sure the Windows partition is mounted with `-t lowntfs-3g -o defaults,ignore_case,windows_names`.
This will allow Clang to find all headers and libraries referenced by scripts and headers, otherwise you will run into case sensitivity errors.
You can run a script to make all filenames lowercase, but that edits your Visual Studio installation, and I don't know if that has an effect on upgradability.
Clang uses the following environment variables to detect the Visual Studio install: `VCINSTALLDIR`, `VCToolsInstallDir`, `INCLUDE`, `LIB`, `LIBPATH`
I just copied these from the output of the `set` command in an MSVC command prompt on Windows and translated the paths to Linux paths.
Notice how the semicolon is still used as a path separator.
See `example_environment_linux.sh` for how my setup looks like. It expects the Windows partition to be mounted on `/mnt/windows`, with VS2017 installed and Windows 10 SDK 10.0.17763.0.
To specify a custom LLVM installation, you can put the path in the `LLVM_PATH` environment variable, or put the path in `cfg.env.LLVM_PATH` in your wscript.

View File

@ -0,0 +1,5 @@
export VCINSTALLDIR="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/"
export VCToolsInstallDir="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/"
export INCLUDE="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/atlmfc/include;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/include;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/ucrt;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/shared;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/um;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/winrt;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/cppwinrt"
export LIB="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/atlmfc/lib/x64;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/lib/x64;/mnt/windows/program files (x86)/windows kits/10/lib/10.0.17763.0/ucrt/x64;/mnt/windows/program files (x86)/windows kits/10/lib/10.0.17763.0/um/x64"
export LIBPATH="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/atlmfc/lib/x64;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/lib/x64;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/lib/x86/store/references;/mnt/windows/program files (x86)/windows kits/10/unionmetadata/10.0.17763.0;/mnt/windows/program files (x86)/windows kits/10/references/10.0.17763.0"

View File

@ -0,0 +1,11 @@
#include <stdio.h>
int main(int argc, char** argv)
{
(void)argc;
(void)argv;
puts("This is a simple test program.\n");
return 0;
}

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
# encoding: utf-8
# vim: ts=4 sw=4 noexpandtab
top = '.'
out = 'build'
def options(opt):
opt.load('clang_cl')
def configure(cfg):
cfg.load('clang_cl')
cfg.env.append_value('CFLAGS','/Zi')
cfg.env.append_value('LDFLAGS','/DEBUG')
def build(bld):
bld.program(
name='test',
source=['test.c'],
target='test',
use='CRT_MULTITHREADED_DLL')

View File

@ -4,7 +4,7 @@
"Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}"
import re
import re, sys
from waflib import Task
from waflib.TaskGen import extension
from waflib.Tools import c_preproc
@ -68,7 +68,21 @@ def configure(conf):
v = conf.env
if not v.WINRC:
if v.CC_NAME == 'msvc':
conf.find_program('RC', var='WINRC', path_list=v.PATH)
if sys.platform == 'win32':
conf.find_program('RC', var='WINRC', path_list=v.PATH)
else:
llvm_env_path = conf.environ.get('LLVM_PATH')
llvm_path = None
if llvm_env_path:
llvm_path = llvm_env_path
elif 'LLVM_PATH' in v:
llvm_path = v['LLVM_PATH']
paths = v.PATH
if llvm_path:
paths = [llvm_path] + v.PATH
conf.find_program('llvm-rc', var='WINRC', path_list=paths)
v.WINRC_TGT_F = '/fo'
v.WINRC_SRC_F = ''
else:

142
waflib/extras/clang_cl.py Normal file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env python
# encoding: utf-8
# vim: sw=4 ts=4 noexpandtab
"""
LLVM Clang-CL support.
Clang-CL is supposed to be a drop-in replacement for MSVC CL, but also serves
well as a cross compiler for Windows from Linux (provided you have set up the
environment). Requires Visual Studio 2015+ to be installed.
On Windows it uses (most) MSVC tools.
See waflib/Tools/msvc.py and waflib/Tools/msvc_common.py for more details.
Usage:
$ waf configure
Or:
$ LLVM_PATH=C:\Program Files\LLVM\bin waf configure
Or:
def configure(conf):
conf.env.LLVM_PATH = 'C:\Program Files\LLVM\bin'
conf.load('clang_cl')
"""
import sys, os
from waflib import Utils, Errors, Logs
from waflib.Configure import conf
def options(opt):
from waflib.Tools.msvc import options as msvc_opt
msvc_opt(opt)
@conf
def find_clang_cl(conf):
"""
Find the program clang-cl.
"""
v = conf.env
del(v.CC)
del(v.CXX)
llvm_path = str()
if sys.platform == 'win32':
try:
llvm_key = Utils.winreg.OpenKey( \
Utils.winreg.HKEY_LOCAL_MACHINE, \
'SOFTWARE\\Wow6432Node\\LLVM\\LLVM')
except OSError:
llvm_key = Utils.winreg.OpenKey( \
Utils.winreg.HKEY_LOCAL_MACHINE, \
'SOFTWARE\\LLVM\\LLVM')
llvm_path,type = Utils.winreg.QueryValueEx(llvm_key, '')
llvm_path = os.path.join(llvm_path, 'bin')
llvm_env_path = conf.environ.get('LLVM_PATH')
if llvm_env_path:
llvm_path = llvm_env_path
elif 'LLVM_PATH' in v:
llvm_path = v['LLVM_PATH']
paths = v.PATH
if llvm_path != 'bin' and llvm_path != str():
paths = [llvm_path] + v.PATH
cc = conf.find_program('clang-cl', var='CC', path_list=paths)
v.CC = v.CXX = cc
v.CC_NAME_SECONDARY = v.CXX_NAME_SECONDARY = 'clang'
if sys.platform != 'win32':
v.MSVC_COMPILER = 'msvc'
v.MSVC_VERSION = 19
if not v.LINK_CXX:
conf.find_program( \
'lld-link', \
path_list=paths, \
errmsg='lld-link was not found (linker)', \
var='LINK_CXX')
if not v.LINK_CC:
v.LINK_CC = v.LINK_CXX
@conf
def find_llvm_tools(conf):
"""
Find the librarian, manifest tool, and resource compiler.
"""
v = conf.env
v.CC_NAME = v.CXX_NAME = 'msvc'
llvm_env_path = conf.environ.get('LLVM_PATH')
llvm_path = None
if llvm_env_path:
llvm_path = llvm_env_path
elif 'LLVM_PATH' in v:
llvm_path = v['LLVM_PATH']
paths = v.PATH
if llvm_path:
paths = [llvm_path] + v.PATH
if not v.AR:
stliblink = conf.find_program('llvm-lib', path_list=paths, var='AR')
if not stliblink:
conf.fatal('Unable to find required program "llvm-lib"')
v.ARFLAGS = ['/nologo']
# We assume clang_cl to only be used with relatively new MSVC installations.
v.MSVC_MANIFEST = True
conf.find_program('llvm-mt', path_list=paths, var='MT')
v.MTFLAGS = ['/nologo']
try:
conf.load('winres')
except Errors.ConfigurationError:
Logs.warn('Resource compiler not found. Compiling resource file is disabled')
def configure(conf):
from waflib.Tools.msvc import autodetect, find_msvc, msvc_common_flags
if sys.platform == 'win32':
conf.autodetect(True)
conf.find_msvc()
else:
conf.find_llvm_tools()
conf.find_clang_cl()
conf.msvc_common_flags()
conf.cc_load_tools()
conf.cxx_load_tools()
conf.cc_add_flags()
conf.cxx_add_flags()
conf.link_add_flags()
conf.visual_studio_add_flags()