Skip to content

Commit

Permalink
Add Windows Desktop arm64 target to Qtbase
Browse files Browse the repository at this point in the history
Allows a qt build to be configured to target arm64 desktop apps cross
platform and build them with nmake.

Change-Id: I99fed12047b45a504a1644201bcc19b18c69f3e6
Reviewed-by: Oswald Buddenhagen <[email protected]>
Reviewed-by: Oliver Wolff <[email protected]>
  • Loading branch information
thomaslmiller authored and liangqi committed Nov 11, 2018
1 parent 59a0902 commit fbbe8ab
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 21 deletions.
15 changes: 15 additions & 0 deletions mkspecs/win32-arm64-msvc2017/qmake.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# qmake configuration for win32-arm64-msvc2017
#
# Written for Microsoft C/C++ Optimizing Compiler targeting arm64.
#

include(../common/msvc-desktop.conf)

WINSDK_VER = 10.0
VCPROJ_ARCH = ARM64

DEFINES += WIN64
QMAKE_COMPILER_DEFINES += _WIN64

load(qt_config)
40 changes: 40 additions & 0 deletions mkspecs/win32-arm64-msvc2017/qplatformdefs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "../win32-msvc/qplatformdefs.h"
46 changes: 34 additions & 12 deletions qmake/generators/win32/msvc_nmake.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,28 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
return MakefileGenerator::writeStubMakefile(t);
#endif
if (!project->isHostBuild()) {
const QString msvcVer = project->first("MSVC_VER").toQString();
if (msvcVer.isEmpty()) {
fprintf(stderr, "Mkspec does not specify MSVC_VER. Cannot continue.\n");
return false;
}

bool winrtBuild = false;
bool crossPlatformDesktopBuild = false;
QString arch = project->first("VCPROJ_ARCH").toQString().toLower();
if (project->isActiveConfig(QStringLiteral("winrt"))) {
QString arch = project->first("VCPROJ_ARCH").toQString().toLower();
winrtBuild = true;

// Only add explicit support for arm64 cross-platform desktop builds.
} else if ((arch == QLatin1String("arm64")) && (msvcVer == QStringLiteral("15.0"))) {
crossPlatformDesktopBuild = true;
}

if (winrtBuild || crossPlatformDesktopBuild) {
QString compiler;
QString compilerArch;
const QString msvcVer = project->first("MSVC_VER").toQString();
if (msvcVer.isEmpty()) {
fprintf(stderr, "Mkspec does not specify MSVC_VER. Cannot continue.\n");
return false;
}

const ProStringList hostArch = project->values("QMAKE_TARGET.arch");
if (msvcVer == QStringLiteral("15.0")) {
const ProStringList hostArch = project->values("QMAKE_TARGET.arch");
if (hostArch.contains("x86_64"))
compiler = QStringLiteral("HostX64/");
else
Expand All @@ -93,6 +103,9 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
} else if (arch == QLatin1String("x64")) {
compiler += QStringLiteral("x64");
compilerArch = QStringLiteral("amd64");
} else if (arch == QLatin1String("arm64")) {
compiler += QStringLiteral("arm64");
compilerArch = QStringLiteral("arm64");
} else {
arch = QStringLiteral("x86");
compiler += QStringLiteral("x86");
Expand All @@ -119,7 +132,7 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
return false;
}
const QString targetVer = project->first("WINTARGET_VER").toQString();
if (targetVer.isEmpty()) {
if (targetVer.isEmpty() && winrtBuild) {
fprintf(stderr, "Mkspec does not specify WINTARGET_VER. Cannot continue.\n");
return false;
}
Expand Down Expand Up @@ -181,10 +194,19 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
incDirs << crtInclude + QStringLiteral("/shared");
incDirs << crtInclude + QStringLiteral("/winrt");

incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
+ crtVersion + QStringLiteral("/Include/WinRT");
if (winrtBuild) {
// Only use mobile-specific headers and link against store-specific libs for
// winrt builds.
incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
+ crtVersion + QStringLiteral("/Include/WinRT");

libDirs << toolsInstallDir + QStringLiteral("lib/") + arch + QStringLiteral("/store");
libDirs << toolsInstallDir + QStringLiteral("lib/") + arch + QStringLiteral("/store");
} else {
// Desktop projects may require the atl headers and libs.
incDirs << toolsInstallDir + QStringLiteral("atlmfc/include");
libDirs << toolsInstallDir + QStringLiteral("atlmfc/lib/") + compilerArch;
libDirs << toolsInstallDir + QStringLiteral("lib/") + arch;
}

libDirs << vcInstallDir + QStringLiteral("VC/Auxiliary/VS/lib/") + arch;

Expand Down
8 changes: 4 additions & 4 deletions src/3rdparty/angle/src/common/mathutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ inline bool supportsSSE2()
return supports;
}

#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) && !defined(_M_ARM64)
{
int info[4];
__cpuid(info, 0);
Expand All @@ -162,7 +162,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
}
#endif // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
#endif // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) && !defined(_M_ARM64)
checked = true;
return supports;
#else // defined(ANGLE_USE_SSE)
Expand Down Expand Up @@ -884,14 +884,14 @@ inline uint32_t BitfieldReverse(uint32_t value)

// Count the 1 bits.
#if defined(ANGLE_PLATFORM_WINDOWS)
#if defined(_M_ARM)
#if defined(_M_ARM) || defined(_M_ARM64)
inline int BitCount(uint32_t bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
return (((bits + (bits >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
#else // _M_ARM
#else // _M_ARM || _M_ARM64
inline int BitCount(uint32_t bits)
{
return static_cast<int>(__popcnt(bits));
Expand Down
2 changes: 1 addition & 1 deletion src/3rdparty/angle/src/common/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
# undef far
#endif

#if defined(_MSC_VER) && !defined(_M_ARM)
#if defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64)
#include <intrin.h>
#define ANGLE_USE_SSE
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && !defined(__MINGW32__)
Expand Down
63 changes: 63 additions & 0 deletions src/angle/patches/0011-ANGLE-Fix-build-for-ARM64.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
From 416fb93dae5009bb51da9f6720a95918a2c79e78 Mon Sep 17 00:00:00 2001
From: Thomas Miller <[email protected]>
Date: Tue Oct 16 08:29:58 2018 -0700
Subject: [PATCH] ANGLE: Fix build for ARM64

__popcnt, SSE, and intrin.h are not available when building for ARM64.
---
src/3rdparty/angle/src/common/mathutil.h | 8 ++++----
src/3rdparty/angle/src/common/platform.h | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
index 372e432066..88aedddfe8 100644
--- a/src/3rdparty/angle/src/common/mathutil.h
+++ b/src/3rdparty/angle/src/common/mathutil.h
@@ -150,7 +150,7 @@ inline bool supportsSSE2()
return supports;
}

-#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) && !defined(_M_ARM64)
{
int info[4];
__cpuid(info, 0);
@@ -162,7 +162,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
}
-#endif // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+#endif // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) && !defined(_M_ARM64)
checked = true;
return supports;
#else // defined(ANGLE_USE_SSE)
@@ -884,14 +884,14 @@ inline uint32_t BitfieldReverse(uint32_t value)

// Count the 1 bits.
#if defined(ANGLE_PLATFORM_WINDOWS)
-#if defined(_M_ARM)
+#if defined(_M_ARM) || defined(_M_ARM64)
inline int BitCount(uint32_t bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
return (((bits + (bits >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
-#else // _M_ARM
+#else // _M_ARM || _M_ARM64
inline int BitCount(uint32_t bits)
{
return static_cast<int>(__popcnt(bits));
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index 47cd57b999..fb251da579 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -83,7 +83,7 @@
# undef far
#endif

-#if defined(_MSC_VER) && !defined(_M_ARM)
+#if defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64)
#include <intrin.h>
#define ANGLE_USE_SSE
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && !defined(__MINGW32__)
9 changes: 5 additions & 4 deletions src/corelib/global/qprocessordetection.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@
ARM is bi-endian, detect using __ARMEL__ or __ARMEB__, falling back to
auto-detection implemented below.
*/
#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(__aarch64__) || defined(__ARM64__)
# if defined(__aarch64__) || defined(__ARM64__)
#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
# if defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64)
# define Q_PROCESSOR_ARM_64
# define Q_PROCESSOR_WORDSIZE 8
# else
Expand All @@ -110,7 +110,8 @@
# elif defined(__ARM64_ARCH_8__) \
|| defined(__aarch64__) \
|| defined(__ARMv8__) \
|| defined(__ARMv8_A__)
|| defined(__ARMv8_A__) \
|| defined(_M_ARM64)
# define Q_PROCESSOR_ARM 8
# elif defined(__ARM_ARCH_7__) \
|| defined(__ARM_ARCH_7A__) \
Expand Down Expand Up @@ -148,7 +149,7 @@
# else
# error "ARM architecture too old"
# endif
# if defined(__ARMEL__)
# if defined(__ARMEL__) || defined(_M_ARM64)
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# elif defined(__ARMEB__)
# define Q_BYTE_ORDER Q_BIG_ENDIAN
Expand Down

0 comments on commit fbbe8ab

Please sign in to comment.