From 6b32b1ec8f7d39c00045cfbebae0aa7b16910ab8 Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Wed, 24 Jul 2024 20:54:43 +0100 Subject: [PATCH] Add support for building with clang-cl This commit allows building with the Visual Studio LLVM toolchain by passing --cc=clangcl to the configure.py script. --- configure.py | 20 +++- src/build-data/cc/clangcl.txt | 102 ++++++++++++++++++ src/build-data/makefile.in | 2 +- src/build-data/ninja.in | 2 +- src/lib/math/bigint/big_ops2.cpp | 14 +++ .../certstor_flatfile/certstor_flatfile.h | 1 + 6 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 src/build-data/cc/clangcl.txt diff --git a/configure.py b/configure.py index aca1b3e3d32..ad72ecceb3a 100755 --- a/configure.py +++ b/configure.py @@ -2311,11 +2311,21 @@ def test_exe_extra_ldflags(): variables['includedir'], 'botan-%d' % (Version.major()), 'botan') - if cc.basename == 'msvc' and variables['cxx_abi_flags'] != '': - # MSVC linker doesn't support/need the ABI options, - # just transfer them over to just the compiler invocations + # On MSVC, the "ABI flags" should be passed to the compiler only, on other platforms, the + # ABI flags are passed to both the compiler and the linker and the compiler flags are also + # passed to the linker(?) + # + # TODO: Extend the build-data/cc/xxx.txt format to allow specifying different CFLAGS for + # different configurations, then /MD etc could be specified there rather than hijacking the ABI + # flags for it and having to special-case their exclusion from the linker command line. + + if cc.basename in ('msvc', 'clangcl'): + # Move the "ABI flags" (/MD etc) into the compiler flags to exclude it from linker invocations variables['cc_compile_flags'] = '%s %s' % (variables['cxx_abi_flags'], variables['cc_compile_flags']) variables['cxx_abi_flags'] = '' + else: + # Append the compiler flags to the linker flags + variables['ldflags'] = '%s %s' % (variables['ldflags'], variables['cc_compile_flags']) variables['lib_flags'] = cc.gen_lib_flags(options, variables) @@ -3275,11 +3285,11 @@ def validate_options(options, info_os, info_cc, available_module_policies): raise UserError('Option --with-pdf requires --with-sphinx') # Warnings - if options.os == 'windows' and options.compiler != 'msvc': + if options.os == 'windows' and options.compiler not in ('msvc', 'clangcl'): logging.warning('The windows target is oriented towards MSVC; maybe you want --os=cygwin or --os=mingw') if options.msvc_runtime: - if options.compiler != 'msvc': + if options.compiler != 'msvc' and options.compiler != 'clangcl': raise UserError("Makes no sense to specify MSVC runtime for %s" % (options.compiler)) if options.msvc_runtime not in ['MT', 'MD', 'MTd', 'MDd']: diff --git a/src/build-data/cc/clangcl.txt b/src/build-data/cc/clangcl.txt new file mode 100644 index 00000000000..43fbc017fa7 --- /dev/null +++ b/src/build-data/cc/clangcl.txt @@ -0,0 +1,102 @@ +macro_name CLANG + +minimum_supported_version 19.30 + +binary_name clang-cl +linker_name lld-link + +output_to_object "/Fo" +output_to_exe "/OUT:" + +add_include_dir_option "/I" +add_system_include_dir_option "/external:W0 /external:I" +add_lib_dir_option "/LIBPATH:" +add_compile_definition_option "/D" +add_lib_option "%s.lib" + +compile_flags "/nologo /c" + +supports_gcc_inline_asm yes + +optimization_flags "/O2 /Oi" +size_optimization_flags "/O1 /Os" + +# for debug info in the object file (required if using sccache): +#debug_info_flags "/Z7" + +# for using a PDB file: +debug_info_flags "/Zi /FS" + +preproc_flags "/nologo /EP" + +lang_flags "/std:c++20 /EHs /GR" + +# 4251: STL types used in DLL interface +# 4275: ??? +# 5072: ASan without debug info +warning_flags "/W4 /wd4251 /wd4275 /wd5072" + +werror_flags "/WX" + +visibility_build_flags "/DBOTAN_DLL=__declspec(dllexport)" +visibility_attribute "__declspec(dllimport)" + +# Include dependency tracking for Ninja +# See: https://ninja-build.org/manual.html#ref_headers +ninja_header_deps_style 'msvc' +header_deps_flag '/showIncludes' + +ar_command lib +ar_options "/nologo" +ar_output_to "/OUT:" + + +default -> address + +iterator -> "/D_ITERATOR_DEBUG_LEVEL=1" +address -> "/fsanitize=address" + + + +sse2 -> "-msse2" +ssse3 -> "-mssse3" +sse41 -> "-msse4.1" +sse42 -> "-msse4.2" +avx2 -> "-mavx2" +avx512 -> "-mavx512f -mavx512bw -mavx512dq -mavx512vbmi -mavx512vbmi2 -mavx512bitalg -mavx512vl -mavx512ifma" + +bmi2 -> "-mbmi -mbmi2" +aesni -> "-maes -mpclmul" +rdrand -> "-mrdrnd" +rdseed -> "-mrdseed" +sha -> "-msha" +altivec -> "-maltivec" + +arm64:armv8crypto -> "-march=armv8+crypto" +arm64:armv8sha512 -> "-march=armv8.2-a+sha3" + +arm32:neon -> "-mfpu=neon" +arm64:neon -> "" + + + +debug -> "/Fd%{build_dir}/%{libname}.pdb" + + + +default -> "{linker} /DLL" +default-debug -> "{linker} /DLL /DEBUG" + + + +default -> "{linker}" +default-debug -> "{linker} /DEBUG" + + + +all -> "/bigobj" + +# These can be overridden with --msvc-runtime option +rt -> "/MD" +rt-debug -> "/MDd" + diff --git a/src/build-data/makefile.in b/src/build-data/makefile.in index e59085667bb..9b3ac587477 100644 --- a/src/build-data/makefile.in +++ b/src/build-data/makefile.in @@ -16,7 +16,7 @@ LANG_EXE_FLAGS = %{cc_lang_binary_linker_flags} CXXFLAGS = %{cc_compile_flags} WARN_FLAGS = %{cc_warning_flags} LIB_FLAGS = %{lib_flags} -LDFLAGS = %{ldflags} %{cc_compile_flags} +LDFLAGS = %{ldflags} EXE_LINK_CMD = %{exe_link_cmd} diff --git a/src/build-data/ninja.in b/src/build-data/ninja.in index e2ee02ed2c2..8746b4690fe 100644 --- a/src/build-data/ninja.in +++ b/src/build-data/ninja.in @@ -10,7 +10,7 @@ LANG_EXE_FLAGS = %{cc_lang_binary_linker_flags} CXXFLAGS = %{cc_compile_flags} WARN_FLAGS = %{cc_warning_flags} -LDFLAGS = %{ldflags} %{cc_compile_flags} +LDFLAGS = %{ldflags} EXE_LINK_CMD = %{exe_link_cmd} diff --git a/src/lib/math/bigint/big_ops2.cpp b/src/lib/math/bigint/big_ops2.cpp index 1b4589f5f13..46032db8ad3 100644 --- a/src/lib/math/bigint/big_ops2.cpp +++ b/src/lib/math/bigint/big_ops2.cpp @@ -11,6 +11,20 @@ #include #include +/* This hack works around an undefined reference to __udivti3() when compiling for 64-bit Windows + * using clang-cl, see: + * + * https://github.com/llvm/llvm-project/issues/25679 + * https://stackoverflow.com/questions/68676184/clang-cl-error-lld-link-error-undefined-symbol-divti3 + * + * I couldn't come up with a way to embed this into the build info files without extending + * configure.py to allow cpu-specific libs in the compiler info or os+cc+arch-specific libs in the + * module info. Hopefully this can go away when the above Clang issue is fixed anyway. +*/ +#if defined(_MSC_VER) && defined(_WIN64) && defined(__clang__) + #pragma comment(lib, "clang_rt.builtins-x86_64.lib") +#endif + namespace Botan { BigInt& BigInt::add(const word y[], size_t y_words, Sign y_sign) { diff --git a/src/lib/x509/certstor_flatfile/certstor_flatfile.h b/src/lib/x509/certstor_flatfile/certstor_flatfile.h index 67075bcebcb..db5547b0160 100644 --- a/src/lib/x509/certstor_flatfile/certstor_flatfile.h +++ b/src/lib/x509/certstor_flatfile/certstor_flatfile.h @@ -10,6 +10,7 @@ #define BOTAN_CERT_STORE_FLATFILE_H_ #include +#include #include #include