From 7e85e7ced7079d620ae73f8664a68530992c6af1 Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Wed, 10 Feb 2016 13:05:26 +0100 Subject: [PATCH] Add initial clang-cl support to Qt This adds the functionality to build Qt with clang under Windows against the Microsoft Visual Studio 2015 runtime. In order to replicate this, a Clang 3.8 build with Visual Studio 2015 Update 1 is needed. Adds compiler detection to Qt to distinguish correctly the clang compiler and Windows with Visual Studio. Clang has some built-in numeric functions, there is no need to use the Microsoft versions, which also conflict here. Task-number: QTBUG-50804 Change-Id: Ia4b267a298310ac7d73edf473b12792991249d8a Reviewed-by: Oswald Buddenhagen Reviewed-by: Friedemann Kleint --- configure.bat | 8 ++++- mkspecs/win32-clang-msvc2015/qmake.conf | 24 ++++++++++++++ mkspecs/win32-clang-msvc2015/qplatformdefs.h | 34 ++++++++++++++++++++ qmake/Makefile.win32 | 19 ++++++++--- src/corelib/global/qcompilerdetection.h | 9 ++++-- src/corelib/global/qnumeric_p.h | 6 ++-- tools/configure/Makefile.win32 | 10 ++++-- 7 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 mkspecs/win32-clang-msvc2015/qmake.conf create mode 100644 mkspecs/win32-clang-msvc2015/qplatformdefs.h diff --git a/configure.bat b/configure.bat index ecb1518f66..372b3faac5 100644 --- a/configure.bat +++ b/configure.bat @@ -34,7 +34,7 @@ set QTDIR=%CD% if not exist %QTSRC%.gitignore goto sconf echo Please wait while bootstrapping configure ... -for %%C in (cl.exe icl.exe g++.exe perl.exe jom.exe) do set %%C=%%~$PATH:C +for %%C in (clang-cl.exe cl.exe icl.exe g++.exe perl.exe jom.exe) do set %%C=%%~$PATH:C if "%perl.exe%" == "" ( echo Perl not found in PATH. Aborting. >&2 @@ -81,6 +81,12 @@ if not "%icl.exe%" == "" ( rem This must have a trailing space. echo QTSRC = %QTSRC% >> Makefile set tmpl=win32 +) else if not "%clang-cl.exe%" == "" ( + echo CXX = clang-cl>>Makefile + echo EXTRA_CXXFLAGS = -fms-compatibility-version=19.00.23506 -Wno-microsoft-enum-value>>Makefile + rem This must have a trailing space. + echo QTSRC = %QTSRC% >> Makefile + set tmpl=win32 ) else if not "%cl.exe%" == "" ( echo CXX = cl>>Makefile echo EXTRA_CXXFLAGS =>>Makefile diff --git a/mkspecs/win32-clang-msvc2015/qmake.conf b/mkspecs/win32-clang-msvc2015/qmake.conf new file mode 100644 index 0000000000..73cfdcbab9 --- /dev/null +++ b/mkspecs/win32-clang-msvc2015/qmake.conf @@ -0,0 +1,24 @@ +# +# qmake configuration for win32-clang-msvc2015 + +# +# Written for Clang 3.8 with Microsoft Visual C++ 2015 Update 1 +# Notice: this uses the clang-cl wrapper +# + +MSC_VER = 1900 +MSVC_VER = 14.0 +include(../common/msvc-desktop.conf) + +QMAKE_COMPILER += clang_cl llvm + +QMAKE_CC = clang-cl +QMAKE_CXX = $$QMAKE_CC + +QMAKE_CFLAGS += -fms-compatibility-version=19.00.23506 -Wno-microsoft-enum-value +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS + +# Precompiled headers are not supported yet by clang +CONFIG -= precompile_header + +load(qt_config) diff --git a/mkspecs/win32-clang-msvc2015/qplatformdefs.h b/mkspecs/win32-clang-msvc2015/qplatformdefs.h new file mode 100644 index 0000000000..7100e3aa41 --- /dev/null +++ b/mkspecs/win32-clang-msvc2015/qplatformdefs.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../win32-msvc2005/qplatformdefs.h" diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 1e8c5129be..1d50f872d9 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -14,6 +14,10 @@ QMKSRC = $(SOURCE_PATH)\qmake CXX = icl LINKER = link CFLAGS_EXTRA = /Zc:forScope /Qstd=c++11 +!elseif "$(QMAKESPEC)" == "win32-clang-msvc2015" +CXX = clang-cl +LINKER = link +CFLAGS_EXTRA = -fms-compatibility-version=19.00.23506 -Wno-microsoft-enum-value !else CXX = cl LINKER = link @@ -21,13 +25,18 @@ LINKER = link CFLAGS_EXTRA = /Zc:wchar_t- ! elseif "$(QMAKESPEC)" == "win32-msvc2008" || "$(QMAKESPEC)" == "win32-msvc2010" || "$(QMAKESPEC)" == "win32-msvc2012" || "$(QMAKESPEC)" == "win32-msvc2013" CFLAGS_EXTRA = /MP /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS $(CFLAGS_CRT) -! elseif "$(QMAKESPEC)" == "win32-msvc2015" +! elseif "$(QMAKESPEC)" == "win32-msvc2015" || "$(QMAKESPEC)" == "win32-clang-msvc2015" CFLAGS_EXTRA = /MP /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /Zc:strictStrings /w44456 /w44457 /w44458 /wd4577 $(CFLAGS_CRT) ! else ! error Unsupported compiler for this Makefile ! endif !endif # !win32-icc +!if "$(QMAKESPEC)" != "win32-clang-msvc2015" +CFLAGS_PCH = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch +PCH_OBJECT = qmake_pch.obj +!endif + CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ -W3 -nologo -O1 \ $(CFLAGS_EXTRA) \ @@ -41,7 +50,7 @@ CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \ -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \ -DUNICODE -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY -DQT_NO_STANDARDPATHS -CFLAGS = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch $(CFLAGS_BARE) $(CFLAGS) +CFLAGS = $(CFLAGS_PCH) $(CFLAGS_BARE) $(CFLAGS) CXXFLAGS_BARE = $(CFLAGS_BARE) CXXFLAGS = $(CFLAGS) @@ -129,7 +138,7 @@ QTOBJS= \ first all: qmake.exe qmake.exe: $(OBJS) $(QTOBJS) - $(LINKQMAKE) qmake_pch.obj + $(LINKQMAKE) $(PCH_OBJECT) -copy qmake.exe $(BUILD_PATH)\bin\qmake.exe clean:: @@ -158,9 +167,9 @@ distclean:: clean .cxx.obj: $(CXX) $(CXXFLAGS) $< -$(OBJS): qmake_pch.obj +$(OBJS): $(PCH_OBJECT) -$(QTOBJS): qmake_pch.obj +$(QTOBJS): $(PCH_OBJECT) qlibraryinfo.obj: $(BUILD_PATH)\src\corelib\global\qconfig.cpp diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index e655aace32..7575fe06b2 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -83,6 +83,9 @@ # endif #elif defined(_MSC_VER) +# ifdef __clang__ +# define Q_CC_CLANG ((__clang_major__ * 100) + __clang_minor__) +# endif # define Q_CC_MSVC (_MSC_VER) # define Q_CC_MSVC_NET # define Q_OUTOFLINE_TEMPLATE inline @@ -97,7 +100,9 @@ # define Q_UNREACHABLE_IMPL() __assume(0) # define Q_NORETURN __declspec(noreturn) # define Q_DECL_DEPRECATED __declspec(deprecated) -# define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text)) +# ifndef Q_CC_CLANG +# define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text)) +# endif # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ @@ -1177,7 +1182,7 @@ # define QT_WARNING_DISABLE_MSVC(number) # define QT_WARNING_DISABLE_CLANG(text) # define QT_WARNING_DISABLE_GCC(text) -#elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 +#elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 && !defined(Q_CC_CLANG) # undef QT_DO_PRAGMA /* not needed */ # define QT_WARNING_PUSH __pragma(warning(push)) # define QT_WARNING_POP __pragma(warning(pop)) diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index f58e062dbd..5705bc29c8 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -222,7 +222,7 @@ template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v # define HAVE_MUL64_OVERFLOW #endif -#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) +#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) { return _addcarry_u32(0, v1, v2, r); } # ifdef Q_CC_MSVC // longs are 32-bit @@ -230,7 +230,7 @@ template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigne { return _addcarry_u32(0, v1, v2, reinterpret_cast(r)); } # endif #endif -#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) +#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r) { return _addcarry_u64(0, v1, v2, reinterpret_cast(r)); } # ifndef Q_CC_MSVC // longs are 64-bit @@ -239,7 +239,7 @@ template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigne # endif #endif -#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) +#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) #pragma intrinsic(_umul128) template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) { diff --git a/tools/configure/Makefile.win32 b/tools/configure/Makefile.win32 index c83ecaaeea..17a758c795 100644 --- a/tools/configure/Makefile.win32 +++ b/tools/configure/Makefile.win32 @@ -2,11 +2,17 @@ CORESRC = $(QTSRC)src\corelib TOOLSRC = $(QTSRC)tools CONFSRC = $(TOOLSRC)\configure -PCH = configure_pch.pch DEFINES = -DUNICODE -DQT_NO_CODECS -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NO_COMPRESS -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -D_CRT_SECURE_NO_DEPRECATE -DQT_BOOTSTRAPPED -DQT_BUILD_CONFIGURE -DQT_VERSION_STR=\"$(QTVERSION)\" -DQT_VERSION_MAJOR=$(QT_VERSION_MAJOR) -DQT_VERSION_MINOR=$(QT_VERSION_MINOR) -DQT_VERSION_PATCH=$(QT_VERSION_PATCH) INCPATH = -I"..\..\include" -I"..\..\include\QtCore" -I"..\..\include\QtCore\$(QTVERSION)" -I"..\..\include\QtCore\$(QTVERSION)\QtCore" -I"$(TOOLSRC)\shared" -I"$(QTSRC)mkspecs\win32-msvc2012" CXXFLAGS_BARE = -nologo -Zc:wchar_t -W3 -GR -EHsc -w34100 -w34189 -wd4577 $(CFLAGS_CRT) $(EXTRA_CXXFLAGS) $(DEFINES) $(INCPATH) +!IF ("$(CXX)" != "clang-cl") +PCH = configure_pch.pch +PCH_OBJECT = configure_pch.obj CXXFLAGS = -FIconfigure_pch.h -Yuconfigure_pch.h -Fp$(PCH) -MP $(CXXFLAGS_BARE) +!ELSE +PCH = +CXXFLAGS = -Wmicrosoft $(CXXFLAGS_BARE) +!ENDIF LINK = link LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO /SUBSYSTEM:CONSOLE "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /MANIFEST /MANIFESTFILE:"configure.intermediate.manifest" LIBS = ole32.lib advapi32.lib shell32.lib @@ -71,7 +77,7 @@ OBJECTS = \ qxmlutils.obj \ quuid.obj \ registry.obj \ - configure_pch.obj + $(PCH_OBJECT) $(TARGET): $(OBJECTS) $(LINK) $(LFLAGS) /OUT:$(TARGET) @<<