1999-03-14 08:34:52 +08:00
|
|
|
To build RPM you will need several other packages:
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2023-04-06 16:33:16 +08:00
|
|
|
The cmake build system, version 3.18 or later.
|
2022-10-20 19:37:23 +08:00
|
|
|
It is available from
|
|
|
|
https://cmake.org/
|
|
|
|
|
2019-11-07 21:34:30 +08:00
|
|
|
The popt library for option parsing, must be version 1.13 or later.
|
2020-06-23 19:27:25 +08:00
|
|
|
It is available from
|
|
|
|
http://ftp.rpm.org/popt/
|
2019-11-07 21:34:30 +08:00
|
|
|
|
2021-06-18 15:17:14 +08:00
|
|
|
The debugedit >= 0.3 tools for producing debuginfo sub-packages.
|
|
|
|
It is available from
|
|
|
|
https://sourceware.org/debugedit/
|
|
|
|
|
2021-10-26 19:43:05 +08:00
|
|
|
Lua >= 5.2 library + development environment.
|
2021-02-04 21:49:39 +08:00
|
|
|
Note that only the library is needed at runtime, RPM never calls external
|
|
|
|
Lua interpreter for anything. Lua is available from
|
|
|
|
http://www.lua.org
|
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
The zlib library for compression support. You might also need/want
|
2008-07-02 01:22:02 +08:00
|
|
|
the unzip executable for java jar dependency analysis. All available from
|
2007-10-08 20:37:38 +08:00
|
|
|
http://www.gzip.org/zlib/
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2008-01-27 23:28:32 +08:00
|
|
|
The libmagic (aka file) library for file type detection (used by rpmbuild).
|
|
|
|
The source for the file utility + library is available from
|
|
|
|
ftp://ftp.astron.com/pub/file/
|
|
|
|
|
2022-03-27 07:53:39 +08:00
|
|
|
You will need a cryptographic library to support digests and
|
2022-11-29 19:40:43 +08:00
|
|
|
signatures. This depends on the OpenPGP parser used: the default is
|
2023-03-17 15:48:24 +08:00
|
|
|
rpm-sequoia library (>= 1.3.0 required), which is available from
|
2022-11-29 19:40:43 +08:00
|
|
|
https://github.com/rpm-software-management/rpm-sequoia
|
|
|
|
|
2023-08-29 18:19:15 +08:00
|
|
|
Use of rpm-sequoia is strongly recommended. Most importantly, the internal
|
|
|
|
parser is considered insecure. It simply ignores various critical aspects of
|
|
|
|
OpenPGP (such as sub-packet binding signatures) that are properly implemented
|
|
|
|
in Sequoia. Some other Sequoia advantages include being implemented in a
|
|
|
|
memory-safe language, configurable policy and user-relevant error messages.
|
|
|
|
For more information, see https://sequoia-pgp.org/
|
|
|
|
|
2022-11-29 19:40:43 +08:00
|
|
|
If using the deprecated internal parser (-DWITH_INTERNAL_OPENPGP=ON),
|
|
|
|
the default is libgcrypt, but alternatively OpenSSL can be used by
|
|
|
|
additionally specifying -DWITH_OPENSSL=ON.
|
2019-09-10 16:05:03 +08:00
|
|
|
|
|
|
|
libgcrypt library is available from https://www.gnupg.org/software/libgcrypt/
|
2017-01-16 22:19:43 +08:00
|
|
|
|
2023-03-17 02:02:56 +08:00
|
|
|
If using the OpenSSL library for encryption, it must be version 3.0.0 or
|
2017-01-16 22:19:43 +08:00
|
|
|
later. Note: when compiling against OpenSSL, there is a possible license
|
|
|
|
incompatibility. For more details on this, see
|
|
|
|
https://people.gnome.org/~markmc/openssl-and-the-gpl.html
|
|
|
|
Some Linux distributions have different legal interpretations of this
|
|
|
|
possible incompatibility. It is recommended to consult with a lawyer before
|
|
|
|
building RPM against OpenSSL.
|
|
|
|
Fedora: https://fedoraproject.org/wiki/Licensing:FAQ#What.27s_the_deal_with_the_OpenSSL_license.3F
|
|
|
|
Debian: https://lists.debian.org/debian-legal/2002/10/msg00113.html
|
|
|
|
|
|
|
|
The OpenSSL crypto library is available from https://www.openssl.org/
|
|
|
|
|
2021-01-29 19:01:48 +08:00
|
|
|
RPM needs a database engine for normal operation. The main options are
|
2022-10-20 19:37:23 +08:00
|
|
|
"ndb" and "sqlite", both enabled by default but can be disabled with
|
|
|
|
-DENABLE_NDB=OFF and -DENABLE_SQLITE=OFF respetively.
|
|
|
|
|
2021-01-29 19:01:48 +08:00
|
|
|
Additionally standalone support for read-only BDB databases is available as
|
2022-10-20 19:37:23 +08:00
|
|
|
"bdb_ro" (-DENABLE_BDB_RO=ON) to aid with migration from BDB.
|
2020-08-20 18:13:50 +08:00
|
|
|
|
|
|
|
The ndb and bdb_ro backends have no external dependencies.
|
|
|
|
SQLite >= 3.22.0 is required for the sqlite database backend.
|
|
|
|
SQLite is available from https://www.sqlite.org/
|
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
SELinux support is enabled by default but can be disabled with
|
|
|
|
-DWITH_SELINUX=OFF. libselinux is is available from
|
2007-10-08 20:37:38 +08:00
|
|
|
http://www.nsa.gov/selinux/
|
|
|
|
|
2009-03-06 19:43:17 +08:00
|
|
|
It may be desired to install bzip2, gzip, and xz/lzma so that RPM can use these
|
2008-07-02 01:22:02 +08:00
|
|
|
formats. Gzip is necessary to build packages that contain compressed
|
1999-03-14 08:34:52 +08:00
|
|
|
tar balls, these are quite common on the Internet.
|
2013-02-17 02:29:33 +08:00
|
|
|
These are available from
|
2007-10-08 20:37:38 +08:00
|
|
|
http://www.gzip.org
|
|
|
|
http://www.bzip.org
|
2009-03-06 19:43:17 +08:00
|
|
|
http://tukaani.org/xz/
|
2007-10-08 20:37:38 +08:00
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
Python bindings to RPM library are built by default, but it can be disabled
|
2023-09-12 20:33:37 +08:00
|
|
|
with -DENABLE_PYTHON=OFF. You'll need to have Python >= 3.7
|
2021-11-23 21:50:01 +08:00
|
|
|
runtime and C API development environment installed.
|
2019-02-26 17:58:15 +08:00
|
|
|
Python is available from:
|
2007-10-08 20:37:38 +08:00
|
|
|
http://www.python.org/
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
POSIX.1e draft 15 file capabilities support is enabled by default, to
|
|
|
|
disable use -DWITH_CAP=OFF. You'll also need recent libcap, available from:
|
2009-03-06 19:43:17 +08:00
|
|
|
http://ftp.kernel.org/pub/linux/libs/security/linux-privs/libcap2/
|
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
POSIX 1003.1e draft 17 ACL verification support is enabled by default,
|
|
|
|
to disable use -DWITH_ACL=OFF. You'll also need the ACL library,
|
|
|
|
available from:
|
2009-03-06 19:43:17 +08:00
|
|
|
ftp://oss.sgi.com/projects/xfs/cmd_tars/
|
|
|
|
|
1999-03-14 08:34:52 +08:00
|
|
|
For best results you should compile with GCC and GNU Make. Users have
|
2000-08-28 03:43:51 +08:00
|
|
|
reported difficulty with other build tools (any patches to lift these
|
|
|
|
dependencies are welcome). Both GCC and GNU Make available from
|
|
|
|
http://www.gnu.org/
|
|
|
|
|
|
|
|
If National Language Support (NLS) is desired you will need gnu
|
|
|
|
gettext (currently this is required to build rpm but we hope to
|
|
|
|
lift this requirement soon), available from
|
|
|
|
http://www.gnu.org/
|
|
|
|
|
2023-08-15 19:52:50 +08:00
|
|
|
By default, Rpm uses C.UTF-8 locale as it's default locale. If your
|
|
|
|
environment does not support this, you can make rpm use the traditional
|
|
|
|
C locale with -DENABLE_CUTF8=OFF.
|
|
|
|
|
2007-10-08 20:37:38 +08:00
|
|
|
If you are going to hack the sources (or compile from source repository)
|
|
|
|
you will need most of the GNU development tools including:
|
2000-08-28 03:43:51 +08:00
|
|
|
autoconf, automake, gettext, libtool, makeinfo, perl, GNU m4, GNU tar
|
|
|
|
available from
|
|
|
|
http://www.gnu.org/
|
|
|
|
|
2007-10-08 20:37:38 +08:00
|
|
|
If you plan on using cryptographic signatures you will need a version
|
|
|
|
of GPG, available from
|
|
|
|
http://www.gnupg.org/
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2020-08-04 22:50:21 +08:00
|
|
|
OpenMP multithreading support is automatically enabled if your C compiler has
|
2022-10-20 19:37:23 +08:00
|
|
|
support for OpenMP version 4.5 or higher (to disable, use -DENABLE_OPENMP=OFF
|
|
|
|
option). For GCC, OpenMP 4.5 is fully supported since GCC 6.1,
|
2020-08-04 22:50:21 +08:00
|
|
|
which is available from
|
|
|
|
http://www.gnu.org/
|
|
|
|
|
2022-05-03 17:26:04 +08:00
|
|
|
If glibc is used, it needs to be of version 2.27 or newer. Older glibc
|
|
|
|
versions have a longstanding bug where glob() does not return dangling
|
|
|
|
symlinks as matches, which broadly affects rpmbuild.
|
|
|
|
|
2022-02-10 20:32:43 +08:00
|
|
|
Rpm requires a POSIX.1-2008 level operating system.
|
|
|
|
|
1999-03-14 08:34:52 +08:00
|
|
|
To compile RPM:
|
|
|
|
--------------
|
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
mkdir _build
|
|
|
|
cd _build
|
|
|
|
cmake ..
|
2000-08-28 03:43:51 +08:00
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
You can view the various cmake compile options with:
|
|
|
|
cmake -L ..
|
2000-08-28 03:43:51 +08:00
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
and fine tune the built components + features, eg:
|
|
|
|
cmake -DENABLE_PYTHON=OFF ..
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2023-07-06 17:18:22 +08:00
|
|
|
If you have tools outside the regular FHS paths that you need rpm to find,
|
|
|
|
you can augment the search path via MYPATH environment variable to cmake.
|
|
|
|
|
2022-10-20 19:37:23 +08:00
|
|
|
Now build the system with:
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
make
|
|
|
|
|
|
|
|
and then install with:
|
|
|
|
|
|
|
|
make install
|
|
|
|
|
2023-07-28 18:16:56 +08:00
|
|
|
|
|
|
|
By default, rpm installs a series of default platforms based on the CPU
|
|
|
|
architecture names in subdirectories called
|
|
|
|
|
|
|
|
/usr/lib/platform/<arch>-<os>
|
|
|
|
|
|
|
|
This is enough for many distributions. However, some distributions
|
|
|
|
may use more specific platform names that refer to particular computer
|
|
|
|
systems, like SBCs or specific CPU tuning when compiling. Examples of such
|
|
|
|
platform names are: "genericx86_64", "intel_skylake_64", "raspberrypi_armv7",
|
|
|
|
"raspberrypi_armv8", etc.
|
|
|
|
|
|
|
|
If the platform name is put into /etc/rpm/platform, then rpmbuild uses it
|
|
|
|
and the only macros file rpmbuild looks for is
|
|
|
|
|
|
|
|
/usr/lib/platform/`cat /etc/rpm/platform`-<os>/macros
|
|
|
|
|
|
|
|
If this file does not exist, many rpm macros will not have their expected
|
|
|
|
values set and e.g. %configure will fail when trying to run rpmbuild.
|
|
|
|
|
|
|
|
To allow creating the macros file for such a custom platform, the shell
|
|
|
|
variables listed below must be set. If RPM_CUSTOM_ARCH is not set, the rest
|
|
|
|
is ignored.
|
|
|
|
|
|
|
|
export RPM_CUSTOM_ARCH=genericx86_64
|
|
|
|
export RPM_CUSTOM_ISANAME=x86
|
|
|
|
export RPM_CUSTOM_ISABITS=64
|
|
|
|
export RPM_CUSTOM_CANONARCH=x86_64
|
|
|
|
export RPM_CUSTOM_CANONCOLOR=0 # to use /usr/lib for %_libdir
|
|
|
|
export RPM_CUSTOM_CANONCOLOR=3 # to use /usr/lib64 for %_libdir
|
|
|
|
|
|
|
|
make install
|
|
|
|
|
|
|
|
This also creates and installs the new platform file e.g.
|
|
|
|
/usr/lib/platform/genericx86_64-linux/macros
|
|
|
|
|
|
|
|
|
2023-10-12 22:05:16 +08:00
|
|
|
Rpm comes with an automated self-test suite. The test-suite requires podman
|
|
|
|
(https://github.com/containers/podman/) or docker (https://github.com/docker/).
|
|
|
|
It is enabled by default but can be disabled with -DENABLE_TESTSUITE=OFF to
|
|
|
|
avoid the dependencies. The test-suite can be executed with:
|
2000-08-28 03:43:51 +08:00
|
|
|
|
2011-04-04 19:39:19 +08:00
|
|
|
make check
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2023-10-12 22:05:16 +08:00
|
|
|
Additionally, rpm supports executing the test-suite in a way that's similar to
|
|
|
|
how the project CI is set up. You can do that with:
|
2022-11-25 16:46:21 +08:00
|
|
|
|
|
|
|
make ci
|
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
Finally, if you wish to prepare an rpm source tar ball, you should do
|
|
|
|
|
|
|
|
make dist
|
|
|
|
|
|
|
|
To package RPM:
|
|
|
|
--------------
|
|
|
|
|
|
|
|
After RPM has been installed you can run rpm to build an rpm package.
|
|
|
|
Edit the rpm.spec file to mirror any special steps you needed to
|
|
|
|
follow to make rpm compile and change the specfile to match your
|
|
|
|
taste. You will need to put the rpm source tar file into the
|
2007-10-08 20:37:38 +08:00
|
|
|
SOURCES directory and we suggest putting the specfile in the
|
|
|
|
SPECS directory, then run rpmbuild -ba rpm.spec. You will end up
|
|
|
|
with two rpms which can be found in RPMS and SRPMS.
|
2000-08-28 03:43:51 +08:00
|
|
|
|
|
|
|
If you are going to install rpm on machines with OS package managers
|
|
|
|
other then rpm, you may choose to install the base rpm package via a
|
|
|
|
cpio instead of a tar file. Instead of running "make tar" during the
|
2013-02-17 02:29:33 +08:00
|
|
|
build process, as described above, use the base rpm packages to create
|
2000-08-28 03:43:51 +08:00
|
|
|
a cpio. After the rpms have been created run rpm2cpio on the base rpm
|
|
|
|
package, this will give you a cpio package which can then use to
|
|
|
|
install rpm on a new system.
|
|
|
|
|
|
|
|
rpm2cpio rpm-4.0-1.solaris2.6-sparc.rpm > rpm-4.0-1.solaris2.6-sparc.cpio
|
1999-03-14 08:34:52 +08:00
|
|
|
|
|
|
|
|
|
|
|
Non Linux Configuration Issues:
|
|
|
|
------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
OS dependencies:
|
|
|
|
----------------
|
|
|
|
|
2007-10-08 20:37:38 +08:00
|
|
|
Under RPM based Linux distributions all libraries (in fact all files
|
|
|
|
distributed with the OS) are under RPM control and this section is not
|
|
|
|
an issue.
|
1999-03-14 08:34:52 +08:00
|
|
|
|
|
|
|
RPM will need to be informed of all the dependencies which were
|
|
|
|
satisfied before RPM was installed. Typically this only refers to
|
|
|
|
libraries that are installed by the OS, but may include other
|
2013-02-17 02:29:33 +08:00
|
|
|
libraries and packages which are available at the time RPM is
|
1999-03-14 08:34:52 +08:00
|
|
|
installed and will not under RPM control. Another common example of
|
|
|
|
libraries which may need dependency provisions are precompiled
|
|
|
|
libraries which are installed by the OS package manager during system
|
|
|
|
build time. The list of dependencies you will wish to load into RPM
|
|
|
|
will depend on exactly how you bootstrap RPM onto your system and what
|
2013-02-17 02:29:33 +08:00
|
|
|
parts of the system you put into packages as well as on the specific OS
|
1999-03-14 08:34:52 +08:00
|
|
|
you are using.
|
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
The script vpkg-provides.sh can be used to generate a package which
|
|
|
|
will satisfy the dependencies on your system. To run it you will need
|
|
|
|
to create a specfile header for this empty package and run the progam
|
|
|
|
with:
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
--spec_header '/path/to/os-base-header.spec
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
and if you wish to ensure that some directories are not traversed you
|
|
|
|
can use the option:
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2009-12-17 05:14:04 +08:00
|
|
|
--ignore_dirs 'grep-E|pattern|of|paths|to|ignore
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
By default the generated rpm will include a %verifyscript to verify
|
|
|
|
checksum of all files traversed has not changed. This additional
|
2013-02-17 02:29:33 +08:00
|
|
|
check can be suppressed with:
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
--no_verify
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
The result of running the script will be a specfile which will create
|
|
|
|
a package continging all the dependencies found on the system. There
|
|
|
|
will be one provides line for each depednecy. The package will contain
|
|
|
|
none of the actual OS library files as it is assumed they are already
|
|
|
|
on your system and managed by other means. Here is a example
|
|
|
|
(truncated) of the provides lines used by one user of Digital Unix. (I
|
|
|
|
have put several provides on the same line for brevity)
|
1999-03-14 08:34:52 +08:00
|
|
|
|
|
|
|
provides: /bin/sh /usr/bin/ksh /usr/bin/csh
|
|
|
|
provides: libc.so.osf.1 libm.so.osf.1 libcurses.so.xpg4 libdb.so.osf.1
|
|
|
|
provides: libX11.so libXaw.so.6.0 libXext.so libXm.so.motif1.2 libXmu.so
|
|
|
|
provides: libdnet_stub.so.osf.1 libsecurity.so.osf.1 libpthread.so.osf.1
|
|
|
|
provides: libexc.so.osf.1 libmach.so.osf.1 libdps.so libdpstk.so
|
|
|
|
|
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
The script vpkg-provides2.sh is underdevelopment as a more advanced
|
|
|
|
version of vpkg-provides.sh which is aware of many different unix
|
|
|
|
vendor packaging schemes. It will create one "dependency package" for
|
|
|
|
each unix package your OS vendor installed.
|
|
|
|
|
1999-03-14 08:34:52 +08:00
|
|
|
|
|
|
|
rpmfilename:
|
|
|
|
-----------
|
|
|
|
|
|
|
|
If you plan on packaging for more then one OS you may want to edit
|
2000-08-28 03:43:51 +08:00
|
|
|
/etc/macros or /usr/lib/rpm/macros and change the line which has
|
|
|
|
rpmfilename to something which include both the %{_target_os} and
|
|
|
|
%{_target_cpu}. This will cause the name of the generated rpm files
|
|
|
|
to the operating system name as well as the architecture which the rpm
|
|
|
|
runs under. The line to change looks like:
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
%_rpmfilename %%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
you may wish to include both the %{_target_os} and %{_target_cpu} in
|
|
|
|
the final base name, so that it's easier to distinguish between what
|
|
|
|
package is appropriate for a particular arch-os-version combo. We
|
|
|
|
suggest:
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
%_rpmfilename %%{_target_platform/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{_target_platform}.rpm
|
1999-03-14 08:34:52 +08:00
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
There is no %{_target_os_version} tag, so if you need to also
|
|
|
|
distinguish between RPMs for certain versions of the OS, you can
|
|
|
|
hard-code the version in the rpmrc on the build machine, so that .rpm
|
|
|
|
files are generated with the version as part of the filename.
|
1999-03-14 08:34:52 +08:00
|
|
|
|
|
|
|
For example when one user builds RPMs for Digital Unix 4.0b and 4.0d,
|
|
|
|
optimization is important and he will build one set of RPMs for the
|
|
|
|
EV4 processor and another set for the EV56 processor. He specifies
|
|
|
|
both the OS version (if it's important, as it is for a few packages)
|
|
|
|
and the processor version by default by setting a special rpmfilename:
|
|
|
|
on the particular build machine.
|
|
|
|
|
|
|
|
The "rpmfilename: "tag on one machine (Digital Unix 4.0d, EV56 PWS 433)
|
|
|
|
looks like:
|
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
rpmfilename: %{_target_os}/4.0d/%{_target_cpu}/%{name}-%{version}-%{release}.%{_target_os}-%{_target_cpu}ev56.rpm
|
1999-03-14 08:34:52 +08:00
|
|
|
|
|
|
|
For package `foo-1.1', at build time that would translate into:
|
|
|
|
|
2000-08-28 03:43:51 +08:00
|
|
|
osf1/4.0d/alpha/foo-1.1-1.osf1-alphaev56.rpm
|
|
|
|
|
|
|
|
The hyphen between the %{_target_cpu} and ev56 is left out for compatibility
|
|
|
|
with GNU Config.guess and because `alphaev56' looks more "normal" to
|
|
|
|
people with an alpha than alpha-ev56 for someone on an Intel Pentium
|
|
|
|
Pro would want `i586pro' over `i586-pro', but it does make parsing
|
|
|
|
this filename by other programs a bit more difficult.
|
|
|
|
|
|
|
|
|
2011-04-04 19:39:19 +08:00
|
|
|
GPG
|
|
|
|
---
|
2000-08-28 03:43:51 +08:00
|
|
|
|
|
|
|
To use the signing features of rpm, you will need to configure certain
|
2007-10-08 20:37:38 +08:00
|
|
|
rpm macros in ~/.rpmmacros:
|
2000-08-28 03:43:51 +08:00
|
|
|
|
2007-10-08 20:37:38 +08:00
|
|
|
%_gpg_name <GPG UID>
|
|
|
|
%_gpg_path %(echo $HOME)/.gnupg
|
1999-03-14 08:34:52 +08:00
|
|
|
|