Arch Linux 软件包制作入门
Arch PKGBUILD
![](/data/attachment/album/202110/02/130702ybexb5tsvkx1xbs1.jpg)


`PKGBUILD` 文件是为 Arch Linux 及其衍生版（如 Manjaro）构建和创建软件包的方式。


如果你曾经使用过 [AUR](https://itsfoss.com/aur-arch-linux/)（即 Arch Linux 的用户维护的 `PKGBUILD` 存储库），你甚至可能也遇到过它们。


但是，到底是如何从 `PKGBUILD` 到可安装软件包的呢？这两者之间到底发生了什么，如何把自己的软件制作成软件包呢？你将在这篇文章中了解这些。


### PKGBUILD 基础知识


对于那些熟悉 Bash 或其他 shell 的人来说，你可能知道，`PKGBUILD` 就是一个带有一些变量的 shell 脚本。


`PKGBUILD` 文件由变量和函数组成，所有这些都是用来定义软件包本身，以及如何构建它。


为了从 `PKGBUILD` 中创建一个软件包，需要使用 `makepkg` 命令行工具。在获得 `PKGBUILD` 文件后，你只需在包含 `PKGBUILD` 的目录中运行 `makepkg'，就可以得到一个可安装的软件包了。


![](/data/attachment/album/202110/02/130710nhaxurp2c6zrrfsr.png)


在本教程中，你将会看到我刚刚制作的软件包，它在运行时打印出 “Hello World!”。


![](/data/attachment/album/202110/02/130711ge1fjv3fh72cfl29.png)


### 准备


为了继续学习本教程，你需要创建几个文件。


首先，你需要创建一个名为 `PKGBUILD` 的文件，它将作为构建你的软件包的“配方”。


你需要做的另一个文件是一个叫 `hello-world.sh` 的文件。我稍后会解释它的用途。


你也可以用一个命令来创建这两个文件：



```
touch PKGBUILD hello-world.sh

```

你可以用 `ls` 命令检查这些文件是否被创建。


![](/data/attachment/album/202110/02/130712dxqn3hb8tkkrftyc.png)


然后你就可以开始了！


### 设置你的 PKGBUILD 文件


我不会让你复制粘贴整个文件，而是和你一起键入每一行，这样你就能更好地理解每一行的目的。如果你不喜欢这种学习方式，我强烈推荐 [Arch 维基](https://wiki.archlinux.org/title/Creating_packages) 中为 Arch Linux 创建软件包的文章。


这篇文章也没有介绍 `PKGBUILD` 中可以设置的每一个选项，只是介绍了一些常用的选项，以便你能尽快上手。


说完了这些，打开你的文本编辑器，让我们直接进入正题吧。


#### pkgname


首先是 `pkgname` 变量。这是安装时定义软件包名称的东西，也是 [Arch Linux 的软件包管理器 pacman](https://itsfoss.com/pacman-command/) 跟踪软件包的方式。


这个变量（以及其他一些变量）的格式是 `variable=value`，变量名在左边，变量的值在右边，用等号隔开。


要设置包的名称，请在 `PKGBUILD` 中输入以下内容：



```
pkgname="hello-world"

```

* 要设置一个不同的软件包名称，用你的软件包的名称替换 `hello-world`。
* 这并不设置用于运行程序的命令，这将在下面的 `package()` 部分中处理。


#### pkgver


正如变量名称本身所述，它设置了你的软件包的版本（即 `1.0.0`）。这在用户更新他们的系统时很有用，因为设置更高的版本会提示用户升级。


要设置版本号，请在 `PKGBUILD` 中输入以下内容（在前一行之后）：



```
pkgver="1.0.0"

```

#### pkgrel


这与 `pkgver` 变量有关，通常不需要知道。不过和 `pkgver` 变量一样，如果它被换到一个更高的数字，就将通知用户进行升级。


它适用于任何需要保持 `pkgver` 不变的情况下，例如 `PKGBUILD` 本身发生了变化。如果你为一个你使用的程序创建了一个 `PKGBUILD`（并希望保持软件包的版本相同），而你需要修复 `PKGBUILD` 本身的一个错误，这将是非常有用的。


要设置这个变量，请在 `PKGBUILD` 中输入以下内容：



```
pkgver="1"

```

这个变量应该 **总是** 从 `1` 开始，然后一次一次地向上移动。当 `pkgver` 本身向上移动时，这个变量可以（也应该）重置为 `1`，因为 `pkgver` 本身会通知用户升级。


#### pkgdesc


这将设置软件包的描述，用于帮助更好地识别该软件包。


要设置它，只需将描述放在引号内：



```
pkgdesc="Hello world in your terminal!"

```

#### arch


这个变量设置软件包所兼容的 [硬件架构](https://www.quora.com/What-is-CPU-architecture)。如果你不明白什么是架构，那也没关系，因为在大多数情况下，这个变量几乎是无用的。


无论如何，`makepkg` 仍然需要设置它，这样它就知道这个软件包与我们的系统是兼容的。


这个变量支持设置多个值，所以 `makepkg` 需要一个不同的语法，如下所示。


要设置它，请在 `PKGBUILD` 中输入以下内容：



```
arch=("x86_64")

```

如果你要设置多个值，需要用空格和引号分隔每个值，像这样。`arch=(“x86_x64" "arm")`。


#### depends


这列出了提供了我们的软件包所需功能的所有软件包。与 `arch` 一样，它也可以包含多个值，因此必须使用括号语法。


由于我们的软件包没有任何依赖关系，所以我们不需要在 `PKGBUILD` 中输入这个字段。然而，如果我们的软件包有依赖关系，我们就会使用与 `arch` 相同的语法。


#### optdepends


这里列出了那些并不是提供所需功能而是额外功能的软件包。


这与 `depends` 的语法相同。


#### conflicts


这告诉 `pacman` 哪些软件包会导致我们的软件包出现问题，或者以我们不希望的方式行事。


这里列出的任何软件包都会在我们的软件包被安装之前被卸载。


这与 `depends` 的语法相同。


#### license


这定义了你的程序所采用的 [软件许可证](https://en.wikipedia.org/wiki/Software_license)。如果你需要帮助你选择一个许可证，[Arch 维基](https://wiki.archlinux.org/title/PKGBUILD#license) 提供了一些信息。如果你不知道该怎么设置，将其设置为 `custom` 也可以。


这与 `arch` 和 `depends` 的语法相同：



```
license=("custom")

```

#### source


这就是 `makepkg` 如何知道要用什么文件来构建我们的软件包。它可以包含各种不同类型的源，包括本地文件和 URL。


在添加本地文件时，要输入相对于 `PKGBUILD` 文件的文件路径，比如以下目录布局：



```
PKGBUILD
file.txt
src/file.sh

```

如果你想在我们的 `PKGBUILD` 中包括 `file.sh`，你需要输入 `src/file.sh` 作为其名称。


当输入 URL 时，你只需输入完整的 URL，即 `https://mirrors.creativecommons.org/presskit/logos/cc.logo.large.png`。


你的这个软件包只需要 `hello-world.sh` 文件，由于它和 `PKGBUILD` 在同一个目录中，你只需输入它的名字作为 `source` 的值。


这个变量也使用与 `arch` 和 `depends` 相同的语法：



```
source=("hello-world.sh")

```

#### sha512sums


这是用来验证 `source` 中的文件没有被修改或下载错误。如何获得这个值的信息可以在 [Arch 维基关于 PKGBUILD 的文章](https://wiki.archlinux.org/title/PKGBUILD#Integrity) 中找到。


如果你宁愿不设置这个（或者你只是不需要，例如对于本地文件），你可以为 `source` 变量中的每个文件输入 `SKIP`：



```
sha512sums=("SKIP")

```

#### package()


这是最后一个，也是实际制作我们的包的最重要的部分。在处理这个问题时，知道两个变量很重要。


* `${srcdir}`：这是 `makepkg` 放置 `source` 变量中文件的地方。在这个目录中，你可以与这些文件进行交互，并对文件进行任何其他需要的修改。
* `${pkgdir}`：这是我们放置将被安装在系统中的文件的地方。 `${pkgdir}` 的文件夹结构是按照实际系统中的情况设置的（例如，使用 `pacman` 安装时，`${pkgdir}/usr/bin/hello-world` 会创建文件 `/usr/bin/hello-world`）。


`package()` 包含一个用于创建软件包的命令列表。


因此，如果（假设）你需要有个在 `/usr/share/motto.txt` 写着 “Linux is superior to Windows ”的文件，你会运行这样的东西：



```
package() {
  mkdir -p "${pkgdir}/usr/share"
  echo "Linux is superior to Windows" | tee "${pkgdir}/usr/share/motto.txt"
}

```

关于上述命令的一些说明：


* `${pkgdir}` 里面最初是 **不包含** 目录的。如果你跳过了 [mkdir 命令](https://linuxhandbook.com/mkdir-command/)，`tee` 会输出一个错误，说这个目录不存在。
* 在指定目录时，**总是** 在它们前面加上 `${pkgdir}` 或 `${srcdir}` 变量。如果输入 `/usr/share/motto.txt`，就会按照字面意义指向你当前运行的系统中的 `/usr/share/motto.txt`。


对于你的 `PKGBUILD`，你将把 `hello-world.sh` 文件放在目标系统的 `/usr/bin/hello-world` 中。你还将使该文件在运行时说 “Hello to you!”。


要做到这一点，请在 `PKGBUILD` 中输入以下内容：



```
package() {
  echo 'Hello to you!' > "${srcdir}/hello-world.sh"
  mkdir -p "${pkgdir}/usr/bin"
  cp "${srcdir}/hello-world.sh" "${pkgdir}/usr/bin/hello-world"
  chmod +x "${pkgdir}/usr/bin/hello-world"
}

```

然后就完成了！用 `makepkg -si` 构建和安装软件包，然后在终端运行 `hello-world`，查看其输出。


![](/data/attachment/album/202110/02/130714d08gygeexx2euoxz.png)


### 总结


就这样，你已经制作了你的第一个 `PKGBUILD`！你走在了为自己甚至是为 AUR 制作实际的软件包的路上。


有什么问题，或者有什么地方不对吗？请随时在下面的评论区发表。




---


via: <https://itsfoss.com/create-pkgbuild/>


作者：[Hunter Wittenborn](https://itsfoss.com/author/hunter/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
![Warp Terminal](/assets/images/warp-terminal.webp)


![Warp Terminal](/assets/images/warp-terminal.webp)

PKGBUILD files are how packages are built and created for Arch Linux and its derivatives, such as Manjaro.

You may have even come across them a bit yourself if you’ve ever used the [AUR](https://itsfoss.com/aur-arch-linux/), Arch Linux’s user-curated repository of PKGBUILDs.

But how exactly do you go from a PKGBUILD to an installable package? What exactly is going on between the two, and how can you make them for your own packages? You’ll learn them in this article.

## PKGBUILD basics

For those who are familiar with Bash or other shells, you’ll be delighted to know, if you didn’t already, that a PKGBUILD is pretty much just a shell script with some variables.

PKGBUILD files consist of variables and functions, all of which are used to define the package itself, and how to build it.

To create a package from a PKGBUILD, the makepkg command line utility is used. After obtaining a PKGBUILD, you simply run `makepkg`

inside the directory containing the PKGBUILD, and voila, you have an installable package!

![PKGBUILD](https://itsfoss.com/content/images/wordpress/2021/05/image.png)

In this tutorial, you’ll be going over the package I just made, which prints “Hello World!” when run:

![PKGBUILD example](https://itsfoss.com/content/images/wordpress/2021/05/image-2.png)

## Getting set up

To follow along with this tutorial, you need to create a couple of files.

First, you need to make a file called **PKGBUILD**. If it wasn’t already made clear, this will serve as the “recipe” for building your package.

The other file you’ll need to make is a file called **hello-world.sh**. I’ll explain its purpose a bit later.

You can create both of these files with a single command as well.

`touch PKGBUILD hello-world.sh`


You can check that the files were created with the ls command:

![PKGBUILD basic guide](https://itsfoss.com/content/images/wordpress/2021/05/image-3.png)

And you’re ready to go!

## Setting up your PKGBUILD file

**Instead of having you copy paste the whole file, I’ll be going over entering every line with you, so you can better understand the purpose of everything that’s happening. If you don’t prefer to learn this way, I’d highly recommend the **

[Arch Wiki article](https://wiki.archlinux.org/title/Creating_packages?ref=itsfoss.com)


*on creating packages for Arch Linux.*With that out of the way, open up your text editor, and let’s get straight into it!

### pkgname

First things first, the pkgname variable. This is what defines the name of your package when installing, and how [Arch Linux’s package manager pacman](https://itsfoss.com/pacman-command/) keeps track of the package.

The format of this variable (and some others) takes the form of variable=value, with the variable name on the left, the value of the variable on the right, separated by an equals sign.

To set the package name, enter the following into the PKGBUILD:

`pkgname="hello-world"`


- To set a different package name, replace
`hello-world`

with the name of the package. - This doesn’t set the command used to run the program. That’s handled a bit below in the
`package()`

section.

### pkgver

As is stated in the variable name itself, this sets the version of your package (i.e. 1.0.0). This is useful when a user updates their system, as setting a higher version will result in the user being prompted for an upgrade.

To set, enter the following into the PKGBUILD (after the previous line):

`pkgver="1.0.0"`


### pkgrel

This is related to the pkgver variable, and isn’t normally important to know about. Like the pkgver variable though, it will notify users for upgrades if it’s moved to a higher number.

It serves for any changes that require the pkgver to remain the same, such as any changes to the PKGBUILD itself. This would be useful if you’ve created a PKGBUILD for a program you use (and want to keep the version the same as the package’s), and you need to fix a bug in the PKGBUILD itself.

To set the variable, enter the following in the PKGBUILD:

`pkgver="1"`


This variable should **always** start at 1, and then move up one at a time. When the **pkgver** itself moves up, this can (and should) be reset to 1, as the pkgver itself will notify users that upgrades are available.

### pkgdesc

This will set the description of the package, which is used to help better identify the package.

To set it, just put the description inside of quotation marks:

`pkgdesc="Hello world in your terminal!"`


### arch

This variable sets the [architecture](https://www.quora.com/What-is-CPU-architecture?ref=itsfoss.com) the package is compatible with. It’s fine if you don’t understand what an architecture is, as it’s pretty much useless in most cases.

Regardless, makepkg still needs it to be set so it knows the package is compatible with our system.

This variable supports setting multiple values, so makepkg requires a different syntax as shown below.

To set it, enter the following in the PKGBUILD:

`arch=("x86_64")`


If you were to set multiple values for this, you would separate each value with a space and quotation marks like so: **arch=(“x86_x64” “arm”)**

### depends

This lists all of the packages that our package needs to function. Like **arch**, it can also contain multiple values, and thus must use the parenthesis syntax.

Since our package won’t have any dependencies, we don’t have to enter this field in the PKGBUILD. If our package did have dependencies however, we’d just use the same syntax as **arch**.

### optdepends

This lists packages that aren’t required to function, but that are needed for extra functionality.

This follows the same syntax as **depends**.

### conflicts

This tells pacman what packages would cause our package to act up or behave in a way we wouldn’t want.

Any package listed here would be uninstalled before ours is installed.

This follows the same syntax as **depends** as well.

### license

This defines the [software license](https://en.wikipedia.org/wiki/Software_license?ref=itsfoss.com) that your program is licensed under. The [Arch Wiki](https://wiki.archlinux.org/title/PKGBUILD?ref=itsfoss.com#license) has some info if you need help choosing a license. Setting this to `custom`

will work if you don’t know what to set this to.

This takes the same syntax as **arch** and **depends**:

`license=("custom")`


### source

This is how makepkg knows what files to use to build our package. This can contain a variety of different kinds of sources, including local files and URLs.

When adding local files, enter the file’s name relative to the PKGBUILD i.e. consider the following directory layout:

```
PKGBUILD
file.txt
src/file.sh
```


If you wanted to include **file.sh** in our PKGBUILD, you would enter **src/file.sh** as its name.

When entering URLs, you simply enter the full URL, i.e. https://mirrors.creativecommons.org/presskit/logos/cc.logo.large.png.

Your package only needs the hello-world.sh file, and since it’s in the same directory as the PKGBUILD, you just type its name as the value for **source**.

This variable also uses the same syntax as **arch** and **depends**:

`source=("hello-world.sh")`


### sha512sums

This is used to verify that the files in **source** haven’t been modified or downloaded incorrectly. Information on obtaining the values for this can be found in the [Arch Wiki article on PKGBUILDs](https://wiki.archlinux.org/title/PKGBUILD?ref=itsfoss.com#Integrity).

If you’d rather just not set this (or you just don’t need to, i.e. for local files), you can just enter SKIP for every file in the **source** variable:

`sha512sums=("SKIP")`


### package()

This is the last, and most important part to actually making our package. It’s important to know two variables when working with this:

**${srcdir}**: This is where makepkg puts the files in the**source**variable. This is the directory where you can interact with the files, and do any other needed modification to the files.- ${pkgdir}: This is where we place the files that will be installed on our system.

The folder structure for ${pkgdir} is set up as if it was on an actual system (i.e. ${pkgdir}/usr/bin/hello-world would create the file /usr/bin/hello-world when installing with pacman.

package() contains a list of commands used create a package.

So, if (hypothetically) you needed to have a file that reads Linux is superior to Windows at /usr/share/motto.txt, you would run something like this:

```
package() {
mkdir -p "${pkgdir}/usr/share"
echo "Linux is superior to Windows" | tee "${pkgdir}/usr/share/motto.txt"
}
```


A few notes on the above command:

- ${pkgdir} contains
**no**directories inside it at first. If you skipped the[mkdir command](https://linuxhandbook.com/mkdir-command/?ref=itsfoss.com), tee would output an error saying the directory doesn’t exist. - When specifying directories,
**always**prepend them with the**${pkgdir}**or**${srcdir}**variable. Entering something like /usr/share/motto.txt without such would point to the literal directory /usr/share/motto.txt on your currently running system.

For your PKGBUILD, you’re going to place the file hello-world.sh at /usr/bin/hello-world on your target system. You’ll also be making the file say “Hello to you!” when ran.

To do so, enter the following into your PKGBUILD:

```
package() {
echo 'Hello to you!' > "${srcdir}/hello-world.sh"
mkdir -p "${pkgdir}/usr/bin"
cp "${srcdir}/hello-world.sh" "${pkgdir}/usr/bin/hello-world"
chmod +x "${pkgdir}/usr/bin/hello-world"
}
```


And you’re done! Your resulting file should now look similar to this:

![pkgbuild file complete](https://itsfoss.com/content/images/wordpress/2021/07/image-2.png)

Now build and install the package with the `makepkg -si`

command, and then run `hello-world`

in your terminal to see its output.

![image 1](https://itsfoss.com/content/images/wordpress/2021/06/image-1.png)

## Wrapping Up

And just like that, you have made your first PKGBUILD! You’re on your way to making actual packages for yourself, and maybe even the AUR.

Got any questions, or something just not working right? Feel free to post it in the comment section below.