After creating an empty project, we will get the following basic configuration file.
add_rules("mode.debug", "mode.release")
target("test")
set_kind("binary")
add_files("src/*.cpp")
Among them, mode.release is the default compilation mode rule, which will automatically add some common optimization compilation options for the target build, such as: -O2, and so on.
We can also switch to mode.debug debugging mode through xmake f -m debug, which will automatically configure some debugging options, such as: -g, and so on.
Of course, we can also configure them completely by ourselves without using the mode rules.
target("test")
set_kind("binary")
add_files("src/*.cpp")
We can add a macro definition option to the target program through add_defines, for example:
target("test")
set_kind("binary")
add_files("src/*.cpp")
add_defines("DEBUG")
In the test target scope, we configure a macro definition compilation option -DDEBUG for it, which will only take effect on the test target.
We can also use the xmake -v command to quickly verify whether the added configuration is effective.
[ 23%]: cache compiling.release src/main.cpp
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -c -Q
unused-arguments -target x86_64-apple-macos15.2 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk -fvisibility=hidden -fvisibility-inline
s-hidden -O3 -DNDEBUG -o build/.objs/test/macosx/x86_64/release/src/main.cpp.o src/main.cpp
As you can see, -DDEBUG has been added to the clang compilation command.
If you want multiple compilation targets to take effect at the same time, we can move them to the global root scope.
add_defines("DEBUG")
target("foo")
set_kind("binary")
add_files("src/*.cpp")
target("bar")
set_kind("binary")
add_files("src/*.cpp")
At this time, both foo and bar target programs will have the -DDEBUG compilation option.
The configuration of the root scope will affect the current xmake.lua configuration file and the target programs in all sub-xmake.lua files (that is, the sub-directory configuration introduced by includes).
add_defines("DEBUG")
target("foo")
set_kind("binary")
add_files("src/*.cpp")
includes("bar")
target("bar")
set_kind("binary")
add_files("src/*.cpp")
If the bar target is in the bar/xmake.lua sub-configuration file, it will also be effective.
::: tip NOTE However, the root scope configuration in the sub-file cannot affect the target in the same level or parent configuration file. :::
target("foo")
set_kind("binary")
add_files("src/*.cpp")
includes("bar")
add_defines("DEBUG")
target("bar")
set_kind("binary")
add_files("src/*.cpp")
target("zoo")
set_kind("binary")
add_files("src/*.cpp")
Here, although add_defines is configured in the root scope, it only affects the bar and zoo targets, and cannot affect the foo target.
In other words, the scope of influence of the root scope is in a tree structure, and it takes effect layer by layer.
mode.release will automatically introduce some optimization options, and we can also configure them ourselves through the set_optimize interface.
For example:
set_optimize("faster")
It will configure the -O2 compilation option for the target.
::: tip NOTE Different compilers have different optimization options, and xmake will automatically map to the most appropriate compilation option.
:::
For more details, please refer to the document: set_optimize.
add_includedirs("/tmp")
It will add the -I/tmp compilation option to the compiler's command line.
For more details, please refer to the document: add_includedirs.
add_linkdirs("/tmp")
It will add the -L/tmp link option to the linker command line.
For more details, please refer to the document: add_linkdirs.
add_links("foo")
It will add the -lfoo link option to the linker command line, which usually needs to be used with add_linkdirs.
add_links("foo")
add_linkdirs("/tmp")
For more details, please refer to the document: add_links.
add_links is usually used to link user-generated libraries, while add_syslinks can add system libraries without the need for an additional add_linkdirs.
And its link order is relatively late (after user libraries).
add_links("foo")
add_syslinks("pthread", "dl")
If links and syslinks are configured at the same time, the link order is as follows:
-lfoo -lpthread -ldl
The add_defines and other interfaces mentioned above are all abstract APIs. Since most compilers support them, Xmake abstracts them to make them more convenient for users to use and provide better cross-platform and cross-compiler support.
However, we can also add specific compilation options for C++ code through the add_cxxflags interface, such as:
add_cxflags("-DDEBUG")
It is equivalent to add_defines("DEBUG"), but add_defines is more general and applicable to all compilers, while add_cxxflags("-DDEBUG") may only be applicable to a few compilers, because not all compilers define macros through -D.
In addition, we can also add compilation options for C code through the add_cflags interface, and add_cxflags to add compilation options for C/C++ code at the same time.
For more details, please refer to the documentation:
You can set different target types through set_kind():
target("app")
set_kind("binary") -- executable program
add_files("src/*.cpp")
target("lib")
set_kind("static") -- static library
add_files("src/*.cpp")
target("dll")
set_kind("shared") -- dynamic library
add_files("src/*.cpp")
target("obj")
set_kind("object") -- object file collection
add_files("src/*.cpp")
target("header")
set_kind("headeronly") -- header-only library
add_headerfiles("include/*.h")
| Type | Description | Output Files |
|---|---|---|
| binary | Executable program | app.exe, app |
| static | Static library | libapp.a, app.lib |
| shared | Dynamic library | libapp.so, app.dll |
| object | Object file collection | *.o, *.obj |
| headeronly | Header-only library | No compilation output |
| phony | Virtual target | No output, only for dependency management |
Virtual targets don't generate actual files, they're only used for managing dependencies:
target("test1")
set_kind("binary")
add_files("src/test1.cpp")
target("test2")
set_kind("binary")
add_files("src/test2.cpp")
target("all-tests")
set_kind("phony")
add_deps("test1", "test2")
Executing xmake build all-tests will build both test1 and test2.
We can configure the dependency between two target programs through the add_deps interface.
This is usually used in scenarios where an executable program depends on a static library (or dynamic library), for example:
target("foo")
set_kind("static")
add_files("src/foo.cpp")
target("test")
set_kind("binary")
add_deps("foo")
add_files("src/main.cpp")
Since the dependency between test and foo library programs is configured through add_deps, when we compile test, the foo dependency library will be automatically compiled and automatically linked to it, without the need for additional add_links and add_linkdirs configurations.
For more information about dependency configuration, please refer to the document: add_deps.
target("app")
add_files("src/*.cpp") -- add all cpp files
add_files("src/*.c") -- add all c files
add_files("src/*.asm") -- add assembly files
add_files("src/*.m") -- add Objective-C files
add_files("src/*.mm") -- add Objective-C++ files
target("app")
add_files("src/*.cpp|test.cpp") -- exclude src/test.cpp file
target("header-lib")
set_kind("headeronly")
add_headerfiles("include/*.h") -- add header files
add_headerfiles("include/*.hpp") -- add C++ header files
add_headerfiles("include/*.h", {install = false}) -- non-installable header files
target("app")
add_installfiles("assets/*.png", {prefixdir = "share/app"}) -- install resource files
add_installfiles("config/*.conf", {prefixdir = "etc"}) -- install config files
target("app")
set_basename("myapp") -- generated filename will be myapp.exe
target("app")
set_targetdir("bin") -- output to bin directory
target("app")
set_installdir("bin") -- install to bin directory
target("app")
set_version("1.0.0") -- set version number
target("lib")
set_kind("shared")
set_symbols("hidden") -- hide symbols, reduce export table size
target("app")
set_optimize("fast") -- fast optimization
set_optimize("faster") -- faster optimization
set_optimize("fastest") -- fastest optimization
set_optimize("smallest") -- size optimization
set_optimize("none") -- no optimization
target("app")
set_symbols("debug") -- add debug symbols
set_strip("debug") -- strip debug symbols during linking
set_strip("all") -- strip all symbols during linking
target("app")
set_languages("c++17") -- set C++ standard
set_languages("c11") -- set C standard
target("app")
set_languages("c++17", "c11") -- support both C++17 and C11
target("app")
set_plat("android") -- set to Android platform
set_arch("arm64-v8a") -- set to ARM64 architecture
target("app")
if is_plat("windows") then
add_defines("WIN32")
add_links("user32")
elseif is_plat("linux") then
add_defines("LINUX")
add_links("pthread")
end
option("enable_gui")
set_default(false)
set_description("Enable GUI support")
target("app")
set_options("enable_gui") -- associate option
target("app")
if has_config("enable_gui") then
add_defines("GUI_ENABLED")
add_links("gtk+-3.0")
end
target("app")
add_rules("mode.debug", "mode.release") -- add debug and release modes
add_rules("qt.widgetapp") -- add Qt application rule
add_rules("wdk.driver") -- add WDK driver rule
rule("myrule")
set_extensions(".my")
on_build_file(function (target, sourcefile, opt)
-- custom build logic
end)
target("app")
add_rules("myrule") -- apply custom rule
target("app")
set_runtimes("MT") -- static runtime (MSVC)
set_runtimes("MD") -- dynamic runtime (MSVC)
target("app")
set_runtimes("MD")
add_rpathdirs("$ORIGIN") -- set relative path lookup
target("app")
set_toolset("clang") -- use Clang toolchain
set_toolset("gcc") -- use GCC toolchain
set_toolset("msvc") -- use MSVC toolchain
target("app")
set_toolset("cc", "clang") -- set C compiler
set_toolset("cxx", "clang++") -- set C++ compiler
target("app")
set_group("apps") -- set group to apps
target("lib")
set_group("libs") -- set group to libs
target("test")
set_group("tests") -- set group to tests
target("app")
set_default(true) -- set as default build target
target("test")
set_default(false) -- not set as default build target
target("app")
set_enabled(true) -- enable target
target("old")
set_enabled(false) -- disable target