.pri 文件详解
.pri 文件是 qmake 的包含文件(Include File),用于在多个 .pro 项目文件中共享配置和设置,类似于 C/C++ 中的头文件。以下是关于 .pri 文件的全面解析。
基本概念
主要特点
-
共享配置:可以在多个
.pro文件中复用相同的配置 -
模块化管理:将公共设置、编译器标志、路径定义等集中管理
-
层次结构:支持嵌套包含,一个
.pri可以包含其他.pri -
平台特定配置:可以在单个文件中管理多平台设置
命名约定
-
通常以
.pri为扩展名 -
常见命名:
common.pri、config.pri、settings.pri等 -
可以按功能模块命名:
qt_settings.pri、thirdparty.pri等
基本语法
包含方式
在 .pro 文件中包含 .pri 文件:
include(path/to/file.pri)
或使用相对路径:
include(../common/config.pri)
示例结构
# common.pri 示例
# 定义变量
MY_PROJECT_ROOT = $$PWD/..
# 公共编译选项
CONFIG += c++17 warn_on debug_and_release
# Qt 模块配置
QT += core gui network
# 公共包含路径
INCLUDEPATH += \
$$MY_PROJECT_ROOT/include \
$$MY_PROJECT_ROOT/thirdparty
# 平台特定设置
win32 {
LIBS += -lws2_32
}
unix:!macx {
LIBS += -lpthread
}
核心功能
1. 变量定义与使用
# 定义变量 MY_LIB_PATH = $$PWD/../libs # 使用变量 LIBS += -L$$MY_LIB_PATH -lmylib # 条件变量赋值 !defined(MY_DEBUG_LEVEL, var): MY_DEBUG_LEVEL = 1
2. 函数定义与使用
# 定义函数
defineTest(addDebug) {
CONFIG += debug
DEFINES += DEBUG_MODE=$$1
return(true)
}
# 使用函数
!addDebug(3) {
message("Debug configuration failed")
}
3. 条件配置
# 根据变量值配置
contains(QT, network) {
DEFINES += HAVE_NETWORK
}
# 平台判断
macx {
ICON = myapp.icns
} else {
DEFINES += NO_RESOURCE_ICON
}
4. 文件操作
# 检查文件是否存在
exists($$MY_PROJECT_ROOT/custom.pri) {
include($$MY_PROJECT_ROOT/custom.pri)
}
# 遍历目录
for(file, $$files($$PWD/*.cpp)) {
SOURCES += $$file
}
高级用法
1. 配置继承与覆盖
# base.pri CONFIG += feature_base DEFINES += BASE_DEFINE=1 # derived.pri include(base.pri) CONFIG -= feature_base CONFIG += feature_derived DEFINES += DERIVED_DEFINE=1
2. 参数化包含
# config.pri !defined(DEBUG_LEVEL, var): DEBUG_LEVEL = 1 DEFINES += DEBUG_LEVEL=$$DEBUG_LEVEL # project.pro include(config.pri DEBUG_LEVEL=3)
3. 错误处理与验证
# 检查必需变量
isEmpty(MY_PROJECT_ROOT) {
error("MY_PROJECT_ROOT must be defined")
}
# 版本检查
versionAtLeast(QT_VERSION, 5.15.0) {
DEFINES += QT_NEW_FEATURES
} else {
warning("Requires Qt 5.15.0 or higher")
}
4. 生成文件
# 生成配置文件 version.target = version.h version.commands = echo "#define APP_VERSION \\"$$VERSION\\"" > $$version.target QMAKE_EXTRA_TARGETS += version PRE_TARGETDEPS += version.h
实际应用示例
场景1:管理第三方库
# thirdparty.pri
# Boost 配置
BOOST_ROOT = $$MY_PROJECT_ROOT/thirdparty/boost
INCLUDEPATH += $$BOOST_ROOT
win32 {
LIBS += -L$$BOOST_ROOT/lib -lboost_system
}
# OpenCV 配置
!defined(OPENCV_DIR): OPENCV_DIR = /usr/local/opencv
exists($$OPENCV_DIR) {
INCLUDEPATH += $$OPENCV_DIR/include
LIBS += -L$$OPENCV_DIR/lib -lopencv_core -lopencv_highgui
} else {
error("OpenCV not found at $$OPENCV_DIR")
}
场景2:跨平台配置
# platform.pri
# 编译器标志
QMAKE_CXXFLAGS += -Wall -Wextra
# 平台特定设置
win32 {
# Windows 配置
DEFINES += WIN32_LEAN_AND_MEAN
RC_FILE = resources.rc
}
macx {
# macOS 配置
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.15
ICON = app.icns
}
linux {
# Linux 配置
DEFINES += LINUX
QMAKE_LFLAGS += -Wl,--as-needed
}
场景3:功能模块化
# features.pri
# 可选功能开关
contains(CONFIG, feature_audio) {
QT += multimedia
DEFINES += WITH_AUDIO
SOURCES += audiomanager.cpp
HEADERS += audiomanager.h
}
contains(CONFIG, feature_network) {
QT += network
DEFINES += WITH_NETWORK
include(network_config.pri)
}
示例分析
!isEmpty(CONFIG_PRI_INCLUDED):error("config.pri already included")
CONFIG_PRI_INCLUDED = 1
CONFIG_VERSION = 1.0.0
QT += core gui widgets
CONFIG += no_batch c++14 no_moc_predefs
CONFIG += force_debug_info
defineReplace(qtLibraryTargetName) {
unset(LIBRARY_NAME)
LIBRARY_NAME = $$1
CONFIG(debug, debug|release) {
!debug_and_release|build_pass {
win32:RET = $$member(LIBRARY_NAME, 0)d
}
}
isEmpty(RET):RET = $$LIBRARY_NAME
return($$RET)
}
defineTest(qtCopy) {
source = $$system_path($$1)
target = $$system_path($$2)
win32:system(xcopy $$source $$target /S /H /D /F /Y)
return(true)
}
exists($$PWD/../userconfig.pri) {
include($$PWD/../userconfig.pri)
isEmpty(CONFIG_OUTPUT_PATH):CONFIG_OUTPUT_PATH = $$PWD/../bin
}
isEmpty(APP_TARGET):APP_TARGET = Application
isEmpty(CONFIG_SOURCE_TREE):CONFIG_SOURCE_TREE = $$PWD
isEmpty(CONFIG_BUILD_TREE) {
sub_dir = $$_PRO_FILE_PWD_
sub_dir ~= s,^$$re_escape($$PWD),,
CONFIG_BUILD_TREE = $$clean_path($$OUT_PWD)
CONFIG_BUILD_TREE ~= s,$$re_escape($$sub_dir)$,,
}
exists($$PWD/../userconfig.pri) {
include($$PWD/../userconfig.pri)
isEmpty(CONFIG_OUTPUT_PATH):CONFIG_OUTPUT_PATH = $$PWD/../bin
}
isEmpty(CONFIG_OUTPUT_PATH){
CONFIG(release, debug|release):CONFIG_OUTPUT_PATH = $$CONFIG_SOURCE_TREE/bin
CONFIG( debug, debug|release):CONFIG_OUTPUT_PATH = $$CONFIG_SOURCE_TREE/bin
}
CONFIG(release, debug|release):CONFIG_APP_PATH = $$CONFIG_OUTPUT_PATH/application
CONFIG( debug, debug|release):CONFIG_APP_PATH = $$CONFIG_OUTPUT_PATH/application_debug
CONFIG(release, debug|release):CONFIG_LIBRARY_PATH = $$CONFIG_OUTPUT_PATH/application
CONFIG( debug, debug|release):CONFIG_LIBRARY_PATH = $$CONFIG_OUTPUT_PATH/application_debug
CONFIG(release, debug|release):CONFIG_PLUGIN_PATH = $$CONFIG_OUTPUT_PATH/plugins
CONFIG_3RDPARTY_PATH = $$CONFIG_OUTPUT_PATH/3rdparty
CONFIG_3RD_ROOT = $$(CONFIG_3RD_ROOT)
isEmpty(CONFIG_3RD_ROOT):error("can't find CONFIG_3RD_ROOT in system environment variable!")
CONFIG_LINK_LIBRARY_PATH = $$CONFIG_LIBRARY_PATH
INSTALL_ROOT = E:/
CONFIG_PREFIX = qframework
INSTALL_BIN_PATH = $$INSTALL_ROOT/$$CONFIG_PREFIX/bin
INSTALL_APP_PATH = $$INSTALL_ROOT/$$CONFIG_PREFIX/bin
INSTALL_LIB_PATH = $$INSTALL_ROOT/$$CONFIG_PREFIX/lib
INCLUDEPATH += \
$$CONFIG_SOURCE_TREE \
$$CONFIG_SOURCE_TREE/libs \
$$CONFIG_SOURCE_TREE/shared
LIBS *= -L$$CONFIG_LINK_LIBRARY_PATH # libraries
exists($$CONFIG_LIBRARY_PATH): LIBS *= -L$$CONFIG_LIBRARY_PATH # library path from output path
CONFIG_PLUGIN_DIRS_FROM_ENVIRONMENT = $$(CONFIG_PLUGIN_DIRS)
CONFIG_PLUGIN_DIRS += $$split(CONFIG_PLUGIN_DIRS_FROM_ENVIRONMENT, $$QMAKE_DIRLIST_SEP)
CONFIG_PLUGIN_DIRS += $$CONFIG_SOURCE_TREE/plugins
for(dir, CONFIG_PLUGIN_DIRS) {
INCLUDEPATH += $$dir
}
CONFIG += \
depend_includepath \
no_include_pwd
# recursively resolve library deps
done_libs =
for(ever) {
isEmpty(CONFIG_LIB_DEPENDS): \
break()
done_libs += $$CONFIG_LIB_DEPENDS
for(dep, CONFIG_LIB_DEPENDS) {
include($$PWD/libs/$$dep/$${dep}_dependencies.pri)
LIBS += -l$$qtLibraryTargetName($$CONFIG_LIB_NAME)
}
CONFIG_LIB_DEPENDS = $$unique(CONFIG_LIB_DEPENDS)
CONFIG_LIB_DEPENDS -= $$unique(done_libs)
}
config.pri 文件
这个文件是一个 Qt 项目配置的共享文件(.pri),用于定义项目构建的通用设置、路径和依赖关系管理。逐一详细分析如下:
!isEmpty(CONFIG_PRI_INCLUDED):error("config.pri already included")
CONFIG_PRI_INCLUDED = 1
-
防止重复包含的保护机制,如果已经包含过则报错
QT += core gui widgets
CONFIG += no_batch c++14 no_moc_predefs
-
添加 Qt 模块依赖
-
配置项目选项:禁用批处理模式、启用 C++14、禁用 moc 预定义
CONFIG += force_debug_info
-
强制生成调试信息,即使是在 release 模式下
defineReplace(qtLibraryTargetName) {
unset(LIBRARY_NAME)
LIBRARY_NAME = $$1
CONFIG(debug, debug|release) {
!debug_and_release|build_pass {
win32:RET = $$member(LIBRARY_NAME, 0)d
}
}
isEmpty(RET):RET = $$LIBRARY_NAME
return($$RET)
}
-
定义替换函数,用于生成库文件名
-
在 Windows 平台 debug 模式下,给库名添加 'd' 后缀
defineTest(qtCopy) {
source = $$system_path($$1)
target = $$system_path($$2)
win32:system(xcopy $$source $$target /S /H /D /F /Y)
return(true)
}
-
定义测试函数,用于文件复制
-
Windows 下使用 xcopy 命令
exists($$PWD/../userconfig.pri) {
include($$PWD/../userconfig.pri)
isEmpty(CONFIG_OUTPUT_PATH):CONFIG_OUTPUT_PATH = $$PWD/../bin
}
-
检查并包含上级目录中的 userconfig.pri(用户自定义配置)
-
如果用户配置中没有定义输出路径,则设置为 ../bin
isEmpty(APP_TARGET):APP_TARGET = Application
-
设置默认应用程序名称
isEmpty(CONFIG_SOURCE_TREE):CONFIG_SOURCE_TREE = $$PWD
-
设置源代码基础路径为当前目录
isEmpty(CONFIG_BUILD_TREE) {
sub_dir = $$_PRO_FILE_PWD_
sub_dir ~= s,^$$re_escape($$PWD),,
CONFIG_BUILD_TREE = $$clean_path($$OUT_PWD)
CONFIG_BUILD_TREE ~= s,$$re_escape($$sub_dir)$,,
}
-
计算构建目录路径,基于输出目录和当前项目相对路径
# 重复的 userconfig.pri 检查(前面已经出现过)
exists($$PWD/../userconfig.pri) {
include($$PWD/../userconfig.pri)
isEmpty(CONFIG_OUTPUT_PATH):CONFIG_OUTPUT_PATH = $$PWD/../bin
}
isEmpty(CONFIG_OUTPUT_PATH){
CONFIG(release, debug|release):CONFIG_OUTPUT_PATH = $$CONFIG_SOURCE_TREE/bin
CONFIG( debug, debug|release):CONFIG_OUTPUT_PATH = $$CONFIG_SOURCE_TREE/bin
}
-
设置默认输出路径为源代码目录下的 bin 目录
#应用程序路径 CONFIG(release, debug|release):CONFIG_APP_PATH = $$CONFIG_OUTPUT_PATH/application CONFIG( debug, debug|release):CONFIG_APP_PATH = $$CONFIG_OUTPUT_PATH/application_debug #库路径 CONFIG(release, debug|release):CONFIG_LIBRARY_PATH = $$CONFIG_OUTPUT_PATH/application CONFIG( debug, debug|release):CONFIG_LIBRARY_PATH = $$CONFIG_OUTPUT_PATH/application_debug
-
设置应用程序和库的输出路径,区分 debug/release
CONFIG(release, debug|release):CONFIG_PLUGIN_PATH = $$CONFIG_OUTPUT_PATH/plugins
-
设置插件输出路径
CONFIG_3RDPARTY_PATH = $$CONFIG_OUTPUT_PATH/3rdparty
-
设置第三方库路径
CONFIG_3RD_ROOT = $$(CONFIG_3RD_ROOT)
isEmpty(CONFIG_3RD_ROOT):error("can't find CONFIG_3RD_ROOT in system environment variable!")
-
从环境变量读取第三方库根目录,如果没有设置则报错
CONFIG_LINK_LIBRARY_PATH = $$CONFIG_LIBRARY_PATH
-
设置链接库路径
INSTALL_ROOT = E:/
CONFIG_PREFIX = qframework
INSTALL_BIN_PATH = $$INSTALL_ROOT/$$CONFIG_PREFIX/bin
INSTALL_APP_PATH = $$INSTALL_ROOT/$$CONFIG_PREFIX/bin
INSTALL_LIB_PATH = $$INSTALL_ROOT/$$CONFIG_PREFIX/lib
-
定义安装路径结构,默认安装到 E:/qframework/
INCLUDEPATH += \
$$CONFIG_SOURCE_TREE \
$$CONFIG_SOURCE_TREE/libs \
$$CONFIG_SOURCE_TREE/shared
-
添加默认包含路径
LIBS *= -L$$CONFIG_LINK_LIBRARY_PATH # libraries
exists($$CONFIG_LIBRARY_PATH): LIBS *= -L$$CONFIG_LIBRARY_PATH # library path from output path
-
添加库搜索路径
CONFIG_PLUGIN_DIRS_FROM_ENVIRONMENT = $$(CONFIG_PLUGIN_DIRS)
CONFIG_PLUGIN_DIRS += $$split(CONFIG_PLUGIN_DIRS_FROM_ENVIRONMENT, $$QMAKE_DIRLIST_SEP)
CONFIG_PLUGIN_DIRS += $$CONFIG_SOURCE_TREE/plugins
-
从环境变量获取插件目录并添加到搜索路径
for(dir, CONFIG_PLUGIN_DIRS) {
INCLUDEPATH += $$dir
}
-
将所有插件目录添加到包含路径
CONFIG += \
depend_includepath \
no_include_pwd
-
添加配置选项:依赖包含路径、不自动包含当前目录
# recursively resolve library deps
done_libs =
for(ever) {
isEmpty(CONFIG_LIB_DEPENDS): \
break()
done_libs += $$CONFIG_LIB_DEPENDS
for(dep, CONFIG_LIB_DEPENDS) {
include($$PWD/libs/$$dep/$${dep}_dependencies.pri)
LIBS += -l$$qtLibraryTargetName($$CONFIG_LIB_NAME)
}
CONFIG_LIB_DEPENDS = $$unique(CONFIG_LIB_DEPENDS)
CONFIG_LIB_DEPENDS -= $$unique(done_libs)
}
-
递归解析库依赖关系,自动包含依赖项并添加链接指令
这个配置文件提供了一个高度可配置的项目构建框架,特别适合大型 Qt 项目
实践建议
-
合理组织目录结构
project/ ├── config/ │ ├── config.pri │ ├── platform.pri │ └── features.pri ├── modules/ │ ├── module1/ │ └── module2/ └── app.pro
-
分层设计
-
基础层:
config.pri(编译器设置) -
平台层:
platform.pri(平台差异) -
功能层:
features.pri(功能模块) -
项目层:项目特定配置
-
-
文档注释
############################################### # Common Configuration # # Variables: # MY_PROJECT_ROOT - 项目根目录 # BUILD_MODE - 构建模式(debug/release) # # Usage: # include(../config/config.pri) ###############################################
-
避免过度复杂
-
保持
.pri文件专注单一功能 -
避免深层嵌套包含
-
限制条件判断的复杂度
-
常见问题解决
1. 变量作用域问题
-
问题:变量在不同
.pri中意外覆盖 -
解决:使用唯一变量名前缀,如
MYPROJ_PATHS
2. 路径问题
-
问题:相对路径在不同包含层级下解析不同
-
解决:始终基于
$$PWD或项目根变量构建路径
3. 循环包含
-
问题:A.pri 包含 B.pri,B.pri 又包含 A.pri
-
解决:重构设计,引入第三方的公共
.pri
4. 调试困难
-
问题:难以追踪变量定义位置
-
解决:使用
message()调试:message("Current value: $$VAR_NAME (defined in $$_FILE_)")
总结
.pri 文件是 qmake 项目中强大的配置管理工具,合理使用可以:
-
大幅减少
.pro文件中的重复配置 -
集中管理平台差异和编译选项
-
实现模块化、可复用的项目配置
-
提高大型项目的可维护性
掌握 .pri 文件的使用技巧,能够使 Qt 项目的构建系统更加清晰、灵活和易于维护。

1万+

被折叠的 条评论
为什么被折叠?



