aboutsummaryrefslogtreecommitdiff
path: root/zh-cn/guide/package_management.md
blob: 0be1fdf19f427a42d52903a621677f070f203be0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518

## 本地内置模式

通过在项目中内置依赖包目录以及二进制包文件,可以方便的集成一些第三方的依赖库,这种方式比较简单直接,但是缺点也很明显,不方便管理。

以tbox工程为例,其依赖包如下:

```
- base.pkg
- zlib.pkg
- polarssl.pkg
- openssl.pkg
- mysql.pkg
- pcre.pkg
- ...
```

如果要让当前工程识别加载这些包,首先要指定包目录路径,例如:

```lua
add_packagedirs("packages")
```

指定好后,就可以在target作用域中,通过[add_packages](/zh-cn/manual/project_target?id=targetadd_packages)接口,来添加集成包依赖了,例如:

```lua
target("tbox")
    add_packages("zlib", "polarssl", "pcre", "mysql")
```

那么如何去生成一个*.pkg的包呢,如果是基于xmake的工程,生成方式很简单,只需要:

```console
$ cd tbox
$ xmake package
```

即可在build目录下生成一个tbox.pkg的跨平台包,给第三方项目使用,我也可以直接设置输出目录,编译生成到对方项目中去,例如:

```console
$ cd tbox
$ xmake package -o ../test/packages
```

这样,test工程就可以通过[add_packages]((/zh-cn/manual/project_target?id=targetadd_packages)和[add_packagedirs](/zh-cn/manual/global_interfaces?id=add_packagedirs)去配置和使用tbox.pkg包了。

关于内置包的详细描述,还可以参考下相关文章,这里面有详细介绍:[依赖包的添加和自动检测机制](https://tboox.org/cn/2016/08/06/add-package-and-autocheck/)

## 系统查找模式

如果觉得上述内置包的管理方式非常不方便,可以通过xmake提供的内置接口`find_packages`。

目前此接口支持以下一些包管理支持:

* vcpkg
* homebrew
* pkg-config

并且通过系统和第三方包管理工具进行依赖包的安装,然后与xmake进行集成使用,例如我们查找一个openssl包:

```lua
local packages = find_packages("openssl", "zlib")
```

返回的结果如下:

```lua
{
    {links = {"ssl", "crypto"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}},
    {links = {"z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}}
}
```

如果查找成功,则返回一个包含所有包信息的table,如果失败返回nil

这里的返回结果可以直接作为`target:add`, `option:add`的参数传入,用于动态增加`target/option`的配置:

```lua
option("zlib")
    set_showmenu(true)
    before_check(function (option)
        option:add(find_packages("openssl", "zlib"))
    end)
```

```lua
target("test")
    on_load(function (target)
        target:add(find_package("openssl", "zlib"))
    end)
```

如果系统上装有`homebrew`, `pkg-config`等第三方工具,那么此接口会尝试使用它们去改进查找结果。

另外,我们也可以从指定的包管理器查找包:

```lua
find_packages("brew::pcre2/libpcre2-8", "vcpkg::zlib")
```

更完整的使用描述,请参考:[find_packages](/zh-cn/manual/builtin_modules?id=find_packages)接口文档。

### homebrew集成支持

由于homebrew一般都是把包直接装到的系统中去了,因此用户不需要做任何集成工作,`find_packages`就已经原生无缝支持。

### vcpkg集成支持

目前xmake v2.2.2版本已经支持了vcpkg,用户只需要装完vcpkg后,执行`$ vcpkg integrate install`,xmake就能自动从系统中检测到vcpkg的根路径,然后自动适配里面包。

当然,我们也可以手动指定vcpkg的根路径来支持:

```console
$ xmake f --vcpkg=f:\vcpkg
```

或者我们可以设置到全局配置中去,避免每次切换配置的时候,重复设置:

```console
$ xmake g --vcpkg=f:\vcpkg
```

## 远程依赖模式

这个在2.2.2版本后已经初步支持,用法上更加的简单,只需要设置对应的依赖包就行了,例如:

```lua
add_requires("tbox 1.6.*", "libpng ~1.16", "zlib")

target("test")
    set_kind("binary")
    add_files("src/*.c") 
    add_packages("tbox", "libpng", "zlib")
```

上面的`add_requires`用于描述当前项目需要的依赖包,而`add_packages`用于应用依赖包到test目标,只有设置这个才会自动追加links, linkdirs, includedirs等设置。

然后直接执行编译即可:

```console
$ xmake 
```

xmake会去远程拉取相关源码包,然后自动编译安装,最后编译项目,进行依赖包的链接,具体效果见下图:

<img src="/assets/img/index/package_manage.png" width="80%" />

关于包依赖管理的更多相关信息和进展见相关issues:[Remote package management](https://github.com/xmake-io/xmake/issues/69) 

### 目前支持的特性

* 语义版本支持,例如:">= 1.1.0 < 1.2", "~1.6", "1.2.x", "1.*"
* 提供官方包仓库、自建私有仓库、项目内置仓库等多仓库管理支持
* 跨平台包编译集成支持(不同平台、不同架构的包可同时安装,快速切换使用)
* debug依赖包支持,实现源码调试

### 依赖包处理机制

这里我们简单介绍下整个依赖包的处理机制:

<img src="/assets/img/index/package_arch.png" width="80%" />

1. 优先检测当前系统目录、第三方包管理下有没有存在指定的包,如果有匹配的包,那么就不需要下载安装了 (当然也可以设置不使用系统包)
2. 检索匹配对应版本的包,然后下载、编译、安装(注:安装在特定xmake目录,不会干扰系统库环境)
3. 编译项目,最后自动链接启用的依赖包

### 快速上手

新建一个依赖tbox库的空工程:

```console
$ xmake create -t console_tbox test
$ cd test
```

执行编译即可,如果当前没有安装tbox库,则会自动下载安装后使用:

```console
$ xmake
```

切换到iphoneos平台进行编译,将会重新安装iphoneos版本的tbox库进行链接使用:

```console
$ xmake f -p iphoneos
$ xmake
```

切换到android平台arm64-v8a架构编译:

```console
$ xmake f -p android [--ndk=~/android-ndk-r16b]
$ xmake
```

### 语义版本设置

xmake的依赖包管理是完全支持语义版本选择的,例如:"~1.6.1",对于语义版本的具体描述见:[https://semver.org/](https://semver.org/)

一些语义版本写法:

```lua
add_requires("tbox 1.6.*", "pcre 1.3.x", "libpng ^1.18")
add_requires("libpng ~1.16", "zlib 1.1.2 || >=1.2.11 <1.3.0")
```

目前xmake使用的语义版本解析器是[uael](https://github.com/uael)贡献的[sv](https://github.com/uael/sv)库,里面也有对版本描述写法的详细说明,可以参考下:[版本描述说明](https://github.com/uael/sv#versions)

当然,如果我们对当前的依赖包的版本没有特殊要求,那么可以直接这么写:

```lua
add_requires("tbox", "libpng", "zlib")
```

这会使用已知的最新版本包,或者是master分支的源码编译的包,如果当前包有git repo地址,我们也能指定特定分支版本:

```lua
add_requires("tbox master")
add_requires("tbox dev")
```

### 额外的包信息设置

#### 可选包设置

如果指定的依赖包当前平台不支持,或者编译安装失败了,那么xmake会编译报错,这对于有些必须要依赖某些包才能工作的项目,这是合理的。
但是如果有些包是可选的依赖,即使没有也可以正常编译使用的话,可以设置为可选包:

```lua
add_requires("tbox", {optional = true})
```

#### 禁用系统库

默认的设置,xmake会去优先检测系统库是否存在(如果没设置版本要求),如果用户完全不想使用系统库以及第三方包管理提供的库,那么可以设置:

```lua
add_requires("tbox", {system = false})
```

#### 使用调试版本的包

如果我们想同时源码调试依赖包,那么可以设置为使用debug版本的包(当然前提是这个包支持debug编译):

```lua
add_requires("tbox", {debug = true})
```

如果当前包还不支持debug编译,可在仓库中提交修改编译规则,对debug进行支持,例如:

```lua
package("openssl")
    on_install("linux", "macosx", function (package)
        os.vrun("./config %s --prefix=\"%s\"", package:debug() and "--debug" or "", package:installdir())
        os.vrun("make -j4")
        os.vrun("make install")
    end)
```

#### 传递额外的编译信息到包

某些包在编译时候有各种编译选项,我们也可以传递进来,当然包本身得支持:

```lua
add_requires("tbox", {configs = {small=true}})
```

传递`--small=true`给tbox包,使得编译安装的tbox包是启用此选项的。

### 第三方依赖包安装

2.2.5版本之后,xmake支持对对第三方包管理器里面的依赖库安装支持,例如:conan,brew, vcpkg等

#### 添加homebrew的依赖包

```lua
add_requires("brew::zlib", {alias = "zlib"}})
add_requires("brew::pcre2/libpcre2-8", {alias = "pcre2"}})

target("test")
    set_kind("binary")
    add_files("src/*.c") 
    add_packages("pcre2", "zlib")
```

#### 添加vcpkg的依赖包

```lua
add_requires("vcpkg::zlib", "vcpkg::pcre2")

target("test")
    set_kind("binary")
    add_files("src/*.c") 
    add_packages("vcpkg::zlib", "vcpkg::pcre2")
```

#### 添加conan的依赖包

```lua
add_requires("CONAN::zlib/1.2.11@conan/stable", {alias = "zlib", debug = true})
add_requires("CONAN::OpenSSL/1.0.2n@conan/stable", {alias = "openssl", 
    configs = {options = "OpenSSL:shared=True"}})

target("test")
    set_kind("binary")
    add_files("src/*.c") 
    add_packages("openssl", "zlib")
```

执行xmake进行编译后:

```console
ruki:test_package ruki$ xmake
checking for the architecture ... x86_64
checking for the Xcode directory ... /Applications/Xcode.app
checking for the SDK version of Xcode ... 10.14
note: try installing these packages (pass -y to skip confirm)?
  -> CONAN::zlib/1.2.11@conan/stable  (debug)
  -> CONAN::OpenSSL/1.0.2n@conan/stable  
please input: y (y/n)

  => installing CONAN::zlib/1.2.11@conan/stable .. ok
  => installing CONAN::OpenSSL/1.0.2n@conan/stable .. ok

[  0%]: ccache compiling.release src/main.c
[100%]: linking.release test
```

#### 添加clib的依赖包

clib是一款基于源码的依赖包管理器,拉取的依赖包是直接下载对应的库源码,集成到项目中编译,而不是二进制库依赖。

其在xmake中集成也很方便,唯一需要注意的是,还需要自己添加上对应库的源码到xmake.lua,例如:

```lua
add_requires("clib::clibs/bytes@0.0.4", {alias = "bytes"})

target("test")
    set_kind("binary")
    add_files("clib/bytes/*.c")
    add_files("src/*.c") 
    add_packages("bytes")
```

### 使用自建私有包仓库

如果需要的包不在官方仓库[xmake-repo](https://github.com/xmake-io/xmake-repo)中,我们可以提交贡献代码到仓库进行支持。
但如果有些包仅用于个人或者私有项目,我们可以建立一个私有仓库repo,仓库组织结构可参考:[xmake-repo](https://github.com/xmake-io/xmake-repo)

比如,现在我们有一个一个私有仓库repo:`git@github.com:myrepo/xmake-repo.git`

我们可以通过下面的命令进行仓库添加:

```console
$ xmake repo --add myrepo git@github.com:myrepo/xmake-repo.git
```

或者我们直接写在xmake.lua中:

```lua
add_repositories("my-repo git@github.com:myrepo/xmake-repo.git")
```

如果我们只是想添加一两个私有包,这个时候特定去建立一个git repo太小题大做了,我们可以直接把包仓库放置项目里面,例如:

```
projectdir
  - myrepo
    - packages
      - t/tbox/xmake.lua
      - z/zlib/xmake.lua
  - src
    - main.c
  - xmake.lua
```

上面myrepo目录就是自己的私有包仓库,内置在自己的项目里面,然后在xmake.lua里面添加一下这个仓库位置:

```lua
add_repositories("my-repo myrepo")
```

这个可以参考[benchbox](https://github.com/tboox/benchbox)项目,里面就内置了一个私有仓库。

我们甚至可以连仓库也不用建,直接定义包描述到项目xmake.lua中,这对依赖一两个包的情况还是很有用的,例如:

```lua
package("libjpeg")

    set_urls("http://www.ijg.org/files/jpegsrc.$(version).tar.gz")

    add_versions("v9c", "650250979303a649e21f87b5ccd02672af1ea6954b911342ea491f351ceb7122")

    on_install("windows", function (package)
        os.mv("jconfig.vc", "jconfig.h")
        os.vrun("nmake -f makefile.vc")
        os.cp("*.h", package:installdir("include"))
        os.cp("libjpeg.lib", package:installdir("lib"))
    end)

    on_install("macosx", "linux", function (package)
        import("package.tools.autoconf").install(package)
    end)

package_end()

add_requires("libjpeg")

target("test")
    set_kind("binary")
    add_files("src/*.c") 
    add_packages("libjpeg")
```

### 包管理命令使用

包管理命令`$ xmake require` 可用于手动显示的下载编译安装、卸载、检索、查看包信息。

#### 安装指定包

```console
$ xmake require tbox
```

安装指定版本包:

```console
$ xmake require tbox "~1.6"
```

强制重新下载安装,并且显示详细安装信息:

```console
$ xmake require -f -v tbox "1.5.x"
```

传递额外的设置信息:

```console
$ xmake require --extra="debug=true,config={small=true}" tbox
```

安装debug包,并且传递`small=true`的编译配置信息到包中去。

#### 卸载指定包

```console
$ xmake require --uninstall tbox
```

这会完全卸载删除包文件。

#### 查看包详细信息

```console
$ xmake require --info tbox
```

#### 在当前仓库中搜索包

```console
$ xmake require --search tbox
```

这个是支持模糊搜素以及lua模式匹配搜索的:

```console
$ xmake require --search pcr
```

会同时搜索到pcre, pcre2等包。

#### 列举当前已安装的包

```console
$ xmake require --list
```

### 仓库管理命令使用

上文已经简单讲过,添加私有仓库可以用(支持本地路径添加):

```console
$ xmake repo --add myrepo git@github.com:myrepo/xmake-repo.git
```

v2.2.3开始,支持添加指定分支的repo,例如:

```console
$ xmake repo --add myrepo git@github.com:myrepo/xmake-repo.git dev
```

我们也可以移除已安装的某个仓库:

```console
$ xmake repo --remove myrepo
```

或者查看所有已添加的仓库:

```console
$ xmake repo --list
```

如果远程仓库有更新,可以手动执行仓库更新,来获取更多、最新的包:

```console
$ xmake repo -u
```

### 提交包到官方仓库

目前这个特性刚完成不久,目前官方仓库的包还不是很多,有些包也许还不支持部分平台,不过这并不是太大问题,后期迭代几个版本后,我会不断扩充完善包仓库。

如果你需要的包,当前的官方仓库还没有收录,可以提交issues或者自己可以在本地调通后,贡献提交到官方仓库:[xmake-repo](https://github.com/xmake-io/xmake-repo)

详细的贡献说明,见:[CONTRIBUTING.md](https://github.com/xmake-io/xmake-repo/blob/master/CONTRIBUTING.md)