preface

Before xmake, I had been using gnumake/ Makefile to maintain my personal C/C++ projects, which was fine at first, but as the projects got bigger and bigger, it became very difficult to maintain, and then I used automake for a while, which didn’t work very well.

Since the process of building C/C++ programs is tedious, it is difficult to quickly build a new C/C++ program without the aid of an IDE tool, and it is even more difficult to build cross-platform.

Although IDE is very useful and powerful, there are still many disadvantages, such as:

  • Cross-platform development support is imperfect
  • Your environment is not necessarily cross-platform
  • bloat
  • This is not conducive to the automatic deployment and construction of the server
  • Not flexible enough and the custom configuration build process has limitations

If you are familiar with makefiles, you can also make makefiles by hand. However, different platforms use different makefiles, such as gnumake, nmake, etc. As a result, makefiles have different syntax, which can not be consistent compilation, and there are certain barriers for developers to use makefiles.

To use Gnumake on Win, you have to install cygwin, mingw-msys, etc., which is also very troublesome. It takes half a day to complete the environment.

There are many modern build tools available for developers to build and maintain C/C++ projects, such as Cmake, scons, Premake, Bazel, GN, gyp, etc.

Many of them can only generate the corresponding IDE project, and then maintain and build through the corresponding IDE. This only solves the consistency maintenance problem of C/C++ projects, but the build method is inconsistent, so it still doesn’t solve most of the shortcomings listed before, and can’t directly build quickly.

Cmake and Scons are very powerful, but the syntax of cmake is strange and unintuitive. I am not used to scons.

In view of this, I use Lua to describe the project, using Lua’s lightweight, simple, flexible, cross-platform characteristics to solve the above problems, using Xmake will bring a different construction experience:

  • Lightweight, cross-platform, no dependencies, no need to install python and other third-party environments, built directly into lua runtime, a installation package (or command) directly done
  • The project description is intuitive and concise, which is more in line with the normal thinking habits of users
  • Support direct build, powerful command line tools, end users of the Gospel, install forced users necessary
  • Support for vscode, IDEA, Clion, Sublime, Vim and other editor plug-ins
  • Intelligent detection is supported to simplify user compilation and configuration
  • Plug-in support, flexible user scalability
  • Vcproj IDE project file generation is also supported
  • More hidden features for you to experience

Quick learning

Can’t write a makefile? To compile, run the following command from the source directory:

xmake
Copy the code

Xmake automatically scans the source code structure in the current directory, generates an Xmake. Lua project description file, and then attempts to compile it directly.

To run the compiled executable directly, simply type:

$ xmake run
Copy the code

For more information, see article: Xmake adds smart code scanning and compilation mode, eliminating the need to write any make files by hand

Quick start

If you want to describe the project further, adjust the source code structure, add some compilation options, and so on, you still need to maintain a project description file called xmake.lua, similar to makefile, cmakelist.txt, but its syntax and API have been improved and simplified to be quite easy to use.

The simplest example of a description would only take three lines:

target("test")
    set_kind("binary")
    add_files("src/*.c")
Copy the code

You can build an executable program that compiles all c source files in the SRC directory.

Then execute Xmake directly to compile.

Add_files () supports wildcard file pattern matching, and supports.c,.cpp,.go,.d,.m,.mm,.s,.swift,.rc,.rs and other native language code files, most of which can support mixed editing.

We can even add.a and.o,.obj files to add_files(), for example:

target("test")
    set_kind("static")
    add_files("src/*.c")
    add_files("lib/libxxx.a"."obj/bbb.o")
Copy the code

Libtest. a is automatically decompress and merged into libtest.a when compiling the archive, and bbb.o is added as well.

The add_files provided by Xmake is very powerful, and we can also add another batch of files while specifying that certain files are excluded, for example:

add_files("src/**.cpp|test.cpp|arm/*.cpp")
Copy the code

The above description, while adding source files recursively, excludes test. CPP and source files in the ARM directory.

For more add_files usage, see the add_files interface usage documentation

Using the demonstration

You can experience the process of using the command line directly through a video:

Create a project

A much easier way to do this is to automatically generate xmake.lua using the dumb-ass operation described in the previous section, and then modify it from there.

If you don’t have the source code and want to start compiling from a new project, you can use the project template provided by Xmake:

$ xmake create test
Copy the code

Create a c executable project named test by default, the source structure is as follows:

.├ ─ SRC │ ├─ main.c ├─ ├Copy the code

Of course you can also choose the language and template type:

$ xmake create -l c++ -t shared test
Copy the code

The above command creates a c++ dynamic library project, and that’s it.

Run and debug

Xmake will automatically find the corresponding target file. You can also pass parameters to the program.

If there are multiple target targets, you can specify the target name to run, for example:

$ xmake run test
Copy the code

Want to debug your program quickly? Add the -d argument

$ xmake run -d test
Copy the code

By default, Xmake will go to the system’s native debugger and run it. Vsjitdebugger is used on Windows, GDB is used on Linux, LLDB is used on MacOS, and you can switch to any debugger you want.

With debug mode compilation, you can use Xmake for source debugging.

Visualize configuration and build

Xmake advocates using the command line, which is very efficient when used, and on Windows, even without Cygwin, can run directly under CMD.

Of course, not all users are comfortable with the command line, so Xmake also provides editor plug-ins that integrate with major editors, such as:

Xmake – vscode plug-in

Xmake – idea plug-ins

Xmake – sublime does the plugin

Xmake – tui interface

In addition to the editor plug-in, Xmake has even implemented a complete cross-platform TUI character interface library itself, and then implemented a similar visual character interface menu configuration modeled after kconfig/ Menuconf.

This does not require additional plugins, just need to be executed under terminal:

$ xmake f --menu
Copy the code

You can display the menu configuration interface for compiling and configuration. After configuration, you can compile according to the current configuration. The result is as follows:

Custom compilation

Want more flexible compilation and configuration? You’ll have to change xmake. Lua, but that’s easy.

Add compilation options

target("test")
    set_kind("binary")
    add_files("src/*.c")
    if is_mode("debug") then
       add_cxflags("-DDEBUG")
    end
Copy the code

In the above code, the add_CXflags interface is the compiler option for configuring C/C++ code at the same time, and only works in debug mode, that is, when the following command is executed:

$ xmake f -m debug
$ xmake
Copy the code

Use built-in options

There is no need to use the original add_CXFLAGS interface to add macro definitions, set warning levels, optimization levels, and search directories for header files. Xmake provides a more convenient interface, more intelligent processing to simplify configuration, and is more versatile across platforms, such as:

add_defines("DEBUG")
set_optimize("fast")
set_warnings("all"."error")

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

target("test2")
    set_kind("binary")
    add_files("src2/*.c")
Copy the code

This setting is not in the target domain. It is the root global setting, which will affect all the following target target program compilation Settings. This can simplify the configuration and avoid redundancy.

Flexible script control

For high-end users, the construction needs are complex and changeable, and Xmake also provides corresponding solutions, which can be flexibly customized at each construction stage:

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

    after_build(function (target)
        os.exec("file %s", target:targetfile())
    end)
Copy the code

At present, Xmake can insert custom scripts before and after build, clean, run, install, uninstall, etc., and can also directly built-in actions, such as: On_install overrides the built-in installation logic, giving the user plenty of flexibility.

Convenient multi-objective dependencies

Many times, a project may have multiple targets with dependencies, such as: An executable hello, relying on a static library libtest. A, we only need two target by add_deps do a connection line, libtest. A search directory, the header file directory set up what all don’t need to care about, xmake automatically processing:

target("test")
    set_kind("static")
    add_files("src/test/*.c")

target("hello")
    add_deps("test")  Add dependencies
    set_kind("binary")
    add_files("src/hello/*.c")
Copy the code

Precompiled header file support

Xmake supports precompiled header files to speed up c/ C ++ program compilation. Currently supported compilers include GCC, CLang, and MSVC.

target("test")
    -...
    set_pcxxheader("header.h")
Copy the code

The compiler to the precompiled header processing mode, there are big differences and xmake difference hides them up and provide consistency description of setting, simplify the user in the processing of cross-platform compile time, the specific about the compiler’s handling of the precompiled header files, refer to related articles: different compiler’s handling of the precompiled header files

Custom compilation rules

Not only does Xmake have native built-in support for building files in multiple languages, but it also allows users to build complex, unknown files themselves through custom build rules.

We can extend build support for other files by pre-setting the file suffixes supported by the rule:

Define the build rules for a Markdown file
rule("markdown")
    set_extensions(".md".".markdown")
    on_build(function (target, sourcefile)
        os.cp(sourcefile, path.join(target:targetdir(), path.basename(sourcefile) .. ".html"))
    end)

target("test")
    set_kind("binary")
    
    Make the test target support the markdown file build rules
    add_rules("markdown")

    Add markdown file build
    add_files("src/*.md")
    add_files("src/*.markdown")
Copy the code

We can also specify some scattered other files to be handled as markdown rules:

target("test")
    -...
    add_files("src/test/*.md.in", {rule = "markdown"})
Copy the code

Note: Rules specified by add_files(“*.md”, {rule = “markdown”}) have a higher priority than those specified by add_rules(“markdown”).

IDE project file generation

Xmake provides a variety of plug-in extensions, in which vcproj, makefile and other project files are generated as plug-ins, and it is very easy to use:

$ xmake project -k vs2017 -m "debug,release"
Copy the code

Can generate with debug, release two kinds of compilation mode vc project, support x86 and X64.

The generated project directory structure will automatically analyze and generate an intuitive file tree according to the directory structure of all the added source files, which is convenient for VS to browse and view.

The makefile is generated as follows:

$ xmake project -k makefile
Copy the code

There will be more project documents in the future, and everyone is welcome to contribute.

Flexible and simple plug-in extensions

The IDE project file generated in the previous section is provided as a plug-in in Xmake, which is more convenient to expand, and also allows users to quickly customize their own plug-in, just need to define a task plug-in task on the line:

Define a plug-in task named Hello
task("hello")

    -- Set type to plug-in
    set_category("plugin")

    -- The entry point to run the plug-in
    on_run(function (a)
        print("hello xmake!")
    end)

    -- Set the command line options for the plug-in. There are no options, only the plug-in description is displayed
    set_menu {
                -- usage
                usage = "xmake hello [options]"

                -- description
            ,   description = "Hello xmake!"

                -- options
            ,   options = {}
            } 
Copy the code

This code is the simplest hello Xmake! Set_menu is used to configure the plug-in command line options. This is an internal task, which cannot be invoked on the command line.

For a more detailed description of the plug-ins and a list of built-in plug-ins, see the plug-in Manual

Finding dependencies

Xmake references cmake’s design for the Find_ * family of interfaces to dynamically find and add package dependencies in a project.

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

The code described above looks for packages through lib.detect.find_package. If zlib packages are found, links, includedirs, and linkdirs are added to target.

Interactive Command Execution (REPL)

Sometimes running commands in interactive mode makes it easier to test and validate modules and apis, and is more flexible without having to write an extra script file to load, but I usually use it as a calculator (ok..).

# execute without any arguments, then enter
$ xmake lua
>

# evaluate the expression> 1 plus 2, 3# Assign and print variable values
> a = 1
> a
1

# multi-line input and execution
> for _, v in pairs({1, 2, 3}) do
>> print(v)
>> end
1
2
3
Copy the code

We can also import extension modules via import:

> task = import("core.project.task")
> task.run("hello")
hello xmake!
Copy the code

Build environment support

The latest version of Xmake already supports integrated compilation of many SDK environments, such as:

  • [x] Visual Studio compilation environment
  • [x] mingw Compilation environment
  • [x] Cygwin compilation environment
  • [x] Android NDK compilation environment
  • [x] Xcode build environment (support iPhoneos/Macosx build)
  • [x] System GCC/Clang compilation environment
  • [x] Cross toolchain compilation environment
  • [x] Cuda compilation environment
  • [] Qt compilation environment (in support)
  • [] Windows WDK compilation environment (under support)

FAQ

What is xmake used for?

  1. Maintain and compile C/C++ projects across platforms
  2. Deploy automated builds on CI
  3. Fast porting of open source code
  4. AD hoc test code writing and fast running
  5. Integrate with your favorite editor to create your own C/C++ development environment
  6. Mixed compilation with other native languages
  7. Cross compilation under embedded development
  8. Ascension pretend bility

For the purpose of the third point, I usually use the most, because I often need to transplant third-party open source projects, which use different building tools, such as Automake, Cmake, etc., and support different building platform strength, so I often encounter the problem that the required platform does not support.

I had no choice but to type the Makefile to transplant the code, and then adapt it to the platform I need to support, and cross the toolchain. It was very painful. Since writing Xmake, I have made it much easier to transplant the code, and the efficiency has improved significantly.

How do I look at real-time build warnings?

To avoid screen-brushing, warnings are not printed in real time at build time by default. If you want to see them, you can use the -w option to enable compilation warnings.

$ xmake [-w|--warning] 
Copy the code

How to view detailed compilation parameter information?

Run xmake again with either -v or –verbose to get more detailed output

Such as:

$ xmake [-v|--verbose] 
Copy the code

The –backtrace option also gets the debug stack information for Xmake at the time of the error

$ xmake -v --backtrace
Copy the code

Fast installation

Finally, how to install Xmake is usually just a script command.

One-click install script

bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
Copy the code

Windows installer

For Windows users, a quick installation package is available, and you can download the corresponding version on Github Releases.

For more details about the installation process, see installation Instructions

conclusion

Xmake also has many useful features, such as: compiler feature detection, rich module libraries, dependency package management, custom options, etc. One article can not cover so much, if you are interested in it, you can go to the official documentation, there are many hidden features waiting for you.

tboox.org/cn/2018/03/…