对于基于qmake的项目来说,这是一个非常基本但易于使用的依赖管理工具
qdep的Python项目详细描述
qdep
对于基于qmake的项目来说,这是一个非常基本但简单易用的依赖关系管理工具。
目录
<;small>;使用markdown-toc生成的目录<;/small>;
功能
- qmake项目中的无缝集成-无需额外文件
- 使用git存储库作为包源的基本依赖关系管理
- 全局缓存源文件以加快生成速度
- 包是目标项目包含的简单pri文件
- 递归依赖项求解
- 允许基于分支和标记的版本控制
- 支持QDEP包的翻译
- 支持从动态库自动导出QDEP包
- 即使在静态库中使用,也可以处理qrc资源和启动挂钩
- 支持特殊的"项目依赖项",允许您将整个qmake项目添加到subdirs项目中
- 可以生成"library export"pri文件,该文件提供了一种与库链接的简单可靠的方法
- 隐式支持导出的qdep包和项目
设计目标/范围
QDEP的设计目标如下:
- 完全qmake集成:qdep不需要任何额外的命令来安装包和准备要构建的项目。只需在目标项目上运行qmake就可以解决这个问题
- 简单的安装:使用python可以在任何平台上轻松使用该工具。除了install之外,对于任何qt安装,只需要一个setup命令就可以使qdep工作
- 完全qt支持:qt的所有功能(包括资源、启动挂钩和翻译)都应该以最小的工作量为应用程序开发人员提供支持
- 库导出:由于所有qdep包都是基于源代码的,因此使用同一个包的多个库可能会有问题。使用QDEP,可以从库中"导出"包,使所有其他包都可用。
- 没有额外的服务器基础设施:qdep不应该需要任何额外的服务器来提供包索引。任何git存储库都可以作为一个包进行服务器,而无需任何额外的准备工作
请注意,qdep故意保持较小,以完全满足这些目标。其他构建系统或更复杂的包管理功能不受支持,而且永远不受支持。在qt公司将其构建系统切换到cmake之前,该项目将一直处于活动状态。届时,该项目将被放弃或移植到CMAKE,具体取决于当时已经存在的替代解决方案。
安装
要安装软件包,请遵循以下可能的操作之一。请注意,官方只支持python>;=3.7。早期版本也可以工作,但尚未经过测试。
准备qmake
安装后(使用aur包时除外),必须为要与qdep一起使用的每个qt工具包"启用"qdep。这可以通过打开终端并呼叫:
qdep prfgen --qmake "</path/to/qmake>"
例如,如果您在Windows上的默认位置(c:\ qt
)安装了用于MSVC 2017 x64的Qt 5.12.0,则该命令将如下所示:
qdep prfgen --qmake "C:\Qt\5.12.0\msvc2017_64\bin\qmake.exe"
注意:根据相应的qt工具包的安装方式,可能需要使用管理员/sudo权限运行该命令。或者,您可以使用--dir/some/path
调用该命令,并将该路径导出到qmakepath
环境变量(如果您没有此类权限)。
外壳完整性
对于unix系统,qdep使用argcomplete来提供bash/zsh激活它们的完整性,添加以下代码您的shell初始化器脚本:
对于zsh,将其添加到~/.zshrc
:
autoload bashcompinit bashcompinit autoload compinit compinit eval"$(register-python-argcomplete qdep)"
对于bash,将其添加到~/.bashrc
:
eval "$(register-python-argcomplete qdep)"
使用bash时,也可以使用全局完成功能-有关详细信息,请参见激活全局完成功能。其他的shell也可以工作,这取决于argcomplete对它们的工作情况。请参阅argcomplete文档及其github存储库。
开始
qdep的基本用法非常简单。对于本例,我们假设您希望通过qdep将示例qhotkey添加到项目中。您只需安装(并准备)qdep,然后将以下两行添加到您的pro文件:
QDEP_DEPENDS += Skycoder42/QHotkey !load(qdep):error("Failed to load qdep feature")
就这样!下次运行qmake qdep时,将自动下载最新版本并将其添加到项目中。只要编译项目,就可以使用库。指定包(以及短字符串扩展到的内容)的更明确的方法是https://github.com/skycoder42/qhotkey.git@1.2.2/qhotkey.pri
越来越深
除了引用qdep包的基本功能之外,qdep还提供了一些额外的功能,使使用(和开发)这些包变得更容易。在以下各节中,将对其进行详细说明。
依赖项ID
qdep依赖项由ids描述。这些ID的格式为<;url>;[@<;version>;[/<;path>;]]
。唯一相关的部分是url,它可以是隐式的,也可以是显式的。隐式URL遵循<;user>;/<;repository>;
格式,并自动展开为https://github.com/<;user>;/<;repository>;.git
。对于显式格式,所有类型的git url都是supportet,即https、ssh和file url。
如果忽略qdep包的路径部分,qdep假设在repositories根目录中有一个名为<;repository_lower>;.pri
的pri文件。如果不是这样,或者如果一个包有多个不同的pri文件可供选择,则可以指定相对于该pri文件的存储库根的路径,以使用该pri文件,而不是自动检测到的pri文件。
版本控制
QDEP支持3种版本控制:未版本化、分支、标记。如果不输入版本,qdep将自动查询相应的存储库并获取最新的标记(通过"creation")并使用该标记。如果您指定了版本,它可以是git标记或git分支。对于一个标签,qdep只需下载它并假设它是持久的,也就是说,永远不要检查特定标签上的更新。然而,引用分支将导致qdep"跟踪"该分支,并在每次构建之前,如有必要,qdep会拉动分支进行更新。
一般来说,建议使用显式标记。隐式版本控制也很好,但是包的更新可能会在您不希望的时候破坏您的构建。分支版本控制总是很危险的,只应用于显式稳定的分支或包删除设备。
包唯一性和版本冲突
在处理递归包依赖项时,有时会发生两个不同的包包含同一个包的不同版本的情况。QDEP避免了这个问题,使舒尔每包产品只包含一个版本。引用的第一个版本是choosen。但是,显式的包路径不被认为是同一个包,即可以包含来自同一git存储库的两个不同的pri文件。一般来说,包的唯一标识符是由其<;url>;
和<;path>;
决定的,两者都不区分大小写。
正常依赖性
通过qdep_dependents
指定的普通依赖项(也称为pri依赖项)是qdep的主要依赖类型。它们通常解析为一个简单的pri文件,由qdep包含在您的项目中。你可以在这些pri文件中做任何事情,你也可以在"普通"pri文件中做任何事情。但是,当包含qdep依赖项时,还有一些额外的事情是可能的。
翻译
第一个特性是对翻译的扩展支持。qdep包可以为自己的源提供翻译源文件。它们通常通过qdep_translations
qmake变量导出。当创建您自己的翻译时,qdep将在构建时自动将它们与您自己的翻译合并。但是,如果您使用qt提供的lrelease
qmake特性,则onyl可以工作。有关详细信息,请参阅qmake translations和qmake qm文件安装路径。
库支持
在静态或动态库中使用qdep时,通常需要一些特殊的步骤才能使其完全工作。但是,qdep会处理这些步骤并为您执行它们。唯一需要做的事情是从库中启用库导出,然后从主项目中导入导出。例如,假设您有以下项目结构:
root (subdirs)
|-library (lib)
|-app (app)
你有一个依赖qhotkey的库。如果要从app使用此库,您可以按如下方式创建library pro文件:
TEMPLATE = lib CONFIG += static # dynamic libraries are also possible, but dependencies must support exporting for them to work on windows # ... QDEP_DEPENDS += Skycoder42/QHotkey QDEP_EXPORTS += Skycoder42/QHotkey CONFIG += qdep_link_export !load(qdep):error("Failed to load qdep feature")
然后引用app pro文件中的库。这还需要将库链接到应用程序,因此不需要额外的includepath
或libs
更改:
TEMPLATE = app # ... QDEP_LINK_DEPENDS += ../library !load(qdep):error("Failed to load qdep feature")
就这样!您现在可以在库和应用程序项目中使用qhotkey,而无需任何额外工作,因为qdep将引用现在嵌入库项目中的qhotkey。
注意:这也适用于动态库,但前提是显式地支持qdep包导出。如果没有,链接将至少在Windows上失败,可能在其他平台上也会失败。
创建正常依赖关系
本节面向希望创建自己的qdep包的开发人员。一般来说,没有什么不同于创建普通的pri-include。然而,在qdep中有一些小东西可以利用它们来创建更好的包。它们在以下小节中进行了说明:
- 翻译生成
- 资源和启动挂钩
- 自动导出
创建qdep翻译
使用qdep创建翻译的唯一区别是m.创建一个名为qdep_translations的qmake变量,并将要生成的所有ts文件添加到其中,而不是转换。接下来,调用以下命令,根据您的pri文件实际生成ts文件:
qdep lupdate --qmake "</path/to/qmake>" --pri-file "</path/to/project.pri>"[-- <extra lupdate arguments>...]
就这样。现在,您应该能够找到生成的ts文件,这些文件是您希望在pri文件中指定的位置。
在创建应该使用和不使用qdep的包时,如果包中不包含qdep,则可以将以下内容添加到pri文件中以使这些翻译仍然可用:
qdep prfgen --qmake "</path/to/qmake>"
0
资源和挂钩
有一点可能会有问题,特别是在使用静态库时,就是使用资源和启动挂钩。为了让它工作,qdep会自动生成代码来加载它们。对于资源,作为包开发人员,您不需要做任何特殊的事情。
不过,对于胡克斯来说,情况就不同了。假设您有以下函数,则希望作为启动函数运行::
qdep prfgen --qmake "</path/to/qmake>"
1
您必须将以下行添加到QDEP PRI文件中,才能使舒尔真正调用此钩子:
qdep prfgen --qmake "</path/to/qmake>"
2
这样,qdep将自动生成调用此方法所需的代码,称为q coreapp_startup_function
当创建应该使用和不使用qdep的包时,您可以将以下内容添加到包含hook函数的cpp文件中,使其适用于非静态项目,即使包中不包含qdep:
qdep prfgen --qmake "</path/to/qmake>"
3
自动出口
另一个非常有用的工具是自动包导出。这允许qdep自动从动态库导出qdep包,因此链接到该库的其他应用程序可以使用导出的qdep包api。这基本上等同于以下内容:
qdep prfgen --qmake "</path/to/qmake>"
4
qdep基本上自动化了define部分,因此您不必关心如何正确定义所有这些宏,您的代码可以简化为:
qdep prfgen --qmake "</path/to/qmake>"
5
要使其正常工作,只需在pri文件中添加以下内容:
qdep prfgen --qmake "</path/to/qmake>"
6
就这样!正常使用包时,qdep将自动添加一个空定义,该定义将my package_export定义为nothing。当构建一个动态库时,最终用户想要导出包,它被定义为q廑decl廑u export(和q廑decl廑u import用于消费应用程序)。
在创建应该使用和不使用qdep的包时,您可以将以下内容添加到pri文件中,以便手动将宏定义为"无",即使包中不包含qdep:
qdep prfgen --qmake "</path/to/qmake>"
7
项目依赖关系
qdep的另一面除了正常的pri依赖之外,是完全的项目依赖。在这个场景中,您将一个完整的qmake项目作为subdirs项目的子项目包含到树中。这允许使用qdep包导出pri文件来链接到这些项目,而无需太多努力。要使用此功能,必须使用引用pro依赖项的subdirs项目以及与之链接的普通项目。使用项目依赖项的一个巨大优势是,它们可以引用它们所依赖的其他项目依赖项,这意味着即使对于完整的项目,qdep也会为您处理递归依赖项解析。
要开始,请假设以下项目结构:
qdep prfgen --qmake "</path/to/qmake>"
8
假定lib和a p p都依赖于理论上的qdep项目依赖名称skycoder42/superlib,但app也依赖于lib。
第一步是选择一个subdirs项目来添加依赖项。对于本例,libs项目是choosen。添加以下行以添加依赖项:
qdep prfgen --qmake "</path/to/qmake>"
9
qdep_project_subdirs用于实际拉入项目依赖项,同时将其添加到lib。qdep_dependents
仅确保在lib之前生成qdep依赖项。如果lib不依赖于qdep依赖项,则不需要这样做。不过,还是建议d对于qdep依赖项总是有一个单独的subdir项目,即对于这个具体的例子,最好将lib项目向上移动一个阶段,或者在libs中创建另一个引用qdep依赖项的subdir项目。
接下来,我们需要在app/lib中引用库本身。这两个程序都是相同的,因此这里仅以app项目为例。在app pro文件中,添加以下行:
qdep prfgen --qmake "C:\Qt\5.12.0\msvc2017_64\bin\qmake.exe"
0
qdep_project_root
告诉qdep项目的位置,其中包含对实际qdep项目依赖项的引用,并列出此项目(应用程序)依赖的所有依赖项。如果libs项目中没有通过qdep_project_subdirs指定列出的任何依赖项,则生成将失败。
这样,项目依赖关系就被成功地添加和引用了。在下一个版本中,项目将被下载、编译并链接到app/lib。
创建项目依赖项
一般来说,项目依赖项只是普通的qmake项目。但是,这样的项目应该始终包含qdep功能并将qdep链接导出添加到配置中,因为没有生成的导出pri文件,它将不能作为qdep项目依赖项使用。除此之外,您还可以做任何想做的事情,例如添加其他正常的qdep pri依赖项等,甚至在需要时导出它们。
但是,还有一个额外的特性只有在qdep项目依赖项中才可能实现:您可以直接引用其他qdep项目依赖项。这样做将确保包含此项目的任何subdirs项目也将依赖项包含为subdirs,并确保qmake构建顺序,以及引用相应的导出pri文件。例如,要从qdep项目依赖项中引用skycoder42/superlib,请添加以下内容:
qdep prfgen --qmake "C:\Qt\5.12.0\msvc2017_64\bin\qmake.exe"
1
文档
在下面的章节中,将记录QDEP的所有函数、变量等,以供参考。
命令行界面
qdep有一个公共和私有的命令行api。公共api旨在供delevopers使用,而内部api则由qdep qmake特性用于执行各种操作。以下各节列出了所有具有简短说明的命令。有关每个命令的详细信息,请键入 这是qdep生成的qmake特性的文档,通过将qdep<;command>;--help
公共api操作:
qdep prfgen --qmake "C:\Qt\5.12.0\msvc2017_64\bin\qmake.exe"
2
私有api操作:
qdep prfgen --qmake "C:\Qt\5.12.0\msvc2017_64\bin\qmake.exe"
3
qmake功能
load(qdep)
添加到项目中来加载。下面记录了所有变量、配置标志等。变量
公共变量
<表><广告>
< /广告><正文>名称 方向
默认值
说明
Qdep_路径 输入/输出 <;系统>;
保存要使用的qdep二进制文件的路径。可以重写以指定自定义位置 QDEP U版本 外 <;系统>;
用于生成QDEP功能的QDEP版本 生成的qdep目录 $$out\u pwd
生成文件夹中的子目录,qdep应在其中放置它生成的所有文件。可以是绝对路径或相对路径 qdep_导出路径 $$qdep_generated_dir/<;type>;
为导出依赖项的库放置导出PRI文件的目录。可以是相对的,也可以是绝对的。使用qdep_export_name获取不带路径的文件名 qdep_取决于 <;空>;
指定要包含在项目中的qdep包的所有依赖项 <;空>;
引用此项目应链接的同一生成树中的其他项目。这些项目必须导出pri文件 QDEP_项目区 <;空>;
指定要作为qmake project添加到subdirs变量的qdep项目的所有依赖项。仅在指定模板为 subdirs
QDEP_项目根 <;空>;
要解析qdep项目链接的项目qmake项目目录或文件的路径取决于 QDEP U项目链接取决于 <;空>;
指定此项目应链接到的QDEP项目的所有依赖项。假设依赖项是通过QDEP_project_subdirs在该项目中提供的。 qdep_定义 <;空>;
指定在库导出PRI文件时导出的定义。所有值都将自动添加到由QDEP定义的值中 qdep_includepath <;空>;
指定在库导出PRI文件时导出的IncludePaths。所有值都由qdep自动添加到includepath中 QDEP库 <;空>;
指定库导出pri文件时导出的lib。所有值都由qdep自动添加到libs中 QDEP U出口 <;空>;
指定应导出api的qdep依赖项。在动态库中使用时导出包非常有用-仅当包明确支持此功能时才有效
qdep_lupdate_输入 <;空>;
运行 make lupdate
QDEP_套餐出口 英寸(包装) <;空>;
变量定义为import/export/nothing,并用作类的前缀。 QDEP U翻译 英寸(包装) <;空>;
在qdep依赖项中指定要与包含它们的项目翻译合并的翻译子文件 QDEP_项目取决于 英寸(包装) <;空>;
指定此qdep项目所依赖的qdep项目的所有依赖项。只能在qdep项目依赖项中使用,并将其内容添加到包含此依赖项的项目的qdep项目子目录中 QDEP_Var_出口 英寸(包装) <;空>;
指定除了defines和includepath之外,还应从qdep依赖项导出的其他qmake变量的名称 街道扩展
qdep_dependents
:可以添加到使用qdep_project_subdirs
指定某个subdir项目依赖于该特定包的项目中传递给subdirs
的任何变量。这样做并不会影响链接等。它只能确保生成目标的顺序正确。高级变量
<表><广告>
< /广告><正文>名称 方向
默认值
说明
qdep_工具 输入/输出 <;系统>;
qdep命令的转义命令行基从qmake中运行 QDEP缓存范围 储存
用于缓存各种qmake相关内容的缓存方法。可以是<;empty>;、super或stash qdep_generated_sources_dir 外 $$qdep_generated_dir/<;t生成键入>;
生成的源文件所在的目录。由生成配置确定,以考虑调试/发布生成 生成的qdep目录 $$qdep_generated_dir/.qdepts/<;type>;
生成的翻译源所在的目录。 qdep_lconvert lconvert-排序上下文
lconvert工具的路径和用于合并翻译的附加参数 qdep_导出名称 输入/输出 <;pro文件名>;_export.pri
生成的库导入文件的名称。必须仅为文件名,请使用qdep_export_path指定位置 导出的qdep定义 外 <;空>;
定义来自QDEP_包导出或定义来自任何直接包含的QDEP依赖项 qdep_导出的包含路径 外 <;空>;
包含来自任何直接包含的QDEP依赖项的路径 qdep_导出的库 外 <;空>;
来自任何直接包含的qdep依赖项的lib qdep_hook_fns 外 <;空>;
保存qdep要作为启动挂钩运行的所有函数的名称 qdep_lupdate_args -递归-相对位置
make lupdate
命令中的lupdate的附加参数,用于控制其行为
配置值
输入值
qdep_force
:强制对qdep进行完整的求值,即使在没有上下文的情况下对pro文件进行求值(这可能是危险的,除非绝对必要,否则不应使用)qdep_no_pull
:不要为基于分支的依赖项的较新版本进行pull。克隆新软件包仍然有效qdep_no_clone
:不要克隆全新的包或包版本。拉上已缓存的分支仍然有效qdep_no_cache
:不要缓存没有指定版本的包的已用版本。相反,每次运行时都会查询最新版本qdep_export_all
:导出所有依赖包,即每个包的任何qdep_包导出都被视为添加到qdep_exports中qdep_no_link
:从库导出包时,不要添加qmake代码以将库(及其包含)链接到generate export.pri文件qdep_no_qm_combine
:不要将翻译与qdep_翻译组合在一起。相反,将qdep_翻译视为额外的翻译,并为它们生成单独的qm文件qdep_link_export
:强制创建导出pri文件。通常只有不定义qdep_no_link的库或指定qdep_export_all或在qdep_export中具有值的项目才会生成此类文件qdep_no_export_link
:不要在生成的导出pri文件中导出qt、pkgconfig或qdep_libs的内容
输出值
qdep_build
:在正确加载qdep功能并启用时设置
定义
qdep_build
:在正确加载qdep功能并启用时定义。
环境变量
qdep_cache_dir
:缓存下载源的目录。为每个系统自动确定,但可以用此变量覆盖qdep_source_override
:允许以<;pkg1>;;<;pkg2>;^<;pkg3>;;<;pkg4>;
格式提供映射。这将使QDEP自动替换任何出现的pkg1
开发人员可以使用withpkg2
等临时覆盖包qdep_default_pkg_fn
:用于将非url包(如用户/package
解析为完整url)的模板。默认方法是https://github.com/{}.git
-用短包名替换{}
。公开制定目标
make lupdate
:运行lupdate
工具以快速简便的方式更新您的翻译,而不必依赖潜在的错误专业文件解析。内部
变量
\uqdep\u private\u分隔符
:数据集之间的分隔符\uqdep\u tuple\u分隔符
:数据集中值之间的分隔符\uqdep\u include\u缓存
:包含有关各种包含深度的详细信息的对象\uqdep_original_translations
:在将翻译组合应用于所包含软件包中的qdep_翻译之前在翻译中的所有原始翻译\uqdep_hook_文件
:指向头文件的路径,这些头文件包含项目必须包含和加载的钩子定义\uqdep_export_qmake_include_guard
:包含的导出PRI文件的缓存,以确保每个文件只包含一次\uqdep_lupdate
:生成的用于lupdate的qmake工具,使用qdep_lupdate_args
配置值
\uqdep_script_version
:在运行时检测到的由qdep可执行文件报告的版本\uqdep_dump_dependencies
:在包含项目所有直接依赖项的生成目录中创建一个名为qdep_dependencies.txt的文件
qmake测试功能
qdepcollectdependencies(dependencies…)
:下载所有指定的正常依赖项,并将它们添加到qdep include\u缓存中,稍后由qdep链接。递归工作qdepCollectProjectDependencies(Dependencies…)
:下载所有指定的项目依赖项,并将它们添加到子目录中。递归工作
qdepresolvesubordepends(subdir vars…)
qdepcreateexportpri(path)
:创建名为path的文件并将所有与导出相关的代码添加到其中
qdepshellquote(路径…)
:基于\u pro_file_pwd_
使给定路径成为绝对路径,并使用shell_quote将其转义
qdeptumpdupdatedeps()
:在包含项目所有直接依赖项的生成目录中创建一个名为qdep_dependents.txt的文件
qmake replace函数
qdepresolveprojectlinkdeps(project root,link dependents…)
:将所有依赖链接的项目包解析为subdir路径,假设它们是由位于project root的项目提供的qdepoutquote(name,values)
:创建多行qmake代码,以安全引用的方式将值中的每个值分配给名为name的变量
qdeplinkexpand(path)
:展开导出依赖项的项目的缩短路径或相对路径,以获取导出pri文件的路径qdepresolvelinkroot(path)
:搜索顶级qmake项目,该项目包含为项目依赖项,并返回该pro文件的路径。搜索基于路径启动,路径必须是生成目录推荐PyPI第三方库