Third-party package manager support

The new version of the built-in package management has been refactored, has been very good support, we can through

Add_requires ("libuv master", "ffmpeg", "zlib 1.20.*") 'Copy the code

The package repository Xmake-repo currently contains very few packages. To expand xmake’s package repository, xmake has added built-in support for third-party package managers that explicitly specify packages from other package managers through the package namespace. Currently, support for Conan ::, Brew :: and VCPKG :: package management for installation.

Install the homebrew dependencies

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")
Copy the code

Install the VCPKG dependency package

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

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

To use VCPKG, you need to integrate VCPKG with Xmake.

Install VCPKG on Windows, install $VCPKG, Xmake can automatically detect the root path of VCPKG from the system, and then automatically integrate bread.

Of course, we can also manually specify the root path of VCPKG to support:

$ xmake f --vcpkg=f:\vcpkg
Copy the code

Install Conan dependency packs

The new version implements a Generator for Conan to integrate package information in Conan, which is very easy to use in Xmake and can pass all configuration parameters of Conan package.

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")Copy the code

After compiling with xmake:

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 testCopy the code

Built-in dependency package lookup support

The previous version provided lib.detect.find_package to find dependent libraries, but this can only be used through import, and can only find one package at a time, which is tedious:

target("test")
    set_kind("binary")
    add_files("src/*.c")
    on_load(function (target)
        import("lib.detect.find_package")
        target:add(find_package("openssl"))
        target:add(find_package("zlib"))
    end)
Copy the code

The new version further encapsulates lib.detect.find_package through built-in find_packages interface to improve ease of use:

target("test")
    set_kind("binary")
    add_files("src/*.c")
    on_load(function (target)
        target:add(find_packages("openssl", "zlib"))
    end)
Copy the code

It also supports lookup from the specified third-party package manager:

Find_packages (" conan: : OpenSSL / 1.0.2 n @ conan/stable ", "the brew: : zlib)"Copy the code

Parameter configuration Dependency package installation

The built-in package management has been extensively refactored and upgraded in the new version, as well as better support for configurable compile-install dependencies, which can be customized by defining some compile-install configuration parameters in the package repository.

For example, let’s take the package for PCRE2:

package("pcre2") set_homepage("https://www.pcre.org/") set_description("A Perl Compatible Regular Expressions Library") set_urls("https://ftp.pcre.org/pub/pcre/pcre2-$(version).zip", "Ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-$(version). Zip") add_versions (" 10.23 ", "6301 a525a8a7e63a5fac0c2fbfa0374d3eb133e511d886771e097e427707094a") add_versions (" 10.30 ", "3677 ce17854fffa68fce6b66442858f48f0de1f537f18439e4bd2771f8b4c7fb") add_versions (" 10.31 ", "b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444") add_configs("shared", {description = "Enable shared library.", default = false, type = "boolean"}) add_configs("jit", {description = "Enable jit.", default = true, type = "boolean"}) add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})Copy the code

Above we define three conditional configuration parameters with add_configs, which enable users to customize jit version, bit wide version, etc when integrating with the PCRE2 library. For example:

add_requires("pcre2", {configs = {jit = true, bitwidth = 8}})
Copy the code

In addition, the configuration parameter is strongly constrained to detect, if the wrong value is passed, an error will be reported, to avoid passing invalid parameters, such as the bitwidth parameter configuration, which is limited to values = {“8”, “16”, “32”}.

How do users know which configuration parameters our package currently supports? We can quickly view all information about the pCRE2 package by using the following command:

$ xmake require --info pcre2
Copy the code

The following output is displayed:

The package info of project: require(pcre2): -> description: A Perl Compatible Regular Expressions Library -> version: 10.31 - > urls: - > https://ftp.pcre.org/pub/pcre/pcre2-10.31.zip - > b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444 - > ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-10.31.zip - > b4b40695a5347a770407d492c1749e35ba3970ca03fe83eb2c35d44343a5a444 -> repo: local-repo /Users/ruki/projects/personal/xmake-repo/ -> cachedir: / Users/ruki /. Xmake/cache/packages/p/pcre2/10.31 - > installdir: / Users/ruki /. Xmake/packages/p/b52ca1c6c8634f5f935903c9e7ea0e pcre2/10.31/23 - > fetchinfo: 10.31, the system, optional - > linkdirs: / usr/local/lib/Cellar/pcre2/10.32 - > defines: PCRE2_CODE_UNIT_WIDTH = 8 - > the links: Pcre2-8 - > version: 10.32 - > includedirs: / usr/local/Cellar/pcre2/10.32 / include - > platforms: linux, macosx -> requires: -> plat: macosx -> arch: x86_64 -> configs: -> vs_runtime: MT -> shared: false -> jit: true -> bitwidth: 8 -> debug: false -> configs: -> shared: Enable shared library. (default: false) -> jit: Enable jit. (default: true) -> bitwidth: Set the code unit width. (default: 8) -> values: {"8","16","32"} -> configs (builtin): -> debug: Enable debug symbols. (default: false) -> cflags: Set the C compiler flags. -> cxflags: Set the C/C++ compiler flags. -> cxxflags: Set the C++ compiler flags. -> asflags: Set the assembler flags. -> vs_runtime: Set vs compiler runtime. (default: MT) -> values: {"MT","MD"}Copy the code

Configs (Builtin): is a set of built-in xmake parameters that can be directly configured by users.

For example, the most common Debug mode package:

add_requires("pcre2", {configs = {debug = true}})
Copy the code

Because this is so common, Xmake provides more convenient configuration support:

add_requires("pcre2", {debug = true})
Copy the code

It requires the configuration status of the current dependency package, so the user can see which mode of the package is currently used.

Preprocess the template configuration file

Xmake provides three new interface apis for adding preprocessed configuration files before compilation to replace old interfaces such as set_config_header.

  • add_configfiles
  • set_configdir
  • set_configvar

Add_configfiles is equivalent to the Configure_file interface in Cmake. Xmake refers to its API design and extends support based on add_Configfiles to provide more flexibility.

This interface is more generic than the previous set_config_header interface, which deals not only with auto-generation and preprocessing of config.h, but also with various file types, whereas set_config_header only deals with header files and does not support template variable substitution.

Let’s start with a simple example:

target("test")
    set_kind("binary")
    add_files("src/*.c")
    set_configdir("$(buildir)/config")
    add_configfiles("src/config.h.in")
Copy the code

The above Settings will automatically preprocess the config.h. n header configuration template before compiling and generate output to the specified build/config/config.h.

One of the most important features of this interface is that some template variables can be preprocessed during preprocessing, such as:

config.h.in

#define VAR1 "${VAR1}"
#define VAR2 "${VAR2}"
#define HELLO "${HELLO}"
Copy the code
set_configvar("VAR1", "1")

target("test")
    set_kind("binary")
    add_files("main.c")

    set_configvar("VAR2", 2)
    add_configfiles("config.h.in", {variables = {hello = "xmake"}})
    add_configfiles("*.man", {copyonly = true})
Copy the code

Set the template variables through the set_configvar interface and replace them with the variables set in {variables = {XXX = “”}}.

The pre-processed file config.h contains:

#define VAR1 "1"
#define VAR2 "2"
#define HELLO "xmake"
Copy the code

The {copyOnly = true} setting forces *.man to be treated as a normal file, copying the file only during the preprocessing phase without variable replacement.

The default template variable matching mode is ${var}, of course we can set other matching mode, for example, @var @matching rule:

target("test")
    add_configfiles("config.h.in", {pattern = "@(.-)@"})
Copy the code

We also provide some built-in variables that can be replaced by default even if they are not set through this interface:

${VERSION} -> 1.6.3 ${VERSION_MAJOR} -> 1 ${VERSION_MINOR} -> 6 ${VERSION_ALTER} -> 3 ${VERSION_BUILD} -> 1.6.3 set_version (" ", {build = "%Y%m%d%H%M"}) -> 201902031421 ${PLAT} and ${plat} -> MACOS and macosx ${ARCH} and ${arch} -> ARM and arm ${MODE} and ${mode} -> DEBUG/RELEASE and debug/release ${DEBUG} and ${debug} -> 1 or 0 ${OS} and ${os} -> IOS or iosCopy the code

Such as:

config.h.in

#define CONFIG_VERSION "${VERSION}"
#define CONFIG_VERSION_MAJOR ${VERSION_MAJOR}
#define CONFIG_VERSION_MINOR ${VERSION_MINOR}
#define CONFIG_VERSION_ALTER ${VERSION_ALTER}
#define CONFIG_VERSION_BUILD ${VERSION_BUILD}
Copy the code

config.h

#define CONFIG_VERSION "1.6.3"
#define CONFIG_VERSION_MAJOR 1
#define CONFIG_VERSION_MINOR 6
#define CONFIG_VERSION_ALTER 3
#define CONFIG_VERSION_BUILD 201902031401
Copy the code

We can also do some variable state control on the #define definition:

config.h.in

${define FOO_ENABLE}
Copy the code
set_configvar("FOO_ENABLE", 1) -- or pass true
set_configvar("FOO_STRING", "foo")
Copy the code

${define XXX} will be replaced with:

#define FOO_ENABLE 1
#define FOO_STRING "foo"
Copy the code

Or (set to 0 when disabled)

/* #undef FOO_ENABLE */
/* #undef FOO_STRING */
Copy the code

This method is useful for automatic detection generation config.h, such as automatic detection with Option:

Option ("foo") set_default(true) set_description("Enable foo") set_configvar("FOO_ENABLE", 1) -- or pass true, FOO_ENABLE set_configvar("FOO_STRING", "Foo ") target("test") add_configfiles(" config.h.N ") -- if foo is enabled -> Define add_options("foo") for FOO_ENABLE and FOO_STRINGCopy the code

config.h.in

${define FOO_ENABLE}
${define FOO_STRING}
Copy the code

config.h

#define FOO_ENABLE 1
#define FOO_STRING "foo"
Copy the code

For option detection and automatic generation of config.h, there are some auxiliary functions: https://github.com/xmake-io/xmake/issues/342

${default XXX 0} : ${default XXX 0} : ${default XXX 0} : ${default XXX 0}

HAVE_SSE2 equ ${default VAR_HAVE_SSE2 0}
Copy the code

Run set_configvar(“HAVE_SSE2”, 1) to enable the variable and change it to HAVE_SSE2 equ 1. If the variable is not set, use the default value: HAVE_SSE2 equ 0

For a full description of this, see: github.com/xmake-io/xm…

More convenient feature detection

Add_configfiles and option can be used to check whether some header files, interface functions, types and compiler features exist. If so, they will be automatically written into config.h, for example:

option("foo")
    set_default(true)
    set_description("Has pthread library")
    add_cincludes("pthread.h")
    add_cfuncs("pthread_create")
    add_links("pthread")
    set_configvar("HAS_PTHREAD", 1) 

target("test")
    add_configfiles("config.h.in")
    add_options("pthread") 
Copy the code

config.h.in

${define HAS_PTHREAD}
Copy the code

config.h

#define HAS_PTHREAD 1
Copy the code

If the pthread library can be used normally, HAS_PTHREAD will be automatically defined in config.h, and related links will be appended in test target.

In order to make Xmake. Lua more simple and intuitive, xmake provides some built-in encapsulation auxiliary interface functions for some common detection through the extension of the includes interface to quickly implement the above option detection. Write config.h functionality.

The above code can be simplified as:

includes("check_cfuncs.lua")
target("test")
    add_configfiles("config.h.in")
    configvar_check_cfuncs("HAS_PTHREAD", "pthread_create", {includes = "pthread.h", links = "pthread"})
Copy the code

In addition to configvar_check_cfuncs, we also have the check_cfuncs function, which simply appends the result directly to the configFiles file at compile time.

Let’s look at another comprehensive example:

includes("check_links.lua") includes("check_ctypes.lua") includes("check_cfuncs.lua") includes("check_features.lua") includes("check_csnippets.lua") includes("check_cincludes.lua") target("test") set_kind("binary") add_files("*.c") add_configfiles("config.h.in") configvar_check_ctypes("HAS_WCHAR", "wchar_t") configvar_check_cincludes("HAS_STRING_H", "string.h") configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"}) configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"}) configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"}) configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");" ) configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}}) configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr") configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"})Copy the code

config.h.in

${define HAS_STRING_H}
${define HAS_STRING_AND_STDIO_H}
${define HAS_WCHAR}
${define HAS_WCHAR_AND_FLOAT}
${define HAS_PTHREAD}
${define HAS_STATIC_ASSERT}
${define HAS_SETJMP}
${define HAS_CONSTEXPR}
${define HAS_CONSEXPR_AND_STATIC_ASSERT}
Copy the code

config.h

/* #undef HAS_STRING_H */
#define HAS_STRING_AND_STDIO_H 1
/* #undef HAS_WCHAR */
/* #undef HAS_WCHAR_AND_FLOAT */
#define HAS_PTHREAD 1
#define HAS_STATIC_ASSERT 1
#define HAS_SETJMP 1
/* #undef HAS_CONSTEXPR */
#define HAS_CONSEXPR_AND_STATIC_ASSERT 1
Copy the code

As you can see, Xmake provides other helper functions to check for C/C ++ types, C/C ++ code snippets, C/C ++ function interfaces, link libraries, the presence of header files, and even the strength of C/C ++ compiler feature support.

A fuller explanation of this can be found at github.com/xmake-io/xm…

Configure a custom installation file

For xmake install/uninstall, xmake has added add_installfiles interface to set some installation files. Compared with on_install, this interface is more convenient and can meet most installation requirements.

For example, we can specify various types of files to be installed in the installation directory:

target("test")
    add_installfiles("src/*.h")
    add_installfiles("doc/*.md")


Copy the code

/usr/local/*. H, /usr/local/*. Md by default, on Linux or other systems, we will install to /usr/local/*.

target("test")
    add_installfiles("src/*.h", {prefixdir = "include"})
    add_installfiles("doc/*.md", {prefixdir = "share/doc"})


Copy the code

/usr/local/include/*. H, /usr/local/share/doc/*

We can also use () to extract subdirectories in the source file to install, for example:

target("test")
    add_installfiles("src/(tbox/*.h)", {prefixdir = "include"})
    add_installfiles("doc/(tbox/*.md)", {prefixdir = "share/doc"})


Copy the code

We put the SRC/tbox / * h in the file, extract the tbox / * h after directory structure, during installation: / usr/local/include/tbox / * h, / usr/local/share/doc/tbox / *. The md

Of course, users can also use set_installdir interface.

For a detailed description of this interface, see https://github.com/xmake-io/xmake/issues/318

CMakelists. TXT export

Cmakelists. TXT file export support, convenient users using Xmake can quickly export cmakelists. TXT for cmake, CLion and some other tools that support Cmake. The usage is as follows:

$ xmake project -k cmakelists


Copy the code

The corresponding cmakelists. TXT file can be generated in the current project directory.