下面我们简单介绍一些常用的工程例子,更多更全的examples工程可以到project examples中查看。
我们也可以通过:xmake create
命令创建各种常用的空工程来快速开始,具体对于这个命令的介绍以及支持的工程模板,可以敲下面的命令查看:
xmake create --help
可执行程序
target("test")
set_kind("binary")
add_files("src/*c")
完整例子请执行下面的命令来创建:
xmake create -l c -t console test
静态库程序
target("library")
set_kind("static")
add_files("src/library/*.c")
target("test")
set_kind("binary")
add_files("src/*c")
add_deps("library")
通过add_deps
将一个静态库自动链接到test可执行程序。
完整例子请执行下面的命令来创建:
xmake create -l c -t static test
动态库程序
target("library")
set_kind("shared")
add_files("src/library/*.c")
target("test")
set_kind("binary")
add_files("src/*c")
add_deps("library")
通过add_deps
将一个动态库自动链接到test可执行程序。
完整例子请执行下面的命令来创建:
xmake create -l c -t shared test
Qt程序
创建一个空工程:
v2.2.9以上版本:
$ xmake create -t qt.console test
$ xmake create -t qt.static test
$ xmake create -t qt.shared test
$ xmake create -t qt.quickapp test
$ xmake create -t qt.widgetapp test
更多工程模板见:xmake create --help
v2.2.8以前老版本:
$ xmake create -l c++ -t console_qt test
$ xmake create -l c++ -t static_qt test
$ xmake create -l c++ -t shared_qt test
$ xmake create -l c++ -t quickapp_qt test
默认会自动探测Qt环境,当然也可以指定Qt SDK环境目录:
$ xmake f --qt=~/Qt/Qt5.9.1
如果想要使用windows下mingw的Qt环境,可以切到mingw的平台配置,并且指定下mingw编译环境的sdk路径即可,例如:
$ xmake f -p mingw --sdk=C:\Qt\Qt5.10.1\Tools\mingw530_32
上述指定的mingw sdk用的是Qt下Tools目录自带的环境,当然如果有其他第三方mingw编译环境,也可以手动指定, 具体可以参考:mingw编译配置。
更多详情可以参考:#160
静态库程序
target("qt_static_library")
add_rules("qt.static")
add_files("src/*.cpp")
add_frameworks("QtNetwork", "QtGui")
动态库程序
target("qt_shared_library")
add_rules("qt.shared")
add_files("src/*.cpp")
add_frameworks("QtNetwork", "QtGui")
控制台程序
target("qt_console")
add_rules("qt.console")
add_files("src/*.cpp")
Quick应用程序
v2.2.9以上版本:
target("qt_quickapp")
add_rules("qt.quickapp")
add_files("src/*.cpp")
add_files("src/qml.qrc")
!> 新版本提供了qt.quickapp
规则,内置了QtQuick的内建规则,使用更加简单,下面老版本的qt.application
还是支持的,向下兼容:
target("qt_quickapp")
add_rules("qt.application")
add_files("src/*.cpp")
add_files("src/qml.qrc")
add_frameworks("QtQuick")
!> 如果使用的自己编译的static版本QT SDK,那么需要切换到add_rules("qt.quickapp_static")
静态规则才行,因为链接的库是不同的,需要做静态链接。
接下来,我们尝试编译下,通常,如果是使用Qt的安装包默认安装,也没有修改安装路径,那么大部分情况下都是可以自动检测到QT SDK的根路径,例如:
$ xmake
checking for the architecture ... x86_64
checking for the Xcode directory ... /Applications/Xcode.app
checking for the SDK version of Xcode ... 10.15
checking for the Qt SDK directory ... /Users/ruki/Qt5.13.2/5.13.2/clang_64
checking for the Qt SDK version ... 5.13.2
[ 0%]: ccache compiling.release src/main.cpp
[ 49%]: compiling.qt.qrc src/qml.qrc
[100%]: linking.release test
build ok!
然后我们继续运行下它:
$ xmake run
效果如下:
Widgets应用程序
v2.2.9以上版本:
target("qt_widgetapp")
add_rules("qt.widgetapp")
add_files("src/*.cpp")
add_files("src/mainwindow.ui")
add_files("src/mainwindow.h") -- 添加带有 Q_OBJECT 的meta头文件
!> 新版本提供了qt.widgetapp
规则,内置了QtWidgets的内建规则,使用更加简单,下面老版本的qt.application
还是支持的,向下兼容:
target("qt_widgetapp")
add_rules("qt.application")
add_files("src/*.cpp")
add_files("src/mainwindow.ui")
add_files("src/mainwindow.h") -- 添加带有 Q_OBJECT 的meta头文件
add_frameworks("QtWidgets")
!> 如果使用的自己编译的static版本QT SDK,那么需要切换到add_rules("qt.widgetapp_static")
静态规则才行,因为链接的库是不同的,需要做静态链接。
运行效果如下:
Android应用程序
2.2.6之后版本,可以直接切到android平台编译Quick/Widgets应用程序,生成apk包,并且可通过xmake install
命令安装到设备。
$ xmake create -t quickapp_qt -l c++ appdemo
$ cd appdemo
$ xmake f -p android --ndk=~/Downloads/android-ndk-r19c/ --android_sdk=~/Library/Android/sdk/ -c
$ xmake
[ 0%]: compiling.qt.qrc src/qml.qrc
[ 50%]: ccache compiling.release src/main.cpp
[100%]: linking.release libappdemo.so
[100%]: generating.qt.app appdemo.apk
然后安装到设备:
$ xmake install
installing appdemo ...
installing build/android/armv7-a/release/appdemo.apk ..
Success
install ok!👌
Cuda程序
创建一个空工程:
$ xmake create -P test -l cuda
$ cd test
$ xmake
-- define target
target("cuda_console")
set_kind("binary")
add_files("src/*.cu")
-- generate SASS code for SM architecture of current host
add_cugencodes("native")
-- generate PTX code for the virtual architecture to guarantee compatibility
add_cugencodes("compute_30")
从v2.2.7版本开始,默认构建会启用device-link。(参见 Separate Compilation and Linking of CUDA C++ Device Code)如果要显示禁用device-link,可以通过add_values("cuda.devlink", false)
来设置。
默认会自动探测cuda环境,当然也可以指定Cuda SDK环境目录:
$ xmake f --cuda=/usr/local/cuda-9.1/
$ xmake
更多详情可以参考:#158
WDK驱动程序
默认会自动探测wdk所在环境,当然也可以指定wdk sdk环境目录:
$ xmake f --wdk="G:\Program Files\Windows Kits\10" -c
$ xmake
更多详情可以参考:#159
相关完整工程example见:WDK examples
umdf驱动程序
target("echo")
add_rules("wdk.driver", "wdk.env.umdf")
add_files("driver/*.c")
add_files("driver/*.inx")
add_includedirs("exe")
target("app")
add_rules("wdk.binary", "wdk.env.umdf")
add_files("exe/*.cpp")
kmdf驱动程序
target("nonpnp")
add_rules("wdk.driver", "wdk.env.kmdf")
add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)", "-func:Hexdump((LEVEL,FLAGS,MSG,...))")
add_files("driver/*.c", {rule = "wdk.tracewpp"})
add_files("driver/*.rc")
target("app")
add_rules("wdk.binary", "wdk.env.kmdf")
add_files("exe/*.c")
add_files("exe/*.inf")
wdm驱动程序
target("kcs")
add_rules("wdk.driver", "wdk.env.wdm")
add_values("wdk.man.flags", "-prefix Kcs")
add_values("wdk.man.resource", "kcsCounters.rc")
add_values("wdk.man.header", "kcsCounters.h")
add_values("wdk.man.counter_header", "kcsCounters_counters.h")
add_files("*.c", "*.rc", "*.man")
target("msdsm")
add_rules("wdk.driver", "wdk.env.wdm")
add_values("wdk.tracewpp.flags", "-func:TracePrint((LEVEL,FLAGS,MSG,...))")
add_files("*.c", {rule = "wdk.tracewpp"})
add_files("*.rc", "*.inf")
add_files("*.mof|msdsm.mof")
add_files("msdsm.mof", {values = {wdk_mof_header = "msdsmwmi.h"}})
生成驱动包
可以通过以下命令生成.cab驱动包:
$ xmake [p|package]
$ xmake [p|package] -o outputdir
输出的目录结构如下:
- drivers
- sampledsm
- debug/x86/sampledsm.cab
- release/x64/sampledsm.cab
- debug/x86/sampledsm.cab
- release/x64/sampledsm.cab
驱动签名
默认编译禁用签名,可以通过set_values("wdk.sign.mode", ...)
设置签名模式来启用签名。
测试签名
测试签名一般本机调试时候用,可以使用xmake自带的test证书来进行签名,例如:
target("msdsm")
add_rules("wdk.driver", "wdk.env.wdm")
set_values("wdk.sign.mode", "test")
不过这种情况下,需要用户手动在管理员模式下,执行一遍:$xmake l utils.wdk.testcert install
,来生成和注册test证书到本机环境。这个只需要执行一次就行了,后续就可以正常编译和签名了。
当然也可以使用本机已有的有效证书去签名。
从sha1来选择合适的证书进行签名:
target("msdsm")
add_rules("wdk.driver", "wdk.env.wdm")
set_values("wdk.sign.mode", "test")
set_values("wdk.sign.thumbprint", "032122545DCAA6167B1ADBE5F7FDF07AE2234AAA")
从store/company来选择合适的证书进行签名:
target("msdsm")
add_rules("wdk.driver", "wdk.env.wdm")
set_values("wdk.sign.mode", "test")
set_values("wdk.sign.store", "PrivateCertStore")
set_values("wdk.sign.company", "tboox.org(test)")
正式签名
通过指定对应的正式签名证书文件进行签名:
target("msdsm")
add_rules("wdk.driver", "wdk.env.wdm")
set_values("wdk.sign.mode", "release")
set_values("wdk.sign.company", "xxxx")
set_values("wdk.sign.certfile", path.join(os.projectdir(), "xxxx.cer"))
生成低版本驱动
如果想在wdk10环境编译生成win7, win8等低版本系统支持的驱动,可以通过设置wdk.env.winver
来切换系统版本:
set_values("wdk.env.winver", "win10")
set_values("wdk.env.winver", "win10_rs3")
set_values("wdk.env.winver", "win81")
set_values("wdk.env.winver", "win8")
set_values("wdk.env.winver", "win7")
set_values("wdk.env.winver", "win7_sp1")
set_values("wdk.env.winver", "win7_sp2")
set_values("wdk.env.winver", "win7_sp3")
我们也可以手动指定编译的目标程序支持的windows版本:
$ xmake f --wdk_winver=[win10_rs3|win8|win7|win7_sp1]
$ xmake
WinSDK程序
target("usbview")
add_rules("win.sdk.application")
add_files("*.c", "*.rc")
add_files("xmlhelper.cpp", {rule = "win.sdk.dotnet"})
更多详情可以参考:#173
MFC程序
MFC静态库
target("test")
add_rules("win.sdk.mfc.static")
add_files("src/*.c")
MFC动态库
target("test")
add_rules("win.sdk.mfc.shared")
add_files("src/*.c")
MFC应用程序(静态链接)
target("test")
add_rules("win.sdk.mfc.static_app")
add_files("src/*.c")
MFC应用程序(动态链接)
target("test")
add_rules("win.sdk.mfc.shared_app")
add_files("src/*.c")
Protobuf程序
使用c库
add_requires("protobuf-c")
target("console_c")
set_kind("binary")
add_packages("protobuf-c")
add_files("src/*.c")
add_files("src/*.proto", {rules = "protobuf.c"})
使用c++库
add_requires("protobuf-cpp")
target("console_c++")
set_kind("binary")
set_languages("c++11")
add_packages("protobuf-cpp")
add_files("src/*.cpp")
add_files("src/*.proto", {rules = "protobuf.cpp"})
Lex&Yacc程序
target("calc")
set_kind("binary")
add_rules("lex", "yacc")
add_files("src/*.l", "src/*.y")