remote_package.html 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>xmake</title>
  6. <link rel="icon" href="/assets/img/favicon.ico">
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  8. <meta name="description" content="Description">
  9. <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  10. <link href="/assets/npm/github-markdown/github-markdown.min.css" rel="stylesheet">
  11. <style>
  12. .markdown-body {
  13. box-sizing: border-box;
  14. min-width: 200px;
  15. max-width: 980px;
  16. margin: 0 auto;
  17. padding: 45px;
  18. }
  19. @media (max-width: 767px) {
  20. .markdown-body {
  21. padding: 15px;
  22. }
  23. }
  24. </style>
  25. </head>
  26. <body>
  27. <article class="markdown-body">
  28. <h4>This is a mirror page, please see the original page: </h4><a href="https://xmake.io/#/zh-cn/package/remote_package">https://xmake.io/#/zh-cn/package/remote_package</a>
  29. <div id="wwads-panel" class="wwads-cn wwads-vertical wwads-sticky" data-id="239" style="max-width:180px;bottom:20px;right:20px;width:200px;height:260px;background:#fff;position:fixed"></div>
  30. </br>
  31. <script type="text/javascript" charset="UTF-8" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
  32. <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
  33. <style>
  34. #carbonads {
  35. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
  36. Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
  37. }
  38. #carbonads {
  39. display: flex;
  40. max-width: 330px;
  41. background-color: hsl(0, 0%, 98%);
  42. box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
  43. }
  44. #carbonads a {
  45. color: inherit;
  46. text-decoration: none;
  47. }
  48. #carbonads a:hover {
  49. color: inherit;
  50. }
  51. #carbonads span {
  52. position: relative;
  53. display: block;
  54. overflow: hidden;
  55. }
  56. #carbonads .carbon-wrap {
  57. display: flex;
  58. }
  59. .carbon-img {
  60. display: block;
  61. margin: 0;
  62. line-height: 1;
  63. }
  64. .carbon-img img {
  65. display: block;
  66. }
  67. .carbon-text {
  68. font-size: 13px;
  69. padding: 10px;
  70. line-height: 1.5;
  71. text-align: left;
  72. }
  73. .carbon-poweredby {
  74. display: block;
  75. padding: 8px 10px;
  76. background: repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4);
  77. text-align: center;
  78. text-transform: uppercase;
  79. letter-spacing: .5px;
  80. font-weight: 600;
  81. font-size: 9px;
  82. line-height: 1;
  83. }
  84. </style>
  85. <p>这个在2.2.2版本后已经初步支持,用法上更加的简单,只需要设置对应的依赖包就行了,例如:</p>
  86. <pre><code class="lang-lua">add_requires("tbox 1.6.*", "libpng ~1.16", "zlib")
  87. target("test")
  88. set_kind("binary")
  89. add_files("src/*.c")
  90. add_packages("tbox", "libpng", "zlib")
  91. </code></pre>
  92. <p>上面的<code>add_requires</code>用于描述当前项目需要的依赖包,而<code>add_packages</code>用于应用依赖包到test目标,只有设置这个才会自动追加links, linkdirs, includedirs等设置。</p>
  93. <p>然后直接执行编译即可:</p>
  94. <pre><code class="lang-console">$ xmake
  95. </code></pre>
  96. <p>xmake会去远程拉取相关源码包,然后自动编译安装,最后编译项目,进行依赖包的链接,具体效果见下图:</p>
  97. <p><img src="/assets/img/index/package_manage.png" width="80%" /></p>
  98. <p>关于包依赖管理的更多相关信息和进展见相关issues:<a href="https://github.com/xmake-io/xmake/issues/69">Remote package management</a></p>
  99. <h2 id="">目前支持的特性</h2>
  100. <ul>
  101. <li>语义版本支持,例如:">= 1.1.0 < 1.2", "~1.6", "1.2.x", "1.*"</li>
  102. <li>提供官方包仓库、自建私有仓库、项目内置仓库等多仓库管理支持</li>
  103. <li>跨平台包编译集成支持(不同平台、不同架构的包可同时安装,快速切换使用)</li>
  104. <li>debug依赖包支持,实现源码调试</li>
  105. </ul>
  106. <h2 id="">依赖包处理机制</h2>
  107. <p>这里我们简单介绍下整个依赖包的处理机制:</p>
  108. <p><img src="/assets/img/index/package_arch.png" width="80%" /></p>
  109. <ol>
  110. <li>优先检测当前系统目录、第三方包管理下有没有存在指定的包,如果有匹配的包,那么就不需要下载安装了 (当然也可以设置不使用系统包)</li>
  111. <li>检索匹配对应版本的包,然后下载、编译、安装(注:安装在特定xmake目录,不会干扰系统库环境)</li>
  112. <li>编译项目,最后自动链接启用的依赖包</li>
  113. </ol>
  114. <h2 id="">快速上手</h2>
  115. <p>新建一个依赖tbox库的空工程:</p>
  116. <pre><code class="lang-console">$ xmake create -t console_tbox test
  117. $ cd test
  118. </code></pre>
  119. <p>执行编译即可,如果当前没有安装tbox库,则会自动下载安装后使用:</p>
  120. <pre><code class="lang-console">$ xmake
  121. </code></pre>
  122. <p>切换到iphoneos平台进行编译,将会重新安装iphoneos版本的tbox库进行链接使用:</p>
  123. <pre><code class="lang-console">$ xmake f -p iphoneos
  124. $ xmake
  125. </code></pre>
  126. <p>切换到android平台arm64-v8a架构编译:</p>
  127. <pre><code class="lang-console">$ xmake f -p android [--ndk=~/android-ndk-r16b]
  128. $ xmake
  129. </code></pre>
  130. <h2 id="">语义版本设置</h2>
  131. <p>xmake的依赖包管理是完全支持语义版本选择的,例如:"~1.6.1",对于语义版本的具体描述见:<a href="https://semver.org/">https://semver.org/</a></p>
  132. <p>一些语义版本写法:</p>
  133. <pre><code class="lang-lua">add_requires("tbox 1.6.*", "pcre 1.3.x", "libpng ^1.18")
  134. add_requires("libpng ~1.16", "zlib 1.1.2 || >=1.2.11 <1.3.0")
  135. </code></pre>
  136. <p>目前xmake使用的语义版本解析器是<a href="https://github.com/uael">uael</a>贡献的<a href="https://github.com/uael/sv">sv</a>库,里面也有对版本描述写法的详细说明,可以参考下:<a href="https://github.com/uael/sv#versions">版本描述说明</a></p>
  137. <p>当然,如果我们对当前的依赖包的版本没有特殊要求,那么可以直接这么写:</p>
  138. <pre><code class="lang-lua">add_requires("tbox", "libpng", "zlib")
  139. </code></pre>
  140. <p>这会使用已知的最新版本包,或者是master分支的源码编译的包,如果当前包有git repo地址,我们也能指定特定分支版本:</p>
  141. <pre><code class="lang-lua">add_requires("tbox master")
  142. add_requires("tbox dev")
  143. </code></pre>
  144. <h2 id="">额外的包信息设置</h2>
  145. <h3 id="">可选包设置</h3>
  146. <p>如果指定的依赖包当前平台不支持,或者编译安装失败了,那么xmake会编译报错,这对于有些必须要依赖某些包才能工作的项目,这是合理的。<br>但是如果有些包是可选的依赖,即使没有也可以正常编译使用的话,可以设置为可选包:</p>
  147. <pre><code class="lang-lua">add_requires("tbox", {optional = true})
  148. </code></pre>
  149. <h3 id="">禁用系统库</h3>
  150. <p>默认的设置,xmake会去优先检测系统库是否存在(如果没设置版本要求),如果用户完全不想使用系统库以及第三方包管理提供的库,那么可以设置:</p>
  151. <pre><code class="lang-lua">add_requires("tbox", {system = false})
  152. </code></pre>
  153. <h3 id="">使用调试版本的包</h3>
  154. <p>如果我们想同时源码调试依赖包,那么可以设置为使用debug版本的包(当然前提是这个包支持debug编译):</p>
  155. <pre><code class="lang-lua">add_requires("tbox", {debug = true})
  156. </code></pre>
  157. <p>如果当前包还不支持debug编译,可在仓库中提交修改编译规则,对debug进行支持,例如:</p>
  158. <pre><code class="lang-lua">package("openssl")
  159. on_install("linux", "macosx", function (package)
  160. os.vrun("./config %s --prefix=\"%s\"", package:debug() and "--debug" or "", package:installdir())
  161. os.vrun("make -j4")
  162. os.vrun("make install")
  163. end)
  164. </code></pre>
  165. <h3 id="">传递额外的编译信息到包</h3>
  166. <p>某些包在编译时候有各种编译选项,我们也可以传递进来,当然包本身得支持:</p>
  167. <pre><code class="lang-lua">add_requires("tbox", {configs = {small = true}})
  168. </code></pre>
  169. <p>传递<code>--small=true</code>给tbox包,使得编译安装的tbox包是启用此选项的。</p>
  170. <p>我们可以通过在工程目录中执行:<code>xmake require --info tbox</code> 来获取指定包所有的可配置参数列表和取值说明。</p>
  171. <p>比如:</p>
  172. <pre><code class="lang-console">xmake require --info spdlog
  173. require(spdlog):
  174. -> requires:
  175. -> plat: macosx
  176. -> arch: x86_64
  177. -> configs:
  178. -> header_only: true
  179. -> shared: false
  180. -> vs_runtime: MT
  181. -> debug: false
  182. -> fmt_external: true
  183. -> noexcept: false
  184. -> configs:
  185. -> header_only: Use header only (default: true)
  186. -> fmt_external: Use external fmt library instead of bundled (default: false)
  187. -> noexcept: Compile with -fno-exceptions. Call abort() on any spdlog exceptions (default: false)
  188. -> configs (builtin):
  189. -> debug: Enable debug symbols. (default: false)
  190. -> shared: Enable shared library. (default: false)
  191. -> cflags: Set the C compiler flags.
  192. -> cxflags: Set the C/C++ compiler flags.
  193. -> cxxflags: Set the C++ compiler flags.
  194. -> asflags: Set the assembler flags.
  195. -> vs_runtime: Set vs compiler runtime. (default: MT)
  196. -> values: {"MT","MD"}
  197. </code></pre>
  198. <p>其中,configs里面就是spdlog包自身提供的可配置参数,而下面带有builtin的configs部分,是所有包都会有的内置配置参数。<br>最上面requires部分,是项目当前配置值。</p>
  199. <p>!> <code>vs_runtime</code>是用于msvc下vs runtime的设置,v2.2.9版本中,还支持所有static依赖包的自动继承,也就是说spdlog如果设置了MD,那么它依赖的fmt包也会自动继承设置MD。</p>
  200. <p>可以看到,我们已经能够很方便的定制化获取需要的包,但是每个包自身也许有很多依赖,如果这些依赖也要各种定制化配置,怎么办?</p>
  201. <p>可以通过 <code>add_requireconfs</code> 去重写内部依赖包的配置参数。</p>
  202. <h3 id="">安装任意版本的包</h3>
  203. <p>默认情况下,<code>add_requires("zlib >1.2.x")</code> 只能选择到 <code>xmake-repo</code> 仓库中存在的包版本,因为每个版本的包,它们都会有一个sha256的校验值,用于包的完整性校验。</p>
  204. <p>因此,未知版本的包不存在校验值,xmake 默认是不让选择使用的,这并不安全。</p>
  205. <p>那如果,我们需要的包版本无法选择使用怎么办呢?有两种方式,一种是提交一个 pr 给 <a href="https://github.com/xmake-io/xmake-repo">xmake-repo</a>,增加指定包的新版本以及对应的 sha256,例如:</p>
  206. <pre><code class="lang-lua">package("zlib")
  207. add_versions("1.2.10", "8d7e9f698ce48787b6e1c67e6bff79e487303e66077e25cb9784ac8835978017")
  208. add_versions("1.2.11", "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
  209. </code></pre>
  210. <p>另外,还有一种方式,就是用户传递 <code>{verify = false}</code> 配置给 <code>add_requires</code>,强制忽略包的文件完整性校验,这样就不需要 sha256 值,因此就可以安装任意版本的包。</p>
  211. <p>当然,这也会存在一定的安全性以及包不完整的风险,这就需要用户自己去选择评估了。</p>
  212. <pre><code class="lang-lua">add_requires("zlib 1.2.11", {verify = false})
  213. </code></pre>
  214. <h3 id="">禁用外部头文件搜索路径</h3>
  215. <p>默认情况下,通过 <code>add_requires</code> 安装的包会采用 <code>-isystem</code> 或者 <code>/external:I</code> 来引用里面的头文件路径,这通常能够避免一些包头文件引入的不可修改的警告信息,<br>但是,我们还是可以通过设置 <code>{external = false}</code> 来禁用外部头文件,切回 <code>-I</code> 的使用。</p>
  216. <p>默认启用了 external 外部头文件的编译 flags 如下:</p>
  217. <pre><code class="lang-console">-isystem /Users/ruki/.xmake/packages/z/zlib/1.2.11/d639b7d6e3244216b403b39df5101abf/include
  218. </code></pre>
  219. <p>手动关闭 external 外部头文件的编译 flags 如下:</p>
  220. <pre><code class="lang-lua">add_requires("zlib 1.x", {external = false})
  221. </code></pre>
  222. <pre><code class="lang-console">-I /Users/ruki/.xmake/packages/z/zlib/1.2.11/d639b7d6e3244216b403b39df5101abf/include
  223. </code></pre>
  224. <h2 id="">第三方依赖包安装</h2>
  225. <p>2.2.5版本之后,xmake支持对对第三方包管理器里面的依赖库安装支持,例如:conan, brew, vcpkg等</p>
  226. <h3 id="homebrew">添加 homebrew 的依赖包</h3>
  227. <pre><code class="lang-lua">add_requires("brew::zlib", {alias = "zlib"})
  228. add_requires("brew::pcre2/libpcre2-8", {alias = "pcre2"})
  229. target("test")
  230. set_kind("binary")
  231. add_files("src/*.c")
  232. add_packages("pcre2", "zlib")
  233. </code></pre>
  234. <h3 id="vcpkg">添加 vcpkg 的依赖包</h3>
  235. <pre><code class="lang-lua">add_requires("vcpkg::zlib", "vcpkg::pcre2")
  236. target("test")
  237. set_kind("binary")
  238. add_files("src/*.c")
  239. add_packages("vcpkg::zlib", "vcpkg::pcre2")
  240. </code></pre>
  241. <p>我们也可以加个包别名,简化对<code>add_packages</code>的使用:</p>
  242. <pre><code class="lang-lua">add_requires("vcpkg::zlib", {alias = "zlib"})
  243. add_requires("vcpkg::pcre2", {alias = "pcre2"})
  244. target("test")
  245. set_kind("binary")
  246. add_files("src/*.c")
  247. add_packages("zlib", "pcre2")
  248. </code></pre>
  249. <p>如果 vcpkg 包带有可选特性,我们也可以直接使用 vcpkg 的语法格式 <code>packagename[feature1,feature2]</code> 来安装包。</p>
  250. <p>例如:</p>
  251. <pre><code class="lang-lua">add_requires("vcpkg::boost[core]")
  252. </code></pre>
  253. <p>v2.6.3 之后,xmake 支持 vcpkg 新的清单模式,通过它,我们就能支持 vcpkg 包的版本选择,例如:</p>
  254. <pre><code class="lang-lua">add_requires("vcpkg::zlib 1.2.11")
  255. add_requires("vcpkg::fmt >=8.0.1", {configs = {baseline = "50fd3d9957195575849a49fa591e645f1d8e7156"}})
  256. add_requires("vcpkg::libpng", {configs = {features = {"apng"}}})
  257. target("test")
  258. set_kind("binary")
  259. add_files("src/*.cpp")
  260. add_packages("vcpkg::zlib", "vcpkg::fmt", "vcpkg::libpng")
  261. </code></pre>
  262. <p>v2.6.8 之后,还可以额外配置私有仓库,仅清单模式有效。</p>
  263. <pre><code class="lang-lua">local registries = {
  264. {
  265. kind = "git",
  266. repository = "https://github.com/SakuraEngine/vcpkg-registry",
  267. baseline = "e0e1e83ec66e3c9b36066f79d133b01eb68049f7",
  268. packages = {
  269. "skrgamenetworkingsockets"
  270. }
  271. }
  272. }
  273. add_requires("vcpkg::skrgamenetworkingsockets >=1.4.0+1", {configs = {registries = registries}})
  274. </code></pre>
  275. <h3 id="conan">添加 conan 的依赖包</h3>
  276. <pre><code class="lang-lua">add_requires("conan::zlib/1.2.11", {alias = "zlib", debug = true})
  277. add_requires("conan::openssl/1.1.1g", {alias = "openssl",
  278. configs = {options = "OpenSSL:shared=True"}})
  279. target("test")
  280. set_kind("binary")
  281. add_files("src/*.c")
  282. add_packages("openssl", "zlib")
  283. </code></pre>
  284. <p>执行xmake进行编译后:</p>
  285. <pre><code class="lang-console">ruki:test_package ruki$ xmake
  286. checking for the architecture ... x86_64
  287. checking for the Xcode directory ... /Applications/Xcode.app
  288. checking for the SDK version of Xcode ... 10.14
  289. note: try installing these packages (pass -y to skip confirm)?
  290. -> conan::zlib/1.2.11 (debug)
  291. -> conan::openssl/1.1.1g
  292. please input: y (y/n)
  293. => installing conan::zlib/1.2.11 .. ok
  294. => installing conan::openssl/1.1.1g .. ok
  295. [ 0%]: cache compiling.release src/main.c
  296. [100%]: linking.release test
  297. </code></pre>
  298. <p>自定义 conan/settings 配置:</p>
  299. <pre><code class="lang-lua">add_requires("conan::poco/1.10.0", {alias = "poco",
  300. configs = {settings = {"compiler=gcc", "compiler.libcxx=libstdc++11"}}})
  301. </code></pre>
  302. <p>其他一些 conan 相关配置项:</p>
  303. <pre><code>{
  304. build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}},
  305. remote = {description = "Set the conan remote server."},
  306. options = {description = "Set the options values, e.g. OpenSSL:shared=True"},
  307. imports = {description = "Set the imports for conan."},
  308. settings = {description = "Set the build settings for conan."},
  309. build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"}
  310. }
  311. </code></pre><h3 id="conda">添加 conda 的依赖包</h3>
  312. <pre><code class="lang-lua">add_requires("conda::zlib 1.2.11", {alias = "zlib"})
  313. target("test")
  314. set_kind("binary")
  315. add_files("src/*.c")
  316. add_packages("zlib")
  317. </code></pre>
  318. <h3 id="pacman">添加 pacman 的依赖包</h3>
  319. <p>我们既支持 archlinux 上的 pacman 包安装和集成,也支持 msys2 上 pacman 的 mingw x86_64/i386 包安装和集成。</p>
  320. <pre><code class="lang-lua">add_requires("pacman::zlib", {alias = "zlib"})
  321. add_requires("pacman::libpng", {alias = "libpng"})
  322. target("test")
  323. set_kind("binary")
  324. add_files("src/*.c")
  325. add_packages("zlib", "libpng")
  326. </code></pre>
  327. <p>archlinux 上只需要:</p>
  328. <pre><code class="lang-console">xmake
  329. </code></pre>
  330. <p>msys2 上安装 mingw 包,需要指定到 mingw 平台:</p>
  331. <pre><code class="lang-console">xmake f -p mingw -a [x86_64|i386]
  332. xmake
  333. </code></pre>
  334. <h3 id="clib">添加 clib 的依赖包</h3>
  335. <p>clib是一款基于源码的依赖包管理器,拉取的依赖包是直接下载对应的库源码,集成到项目中编译,而不是二进制库依赖。</p>
  336. <p>其在xmake中集成也很方便,唯一需要注意的是,还需要自己添加上对应库的源码到xmake.lua,例如:</p>
  337. <pre><code class="lang-lua">add_requires("clib::clibs/[email protected]", {alias = "bytes"})
  338. target("test")
  339. set_kind("binary")
  340. add_files("clib/bytes/*.c")
  341. add_files("src/*.c")
  342. add_packages("bytes")
  343. </code></pre>
  344. <h3 id="dubdlang">添加 dub/dlang 的依赖包</h3>
  345. <p>xmake 也支持 dlang 的 dub 包管理器,集成 dlang 的依赖包来使用。</p>
  346. <pre><code class="lang-lua">add_rules("mode.debug", "mode.release")
  347. add_requires("dub::log 0.4.3", {alias = "log"})
  348. add_requires("dub::dateparser", {alias = "dateparser"})
  349. add_requires("dub::emsi_containers", {alias = "emsi_containers"})
  350. add_requires("dub::stdx-allocator", {alias = "stdx-allocator"})
  351. add_requires("dub::mir-core", {alias = "mir-core"})
  352. target("test")
  353. set_kind("binary")
  354. add_files("src/*.d")
  355. add_packages("log", "dateparser", "emsi_containers", "stdx-allocator", "mir-core")
  356. </code></pre>
  357. <h3 id="ubuntuapt">添加 ubuntu/apt 的依赖包</h3>
  358. <p>v2.5.4 之后版本支持使用 apt 集成依赖包,也会自动查找 ubuntu 系统上已经安装的包。</p>
  359. <pre><code class="lang-lua">add_requires("apt::zlib1g-dev", {alias = "zlib"})
  360. target("test")
  361. set_kind("binary")
  362. add_files("src/*.c")
  363. add_packages("zlib")
  364. </code></pre>
  365. <h3 id="gentooportage">添加 gentoo/portage 的依赖包</h3>
  366. <p>v2.5.4 之后版本支持使用 Portage 集成依赖包,也会自动查找 Gentoo 系统上已经安装的包。</p>
  367. <pre><code class="lang-lua">add_requires("portage::libhandy", {alias = "libhandy"})
  368. target("test")
  369. set_kind("binary")
  370. add_files("src/*.c")
  371. add_packages("libhandy")
  372. </code></pre>
  373. <h3 id="nimble">添加 nimble 的依赖包</h3>
  374. <p>v2.5.8 之后支持集成 nimble 包管理器中的包,但是目前仅用于 nim 项目,因为它并没有提供二进制的包,而是直接安装的 nim 代码包。</p>
  375. <pre><code class="lang-lua">add_requires("nimble::zip >1.3")
  376. target("test")
  377. set_kind("binary")
  378. add_files("src/main.nim")
  379. add_packages("nimble::zip")
  380. </code></pre>
  381. <h3 id="cargo">添加 cargo 的依赖包</h3>
  382. <p>Cargo 依赖包主要给 rust 项目集成使用,例如:</p>
  383. <pre><code class="lang-lua">add_rules("mode.release", "mode.debug")
  384. add_requires("cargo::base64 0.13.0")
  385. add_requires("cargo::flate2 1.0.17", {configs = {features = "zlib"}})
  386. target("test")
  387. set_kind("binary")
  388. add_files("src/main.rs")
  389. add_packages("cargo::base64", "cargo::flate2")
  390. </code></pre>
  391. <p>不过,我们也可以在 C++ 中通过 cxxbridge 的方式,调用 Rust 库接口,来变相复用所有的 Rust 包。</p>
  392. <p>完整例子见:<a href="https://github.com/xmake-io/xmake/tree/dev/tests/projects/rust/cxx_call_rust_library">Call Rust in C++</a></p>
  393. <h3 id="nuget">添加 NuGet 的依赖包</h3>
  394. <p>2.9.7 之后,我们也支持从 dotnet/nuget 中,获取 native 库并快速集成。</p>
  395. <pre><code class="lang-lua">add_requires("nuget::zlib_static", {alias = "zlib"})
  396. target("test")
  397. set_kind("binary")
  398. add_files("src/*.cpp")
  399. add_packages("zlib")
  400. </code></pre>
  401. <h2 id="">使用自建私有包仓库</h2>
  402. <p>如果需要的包不在官方仓库<a href="https://github.com/xmake-io/xmake-repo">xmake-repo</a>中,我们可以提交贡献代码到仓库进行支持。<br>但如果有些包仅用于个人或者私有项目,我们可以建立一个私有仓库repo,仓库组织结构可参考:<a href="https://github.com/xmake-io/xmake-repo">xmake-repo</a></p>
  403. <p>比如,现在我们有一个一个私有仓库repo:<a href="mailto:`[email protected]">`[email protected]</a>:myrepo/xmake-repo.git`</p>
  404. <p>我们可以通过下面的命令进行仓库添加:</p>
  405. <pre><code class="lang-console">$ xmake repo --add myrepo [email protected]:myrepo/xmake-repo.git [branch]
  406. </code></pre>
  407. <p>!> [branch]是可选的,我们也可以切换到指定repo分支</p>
  408. <p>或者我们直接写在xmake.lua中:</p>
  409. <pre><code class="lang-lua">add_repositories("my-repo [email protected]:myrepo/xmake-repo.git")
  410. </code></pre>
  411. <p>同样,我们也可以切换到指定repo分支</p>
  412. <pre><code class="lang-lua">add_repositories("my-repo [email protected]:myrepo/xmake-repo.git dev")
  413. </code></pre>
  414. <p>如果我们只是想添加一两个私有包,这个时候特定去建立一个git repo太小题大做了,我们可以直接把包仓库放置项目里面,例如:</p>
  415. <pre><code>projectdir
  416. - myrepo
  417. - packages
  418. - t/tbox/xmake.lua
  419. - z/zlib/xmake.lua
  420. - src
  421. - main.c
  422. - xmake.lua
  423. </code></pre><p>上面myrepo目录就是自己的私有包仓库,内置在自己的项目里面,然后在xmake.lua里面添加一下这个仓库位置:</p>
  424. <pre><code class="lang-lua">add_repositories("my-repo myrepo")
  425. </code></pre>
  426. <p>这个可以参考<a href="https://github.com/xmake-io/benchbox">benchbox</a>项目,里面就内置了一个私有仓库。</p>
  427. <p>我们甚至可以连仓库也不用建,直接定义包描述到项目xmake.lua中,这对依赖一两个包的情况还是很有用的,例如:</p>
  428. <pre><code class="lang-lua">package("libjpeg")
  429. set_urls("http://www.ijg.org/files/jpegsrc.$(version).tar.gz")
  430. add_versions("v9c", "650250979303a649e21f87b5ccd02672af1ea6954b911342ea491f351ceb7122")
  431. on_install("windows", function (package)
  432. os.mv("jconfig.vc", "jconfig.h")
  433. os.vrun("nmake -f makefile.vc")
  434. os.cp("*.h", package:installdir("include"))
  435. os.cp("libjpeg.lib", package:installdir("lib"))
  436. end)
  437. on_install("macosx", "linux", function (package)
  438. import("package.tools.autoconf").install(package)
  439. end)
  440. package_end()
  441. add_requires("libjpeg")
  442. target("test")
  443. set_kind("binary")
  444. add_files("src/*.c")
  445. add_packages("libjpeg")
  446. </code></pre>
  447. <p>关于如何编写自定义包描述规则,详情见:<a href="#添加包到仓库">添加包到仓库</a></p>
  448. <h2 id="">包管理命令使用</h2>
  449. <p>包管理命令<code>$ xmake require</code> 可用于手动显示的下载编译安装、卸载、检索、查看包信息。</p>
  450. <h3 id="xrepo">xrepo 命令</h3>
  451. <p><code>xmake require</code> 仅用于当前工程,我们也提供了更加方便的独立 <code>xrepo</code> 包管理器命令,来全局对包进行安装,卸载和查找管理。</p>
  452. <p>详细文档见:<a href="https://xrepo.xmake.io/#/zh-cn/getting_started">Xrepo 命令使用入门</a></p>
  453. <h3 id="">安装指定包</h3>
  454. <pre><code class="lang-console">$ xmake require tbox
  455. </code></pre>
  456. <p>安装指定版本包:</p>
  457. <pre><code class="lang-console">$ xmake require tbox "~1.6"
  458. </code></pre>
  459. <p>强制重新下载安装,并且显示详细安装信息:</p>
  460. <pre><code class="lang-console">$ xmake require -f -v tbox "1.5.x"
  461. </code></pre>
  462. <p>传递额外的设置信息:</p>
  463. <pre><code class="lang-console">$ xmake require --extra="{debug=true,config={small=true}}" tbox
  464. </code></pre>
  465. <p>安装debug包,并且传递<code>small=true</code>的编译配置信息到包中去。</p>
  466. <h3 id="">卸载指定包</h3>
  467. <pre><code class="lang-console">$ xmake require --uninstall tbox
  468. </code></pre>
  469. <p>这会完全卸载删除包文件。</p>
  470. <h3 id="">查看包详细信息</h3>
  471. <pre><code class="lang-console">$ xmake require --info tbox
  472. </code></pre>
  473. <h3 id="">在当前仓库中搜索包</h3>
  474. <pre><code class="lang-console">$ xmake require --search tbox
  475. </code></pre>
  476. <p>这个是支持模糊搜素以及lua模式匹配搜索的:</p>
  477. <pre><code class="lang-console">$ xmake require --search pcr
  478. </code></pre>
  479. <p>会同时搜索到pcre, pcre2等包。</p>
  480. <h3 id="">列举当前已安装的包</h3>
  481. <pre><code class="lang-console">$ xmake require --list
  482. </code></pre>
  483. <h2 id="">仓库管理命令使用</h2>
  484. <p>上文已经简单讲过,添加私有仓库可以用(支持本地路径添加):</p>
  485. <pre><code class="lang-console">$ xmake repo --add myrepo [email protected]:myrepo/xmake-repo.git
  486. </code></pre>
  487. <p>v2.2.3开始,支持添加指定分支的repo,例如:</p>
  488. <pre><code class="lang-console">$ xmake repo --add myrepo [email protected]:myrepo/xmake-repo.git dev
  489. </code></pre>
  490. <p>!> 我们也可以添加本地仓库路径,即使没有git也是可以支持的,用于在本地快速的调试repo中的包。</p>
  491. <p>我们也可以移除已安装的某个仓库:</p>
  492. <pre><code class="lang-console">$ xmake repo --remove myrepo
  493. </code></pre>
  494. <p>或者查看所有已添加的仓库:</p>
  495. <pre><code class="lang-console">$ xmake repo --list
  496. </code></pre>
  497. <p>如果远程仓库有更新,可以手动执行仓库更新,来获取更多、最新的包:</p>
  498. <pre><code class="lang-console">$ xmake repo -u
  499. </code></pre>
  500. <h2 id="">远程包下载优化</h2>
  501. <p>如果由于网络不稳定,导致下载包速度很慢或者下载失败,我们可以通过的下面的一些方式来解决。</p>
  502. <h3 id="">手动下载</h3>
  503. <p>默认xmake会调用curl, wget等工具来下载,用户也可以手动用自己的下载器下载(也可以使用代理),把下载后的包放到自己的目录下,比如: <code>/download/packages/zlib-v1.0.tar.gz</code></p>
  504. <p>然后使用下面的命令,设置包下载的搜索目录:</p>
  505. <pre><code class="lang-console">$ xmake g --pkg_searchdirs="/download/packages"
  506. </code></pre>
  507. <p>然后重新执行xmake编译时候,xmake会优先从<code>/download/packages</code>找寻源码包,然后直接使用,不再自己下载了。</p>
  508. <p>至于找寻的包名是怎样的呢,可以通过下面的命令查看:</p>
  509. <pre><code class="lang-console">$ xmake require --info zlib
  510. -> searchdirs: /download/packages
  511. -> searchnames: zlib-1.2.11.tar.gz
  512. </code></pre>
  513. <p>我们可以看到对应的搜索目录以及搜索的包名。</p>
  514. <h3 id="">设置代理</h3>
  515. <p>如果觉得手动下载还是麻烦,我们也可以让xmake直接走代理。</p>
  516. <pre><code class="lang-console">$ xmake g --proxy="socks5://127.0.0.1:1086"
  517. $ xmake g --help
  518. -x PROXY, --proxy=PROXY Use proxy on given port. [PROTOCOL://]HOST[:PORT]
  519. e.g.
  520. - xmake g --proxy=&#39;http://host:port&#39;
  521. - xmake g --proxy=&#39;https://host:port&#39;
  522. - xmake g --proxy=&#39;socks5://host:port&#39;
  523. </code></pre>
  524. <p><code>--proxy</code>参数指定代理协议和地址,具体语法可以参考curl的,通常可以支持http, https, socks5等协议,但实际支持力度依赖curl, wget和git,比如wget就不支持socks5协议。</p>
  525. <p>我们可以通过下面的参数指定哪些host走代理,如果没设置,默认全局走代理。</p>
  526. <pre><code class="lang-console">--proxy_hosts=PROXY_HOSTS Only enable proxy for the given hosts list, it will enable all if be unset,
  527. and we can pass match pattern to list:
  528. e.g.
  529. - xmake g --proxy_hosts=&#39;github.com,gitlab.*,*.xmake.io&#39;
  530. </code></pre>
  531. <p>如果设置了hosts列表,那么之后这个列表里面匹配的host才走代理。。</p>
  532. <p><code>--proxy_host</code>支持多个hosts设置,逗号分隔,并且支持基础的模式匹配 *.github.com, 以及其他lua模式匹配规则也支持</p>
  533. <p>如果觉得上面的hosts模式配置还不够灵活,我们也可以走pac的自动代理配置规则:</p>
  534. <pre><code class="lang-console">--proxy_pac=PROXY_PAC Set the auto proxy configuration file. (default: pac.lua)
  535. e.g.
  536. - xmake g --proxy_pac=pac.lua (in /Users/ruki/.xmake or absolute path)
  537. - function main(url, host)
  538. if host == &#39;github.com&#39; then
  539. return true
  540. end
  541. end
  542. </code></pre>
  543. <p>!> 如果有proxy_hosts优先走hosts配置,没有的话才走pac配置。</p>
  544. <p>pac的默认路径:~/.xmake/pac.lua,如果--proxy被设置,并且这个文件存在,就会自动走pac,如果不存在,也没hosts,那就全局生效代理。</p>
  545. <p>也可以手动指定pac全路径</p>
  546. <pre><code class="lang-console">$ xmake g --proxy_pac=/xxxx/xxxxx_pac.lua
  547. </code></pre>
  548. <p>配置规则描述:</p>
  549. <pre><code class="lang-lua">function main(url, host)
  550. if host:find("bintray.com") then
  551. return true
  552. end
  553. end
  554. </code></pre>
  555. <p>如果返回true,那么这个url和host就是走的代理,不返回或者返回false,就是不走代理。</p>
  556. <p>这块的具体详情见:<a href="https://github.com/xmake-io/xmake/issues/854">https://github.com/xmake-io/xmake/issues/854</a></p>
  557. <p>!> 另外,除了依赖包下载,其他涉及网络下载的命令也都支持代理,比如:<code>xmake update</code></p>
  558. <h4 id="">镜像代理</h4>
  559. <p>v2.5.4 之后,pac.lua 配置里面还可以配置镜像代理规则,比如对所有 github.com 域名的访问切到 hub.fastgit.org 域名,实现加速下载包。</p>
  560. <pre><code class="lang-lua">function mirror(url)
  561. return url:gsub("github.com", "hub.fastgit.org")
  562. end
  563. </code></pre>
  564. <pre><code class="lang-console">$ xrepo install libpng
  565. > curl https://hub.fastgit.org/glennrp/libpng/archive/v1.6.37.zip -o v1.6.37.zip
  566. </code></pre>
  567. <h2 id="">添加包到仓库</h2>
  568. <h3 id="">仓库包结构</h3>
  569. <p>在制作自己的包之前,我们需要先了解下一个包仓库的结构,不管是官方包仓库,还是自建私有包仓库,结构都是相同的:</p>
  570. <pre><code>xmake-repo
  571. - packages
  572. - t/tbox/xmake.lua
  573. - z/zlib/xmake.lua
  574. </code></pre><p>通过上面的结构,可以看到每个包都会有个xmake.lua用于描述它的安装规则,并且根据<code>z/zlib</code>两级子目录分类存储,方便快速检索。</p>
  575. <h3 id="">包描述说明</h3>
  576. <p>关于包的描述规则,基本上都是在它的xmake.lua里面完成的,这跟项目工程里面的xmake.lua描述很类似,不同的是描述域仅支持<code>package()</code>,</p>
  577. <p>不过,在项目xmake.lua里面,也是可以直接添加<code>package()</code>来内置包描述的,连包仓库都省了,有时候这样会更加方便。</p>
  578. <p>首先,我们先拿zlib的描述规则,来直观感受下,这个规则可以在<a href="https://github.com/xmake-io/xmake-repo/blob/master/packages/z/zlib/xmake.lua">xmake-repo/z/zlib/xmake.lua</a>下找到。</p>
  579. <pre><code>package("zlib")
  580. set_homepage("http://www.zlib.net")
  581. set_description("A Massively Spiffy Yet Delicately Unobtrusive Compression Library")
  582. set_urls("http://zlib.net/zlib-$(version).tar.gz",
  583. "https://downloads.sourceforge.net/project/libpng/zlib/$(version)/zlib-$(version).tar.gz")
  584. add_versions("1.2.10", "8d7e9f698ce48787b6e1c67e6bff79e487303e66077e25cb9784ac8835978017")
  585. add_versions("1.2.11", "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
  586. on_install("windows", function (package)
  587. io.gsub("win32/Makefile.msc", "%-MD", "-" .. package:config("vs_runtime"))
  588. os.vrun("nmake -f win32\\Makefile.msc zlib.lib")
  589. os.cp("zlib.lib", package:installdir("lib"))
  590. os.cp("*.h", package:installdir("include"))
  591. end)
  592. on_install("linux", "macosx", function (package)
  593. import("package.tools.autoconf").install(package, {"--static"})
  594. end)
  595. on_install("iphoneos", "android@linux,macosx", "mingw@linux,macosx", function (package)
  596. import("package.tools.autoconf").configure(package, {host = "", "--static"})
  597. io.gsub("Makefile", "\nAR=.-\n", "\nAR=" .. (package:build_getenv("ar") or "") .. "\n")
  598. io.gsub("Makefile", "\nARFLAGS=.-\n", "\nARFLAGS=cr\n")
  599. io.gsub("Makefile", "\nRANLIB=.-\n", "\nRANLIB=\n")
  600. os.vrun("make install -j4")
  601. end)
  602. on_test(function (package)
  603. assert(package:has_cfuncs("inflate", {includes = "zlib.h"}))
  604. end)
  605. </code></pre><p>这个包规则对windows, linux, macosx, iphoneos,mingw等平台都添加了安装规则,基本上已经做到了全平台覆盖,甚至一些交叉编译平台,算是一个比较典型的例子了。</p>
  606. <p>当然,有些包依赖源码实现力度,并不能完全跨平台,那么只需对它支持的平台设置安装规则即可。</p>
  607. <p>更多详细的包配置 API 说明见:<a href="/mirror/zh-cn/manual/package_dependencies.html">包接口文档</a></p>
  608. <h3 id="">扩展配置参数</h3>
  609. <p>详情见:<a href="/mirror/zh-cn/manual/package_dependencies.html#packageadd_configs">add_configs</a></p>
  610. <h3 id="">内置配置参数</h3>
  611. <p>除了可以通过<a href="/mirror/zh-cn/manual/package_dependencies.html#packageadd_configs">add_configs</a>设置一些扩展的配置参数以外,xmake还提供了一些内置的配置参数,可以使用</p>
  612. <h4 id="">启用调试包</h4>
  613. <pre><code class="lang-lua">add_requires("xxx", {debug = true})
  614. </code></pre>
  615. <p>包描述里面必须有相关处理才能支持:</p>
  616. <pre><code class="lang-lua">on_install(function (package)
  617. local configs = {}
  618. if package:debug() then
  619. table.insert(configs, "--enable-debug")
  620. end
  621. import("package.tools.autoconf").install(package)
  622. end)
  623. </code></pre>
  624. <h4 id="msvc">设置msvc运行时库</h4>
  625. <pre><code class="lang-lua">add_requires("xxx", {configs = {vs_runtime = "MT"}})
  626. </code></pre>
  627. <p>通常情况下,通过<code>import("package.tools.autoconf").install</code>等内置工具脚本安装的包,内部都对vs_runtime自动处理过了。</p>
  628. <p>但是如果是一些特殊的源码包,构建规则比较特殊,那么需要自己处理了:</p>
  629. <pre><code class="lang-lua">on_install(function (package)
  630. io.gsub("build/Makefile.win32.common", "%-MD", "-" .. package:config("vs_runtime"))
  631. end)
  632. </code></pre>
  633. <h3 id="">添加环境变量</h3>
  634. <p>对于一些库,里面也带了可执行的工具,如果需要在集成包的时候,使用上这些工具,那么也可以设置上对应PATH环境变量:</p>
  635. <pre><code class="lang-lua">package("luajit")
  636. on_load(function (package)
  637. if is_plat("windows") then
  638. package:addenv("PATH", "lib")
  639. end
  640. package:addenv("PATH", "bin")
  641. end)
  642. </code></pre>
  643. <p>而在项目工程中,只有通过<code>add_packages</code>集成对应的包后,对应的环境变量才会生效。</p>
  644. <pre><code class="lang-lua">add_requires("luajit")
  645. target("test")
  646. set_kind("binary")
  647. add_packages("luajit")
  648. after_run(function (package)
  649. os.exec("luajit --version")
  650. end)
  651. </code></pre>
  652. <h3 id="">安装二进制包</h3>
  653. <p>xmake也是支持直接引用二进制版本包,直接安装使用,例如:</p>
  654. <pre><code class="lang-lua">if is_plat("windows") then
  655. set_urls("https://www.libsdl.org/release/SDL2-devel-$(version)-VC.zip")
  656. add_versions("2.0.8", "68505e1f7c16d8538e116405411205355a029dcf2df738dbbc768b2fe95d20fd")
  657. end
  658. on_install("windows", function (package)
  659. os.cp("include", package:installdir())
  660. os.cp("lib/$(arch)/*.lib", package:installdir("lib"))
  661. os.cp("lib/$(arch)/*.dll", package:installdir("lib"))
  662. end)
  663. </code></pre>
  664. <h3 id="">本地测试</h3>
  665. <p>如果在本地xmake-repo仓库中,已经添加和制作好了新的包,可以在本地运行测试下,是否通过,如果测试通过,即可提交pr到官方仓库,请求merge。</p>
  666. <p>我们可以执行下面的脚本进行测试指定包:</p>
  667. <pre><code class="lang-bash">cd xmake-repo
  668. xmake l scripts/test.lua -v -D zlib
  669. </code></pre>
  670. <p>上面的命令,会强制重新下载和安装zlib包,测试整个安装流程是否ok,加上<code>-v -D</code>是为了可以看到完整详细的日志信息和出错信息,方便调试分析。</p>
  671. <p>如果网络环境不好,不想每次测试都去重新下载所有依赖,可以加上<code>--shallow</code>参数来执行,这个参数告诉脚本,仅仅重新解压本地缓存的zlib源码包,重新执行安装命令,但不会下载各种依赖。</p>
  672. <pre><code class="lang-bash">cd xmake-repo
  673. xmake l scripts/test.lua -v -D --shallow zlib
  674. </code></pre>
  675. <p>如果我们想测试其他平台的包规则是否正常,比如: android, iphoneos等平台,可以通过<code>-p/--plat</code>或者<code>-a/--arch</code>来指定。</p>
  676. <pre><code class="lang-bash">cd xmake-repo
  677. xmake l scripts/test.lua -v -D --shallow -p iphoneos -a arm64 zlib
  678. xmake l scripts/test.lua -v -D --shallow -p android --ndk=/xxxx zlib
  679. </code></pre>
  680. <h2 id="">提交包到官方仓库</h2>
  681. <p>目前这个特性刚完成不久,目前官方仓库的包还不是很多,有些包也许还不支持部分平台,不过这并不是太大问题,后期迭代几个版本后,我会不断扩充完善包仓库。</p>
  682. <p>如果你需要的包,当前的官方仓库还没有收录,可以提交issues或者自己可以在本地调通后,贡献提交到官方仓库:<a href="https://github.com/xmake-io/xmake-repo">xmake-repo</a></p>
  683. <p>详细的贡献说明,见:<a href="https://github.com/xmake-io/xmake-repo/blob/master/CONTRIBUTING.md">CONTRIBUTING.md</a></p>
  684. <p>关于如何制作自己的包,可以看下上文:<a href="#添加包到仓库">添加包到仓库</a>。</p>
  685. <h2 id="">依赖包的锁定和升级</h2>
  686. <p>v2.5.7 之后,新增依赖包的版本锁定,类似 npm 的 package.lock, cargo 的 cargo.lock。</p>
  687. <p>比如,我们引用一些包,默认情况下,如果不指定版本,那么 xmake 每次都会自动拉取最新版本的包来集成使用,例如:</p>
  688. <pre><code class="lang-lua">add_requires("zlib")
  689. </code></pre>
  690. <p>但如果上游的包仓库更新改动,比如 zlib 新增了一个 1.2.11 版本,或者安装脚本有了变动,都会导致用户的依赖包发生改变。</p>
  691. <p>这容易导致原本编译通过的一些项目,由于依赖包的变动出现一些不稳定因素,有可能编译失败等等。</p>
  692. <p>为了确保用户的项目每次使用的包都是固定的,我们可以通过下面的配置去启用包依赖锁定。</p>
  693. <pre><code class="lang-lua">set_policy("package.requires_lock", true)
  694. </code></pre>
  695. <p>这是一个全局设置,必须设置到全局根作用域,如果启用后,xmake 执行完包拉取,就会自动生成一个 <code>xmake-requires.lock</code> 的配置文件。</p>
  696. <p>它包含了项目依赖的所有包,以及当前包的版本等信息。</p>
  697. <pre><code class="lang-lua">{
  698. __meta__ = {
  699. version = "1.0"
  700. },
  701. ["macosx|x86_64"] = {
  702. ["cmake#31fecfc4"] = {
  703. repo = {
  704. branch = "master",
  705. commit = "4498f11267de5112199152ab030ed139c985ad5a",
  706. url = "https://github.com/xmake-io/xmake-repo.git"
  707. },
  708. version = "3.21.0"
  709. },
  710. ["glfw#31fecfc4"] = {
  711. repo = {
  712. branch = "master",
  713. commit = "eda7adee81bac151f87c507030cc0dd8ab299462",
  714. url = "https://github.com/xmake-io/xmake-repo.git"
  715. },
  716. version = "3.3.4"
  717. },
  718. ["opengl#31fecfc4"] = {
  719. repo = {
  720. branch = "master",
  721. commit = "94d2eee1f466092e04c5cf1e4ecc8c8883c1d0eb",
  722. url = "https://github.com/xmake-io/xmake-repo.git"
  723. }
  724. }
  725. }
  726. }
  727. </code></pre>
  728. <p>当然,我们也可以执行下面的命令,强制升级包到最新版本。</p>
  729. <pre><code class="lang-console">$ xmake require --upgrade
  730. upgrading packages ..
  731. zlib: 1.2.10 -> 1.2.11
  732. 1 package is upgraded!
  733. </code></pre>
  734. <h2 id="">分发和使用自定义包规则</h2>
  735. <p>2.7.2 版本之后,我们可以在包管理仓库中,添加自定义构架规则脚本,实现跟随包进行动态下发和安装。</p>
  736. <p>我们需要将自定义规则放到仓库的 <code>packages/x/xxx/rules</code> 目录中,它会跟随包一起被安装。</p>
  737. <p>但是,它也存在一些限制:</p>
  738. <ul>
  739. <li>在包中规则,我们不能添加 <code>on_load</code>, <code>after_load</code> 脚本,但是通常我们可以使用 <code>on_config</code> 来代替。</li>
  740. </ul>
  741. <h3 id="">添加包规则</h3>
  742. <p>我们需要将规则脚本添加到 rules 固定目录下,例如:packages/z/zlib/rules/foo.lua</p>
  743. <pre><code class="lang-lua">rule("foo")
  744. on_config(function (target)
  745. print("foo: on_config %s", target:name())
  746. end)
  747. </code></pre>
  748. <h3 id="">应用包规则</h3>
  749. <p>使用规则的方式跟之前类似,唯一的区别就是,我们需要通过 <code>@packagename/</code> 前缀去指定访问哪个包里面的规则。</p>
  750. <p>具体格式:<code>add_rules("@packagename/rulename")</code>,例如:<code>add_rules("@zlib/foo")</code>。</p>
  751. <pre><code class="lang-lua">add_requires("zlib", {system = false})
  752. target("test")
  753. set_kind("binary")
  754. add_files("src/*.cpp")
  755. add_packages("zlib")
  756. add_rules("@zlib/foo")
  757. </code></pre>
  758. <h3 id="">通过包别名引用规则</h3>
  759. <p>如果存在一个包的别名,xmake 将优先考虑包的别名来获得规则。</p>
  760. <pre><code class="lang-lua">add_requires("zlib", {alias = "zlib2", system = false})
  761. target("test")
  762. set_kind("binary")
  763. add_files("src/*.cpp")
  764. add_packages("zlib2")
  765. add_rules("@zlib2/foo")
  766. </code></pre>
  767. <h3 id="">添加包规则依赖</h3>
  768. <p>我们可以使用<code>add_deps("@bar")</code>来添加相对于当前包目录的其他规则。</p>
  769. <p>然而,我们不能添加来自其他包的规则依赖,它们是完全隔离的,我们只能参考用户项目中由<code>add_requires</code>导入的其他包的规则。</p>
  770. <p>packages/z/zlib/rules/foo.lua</p>
  771. <pre><code class="lang-lua">rule("foo")
  772. add_deps("@bar")
  773. on_config(function (target)
  774. print("foo: on_config %s", target:name())
  775. end)
  776. </code></pre>
  777. <p>packages/z/zlib/rules/bar.lua</p>
  778. <pre><code class="lang-lua">rule("bar")
  779. on_config(function (target)
  780. print("bar: on_config %s", target:name())
  781. end)
  782. </code></pre>
  783. <h2 id="cmakexrepo">在 CMake 中使用 Xrepo 的依赖包管理</h2>
  784. <p>我们新增了一个独立项目 <a href="https://github.com/xmake-io/xrepo-cmake">xrepo-cmake</a>。</p>
  785. <p>它是一个基于 Xrepo/Xmake 的 C/C++ 包管理器的 CMake 包装器。</p>
  786. <p>这允许使用 CMake 来构建您的项目,同时使用 Xrepo 来管理依赖包。这个项目的部分灵感来自 <a href="https://github.com/conan-io/cmake-conan">cmake-conan</a>。</p>
  787. <p>此项目的示例用例:</p>
  788. <ul>
  789. <li>想要使用 Xrepo 管理包的现有 CMake 项目。</li>
  790. <li>必须使用 CMake,但想使用 Xrepo 管理的新项目包。</li>
  791. </ul>
  792. <h3 id="apis">Apis</h3>
  793. <h4 id="xrepo_package">xrepo_package</h4>
  794. <p><a href="https://github.com/xmake-io/xrepo-cmake/blob/main/xrepo.cmake">xrepo.cmake</a> 提供<code>xrepo_package</code>函数来管理包。</p>
  795. <pre><code class="lang-cmake">xrepo_package(
  796. "foo 1.2.3"
  797. [CONFIGS feature1=true,feature2=false]
  798. [CONFIGS path/to/script.lua]
  799. [DEPS]
  800. [MODE debug|release]
  801. [ALIAS aliasname]
  802. [OUTPUT verbose|diagnosis|quiet]
  803. [DIRECTORY_SCOPE]
  804. )
  805. </code></pre>
  806. <p>一些函数参数直接对应于 Xrepo 命令选项。</p>
  807. <p><code>xrepo_package</code> 将软件包安装目录添加到 <code>CMAKE_PREFIX_PATH</code>。所以<code>find_package</code><br>可以使用。如果 <code>CMAKE_MINIMUM_REQUIRED_VERSION</code> >= 3.1,cmake <code>pkgConfig</code> 也会搜索<br>对于软件包安装目录下的 pkgconfig 文件。</p>
  808. <p>调用 <code>xrepo_package(foo)</code> 后,有 <code>foo</code> 包的三种使用方式:</p>
  809. <ol>
  810. <li>如果包提供 cmake 配置文件,则调用 <code>find_package(foo)</code>。<ul>
  811. <li>有关详细信息,请参阅 CMake <a href="https://cmake.org/cmake/help/latest/command/find_package.html"><code>find_package</code></a> 文档。<br>2.如果包没有提供cmake配置文件或者找不到模块<ul>
  812. <li>以下变量可用于使用pacakge(cmake后的变量名<br>查找模块 <a href="https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#standard-variable-names">标准变量名称</a>)</li>
  813. <li><code>foo_INCLUDE_DIRS</code></li>
  814. <li><code>foo_LIBRARY_DIRS</code></li>
  815. <li><code>foo_LIBRARIES</code></li>
  816. <li><code>foo_DEFINITIONS</code></li>
  817. <li>如果指定了 <code>DIRECTORY_SCOPE</code>,则 <code>xrepo_package</code> 将运行以下代码<pre><code class="lang-cmake">include_directories(${foo_INCLUDE_DIRS})
  818. link_directories(${foo_LIBRARY_DIRS})
  819. </code></pre>
  820. </li>
  821. </ul>
  822. </li>
  823. </ul>
  824. </li>
  825. <li>使用<code>xrepo_target_packages</code>。请参阅以下部分。</li>
  826. </ol>
  827. <p>注意 <code>CONFIGS path/to/script.lua</code> 用于对包配置进行精细控制。<br>例如:</p>
  828. <ul>
  829. <li>排除系统上的包。</li>
  830. <li>覆盖依赖包的默认配置,例如设置<code>shared=true</code>。</li>
  831. </ul>
  832. <p>如果指定了 <code>DEPS</code>,所有依赖库都将添加到 <code>CMAKE_PREFIX_PATH</code>,以及 include 和 libraries 那四个变量中。</p>
  833. <h4 id="xrepo_target_packages">xrepo_target_packages</h4>
  834. <p>将包 includedirs 和 links/linkdirs 添加到给定的目标。</p>
  835. <pre><code class="lang-cmake">xrepo_target_packages(
  836. target
  837. [NO_LINK_LIBRARIES]
  838. [PRIVATE|PUBLIC|INTERFACE]
  839. package1 package2 ...
  840. )
  841. </code></pre>
  842. <h3 id="">使用来自官方存储库的包</h3>
  843. <p>Xrepo 官方仓库:<a href="https://github.com/xmake-io/xmake-repo">xmake-repo</a></p>
  844. <p>这是一个使用 <code>gflags</code> 包版本 2.2.2 的示例 <code>CMakeLists.txt</code> 由 Xrepo 管理。</p>
  845. <h4 id="xrepocmake">集成 xrepo.cmake</h4>
  846. <pre><code class="lang-cmake">cmake_minimum_required(VERSION 3.13.0)
  847. project(foo)
  848. # Download xrepo.cmake if not exists in build directory.
  849. if(NOT EXISTS "${CMAKE_BINARY_DIR}/xrepo.cmake")
  850. message(STATUS "Downloading xrepo.cmake from https://github.com/xmake-io/xrepo-cmake/")
  851. # mirror https://cdn.jsdelivr.net/gh/xmake-io/xrepo-cmake@main/xrepo.cmake
  852. file(DOWNLOAD "https://raw.githubusercontent.com/xmake-io/xrepo-cmake/main/xrepo.cmake"
  853. "${CMAKE_BINARY_DIR}/xrepo.cmake"
  854. TLS_VERIFY ON)
  855. endif()
  856. # Include xrepo.cmake so we can use xrepo_package function.
  857. include(${CMAKE_BINARY_DIR}/xrepo.cmake)
  858. </code></pre>
  859. <h4 id="">添加包</h4>
  860. <pre><code class="lang-cmake">xrepo_package("zlib")
  861. add_executable(example-bin "")
  862. target_sources(example-bin PRIVATE
  863. src/main.cpp
  864. )
  865. xrepo_target_packages(example-bin zlib)
  866. </code></pre>
  867. <h4 id="">添加带有配置的包</h4>
  868. <pre><code class="lang-cmake">xrepo_package("gflags 2.2.2" CONFIGS "shared=true,mt=true")
  869. add_executable(example-bin "")
  870. target_sources(example-bin PRIVATE
  871. src/main.cpp
  872. )
  873. xrepo_target_packages(example-bin gflags)
  874. </code></pre>
  875. <h4 id="cmake">添加带有 cmake 导入模块的包</h4>
  876. <pre><code class="lang-cmake">xrepo_package("gflags 2.2.2" CONFIGS "shared=true,mt=true")
  877. # `xrepo_package` 会将 gflags 安装目录添加到 CMAKE_PREFIX_PATH.
  878. # `find_package(gflags)` 会从 CMAKE_PREFIX_PATH 包含的目录中找到 gflags 提供的
  879. # config-file 文件。
  880. # 参考 https://cmake.org/cmake/help/latest/command/find_package.html#search-modes
  881. find_package(gflags CONFIG COMPONENTS shared)
  882. add_executable(example-bin "")
  883. target_sources(example-bin PRIVATE
  884. src/main.cpp
  885. )
  886. target_link_libraries(example-bin gflags)
  887. </code></pre>
  888. <h4 id="">添加自定义包</h4>
  889. <pre><code class="lang-cmake">set(XREPO_XMAKEFILE ${CMAKE_CURRENT_SOURCE_DIR}/packages/xmake.lua)
  890. xrepo_package("myzlib")
  891. add_executable(example-bin "")
  892. target_sources(example-bin PRIVATE
  893. src/main.cpp
  894. )
  895. xrepo_target_packages(example-bin myzlib)
  896. </code></pre>
  897. <p>在 packages/xmake.lua 中定义一个包:</p>
  898. <pre><code class="lang-lua">package("myzlib")
  899. -- ...
  900. </code></pre>
  901. <p>我们可以自定义一个包,具体定义方式,参考文档:<a href="https://xmake.io/#/zh-cn/package/remote_package?id=package-description">自定义 Xrepo 包</a>。</p>
  902. <h3 id="">使用来自第三个存储库的包</h3>
  903. <p>除了从官方维护的存储库安装软件包之外,Xrepo 还可以安装来自第三方包管理器的包,例如 vcpkg/conan/conda/pacman/homebrew/apt/dub/cargo。</p>
  904. <p>关于命令行的使用,我们可以参考文档:<a href="https://xrepo.xmake.io/#/getting_started?id=install-packages-from-third-party-package-manager">Xrepo命令用法</a></p>
  905. <p>我们也可以直接在 cmake 中使用它来安装来自第三方仓库的包,只需将仓库名称添加为命名空间即可。例如:<code>vcpkg::zlib</code>, <code>conan::pcre2</code></p>
  906. <h4 id="conan">Conan</h4>
  907. <pre><code class="lang-cmake">xrepo_package("conan::gflags/2.2.2")
  908. </code></pre>
  909. <h4 id="conda">Conda</h4>
  910. <pre><code class="lang-cmake">xrepo_package("conda::gflags 2.2.2")
  911. </code></pre>
  912. <h4 id="vcpkg">Vcpkg</h4>
  913. <pre><code class="lang-cmake">xrepo_package("vcpkg::gflags")
  914. </code></pre>
  915. <h4 id="homebrew">Homebrew</h4>
  916. <pre><code class="lang-cmake">xrepo_package("brew::gflags")
  917. </code></pre>
  918. </article>
  919. </body>
  920. </html>