mirror of
https://gitlab.com/ita1024/waf.git
synced 2024-11-23 10:20:24 +01:00
Merge branch 'ClangCross' into 'master'
Better support for cross compilation with clang v2 See merge request ita1024/waf!2233
This commit is contained in:
commit
89146d9030
14
playground/clang_cross/msvc/ReadMe.txt
Normal file
14
playground/clang_cross/msvc/ReadMe.txt
Normal file
@ -0,0 +1,14 @@
|
||||
To cross compile for Windows in MSVC mode 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.
|
||||
|
||||
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.
|
5
playground/clang_cross/msvc/example_environment_linux.sh
Normal file
5
playground/clang_cross/msvc/example_environment_linux.sh
Normal 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"
|
11
playground/clang_cross/msvc/hello.c
Normal file
11
playground/clang_cross/msvc/hello.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <Windows.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), "Hello world!\n", 13, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
32
playground/clang_cross/msvc/wscript
Normal file
32
playground/clang_cross/msvc/wscript
Normal file
@ -0,0 +1,32 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# DragoonX6 2019
|
||||
|
||||
# the following two variables are used by the target "waf dist"
|
||||
VERSION='0.0.1'
|
||||
APPNAME='hello_msvc'
|
||||
|
||||
top = '.'
|
||||
|
||||
from waflib.Configure import conf, ConfigurationContext
|
||||
from waflib.Options import OptionsContext
|
||||
|
||||
def options(opt):
|
||||
opt.load('clang_cross')
|
||||
|
||||
def configure(conf):
|
||||
conf.load('clang_cross')
|
||||
|
||||
if not conf.env.implib_PATTERN == '%s.lib':
|
||||
conf.fatal('''clang is not configured to compile in msvc mode.
|
||||
Use flag '--clang-target-triple=x86_64-windows-msvc' to configure.
|
||||
On Windows you're likely to require running from an MSVC command prompt.
|
||||
On Linux you will need to have access to a Windows partition with VS installed, and the environment set up properly.
|
||||
See the ReadMe for more information.''')
|
||||
|
||||
conf.env.append_value('CFLAGS', conf.env.CFLAGS_CRT_MULTITHREADED_DLL)
|
||||
|
||||
def build(bld):
|
||||
bld.program(
|
||||
source = 'hello.c',
|
||||
target = 'hello_msvc')
|
92
waflib/extras/clang_cross.py
Normal file
92
waflib/extras/clang_cross.py
Normal file
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# Krzysztof Kosiński 2014
|
||||
# DragoonX6 2018
|
||||
|
||||
"""
|
||||
Detect the Clang C compiler
|
||||
This version is an attempt at supporting the -target and -sysroot flag of Clang.
|
||||
"""
|
||||
|
||||
from waflib.Tools import ccroot, ar, gcc
|
||||
from waflib.Configure import conf
|
||||
import waflib.Context
|
||||
import waflib.extras.clang_cross_common
|
||||
|
||||
def options(opt):
|
||||
"""
|
||||
Target triplet for clang::
|
||||
$ waf configure --clang-target-triple=x86_64-pc-linux-gnu
|
||||
"""
|
||||
cc_compiler_opts = opt.add_option_group('Configuration options')
|
||||
cc_compiler_opts.add_option('--clang-target-triple', default=None,
|
||||
help='Target triple for clang',
|
||||
dest='clang_target_triple')
|
||||
cc_compiler_opts.add_option('--clang-sysroot', default=None,
|
||||
help='Sysroot for clang',
|
||||
dest='clang_sysroot')
|
||||
|
||||
@conf
|
||||
def find_clang(conf):
|
||||
"""
|
||||
Finds the program clang and executes it to ensure it really is clang
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
cc = conf.find_program('clang', var='CC')
|
||||
|
||||
if conf.options.clang_target_triple != None:
|
||||
conf.env.append_value('CC', ['-target', conf.options.clang_target_triple])
|
||||
|
||||
if conf.options.clang_sysroot != None:
|
||||
sysroot = str()
|
||||
|
||||
if os.path.isabs(conf.options.clang_sysroot):
|
||||
sysroot = conf.options.clang_sysroot
|
||||
else:
|
||||
sysroot = os.path.normpath(os.path.join(os.getcwd(), conf.options.clang_sysroot))
|
||||
|
||||
conf.env.append_value('CC', ['--sysroot', sysroot])
|
||||
|
||||
conf.get_cc_version(cc, clang=True)
|
||||
conf.env.CC_NAME = 'clang'
|
||||
|
||||
@conf
|
||||
def clang_modifier_x86_64_w64_mingw32(conf):
|
||||
conf.gcc_modifier_win32()
|
||||
|
||||
@conf
|
||||
def clang_modifier_i386_w64_mingw32(conf):
|
||||
conf.gcc_modifier_win32()
|
||||
|
||||
@conf
|
||||
def clang_modifier_x86_64_windows_msvc(conf):
|
||||
conf.clang_modifier_msvc()
|
||||
|
||||
# Allow the user to override any flags if they so desire.
|
||||
clang_modifier_user_func = getattr(conf, 'clang_modifier_x86_64_windows_msvc_user', None)
|
||||
if clang_modifier_user_func:
|
||||
clang_modifier_user_func()
|
||||
|
||||
@conf
|
||||
def clang_modifier_i386_windows_msvc(conf):
|
||||
conf.clang_modifier_msvc()
|
||||
|
||||
# Allow the user to override any flags if they so desire.
|
||||
clang_modifier_user_func = getattr(conf, 'clang_modifier_i386_windows_msvc_user', None)
|
||||
if clang_modifier_user_func:
|
||||
clang_modifier_user_func()
|
||||
|
||||
def configure(conf):
|
||||
conf.find_clang()
|
||||
conf.find_program(['llvm-ar', 'ar'], var='AR')
|
||||
conf.find_ar()
|
||||
conf.gcc_common_flags()
|
||||
# Allow the user to provide flags for the target platform.
|
||||
conf.gcc_modifier_platform()
|
||||
# And allow more fine grained control based on the compiler's triplet.
|
||||
conf.clang_modifier_target_triple()
|
||||
conf.cc_load_tools()
|
||||
conf.cc_add_flags()
|
||||
conf.link_add_flags()
|
113
waflib/extras/clang_cross_common.py
Normal file
113
waflib/extras/clang_cross_common.py
Normal file
@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# DragoonX6 2018
|
||||
|
||||
"""
|
||||
Common routines for cross_clang.py and cross_clangxx.py
|
||||
"""
|
||||
|
||||
from waflib.Configure import conf
|
||||
import waflib.Context
|
||||
|
||||
def normalize_target_triple(target_triple):
|
||||
target_triple = target_triple[:-1]
|
||||
normalized_triple = target_triple.replace('--', '-unknown-')
|
||||
|
||||
if normalized_triple.startswith('-'):
|
||||
normalized_triple = 'unknown' + normalized_triple
|
||||
|
||||
if normalized_triple.endswith('-'):
|
||||
normalized_triple += 'unknown'
|
||||
|
||||
# Normalize MinGW builds to *arch*-w64-mingw32
|
||||
if normalized_triple.endswith('windows-gnu'):
|
||||
normalized_triple = normalized_triple[:normalized_triple.index('-')] + '-w64-mingw32'
|
||||
|
||||
# Strip the vendor when doing msvc builds, since it's unused anyway.
|
||||
if normalized_triple.endswith('windows-msvc'):
|
||||
normalized_triple = normalized_triple[:normalized_triple.index('-')] + '-windows-msvc'
|
||||
|
||||
return normalized_triple.replace('-', '_')
|
||||
|
||||
@conf
|
||||
def clang_modifier_msvc(conf):
|
||||
import os
|
||||
|
||||
"""
|
||||
Really basic setup to use clang in msvc mode.
|
||||
We actually don't really want to do a lot, even though clang is msvc compatible
|
||||
in this mode, that doesn't mean we're actually using msvc.
|
||||
It's probably the best to leave it to the user, we can assume msvc mode if the user
|
||||
uses the clang-cl frontend, but this module only concerns itself with the gcc-like frontend.
|
||||
"""
|
||||
v = conf.env
|
||||
v.cprogram_PATTERN = '%s.exe'
|
||||
|
||||
v.cshlib_PATTERN = '%s.dll'
|
||||
v.implib_PATTERN = '%s.lib'
|
||||
v.IMPLIB_ST = '-Wl,-IMPLIB:%s'
|
||||
v.SHLIB_MARKER = []
|
||||
|
||||
v.CFLAGS_cshlib = []
|
||||
v.LINKFLAGS_cshlib = ['-Wl,-DLL']
|
||||
v.cstlib_PATTERN = '%s.lib'
|
||||
v.STLIB_MARKER = []
|
||||
|
||||
del(v.AR)
|
||||
conf.find_program(['llvm-lib', 'lib'], var='AR')
|
||||
v.ARFLAGS = ['-nologo']
|
||||
v.AR_TGT_F = ['-out:']
|
||||
|
||||
# Default to the linker supplied with llvm instead of link.exe or ld
|
||||
v.LINK_CC = v.CC + ['-fuse-ld=lld', '-nostdlib']
|
||||
v.CCLNK_TGT_F = ['-o']
|
||||
v.def_PATTERN = '-Wl,-def:%s'
|
||||
|
||||
v.LINKFLAGS = []
|
||||
|
||||
v.LIB_ST = '-l%s'
|
||||
v.LIBPATH_ST = '-Wl,-LIBPATH:%s'
|
||||
v.STLIB_ST = '-l%s'
|
||||
v.STLIBPATH_ST = '-Wl,-LIBPATH:%s'
|
||||
|
||||
CFLAGS_CRT_COMMON = [
|
||||
'-Xclang', '--dependent-lib=oldnames',
|
||||
'-Xclang', '-fno-rtti-data',
|
||||
'-D_MT'
|
||||
]
|
||||
|
||||
v.CFLAGS_CRT_MULTITHREADED = CFLAGS_CRT_COMMON + [
|
||||
'-Xclang', '-flto-visibility-public-std',
|
||||
'-Xclang', '--dependent-lib=libcmt',
|
||||
]
|
||||
v.CXXFLAGS_CRT_MULTITHREADED = v.CFLAGS_CRT_MULTITHREADED
|
||||
|
||||
v.CFLAGS_CRT_MULTITHREADED_DBG = CFLAGS_CRT_COMMON + [
|
||||
'-D_DEBUG',
|
||||
'-Xclang', '-flto-visibility-public-std',
|
||||
'-Xclang', '--dependent-lib=libcmtd',
|
||||
]
|
||||
v.CXXFLAGS_CRT_MULTITHREADED_DBG = v.CFLAGS_CRT_MULTITHREADED_DBG
|
||||
|
||||
v.CFLAGS_CRT_MULTITHREADED_DLL = CFLAGS_CRT_COMMON + [
|
||||
'-D_DLL',
|
||||
'-Xclang', '--dependent-lib=msvcrt'
|
||||
]
|
||||
v.CXXFLAGS_CRT_MULTITHREADED_DLL = v.CFLAGS_CRT_MULTITHREADED_DLL
|
||||
|
||||
v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = CFLAGS_CRT_COMMON + [
|
||||
'-D_DLL',
|
||||
'-D_DEBUG',
|
||||
'-Xclang', '--dependent-lib=msvcrtd',
|
||||
]
|
||||
v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CFLAGS_CRT_MULTITHREADED_DLL_DBG
|
||||
|
||||
@conf
|
||||
def clang_modifier_target_triple(conf, cpp=False):
|
||||
compiler = conf.env.CXX if cpp else conf.env.CC
|
||||
output = conf.cmd_and_log(compiler + ['-dumpmachine'], output=waflib.Context.STDOUT)
|
||||
|
||||
modifier = ('clangxx' if cpp else 'clang') + '_modifier_'
|
||||
clang_modifier_func = getattr(conf, modifier + normalize_target_triple(output), None)
|
||||
if clang_modifier_func:
|
||||
clang_modifier_func()
|
106
waflib/extras/clangxx_cross.py
Normal file
106
waflib/extras/clangxx_cross.py
Normal file
@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# Thomas Nagy 2009-2018 (ita)
|
||||
# DragoonX6 2018
|
||||
|
||||
"""
|
||||
Detect the Clang++ C++ compiler
|
||||
This version is an attempt at supporting the -target and -sysroot flag of Clang++.
|
||||
"""
|
||||
|
||||
from waflib.Tools import ccroot, ar, gxx
|
||||
from waflib.Configure import conf
|
||||
import waflib.extras.clang_cross_common
|
||||
|
||||
def options(opt):
|
||||
"""
|
||||
Target triplet for clang++::
|
||||
$ waf configure --clangxx-target-triple=x86_64-pc-linux-gnu
|
||||
"""
|
||||
cxx_compiler_opts = opt.add_option_group('Configuration options')
|
||||
cxx_compiler_opts.add_option('--clangxx-target-triple', default=None,
|
||||
help='Target triple for clang++',
|
||||
dest='clangxx_target_triple')
|
||||
cxx_compiler_opts.add_option('--clangxx-sysroot', default=None,
|
||||
help='Sysroot for clang++',
|
||||
dest='clangxx_sysroot')
|
||||
|
||||
@conf
|
||||
def find_clangxx(conf):
|
||||
"""
|
||||
Finds the program clang++, and executes it to ensure it really is clang++
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
cxx = conf.find_program('clang++', var='CXX')
|
||||
|
||||
if conf.options.clangxx_target_triple != None:
|
||||
conf.env.append_value('CXX', ['-target', conf.options.clangxx_target_triple])
|
||||
|
||||
if conf.options.clangxx_sysroot != None:
|
||||
sysroot = str()
|
||||
|
||||
if os.path.isabs(conf.options.clangxx_sysroot):
|
||||
sysroot = conf.options.clangxx_sysroot
|
||||
else:
|
||||
sysroot = os.path.normpath(os.path.join(os.getcwd(), conf.options.clangxx_sysroot))
|
||||
|
||||
conf.env.append_value('CXX', ['--sysroot', sysroot])
|
||||
|
||||
conf.get_cc_version(cxx, clang=True)
|
||||
conf.env.CXX_NAME = 'clang'
|
||||
|
||||
@conf
|
||||
def clangxx_modifier_x86_64_w64_mingw32(conf):
|
||||
conf.gcc_modifier_win32()
|
||||
|
||||
@conf
|
||||
def clangxx_modifier_i386_w64_mingw32(conf):
|
||||
conf.gcc_modifier_win32()
|
||||
|
||||
@conf
|
||||
def clangxx_modifier_msvc(conf):
|
||||
v = conf.env
|
||||
v.cxxprogram_PATTERN = v.cprogram_PATTERN
|
||||
v.cxxshlib_PATTERN = v.cshlib_PATTERN
|
||||
|
||||
v.CXXFLAGS_cxxshlib = []
|
||||
v.LINKFLAGS_cxxshlib = v.LINKFLAGS_cshlib
|
||||
v.cxxstlib_PATTERN = v.cstlib_PATTERN
|
||||
|
||||
v.LINK_CXX = v.CXX + ['-fuse-ld=lld', '-nostdlib']
|
||||
v.CXXLNK_TGT_F = v.CCLNK_TGT_F
|
||||
|
||||
@conf
|
||||
def clangxx_modifier_x86_64_windows_msvc(conf):
|
||||
conf.clang_modifier_msvc()
|
||||
conf.clangxx_modifier_msvc()
|
||||
|
||||
# Allow the user to override any flags if they so desire.
|
||||
clang_modifier_user_func = getattr(conf, 'clangxx_modifier_x86_64_windows_msvc_user', None)
|
||||
if clang_modifier_user_func:
|
||||
clang_modifier_user_func()
|
||||
|
||||
@conf
|
||||
def clangxx_modifier_i386_windows_msvc(conf):
|
||||
conf.clang_modifier_msvc()
|
||||
conf.clangxx_modifier_msvc()
|
||||
|
||||
# Allow the user to override any flags if they so desire.
|
||||
clang_modifier_user_func = getattr(conf, 'clangxx_modifier_i386_windows_msvc_user', None)
|
||||
if clang_modifier_user_func:
|
||||
clang_modifier_user_func()
|
||||
|
||||
def configure(conf):
|
||||
conf.find_clangxx()
|
||||
conf.find_program(['llvm-ar', 'ar'], var='AR')
|
||||
conf.find_ar()
|
||||
conf.gxx_common_flags()
|
||||
# Allow the user to provide flags for the target platform.
|
||||
conf.gxx_modifier_platform()
|
||||
# And allow more fine grained control based on the compiler's triplet.
|
||||
conf.clang_modifier_target_triple(cpp=True)
|
||||
conf.cxx_load_tools()
|
||||
conf.cxx_add_flags()
|
||||
conf.link_add_flags()
|
Loading…
Reference in New Issue
Block a user