xmake使用总结

GitHub - Meidozuki/VBAO: A library aiming for building an MVVM (or MVFM) project

https://github.com/Btk-Project/xmake-repo

https://github.com/tboox/tbox

GitHub - tboox/gbox: 🎨 A multi-platform graphic library

GitHub - tboox/vm86: 🍔 A x86 Script Instruction Virtual Machine

GitHub - tboox/ltui: 🍖 A cross-platform terminal ui library based on Lua

xmake

#https://xmake.io/#/guide/faq?id=breakpoint-debugging
xrepo update-repo
xrepo env -b emmylua_debugger -- xmake build  #调试构建
xrepo env -b emmylua_debugger -- xmake install -o /tmp #调试安装

Create Project:
    xmake create -l c -P ./hello
    xmake create -l c -t console test
    xmake create -l c -t static test
    xmake create -l c -t shared test
    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
    xmake create -t quickapp_qt -l c ++ appAndroidDemo
    xmake create -t xcode.macapp -l objc test
    xmake create -t xcode.iosapp -l objc test
    xmake create -t xcode.framework -l objc test
    xmake create -t xcode.bundle -l objc test
    xmake create -l go -t console test
Build Project:  
    xmake  #generate xmake.lua automatically and build
    xmake f -y   #generate xmake.lua automatically
Run Program:     
    xmake run hello || xmake r hello
Debug Program:     
    xmake config -m debug && xmake && xmake f --debugger=gdb && xmake run -d hello
Paltform:        
    xmake f -p wasm --toolchain=wasi [--qt=~/Qt]
    xmake f -p [iphoneos|macosx|windows|android] -a [armv7|armv7s|arm64|i386|x86_64]
    xmake f -p mingw --sdk=/usr/local/i386-mingw32-4.3.0/ [-a i386|x86_64|arm|arm64]
    xmake f -p myplat --sdk=/usr/local/arm-xxx-gcc/
SDK:
    xmake f --qt=~/Qt/Qt5.9.1
    xmake f -p cross android --ndk=~/Downloads/android-ndk-r19c/ --android_sdk=~/Library/Android/sdk/ --bin=/usr/opt/bin --cross=armv7-linux- -c
    xmake f --wdk="G:\Program Files\Windows Kits\10" -c
    xmake f --wdk_winver=[win10_rs3|win8|win7|win7_sp1]
    xmake f --cuda=/usr/local/cuda-9.1/
Flags:
    --cflags,--cxxflags, --ldflags, --shflags and --arflags
    xmake f -p cross --sdk=/user/toolsdk 
    --cc=armv7-linux-clang 
    --cxx=armv7-linux-clang++ 
    --ld=armv7-linux-clang++ 
    --sh=armv7-linux-clang++ 
    --ar=armv7-linux-ar 
    --includedirs=/usr/toolsdk/xxx/include 
    --linkdirs=/usr/toolsdk/xxx/lib 
    --links=pthread  
    --cflags="-DTEST -I/xxx/xxx" 
    --ldflags="-lpthread"
    --cxflags    Set c/c++ compiler option
    g              global configuration
    -c             clean all cached configuration and re-configure project.
        
    (multiple directories use : under linux / macos, and ; under win.)
    
    set_config("cflags", "-DTEST")
    set_config("sdk", "/home/xxx/tooksdk")
    set_config("cc", "gcc")
    set_config("ld", "g++")
    xmake f -m debug --menu --xxx=y --export=/tmp/config.txt --import=/tmp/config.txt
Install:
    xmake install
    xmake [p|package] -o outputdir -f remote  #generate package
    xmake uninstall
Custom toolchain:
    xmake f --toolchain=[myclang,emcc]
    --bin        Set the bin directory of toolchains
    --cross        Set the prefix of compilation tools
    --as        Set asm assembler
    --asflags    Set asm assembler option
    toolchain("myclang")
        set_kind("standalone")
        set_toolset("cc", "clang")
        set_toolset("cxx", "clang", "clang++")
        set_toolset("ld", "clang++", "clang")
        set_toolset("sh", "clang++", "clang")
        set_toolset("ar", "ar")
        set_toolset("ex", "ar")
        set_toolset("strip", "strip")
        set_toolset("mm", "clang")
        set_toolset("mxx", "clang", "clang++")
        set_toolset("as", "clang")
Policies:
    xmake f --ccache=n || xmake f --policies=build.ccache:n,build.sanitizer.address  #n->禁用缓存,没有表示开启
    set_policy("build.warning", true)
    set_warnings("all", "extra")
    set_policy("build.optimization.lto", true)     #link-time optimisation (LTO)
    set_policy("check.auto_ignore_flags", false)  #自动忽略
    set_policy("check.auto_map_flags", false)    #自定映射到不同平台
    set_policy("build.across_targets_in_parallel", false) #多目标并行编译
    set_policy("build.ccache", false)
    set_policy("build.sanitizer.address", true)
    set_policy("build.sanitizer.undefined", true)
    set_policy("build.sanitizer.thread", true)
    set_policy("build.sanitizer.memory", true)
    set_policy("build.sanitizer.leak", true)
    add_requires("zlib", {configs = {asan = true}})  #Address Sanitizer (ASan) 
    xmake f --policies=run.autobuild
    set_policy("package.librarydeps.strict_compatibility", true)
    set_policy("package.download.http_headers", "TEST1: foo", "TEST2: bar")
    add_urls("https://github.com/madler/zlib/archive/$(version).tar.gz", {
        http_headers = {"TEST1: foo", "TEST2: bar"}
    })
    preprocessor.linemarkers
    preprocessor.gcc.directives_only
    package.requires_lock
    package.precompiled
    package.fetch_only
    package.install_only
    package.strict_compatibility
    package.install_always
Help:             
    xmake create --help
    xmake f --help
    xmake show -l toolchains
    xmake -v -D
    xmake show -l envs
    xmake l os.programdir
    xmake [action|plugin] [-h|--help]
    xmake [-q|--quiet]
    xmake [-w|--warning]
    xmake l find_package cmake::ZLIB
构建脚本调试:
    https://xmake.io/#/guide/faq?id=breakpoint-debugging 
    无法连接9966端口,改"host": "127.0.0.1"。或vscode底部重启EmmyLua。
    xrepo update-repo
    xrepo env -b emmylua_debugger -- xmake build  #调试构建
    xrepo env -b emmylua_debugger -- xmake install -o /tmp #调试安装
文档生成:
    xmake doxygen
    
Executable Program:
    -- set project name
    set_project("tbox")
    -- set project version
    set_version("1.5.1", {build = "%Y%m%d%H%M", soname = true})\
    -- the current xmake version must be larger than 2.1.0
    set_xmakever("2.1.0")
    add_moduledirs("$(projectdir)/modules")
    add_packagedirs("packages")
    add_rules("mode.debug", "mode.release")
    add_requires("qt5widgets", {optional = true, asan = true, debug = true, small=true, verify = false, external = false})
    add_requires("go::github.com/sirupsen/logrus", {alias = "logrus"})
    add_requires("go::golang.org/x/sys/internal/unsafeheader", {alias = "unsafeheader"})
    add_requires("cmake::ZLIB", {alias = "zlib", system = true})
    add_requires("cmake::Boost", {system = true, configs = {components = {"regex", "system"}}))
    add_requires("cmake::OpenCV", {system = true, configs = {envs = {CMAKE_PREFIX_PATH = "xxx"}}})
    add_requires("cmake::xxx", {configs = {link_libraries = {"abc::lib1", "abc::lib2"}}})
    add_requires("libpng ~1.16", "zlib 1.1.2 || >=1.2.11 <1.3.0")
    add_configfiles("../include/co/config.h.in", {filename = "../include/co/config.h"})
    add_repositories("my-repo my-repo")
    option("linux-headers", {showmenu = true, description = "Set linux-headers path."})
    if is_plat("windows", "macosx") then
        add_requires("go::golang.org/x/sys/windows", {alias = "syshost"})
        add_links("pthread", "m", "dl")
    else
        for _, name in ipairs({"pthread", "m", "dl"}) do
            add_links(name)
        end
        add_requires("go::golang.org/x/sys/unix", {alias = "syshost"})
    end
    if is_plat("myplat") then
        add_defines("TEST")
    end
    target("test")
        set_plat("cross")
        set_arch("c-sky")
        set_targetdir("$(projectdir)/lib")
        set_rundir("$(projectdir)")
        set_basename("co")
        add_rules("xcode.application" || "xcode.framework" || "xcode.bundle")
        add_files("src/*.m", "src/**.storyboard", "src/*.xcassets")
        add_files("src/Info.plist")
        add_values("xcode.bundle_identifier", "org.tboox.test")
        add_values("xcode.codesign_identity", "Apple Development: xxx@gmail.com (T3NA4MRVPU)")
        add_values("xcode.mobile_provision", "iOS Team Provisioning Profile: org.tboox.test")
        after_load(function (target)
            for _, sourcebatch in pairs(target:sourcebatches()) do
                if sourcebatch.sourcekind == "as" then -- only asm files
                    for idx, objectfile in ipairs(sourcebatch.objectfiles) do
                        sourcebatch.objectfiles[idx] = objectfile:gsub("%.S%.o", ".o")
                    end
                end
            end
        end)
        target:set("filename", TARGET_NAME..".elf")
        target:add("ldflags", flto .. "-Wl,--gc-sections -Wl,-zmax-page-size=1024 -Wl,--whole-archive ./lib/libwmarch.a ./lib/libgt.a ./lib/libwlan.a ./lib/libdsp.a ./lib/libbtcontroller.a -Wl,--no-whole-archive -mcpu=ck804ef -nostartfiles -mhard-float -lm -Wl,-T./ld/air101_103.ld -Wl,-ckmap=./build/out/"..TARGET_NAME..".map ",{force = true})

    target("usbview")
        add_rules("win.sdk.application")
        add_files("*.c", "*.rc")
        add_files("xmlhelper.cpp", {rule = "win.sdk.dotnet"})
        set_values("wdk.sign.certfile", path.join(os.projectdir(), "xxxx.cer"))
        set_values("wdk.env.winver", "win10")
    target("qt_static_library")
        add_rules("qt.static" || "qt.shared" || "qt.console" || "qt.quickapp" || "qt.quickapp_static" || "qt.qmlplugin" || "qt.widgetapp")
        add_packages("qt5widgets")
        add_headerfiles("src/*.h")
        add_files("src/*.cpp")
        add_files("src/mainwindow.ui")
        set_values("qt.qmlplugin.import_name", "My.Plugin")
        add_frameworks("QtNetwork", "QtGui", "QtWidgets")
    target("library")
        set_kind("static" || "shared")
        add_files("src/library/*.c")
        add_deps("add", "sub")
        set_policy("build.merge_archive", true)  #合并静态库
    target("test")
        set_kind("binary")
        set_languages("c++11")
        add_packages("protobuf-cpp")
        add_packages("logrus", "syshost", "unsafeheader")
        add_rules("lex", "yacc")
        add_files("src/*.c")
        add_files("*.mpp", { install = true })
        add_deps("library")
        -- 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")
        add_values("iverilogs.flags", "-DTEST")
        add_defines("DEBUG")
        add_syslinks("pthread")
        set_license("GPL-2.0")
        set_policy("build.c++.modules", true)
        set_toolchains("@iverilog", "clang", "yasm")
        set_toolset("cxx", "clang")
        set_toolset("ld", "clang++")
        add_ldflags("-static", {force = true})
    target_end()
    target("VBAO")
        set_installdir("$(buildir)/install")
        add_installfiles("Lib_VBao/COPYING.LESSER",{prefixdir = "VBAO"})
        add_installfiles("Lib_VBao/VBAO/*",{prefixdir = "VBAO/include"})
        set_languages("cxx17")
        set_kind("headeronly")
    package("foo")        #        on/after/before_build/install/package/run
        set_sourcedir(path.join(os.scriptdir(), "src"))
        on_install(function(package)
            import("package.tools.xmake").install(package, {})
        end)
        after_link(function (target)
            import("utils.archive.merge_staticlib")
            merge_staticlib(target, "libout.a", {"libfoo.a", "libbar.a"})
        end)
        on_fetch(function (package, opt)
            return {includedirs = "/usr/src/linux-headers-5.0/include"}
        end)
        on_load(function (target)
            if is_plat("linux", "macosx") then
                target:add("links", "pthread", "m", "dl")
            end
        end)
        after_build(function (target)
            Import("core.project.config")
            Local targetfile = target:targetfile()
            Os.cp(targetfile, path.join(config.buildir(), path.filename(targetfile)))
            Print("build %s", targetfile)
            -- Execute signature, if it fails, automatically interrupt, giving a highlight error message
            os.run("ldid -S$(projectdir)/entitlements.plist %s", target:targetfile())
        end)
        on_load("modules.test.load")
        on_install("modules.test.install")
        on_run(function ()
            -- Internal scope
            end)

        after_package(function ()
            -- Internal scope
            end)
        if is_host("windows") then
            set_urls("http://cdndownload.openluat.com/xmake/toolchains/csky/csky-elfabiv2-tools-mingw-minilibc-$(version).tar.gz")
            add_versions("20210423", "e7d0130df26bcf7b625f7c0818251c04e6be4715ed9b3c8f6303081cea1f058b")
            add_versions("20230301", "1b958769601e8ba94a866df68215700614f55e0152933d5f5263899bb44d24f5")
        elseif is_host("linux") then
            set_urls("http://cdndownload.openluat.com/xmake/toolchains/csky/csky-elfabiv2-tools-x86_64-minilibc-$(version).tar.gz")
            add_versions("20210423", "8b9a353c157e4d44001a21974254a21cc0f3c7ea2bf3c894f18a905509a7048f")
            add_versions("20230301", "dac3c285d7dc9fe91805d6275c11fa260511cdd6a774891cbe2d79ec73535e10")
        end
        on_install("@windows", "@linux", function (package)
            os.vcp("*", package:installdir())
        end)
    -- external scope
    task("hello") do
        -- external scope
        on_run(function ()
            -- Internal scope
            end)
    end
    -- option settings, only local settings are supported, not affected by global api settings
    option("test")
        -- local scope of the current option
        set_default(false)
        set_showmenu(true)
        set_description("test1 option")
    option_end()
    -- local variables, only valid for current xmake.lua
    local var1 = 0
    -- global variables that affect all subsmake.lua included after includes()
    var2 = 1
    includes("src")
    target("demo", {kind = "binary", files = "src/*.c"})
    option("test1", {default = true, showmenu = true, description = "test1 option"})
    
Integrate CMake source library:
    add_rules("mode.debug", "mode.release")

    package("foo")
        add_deps("cmake")
        set_sourcedir(path.join(os.scriptdir(), "foo"))
        on_install(function (package)
            local configs = {}
            table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))
            table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
            import("package.tools.cmake").install(package, configs)
        end)
        on_test(function (package)
            assert(package:has_cfuncs("add", {includes = "foo.h"}))
        end)
    package_end()

    add_requires("foo")

    target("demo")
        set_kind("binary")
        add_files("src/main.c")
        add_packages("foo")
        
常用命令:
     -- 显示目标文件路径
     print(target:targetfile())
     -- 显示目标的构建类型
     print(target:get("kind"))
     -- 显示目标的宏定义
     print(target:get("defines"))
    -- 获取当前工程目录
    print(project.directory())
    -- add_deps("UIEvent")
    -- add_links("tbox")
    -- add_linkdirs("lib")
    
    import("module", {alias="test", rootdir="./", inherit = true})
    testModule()
    target("Global")
        set_kind("shared")
        add_files("*.cpp")
        add_files("Private/*.cpp")
        add_files("Private/*/*.cpp", "Private/**/*.cpp")
        -- 添加src下的所有cpp文件,但是不包括src/test.cpp、src/hello.cpp以及src下所有带xx_前缀的cpp文件
        -- add_files("src/*.cpp|test.cpp|hello.cpp|xx_*.cpp")
        add_includedirs("Private", {private = true})
        add_includedirs("Private/Port", {private = true})
        add_includedirs("Public", {interface = true})  -- public 当前target,依赖的子target都会被设置
        add_defines("BUILDING_$(target:name():upper)")
    
    -- os模块
    
    -- 运行shell命令,如果运行失败直接中断,并显示出错信息,我们不需要判断返回值
    os.run("echo hello xmake!")

    -- 复制文件
    os.cp("/tmp/src", "/tmp/dst")

    -- 删除文件或者目录
    os.rm("/tmp/dir")

    -- 移动文件
    os.mv("/tmp/old", "/tmp/new")

    -- 判断文件是否存在
    if os.isfile("/tmp/file") then
    end

    -- 判断目录是否存在
    if os.isdir("/tmp/dir") then
    end

    -- 匹配遍历文件,*为非递归匹配,**为递归匹配
    for _, file in ipairs(os.match("src/*.c")) do
        print(file)
    end

    -- 匹配遍历目录,*为非递归匹配,**为递归匹配
    for _, file in ipairs(os.match("src/*", true)) do
        print(file)
    end
    
    -- 常用api
    
    -- 抛出异常,立即中断
    raise()

    -- 抛出异常,立即中断,并抛出异常错误信息
    raise("error info")

    -- 抛出异常,立即中断,并抛出异常错误代码
    raise(-1)

    -- 显示输出并换行,支持格式化输出,跟lua的print稍有不同
    print("hello %s", "xmake")

    -- 显示输出不换行
    printf("hello %s", "xmake")

    -- 格式化字符串
    s = format("hello %s", "xmake")
    
    -- 异常捕获api
    
      try
    {
        -- try块,里面抛出异常
        function ()
            raise("error")
        end,

        catch
        {
            -- catch块,捕获异常
            function (errors)
                print(errors)
            end
        }
    }

    -- 获取try块的返回值,如果没有异常的话返回true
    local ok = try
    {
        -- try块,里面抛出异常
        function ()
            -- may be error
            return true
        end
    }

    try
    {
        -- try块,里面抛出异常
        function ()
            raise("error")
        end,

        catch
        {
            -- catch块,捕获异常
            function (errors)
                print(errors)
            end
        },

        finally
        { 
            -- finally 块
            function ()
            end
        }
    }
    
    -- path模块
    
     -- 获取相对路径
    path.relative("/tmp/a")

    -- 获取绝对路径
    path.absolute("src")

    -- 获取目录
    path.directory("/tmp/a")

    -- 获取文件名 test.c
    path.filename("/tmp/test.c")

    -- 获取base名 test
    path.basename("/tmp/test.c")

    -- 获取扩展名
    path.extension("/tmp/test.c")

    -- 拼接路径 /tmp/test.c
    path.join("/tmp", "test.c")
    
    -- io 模块
    
  -- 打开一个写文件
    file = io.open("/tmp/a", "w")

    -- 写文件数据
    file:write("hello")

    -- 写文件格式化行
    file:print("hello %s", "xmake")

    -- 写文件格式化不换行
    file:printf("hello %s", "xmake")

    -- 关闭文件
    file:close()

    -- 序列化写一个lua对象到文件
    io.save("/tmp/a", object)

    -- 反序列化读取一个文件对象
    object = io.load("/tmp/a")

    -- 读取文件数据,并显示
    io.cat("/tmp/a")

    -- 模式替换文件内容, 替换空格字符为 "space"
    io.gsub("/tmp/a", "%s", "space")
    
    -- tostring, tonumber
    
    print("$(tmpdir)")
    add_ldflags("$(shell pkg-config --libs sqlite3)")
    
    -- 如果手动启用了xmake f --demo=y 选项
    if is_option("demo") then
       
        -- 编译demo目录下的代码
        add_subdirs("src/demo")
    end
    
    -- 外置变量
    
    local root = "/tmp"
    set_objectdir(root .. ".objs")
    set_dependir("$(buildir)/.deps")
    local ld_data = io.readfile("./ld/air101_103.ld")
    local ORIGIN, I_SRAM_LENGTH = ld_data:match("I-SRAM : ORIGIN = 0x(%x+) , LENGTH = 0x(%x+)")

skia编译:

add_requires("skia")
target("demo")
 


创作不易,小小的支持一下吧!

简介 XMake 是一个跨平台自动构建工具,支持在各种主流平台上构建项目,类似 cmake、automake、premake,但是更加的方便易用,工程描述语法更简洁直观,支持平台更多,并且集创建、配置、编译、打包、安装、卸载、运行于一体。 支持特性 支持windows、mac、linux、ios、android等平台,自动检测不同平台上的编译工具链(也可手动配置) 编译windows项目采用原生vs的工具链,不需要使用cygwin、mingw(当然这些也支持) 支持自定义平台编译配置,可以很方便的扩展第三方平台支持 采用lua脚本语法描述项目,描述规则简单高效,逻辑规则可灵活修改,并且不会生成相关平台的工程文件,是工程更加简单明了 支持创建模板工程、配置项目、编译项目、运行、打包、安装和卸载等常用功能(后续还会增加:自动生成文档、调试等模块) 支持编译c/c /objc成静态库、动态库、命令行可执行程序(后续还会增加:mac、ios、android的app的生成规则) 提供丰富的工程描述api,使用简单灵活,例如添加编译文件只需(还支持过滤排除): add_files("src/*.c", "src/asm/**.S", "src/*.m") 支持头文件、接口、链接库依赖、类型的自动检测,并可自动生成配置头文件config.h 支持自定义编译配置开关,例如如果在工程描述文件中增加了enable_xxx的开关,那么配置编译的时候就可以手动进行配置来启用它: xmake config --enable_xxx=true 提供一键打包功能,不管在哪个平台上进行打包,都只需要执行一条相同的命令,非常的方便 支持自定义编译工具和规则,例如想要增加对masm/yasm的编译规则,只需将自己写的masm.lua/yasm.lua规则文件,放到当前项目目录下即可。。 支持全局配置,一些常用的项目配置,例如工具链、规则描述等等,都可以进行全局配置,这样就不需要每次编译不同工程,都去配置一遍 除了可以自动检测依赖模块,也支持手动强制配置模块,还有各种编译flags。 简单例子 创建一个c console项目:xmake create -l c  -t 1 console  or xmake create --language=c  --template=1 console 工程描述文件:xmake.luaadd_target("console")     set_kind("binary")     add_files("src/*.c") 配置工程: 这个是可选的步骤,如果只想编译当前主机平台的项目,是可以不用配置的,默认编译release版本。   当然每次配置都会被缓存,不需要每次全部重新配置。xmake f -p iphoneos -m debug or xmake f --ldflags="-Lxxx -lxxx" or xmake f --plat=macosx --arch=x86_64 or xmake config --plat=iphoneos --mode=debug or xmake config --plat=iphonesimulator or xmake config --plat=android --arch=armv7-a --ndk=xxxxx or xmake config --cross=i386-mingw32- --toolchains=/xxx/bin or xmake config --cxflags="-Dxxx -Ixxx" or xmake config --help 编译工程:xmake or xmake -r or xmake --rebuild 运行目标:xmake r console or xmake run console 打包所有:xmake p or xmake p --archs="armv7, arm64" or xmake package or xmake package console or xmake package -o /tmp or xmake package --output=/tmp 安装目标:xmake i or xmake install or xmake install console or xmake install -o /tmp or xmake install --output=/tmp 详细使用方式和参数说明,请参考文档 或者运行:xmake -h or xmake --help or xmake config --help or xmake package --help ... 也可以参考使用xmake的实际项目:TBOX 后续工作 完善打包模块,支持对ios、mac、android的app进行一键打包和签名,生成.ipa、.apk、.app的应用程序文件 完善安装功能,支持对ios、android的app进行安装到设备 实现调试功能 实现自动生成doxygen文档功能 增加一些实用的工程描述api,例如:下载api,可以自动下载缺少的依赖库等等。。 解析automake、cmake的工程,并自动生成xmake的描述文件,实现无缝编译(如果这个实现成功的话,以后移植编译一些开源代码就更方便了) 标签:构建工具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力码力我爱你

创作不易,小小的支持一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值