From 9fee4dfa755a85005482ac853456b1a8b823f351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Tue, 22 Oct 2019 02:55:43 +0200 Subject: [PATCH 1/5] Ignore VIM temporary files and Windows waf unpacks --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index f54a7ef5..28a82555 100644 --- a/.gitignore +++ b/.gitignore @@ -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 From 7310ade7c397491ed4a64b33e876da8a8769f392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Tue, 22 Oct 2019 16:26:45 +0200 Subject: [PATCH 2/5] Initial clang-cl support --- waflib/extras/clang_cl.py | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 waflib/extras/clang_cl.py diff --git a/waflib/extras/clang_cl.py b/waflib/extras/clang_cl.py new file mode 100644 index 00000000..cfbbdbd6 --- /dev/null +++ b/waflib/extras/clang_cl.py @@ -0,0 +1,86 @@ +#!/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 +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' + +def configure(conf): + from waflib.Tools.msvc import autodetect, find_msvc, msvc_common_flags + + conf.autodetect(True) + conf.find_msvc() + 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() From 32c2a49bf09721e3d40cd3058dd9d27ce1884a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Wed, 4 Dec 2019 20:49:08 +0100 Subject: [PATCH 3/5] Support pure clang-cl builds on not Windows A.k.a. I just tested it on Linux. --- waflib/Tools/winres.py | 18 ++++++++++-- waflib/extras/clang_cl.py | 62 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py index 9be1ed66..80b1f5b1 100644 --- a/waflib/Tools/winres.py +++ b/waflib/Tools/winres.py @@ -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: diff --git a/waflib/extras/clang_cl.py b/waflib/extras/clang_cl.py index cfbbdbd6..7634e5b5 100644 --- a/waflib/extras/clang_cl.py +++ b/waflib/extras/clang_cl.py @@ -24,7 +24,7 @@ Or: import sys, os -from waflib import Utils +from waflib import Utils, Errors, Logs from waflib.Configure import conf def options(opt): @@ -71,11 +71,67 @@ def find_clang_cl(conf): 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 - conf.autodetect(True) - conf.find_msvc() + 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() From 273d9dbe730fdc3cf01d30775a75a75667bb5915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Tue, 22 Oct 2019 16:28:17 +0200 Subject: [PATCH 4/5] Add a small example utilizing clang-cl --- playground/clang_cl/test.c | 11 +++++++++++ playground/clang_cl/wscript | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 playground/clang_cl/test.c create mode 100644 playground/clang_cl/wscript diff --git a/playground/clang_cl/test.c b/playground/clang_cl/test.c new file mode 100644 index 00000000..9476f106 --- /dev/null +++ b/playground/clang_cl/test.c @@ -0,0 +1,11 @@ +#include + +int main(int argc, char** argv) +{ + (void)argc; + (void)argv; + + puts("This is a simple test program.\n"); + + return 0; +} diff --git a/playground/clang_cl/wscript b/playground/clang_cl/wscript new file mode 100644 index 00000000..e6c73b1a --- /dev/null +++ b/playground/clang_cl/wscript @@ -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') From c4f18f8182948d07716a0a131a7325f2fa3b8642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Wed, 4 Dec 2019 21:14:55 +0100 Subject: [PATCH 5/5] Add a ReadMe and example environment for clang-cl on Linux --- playground/clang_cl/ReadMe.md | 27 +++++++++++++++++++ .../clang_cl/example_environment_linux.sh | 5 ++++ 2 files changed, 32 insertions(+) create mode 100644 playground/clang_cl/ReadMe.md create mode 100644 playground/clang_cl/example_environment_linux.sh diff --git a/playground/clang_cl/ReadMe.md b/playground/clang_cl/ReadMe.md new file mode 100644 index 00000000..d973e80f --- /dev/null +++ b/playground/clang_cl/ReadMe.md @@ -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. diff --git a/playground/clang_cl/example_environment_linux.sh b/playground/clang_cl/example_environment_linux.sh new file mode 100644 index 00000000..1fd5a005 --- /dev/null +++ b/playground/clang_cl/example_environment_linux.sh @@ -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"