1、如何理解Qt支持跨平台?
答:我们经常听到这样的说法“如果考虑跨平台的话,qt是一个很好的选择”,感性认识上可能有一个模糊的认识,好像是这么回事,但是往深处想一想,可能又不知道所以然。这里说下我个人的浅浅的见解,不一定正确,希望给大家以启发。如果理解有误,请留言给我,不胜感激。
跨平台一般意义上的理解就是,开发人员写一份代码,理想情况下不需要修改任何代码,在别的平台上重新编译一下就可以运行。这里首先要理解“平台”的概念,什么是平台?平台就是硬件平台+操作系统的组合。例如X86+Windows组合,X86+Linux组合,arm+Linux组合等。硬件平台影响的是指令集,操作系统影响的是底层API接口。对于硬件平台来说,只要使用正确的编译器就可以生成对应的指令集。而操作系统则的不同可能会造成一些底层API的不同。所以说跨平台更多的是讲跨不同的操作系统。QT是如何解决这个问题的呢?QT支持大多数操作系统,并针对支持的操作系统进行了封装处理,将这些操作系统的接口抽象封装为统一接口(相当于一个平台层,该平台层对外呈现统一的接口,但是在不同的操作系统下调用不同的API接口),开发人员只要使用QT提供的类(如QDIR,用户无需关心操作系统的接口什么)进行操作,就能屏蔽底层操作系统差异,实现用统一的接口来实现系统调用的功能。从这个角度来说,qt是跨平台的。
QT支持的操作系统可以通过代码中提供的宏来体现:
在<QtGlobal>中,定义了各个系统的宏定义
Q_OS_AIX
Defined on AIX.
Q_OS_ANDROID
Defined on Android.
Q_OS_BSD4
Defined on Any BSD 4.4 system.
Q_OS_BSDI
Defined on BSD/OS.
Q_OS_CYGWIN
Defined on Cygwin.
Q_OS_DARWIN
Defined on Darwin-based operating systems such as macOS, iOS, watchOS, and tvOS.
Q_OS_DGUX
Defined on DG/UX.
Q_OS_DYNIX
Defined on DYNIX/ptx.
Q_OS_FREEBSD
Defined on FreeBSD.
Q_OS_HPUX
Defined on HP-UX.
Q_OS_HURD
Defined on GNU Hurd.
Q_OS_IOS
Defined on iOS.
Q_OS_IRIX
Defined on SGI Irix.
Q_OS_LINUX
Defined on Linux.
Q_OS_LYNX
Defined on LynxOS.
Q_OS_MAC
Deprecated synonym for Q_OS_DARWIN. Do not use.
Q_OS_MACOS
Defined on macOS.
Q_OS_NETBSD
Defined on NetBSD.
Q_OS_OPENBSD
Defined on OpenBSD.
Q_OS_OSF
Defined on HP Tru64 UNIX.
Q_OS_OSX
Deprecated synonym for Q_OS_MACOS. Do not use.
Q_OS_QNX
Defined on QNX Neutrino.
Q_OS_RELIANT
Defined on Reliant UNIX.
Q_OS_SCO
Defined on SCO OpenServer 5.
Q_OS_SOLARIS
Defined on Sun Solaris.
Q_OS_TVOS
Defined on tvOS.
Q_OS_ULTRIX
Defined on DEC Ultrix.
Q_OS_UNIX
Defined on Any UNIX BSD/SYSV system.
Q_OS_UNIXWARE
Defined on UnixWare 7, Open UNIX 8.
Q_OS_WATCHOS
Defined on watchOS.
Q_OS_WIN32
Defined on 32-bit and 64-bit versions of Windows.
Q_OS_WIN64
Defined on 64-bit versions of Windows.
Q_OS_WIN
Defined on all supported versions of Windows. That is, if Q_OS_WIN32, Q_OS_WIN64, or Q_OS_WINRT is defined.
Q_OS_WINPHONE
Defined on Windows Phone 8.
Q_OS_WINRT
Defined for Windows Runtime (Windows Store apps) on Windows 8, Windows RT, and Windows Phone 8.
2、Qt的是否支持交叉编译?
答:支持。我们大多数使用场景是桌面环境下,安装qt和对应的IDE(qtcreator),通过 IDE编译本平台下的应用程序或者库。那么对于交叉编译场景下(交叉编译使用场景)应该如何实现交叉编译呢?问出这个问题说明对qt的编译原理还是不太清楚的。qt编译过程中使用了qmake工具,通过这个工具可以生成工程项目的makefile文件。
我们都知道编译链接过程是根据makefile来完成的,所以我们若想实现交叉编译,只需要在在makefile中指定好编译要是用的交叉编译工具链即可。这里就涉及到了qmake是如何生成出makefile的,相关资料网上一大堆,这里不进行赘述。着重提一下的是需要修改对应平台的qmake.conf文件,在该文件中通过QMAKE_CC = xxx的方式指定交叉编译工具即可。
上述完成之后可以打开makefile文件查看编译器,若编译器中的CC中的内容为指定的编译器则表示修改成功。
3、qmake.cache的作用
答:在我们的工程目录中不知道大家是否注意过.qmake.cache这个文件,是否思考过这个文件的作用,这个文件是如何产生的?下面我将尽量详细的把这个文件讲明白。
首先要将这个文件不能绕开的是就是qmake,qmake的作用就是通过工程文件(.pro)生成该工程对应的makefile文件,qmake寻找pro文件有其固定的规则,这个不进行展开。更进一步将qmake是一个应用程序,该应用程序中使用c++实现,定义了一些函数接口,这些函数接口可以在pro文件以某种形式使用,达到函数调用的效果。下面介绍几个比较好的介绍qmake的网址:
qmake language 内建函数 内置函数 自定义函数 defineTest(testfunctionname) defineReplace(repacefunctionname)_丘上人的博客-CSDN博客
qmake 乱乱乱谈(二) | 求索阁
https://www.cnblogs.com/iriczhao/p/11274598.html
通过上面的介绍对qmake的有一个基本的认识,qmake要生成makefile,首先要有工程文件(.pro),然后是要告知qmake平台+编译器,没有这两项就无法生成对应的makefile。
qmake的工作方式流程默认情况下是首先查找.qmake.cache,若有则首先读取该文件中的配置;若没有找到,则读取工程文件和对应平台的qmake.conf文件,生成makefile。注意若.qmake.cache文件,则该文件中的配置会体现到makefile中,通过前面的讲述我们已经知道qmake整个过程涉及qmake.conf/.pro/.qmake.cache等三个文件,通过这几种类型的文件最终输出该工程对应的makefile文件。如果我们要修改makefile文件,只能从修改这三个文件入手,一般而言qmake.conf文件不进行修改(也可以进行修改,但是修改后会影响所有使用这个conf
的工程,除非重新自定义一个新的qmake.conf文件,方法在上面的链接中有涉及),所以我们一般修改.pro文件或者.qmake.cache文件来实现,从我的角度理解,一些针对某个平台需要的配置可以声明在.qmake.cache中,这是一般的做法,当然也可以将配置写在.pro文件中,使用.qmake.cache的好处是针对一个包含多个子项目(subdir)的工程来说,不需要在每个pro文件中写入同样的配置语句,在这个场景下是很有用处的。如果只有一个pro文件,那么.qmake.cache的必要性就没那么高。
.qmake.cahce的生成方法,在pro文件文件中写入如下例子代码,然后执行qmake就可以生成.qmake.cache:
var = 111
var1 = tt1
vars = gggg
!build_pass:cache(var,set) #向目标路径下的.qmake.cache中以append的方式写入var = 111
!build_pass:cache(var,set) #var与.qmake.cache中的var值一直,不写入
var=222
!build_pass:cache(var,set) #向目标路径下的.qmake.cache中以append的方式写入var = 222
!build_pass:cache(var,add,var1) #向目标路径下的.qmake.cache中以append的方式写入var += tt1
var2=111 zzz
!build_pass:cache(var,add,var2) #向目标路径下的.qmake.cache中以append的方式写入
#var += \
# 111 \
# zzz
var3=111 xxx
!build_pass:cache(var,sub,var3) #向目标路径下的.qmake.cache中以append的方式写入
#var -= \
# 111 \
# zzz
!build_pass:cache(var1,set transient) #为.qmake.cache所在的上下文(QMakeEvaluator)添加变量,但是不写入文件。
!build_pass:cache(vars,set stash) #向目标路径下的.qmake.stash中以append的方式写入var = 111
总结:
1、.qmake.cache文件在包含多个子项目中的工程中很有用,无需在每个pro文件中添加同样的配置代码
2、qmake执行时首先查找.qmake.cache文件,如果存在则将配置保存起来。然后再解析pro文件
3、一般而言,我们不会去修改qmake.conf,因为修改该文件,会影响所有使用该配置文件的工程,除非我们自定义一个qmake.conf文件
4、给出了如何生成.qmake.cache文件的方法