qmake的使用

qmake的使用前言在linux环境下进行程序开发时,经常需要使用makefile管理编译代码,特别是一些大型工程,而makefile工具语法晦涩深入研究较为困难,好在有很多工具可以自动生成makefile,qmake就是其中的一种。qmake特点为不同的平台的开发项目创建makefile。可以供给任何一个软件项目使用,而不用管它是不是用Qt写的,尽管它包含了为支持Qt开发所拥有的额外的特征。…

大家好,又见面了,我是你们的朋友全栈君。

前言

在linux环境下进行程序开发时,经常需要使用makefile管理编译代码,特别是一些大型工程,而makefile工具语法晦涩深入研究较为困难,好在有很多工具可以自动生成makefile,qmake就是其中的一种。

qmake特点

  • 为不同的平台的开发项目创建makefile。
  • 可以供给任何一个软件项目使用,而不用管它是不是用Qt写的,尽管它包含了为支持Qt开发所拥有的额外的特征。
  • qmake基于一个项目文件这样的信息来生成makefile。项目文件可以由开发者生成。
  • 不用修改项目文件,qmake也可以为Microsoft Visual Studio生成项目。

.pro文件说明

  • 注释-#

  • TEMPLATE 模板

    app – 建立一个应用程序的makefile(默认值)。
    vcapp – 建立一个应用程序的Visual Studio项目文件。
    lib – 建立一个库的makefile。
    vclib – 建立一个库的Visual Studio项目文件。
    subdirs – 这是一个特殊的模板,它可以创建一个能够进入特定目录,并且为一个项目文件生成。 makefile,并且为它调用make的makefile。

  • app模板

    使用该模板时,下面这些qmake系统变量是被承认的,在.pro文件中使用它们来为应用程序指定特定信息。

    TARGET – 可执行应用程序的名称。
    HEADERS – 应用程序中的所有头文件的列表。
    SOURCES – 应用程序中的所有源文件的列表。
    DEFINES – 应用程序所需的额外的预处理程序定义的列表。
    DESTDIR – 放置可执行程序目标的目录。
    OBJECTS_DIR – 指定目标文件(obj)的存放目录。
    INCLUDEPATH – 应用程序所需的额外的包含路径的列表。
    DEPENDPATH – 应用程序所依赖的搜索路径。
    VPATH – 寻找补充文件的搜索路径。
    LIBS – 包含要链接到project的库的列表文件/ 路径。用-l (library) 和 -L(library path)。
    FORMS – 应用程序中的所有.ui文件(由Qt设计器生成)的列表。
    LEXSOURCES – 应用程序中的所有lex源文件的列表。
    YACCSOURCES – 应用程序中的所有yacc源文件的列表。
    DEF_FILE – 只有Windows需要:应用程序所要连接的.def文件。
    RC_FILE – 只有Windows需要:应用程序的资源文件。
    RES_FILE – 只有Windows需要:应用程序所要连接的资源文件。
    QMAKE_LFLAGS-设置链接器flag参数,会修改Makefile的LFLAGS选项。该参数包含了传递给连接器的一组通用的标记。使用指定的QMAKE_LFLAGS的好处在于,能够根据当前编译的不同配置选择不同路径下的依赖库。QMAKE_LFLAGS += -Wl,-rpath=./sqlite3,这样编译生成的可执行文件依赖的sqlite库就会是./sqlite3

  • lib模板

    lib模板告诉qmake为建立一个而生成makefile。当使用这个模板时,除了app模板中提到系统变量,还有一个VERSION是被支持的。VERSION – 目标库的版本号,比如2.3.1。

  • subdirs模板

    subdirs模板告诉qmake生成一个makefile,它可以进入到特定子目录并为这个目录中的项目文件生成makefile并且为它调用make。在这个模板中只有一个系统变量SUBDIRS可以被识别。这个变量中包含了所要处理的含有项目文件的子目录的列表。这个项目文件的名称是和子目录同名的,这样qmake就可以发现它。例如,如果子目里是“myapp”,那么在这个目录中的项目文件应该被叫做myapp.pro。

  • CONFIG变量

    配置变量指定了编译器所要使用的选项和所需要被连接的库。

    下面这些选项控制着使用哪些编译器标志:

    release – 应用程序将以release模式连编,如果“debug”被指定,它将被忽略。
    debug – 应用程序将以debug模式连编。
    warn_on – 编译器会输出尽可能多的警告信息,如果“warn_off”被指定,它将被忽略。
    warn_off – 编译器会输出尽可能少的警告信息。
    debug_and_release : The project is built in both debug and release modes.
    debug_and_release_target: The project is built in both debug and release modes. TARGET is built into both the debug and release directories.
    build_all : If debug_and_release is specified, the project is built in both debug and release modes by default.

    下面这些选项定义了所要连编的库/应用程序的类型:

    qt – 应用程序是一个Qt应用程序,并且Qt库将会被连接。
    thread – 应用程序是一个多线程应用程序。
    x11 – 应用程序是一个x11应用程序或库。
    windows – 只用于app模板:应用程序是一个Windows下的窗口应用程序。
    console – 只用于app模板:应用程序是一个Windows下的控制台应用程序。
    dll – 只用于lib模板:库是一个共享库(dll)。
    staticlib – 只用于lib模板:库是一个静态库。
    plugin – 只用于lib模板:库是一个插件,这将会使dll选项生效。

  • 不同平台

    win32{ SOURCES += xx.cpp }
    unix{ SOURCES += xx.cpp }

.pro实例

TEMPLATE = lib #lib库,app可执行工程
TARGET = Func
CONFIG += console c++11 #C++11标准
CONFIG -= qt

DEFINES += IOS_64 #64位
DEFINES += IOS_LINUX #Linux系统

QMAKE_CXXFLAGS += -fPIC
QMAKE_LFLAGS_DEBUG += -L$$PWD/../../Bin/Debug/
QMAKE_LFLAGS_DEBUG += -Wl,-rpath=../../Bin/Debug/
QMAKE_LFLAGS_RELEASE += -L$$PWD/../../Bin/Debug/
QMAKE_LFLAGS_RELEASE += -Wl,-rpath=../../Bin/Debug/

LIBS += -ldl #要链接的库
LIBS += -lboost_thread

release: CurConfig = Release
debug:   CurConfig = Debug

DESTDIR = ../../Bin/$$CurConfig/ #目标文件的最终路径,从pro文件开始的相对路径 
OBJECTS_DIR = obj/$$CurConfig #.o文件的目录

SOURCES += \
    ../FunPublic/ts1.cpp \
    ../FunPublic/ts2.cpp \
    ../FunPublic/ts3.cpp \

HEADERS += \
    ../FunPublic/ts1.h \
    ../FunPublic/ts2.h \
    ../FunPublic/ts3.h \

unix {
    target.path = /usr/lib
    INSTALLS += target
}

INCLUDEPATH += /usr/local/cuda/include/

QMAKE_LFLAGS += -shared
QMAKE_LFLAGS += -L$$PWD/../../Bin/Debug/

QMAKE_LFLAGS += -L$$PWD/../../../../ThirdPartyLib/openrave-0.9/lib
QMAKE_LFLAGS += -Wl,-rpath=../../../../ThirdPartyLib/openrave-0.9/lib/


#如果要添加链接库,只需要加载头文件路径和动态库路径即可
# INCLUDEPATH += /usr/local/cuda/include/ #相对路径是相对工程文件pro的路径
# QMAKE_LFLAGS += -L$$PWD/../../../../ThirdPartyLib/openrave-0.9/lib #相对路径是相对工程文件pro的路径 编译时静态链接
# QMAKE_LFLAGS += -Wl,-rpath=../../../../ThirdPartyLib/openrave-0.9/lib/ #相对路径是相对工作路径 运行时动态链接
# QMAKE_LFLAGS += -Wl,-rpath=\\\$\$ORIGIN/jsoncpp #相对路径是相对so库路径 运行时动态链接

qmake实例

SOURCES = hello.cpp main.cpp
HEADERS = hello.h
CONFIG += qt warn_on release

生成makefile (makefile是根据.pro文件参数生成的):
qmake -o Makefile hello.pro
qmake -t vcapp -o hello.dsp hello.pro
可以使用qmake -h查看具体的说明

qmake生成makefile

  • 使用Qt编译一次,查看是否有程序错误链接错误等

  • 若编译无误,则在pro目录下使用qmake xx.pro -o Makefile这时便自动生成了Makefile文件

  • 当在其他平台上make编译时,可能编译出现如下错误(如NanoPi)

    g++ -c -m64 -pipe -O2 -Wall -W   -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include -o main.o main.cpp 
    In file included from /usr/include/c++/4.8/thread:35:0,
                   from baseserver.h:10,
                   from server.h:4,
                   from rdatas.h:4,
                   from main.cpp:3:
    /usr/include/c++/4.8/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
    
    #error This file requires compiler and library support for the \
    
    ^
    In file included from rdatas.h:4:0,
                   from main.cpp:3:
    server.h:20:14: warning: ‘void* ServerThread(void*)’ declared ‘static’ but never defined [-Wunused-function]
    static void *ServerThread(void *);
                ^
    make: *** [main.o] Error 1
    
  • 根据提示需要添加-std=c++11,于是把该项添加到CXXFLAGS即可

    其实qmake生成的Makefile内容很多无用的关于qt的项目可以删除,最主要的是如下部分

    
    # 以下可以选择性删除
    
    CC            = gcc
    CXX           = g++
    CXXFLAGS      = -pipe -O2 -Wall -W $(DEFINES) -std=c++11
    INCPATH       = -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include
    LINK          = g++
    LFLAGS        = -Wl,-O1
    LIBS          = $(SUBLIBS)   -ljson -lpthread 
    OBJS        = main.o baseserver.o server.o baseuart.o rdatas.o
    
    
    # 这里自己添加总的编译结果
    
    demo: $(OBJS)
    $(CXX) $(CXXFLAGS) $(OBJS) $(LIBS) -o $@ 
    
    
    # 以下是copy的qmake自动生成的compile
    
    main.o: main.cpp rdatas.h \
        server.h \
        baseserver.h
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp 
    
    baseserver.o: baseserver.cpp baseserver.h
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o baseserver.o baseserver.cpp
    
    server.o: server.cpp server.h \
        baseserver.h
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o server.o server.cpp
    
    baseuart.o: baseuart.cpp baseuart.h
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o baseuart.o baseuart.cpp
    
    rdatas.o: rdatas.cpp rdatas.h \
        server.h \
        baseserver.h
    $(CXX) -c $(CXXFLAGS) $(INCPATH) -o rdatas.o rdatas.cpp
    
    clean:
    rm *.o demo
  • 在不同平台上运行时可能有找不到文件或识别不了文件格式等错误,删除相关项目即可

调试经验

  • 在linux平台下可以用ldd命令查看so库所依赖的其他so库,readelf -d libxxx.so | grep rpath查看xxx.so配置的依赖库的链接路径
  • qt如果勾选编译的shadow路径,那么生成的系列文件将不按照pro文件生成,而是生成在shadow路径
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144239.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 宽字节注入原理分析[通俗易懂]

    宽字节注入原理分析[通俗易懂]什么是宽字节?如果一个字符的大小是一个字节的,称为窄字节;如果一个字符的大小是两个字节的,成为宽字节。像GB2312、GBK、GB18030、BIG5、Shift_JIS等这些编码都是常说的宽字节,也就是只有两字节英文默认占一个字节,中文占两个字节什么是宽字节注入?原理:宽字节注入是利用了mysql的一个特性,即mysql在使用GBK编码时,在url解码时会认为两个字符是一个汉字(前一个ASCII码要大于128,才表示到汉字的范围)通常情况下,一个utf-8编码的汉子占用3个字节,一个GBK编

    2022年10月15日
    0
  • Vue上传文件遇到的问题[通俗易懂]

    Vue上传文件遇到的问题[通俗易懂]问题之前项目中前端使用了vue-cli,引入了上传组件,所以在上传文件时很容易,没有考虑太多问题。image-cropper组件中有url属性,直接使用:url=”文件服务器地址”绑定上传的地址即可。<el-form-itemlabel=”讲师头像”><!–头衔缩略图–><pan-thumb:image=”teacher.avatar”/><!–文件上传按钮–><el-buttontype=

    2022年10月9日
    0
  • 在浏览器中调试 JavaScript

    在浏览器中调试 JavaScript在本教程中 您将借助示例了解 JavaScript 中的调试

    2025年6月5日
    0
  • equals和==的区别

    equals和==的区别

    2021年9月12日
    55
  • django_filters实现数据过滤

    django_filters实现数据过滤1、视图classUserView(ListAPIView):”””用户列表”””queryset=User.objects.all()serializer_class=UserSerializerfilter_backends=(DjangoFilterBackend,)filter_class=UserMonthFilt…

    2022年5月21日
    32
  • uuid截取_jsp获取session中的值

    uuid截取_jsp获取session中的值switch_core_session_t*session=NULL;if(!(session=switch_core_session_locate(channel_uuid))){       return;}

    2022年8月10日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号