Package Distribution
Define package configuration
Package structure in repository
Before making our own package, we need to understand the structure of the next package repository, whether it is the official package repository or the self-built private package repository, the structure is the same:
xmake-repo
- packages
- t/tbox/xmake.lua
- z/zlib/xmake.lua
Through the above structure, you can see that each package will have a xmake.lua to describe its installation rules, and according to the z/zlib
two-level sub-category storage, convenient for quick retrieval.
Package Description
The description rules for the package are basically done in its xmake.lua, which is similar to the xmake.lua description in the project project. The difference is that the description field only supports package()
.
However, in the project xmake.lua, you can also directly add package()
to the built-in package description, and even the package warehouse is saved, sometimes it will be more convenient.
First, let's take a look at zlib's description rules first. This rule can be found at [xmake-repo/z/zlib/xmake.lua](https://github.com/xmake-io/xmake-repo/blob Found under /master/packages/z/zlib/xmake.lua).
package("zlib")
set_homepage("http://www.zlib.net")
set_description("A Massively Spiffy Yet Delicately Unobtrusive Compression Library")
set_urls("http://zlib.net/zlib-$(version).tar.gz",
"https://downloads.sourceforge.net/project/libpng/zlib/$(version)/zlib-$(version).tar.gz")
add_versions("1.2.10", "8d7e9f698ce48787b6e1c67e6bff79e487303e66077e25cb9784ac8835978017")
add_versions("1.2.11", "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
on_install("windows", function (package)
io.gsub("win32/Makefile.msc", "%-MD", "-" .. package:config("vs_runtime"))
os.vrun("nmake -f win32\\Makefile.msc zlib.lib")
os.cp("zlib.lib", package:installdir("lib"))
os.cp("*.h", package:installdir("include"))
end)
on_install("linux", "macosx", function (package)
import("package.tools.autoconf").install(package, {"--static"})
end)
on_install("iphoneos", "android@linux,macosx", "mingw@linux,macosx", function (package)
import("package.tools.autoconf").configure(package, {host = "", "--static"})
io.gsub("Makefile", "\nAR=.-\n", "\nAR=" .. (package:build_getenv("ar") or "") .. "\n")
io.gsub("Makefile", "\nARFLAGS=.-\n", "\nARFLAGS=cr\n")
io.gsub("Makefile", "\nRANLIB=.-\n", "\nRANLIB=\n")
os.vrun("make install -j4")
end)
on_test(function (package)
assert(package:has_cfuncs("inflate", {includes = "zlib.h"}))
end)
This package rule adds installation rules to windows, linux, macosx, iphoneos, mingw and other platforms. Basically, it has achieved full platform coverage, and even some cross-compilation platforms, which is a typical example.
Of course, some packages rely on source code implementation and are not completely cross-platform, so you only need to set the installation rules for the platforms it supports.
For more detailed package configuration API descriptions see: Package Interface Documentation
Extended configuration parameters
See: add_configs for details.
Built-in configuration parameters
In addition to setting some extended configuration parameters via add_configs, xmake also provides some built-in configuration parameters that can be used.
Enable debug package
add_requires("xxx", {debug = true})
There must be relevant processing in the package description to support:
on_install(function (package)
Local configs = {}
if package:debug() then
Table.insert(configs, "--enable-debug")
end
import("package.tools.autoconf").install(package)
end)
Setting up the msvc runtime library
add_requires("xxx", {configs = {vs_runtime = "MT"}})
Normally, packages installed by built-in tool scripts such as import("package.tools.autoconf").install
are automatically processed internally by vs_runtime.
But if it is a special source package, the build rules are special, then you need to handle it yourself:
on_install(function (package)
io.gsub("build/Makefile.win32.common", "%-MD", "-" .. package:config("vs_runtime"))
end)
Adding environment variables
For some libraries, there are also executable tools. if you need to use these tools in the integration package, you can also set the corresponding PATH environment variable:
package("luajit")
on_load(function (package)
if is_plat("windows") then
Package:addenv("PATH", "lib")
end
Package:addenv("PATH", "bin")
end)
In the project project, the corresponding environment variables will only take effect after the corresponding package is integrated by add_packages
.
add_requires("luajit")
target("test")
set_kind("binary")
add_packages("luajit")
after_run(function (package)
os.exec("luajit --version")
end)
Installing binary packages
Xmake also supports direct reference to the binary version package, which is used directly for installation, for example:
if is_plat("windows") then
set_urls("https://www.libsdl.org/release/SDL2-devel-$(version)-VC.zip")
add_versions("2.0.8", "68505e1f7c16d8538e116405411205355a029dcf2df738dbbc768b2fe95d20fd")
end
on_install("windows", function (package)
os.cp("include", package:installdir())
os.cp("lib/$(arch)/*.lib", package:installdir("lib"))
os.cp("lib/$(arch)/*.dll", package:installdir("lib"))
end)
Local test
If you have added and created a new package in the local xmake-repo repository, you can run the test locally and pass it. If the test passes, you can submit the pr to the official repository and request the merge.
We can execute the following script to test the specified package:
cd xmake-repo
xmake l scripts/test.lua -v -D zlib
The above command will force the download and installation of the zlib package to test whether the entire installation process is ok, plus -v -D
is to see the complete detailed log information and error information, which is convenient for debugging analysis.
If the network environment is not good, do not want to re-download all dependencies every time, you can add the --shallow
parameter to execute, this parameter tells the script, just re-decompress the local cached zlib source package, re-execute the installation command, but Will not download various dependencies.
cd xmake-repo
xmake l scripts/test.lua -v -D --shallow zlib
If we want to test the package rules of other platforms, such as: android, iphoneos and other platforms, you can specify by -p/--plat
or -a/--arch
.
cd xmake-repo
xmake l scripts/test.lua -v -D --shallow -p iphoneos -a arm64 zlib
xmake l scripts/test.lua -v -D --shallow -p android --ndk=/xxxx zlib
Generate package configuration
We can also run xmake package
to generate a remote package configuration.
$ xmake package -f remote
package("foo")
set_description("The foo package")
set_license("Apache-2.0")
add_deps("add", "sub")
add_urls("https://github.com/myrepo/foo.git")
add_versions("1.0", "<shasum256 or gitcommit>")
on_install(function (package)
local configs = {}
if package:config("shared") then
configs.kind = "shared"
end
import("package.tools.xmake").install(package, configs)
end)
on_test(function (package)
- TODO check includes and interfaces
- assert(package:has_cfuncs("foo", {includes = "foo.h"})
end)
Compared with the local package, the package definition configuration has more actual installation logic, as well as the settings of urls and versions,
We can also modify urls, versions and other configuration values through additional parameters, for example:
$ xmake package -f remote --url=https://xxxx/xxx.tar.gz --shasum=xxxxx --homepage=xxxxx`
xmake will also read the relevant configuration information from the target's set_license
and set_version
configurations.
Submit package to the official repository
If you need a package that is not supported by the current official repository, you can commit it to the official repository after local tuning: xmake-repo
For detailed contribution descriptions, see: CONTRIBUTING.md
For how to make your own package, you can look at the above: Submit packages to the official repository.
Distributing and using custom package rules
Since version 2.7.2 we have been able to add custom build rule scripts to the package management repository to enable dynamic distribution and installation following packages.
We need to place the custom rules in the packages/x/xxx/rules
directory of the repository and it will follow the package as it is installed.
But it has also some limits:
- For in-package rules, we cannot add
on_load
,after_load
scripts, but we can usually useon_config
instead.
Adding package rules
We need to add the rules script to the rules fixed directory, for example: packages/z/zlib/rules/foo.lua
rule("foo")
on_config(function (target)
print("foo: on_config %s", target:name())
end)
Applying package rules
The rules are used in a similar way as before, the only difference being that we need to specify which package's rules to access by prefixing them with @packagename/
.
The exact format: add_rules("@packagename/rulename")
, e.g.: add_rules("@zlib/foo")
.
add_requires("zlib", {system = false})
target("test")
set_kind("binary")
add_files("src/*.cpp")
add_packages("zlib")
add_rules("@zlib/foo")
Referencing rules by package alias
If a package alias exists, xmake will give preference to the package alias to get the rules.
add_requires("zlib", {alias = "zlib2", system = false})
target("test")
set_kind("binary")
add_files("src/*.cpp")
add_packages("zlib2")
add_rules("@zlib2/foo")
Adding package rule dependencies
We can use add_deps("@bar")
to add additional rules relative to the current package directory.
However, we cannot add rule dependencies from other packages, they are completely isolated and we can only refer to rules from other packages imported by add_requires
in the user project.
packages/z/zlib/rules/foo.lua
rule("foo")
add_deps("@bar")
on_config(function (target)
print("foo: on_config %s", target:name())
end)
packages/z/zlib/rules/bar.lua
rule("bar")
on_config(function (target)
print("bar: on_config %s", target:name())
end)
ry, so it maybe unreliable to detect the correct paths.