xmake vs cmake對比分析

首先,不得不認可,cmake很強大,發展了這麼多年,整個生態已經至關完善,功能也至關豐富,這點xmake目前是比不了的。html

當初我作xmake的目的,也並非爲了徹底替代cmake,這沒啥意義,只是以爲cmake的語法和易用性知足不了我,我仍是更喜歡更簡單直觀的方式去描述和維護項目,在不一樣平臺下提供近乎一致的使用體驗。linux

所以,xmake的語法描述和使用體驗仍是很是好的,這也是xmake最大的亮點之一,我在這塊設計上作了不少改進,爲了下降學習和項目維護門檻,也更容易快速上手。android

在這裏,我只拿xmake中一些比較佔優的特性去跟cmake做對比,僅僅只是爲了突出說明xmake在某些方面的優點和易用性,並無任何貶低cmake的意思。git

若是你們看完此篇文章的對比分析,以爲xmake確實好用,可以知足部分項目維護上的需求,解決一些痛點,提升項目維護效率的話,不妨試試體驗下。github

特性支持

我先羅列下構建工具的一些主要基礎特性對比,大部分特性二者都是支持的,而xmake的優點主要仍是在:語法、包倉庫管理、構建體驗上macos

feature xmake cmake
語法 Lua語法,簡潔直觀,快速上手 DSL,複雜,學習成本高
自建包倉庫管理 多倉庫支持,可自建私有包倉庫 不支持
第三方包管理集成 vcpkg/conan/brew vcpkg/conan/其餘
構建行爲 直接構建,無依賴 生成工程文件,調用第三方構建工具
依賴 僅依賴編譯工具鏈 依賴編譯工具鏈+第三方構建工具
查找依賴包 支持 支持
編譯器特性檢測 支持 支持
工程文件生成 支持 支持
跨平臺 支持 支持
IDE/編輯器插件 支持 支持
模塊和插件擴展 支持 支持

語法對比

空工程

xmake
target("test")
    set_kind("binary")
    add_files("src/main.c")
複製代碼
cmake
add_executable(test "")
target_sources(test PRIVATE src/main.c)
複製代碼

源文件添加

xmake

xmake支持通配符匹配的方式,添加一批源文件進來,*.c匹配當前目錄下全部文件,**.c匹配遞歸目錄下全部文件。windows

這種方式,對於日常項目中新增一些文件編譯,就不須要每次修改xmake.lua了,自動同步,能夠節省很多時間。架構

target("test")
    set_kind("binary")
    add_files("src/*.c")
    add_files("test/*.c", "example/**.cpp")
複製代碼

xmake的add_files()是很是靈活強大的,不只能夠支持各類不一樣類型源文件添加,還能夠在添加的同時排除一些指定文件。iphone

好比:遞歸添加src下的全部c文件,可是不包括src/impl/下的全部c文件。編輯器

add_files("src/**.c|impl/*.c")
複製代碼

更多關於這個接口的使用說明,見相關文檔:add_files接口文檔

cmake

cmake彷佛須要先遍歷文件列表到對應變量,再添加到對應的target中去才行,稍微繁瑣些。

add_executable(test "")
file(GLOB SRC_FILES "src/*.c")
file(GLOB TEST_FILES "test/*.c")
file(GLOB_RECURSE EXAMPLE_FILES "example/*.cpp")
target_sources(test PRIVATE 
    ${SRC_FILES}
    ${TEST_FILES}
    ${EXAMPLE_FILES}
)
複製代碼

條件編譯

xmake
target("test")
    set_kind("binary")
    add_files("src/main.c")
    if is_plat("macosx", "linux") then
        add_defines("TEST1", "TEST2")
    end
    if is_plat("windows") and is_mode("release") then
        add_cxflags("-Ox", "-fp:fast")
    end
複製代碼
cmake
add_executable(test "")
if (APPLE OR LINUX)
    target_compile_definitions(test PRIVATE TEST1 TEST2)
endif()
if (WIN32)
    target_compile_options(test PRIVATE $<$<CONFIG:Release>:-Ox -fp:fast>)
endif()
target_sources(test PRIVATE
    src/main.c
)
複製代碼

自定義腳本

xmake

xmake能夠在編譯構建的不一樣階段(包括編譯、安裝、打包、運行),方便的插入一段自定義腳原本處理本身的邏輯,好比編譯完成以後打印一行輸出:

target("test")
    set_kind("binary")
    add_files("src/*.c")
    after_build(function (target)
        print("target file: %s", target:targetfile())
    end)
複製代碼

或者自定義運行和安裝邏輯:

target("test")
    set_kind("binary")
    add_files("src/*.c")
    on_install(function (target)
        os.cp(target:targetfile(), "/usr/local/bin")
    end)
    on_run(function (target)
        os.run("%s --help", target:targetfile())
    end)
複製代碼

在自定義腳本中,用戶能夠寫各類複雜腳本,經過import接口,能夠導入各類擴展模塊來使用。

target("test")
    set_kind("binary")
    add_files("src/*.c")
    before_build(function (target)
        import("net.http")
        import("devel.git")
        http.download("https://xmake.io", "/tmp/index.html")
        git.clone("git@github.com:tboox/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"})
    end)
複製代碼
cmake

cmake也能夠經過add_custom_command來實現:

add_executable(test "")
target_sources(test PRIVATE src/main.c)
add_custom_command(TARGET test POST_BUILD
    COMMENT "hello cmake!"
)
複製代碼

不過看了下,不一樣階段,自定義腳本的方式並不徹底同樣,add_custom_command只能用於構建階段的自定義,若是要對安裝階段進行自定義,得:

install(SCRIPT cmake_install.cmake)
複製代碼

而且只能整個替換安裝邏輯,沒法對安裝先後的實現一些自定義邏輯,另外像打包、運行等其餘階段的自定義彷佛不支持。

構建方式

編譯默認平臺

xmake

一般狀況,編譯默認平臺執行敲xmake,執行構建期間,xmake不會依賴其餘第三方構建工具,連make也不依賴,也不會生成IDE/Makefile文件, 而是直接調用的編譯工具鏈進行編譯,默認會根據cpu核數自動開啓多任務加速構建。

xmake
複製代碼
cmake

而cmake的一般是先生成對應IDE/Makefile等第三方構建文件,而後調用make/msbuild等第三方構建工具去編譯。

cmake .
cmake --build .
複製代碼

編譯指定平臺

xmake

xmake能夠以近乎一致的方式快速切換不一樣平臺和架構來編譯。

xmake f -p [iphoneos|android|linux|windows|mingw] -a [arm64|armv7|i386|x86_64]
xmake
複製代碼
cmake

cmake彷佛對不一樣平臺和架構的編譯配置方式,差別性仍是有些的,須要花點時間研究下才行。

cmake -G Xcode -DIOS_ARCH="arm64" .
cmake --build .
複製代碼
cmake -G "Visual Studio 9 2008" -A x64
cmake --build .
複製代碼

像android平臺編譯,配置ndk的方式彷佛也很繁瑣。

cmake .. -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK%\build\cmake\android.toolchain.cmake -DCMAKE_SYSTEM_NAME="Android" -DANDROID_NDK=%ANDROID_NDK% -DANDROID_TOOLCHAIN=clang -DANDROID_PLATFORM=android-24
複製代碼

安裝目標

xmake
xmake install 
複製代碼
cmake
cmake -P cmake_install.cmake
複製代碼

運行目標

xmake

大部分狀況下,xmake不須要寫自定義腳本就能夠直接加載運行編譯生成的目標程序。

xmake run 
複製代碼
cmake

cmake我沒找到能夠快速運行指定目標程序的方式,可是應該能夠經過寫一個自定義腳本去加載運行它。

cmake -P cmake_run.cmake
複製代碼

依賴支持

查找依賴庫

xmake

xmake也是支持跟cmake的find_package相似的接口去直接查找系統庫,而後集成使用,找到庫後,會自動追加includedirs, links, linkdirs等相關設置。

target("test")
    set_kind("binary")
    add_files("src/*.c")
    on_load(function (target)
        target:add(find_packages("openssl", "zlib"))
    end)
複製代碼
cmake
add_executable(test main.c)

find_package(OpenSSL REQUIRED)
if (OpenSSL_FOUND)
    target_include_directories(test ${OpenSSL_INCLUDE_DIRS})
    target_link_libraries(test ${OpenSSL_LIBRARIES})
endif() 

find_package(Zlib REQUIRED)
if (Zlib_FOUND)
    target_include_directories(test ${Zlib_INCLUDE_DIRS})
    target_link_libraries(test ${Zlib_LIBRARIES})
endif() 
複製代碼

使用第三方庫(Conan)

xmake

xmake會自動調用conan工具去下載安裝openssl庫,而後集成使用,只須要執行xmake命令便可完成編譯。

add_requires("conan::OpenSSL/1.0.2n@conan/stable", {alias = "openssl"}) 
target("test")
    set_kind("binary")
    add_files("src/*.c")
    add_packages("openssl")
複製代碼
cmake
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
   message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
   file(DOWNLOAD "https://github.com/conan-io/cmake-conan/raw/v0.14/conan.cmake"
                 "${CMAKE_BINARY_DIR}/conan.cmake")
endif()

include(${CMAKE_BINARY_DIR}/conan.cmake)

conan_cmake_run(REQUIRES OpenSSL/1.0.2n@conan/stable
                BASIC_SETUP 
                BUILD missing)

add_executable(test main.c)
target_link_libraries(main ${CONAN_LIBS})
複製代碼

使用內建包倉庫

xmake

xmake有自建的包倉庫,雖然如今裏面包還不是不少,但後期會不斷完善:xmake-repo

咱們只須要添加相關須要的包就好了,很是方便,而且支持多版本選擇和語義版本控制哦。

甚至有些經常使用包支持多平臺集成使用,例如:zlib庫等,即便編譯android/iphoneos/mingw等平臺,也均可以直接下載安裝使用。

add_requires("libuv master", "ffmpeg", "zlib 1.20.*")
add_requires("tbox >1.6.1", {optional = true, debug = true})
target("test")
    set_kind("shared")
    add_files("src/*.c")
    add_packages("libuv", "ffmpeg", "tbox", "zlib")
複製代碼

執行xmake命令後,會去自動從倉庫中下載對應的包而後編譯安裝,集成連接進來,效果以下:

除了官方的包倉庫,用戶也能夠本身建立多個私有倉庫,用來集成使用一些私有包,這對於公司內部項目的依賴維護仍是頗有幫助的。

咱們只須要在xmake.lua加上本身的私有倉庫地址就好了:

add_repositories("my-repo git@github.com:myrepo/xmake-repo.git")
複製代碼

或者直接命令行添加:

xmake repo --add my-repo git@github.com:myrepo/xmake-repo.git
複製代碼

關於這塊的詳細說明能夠看下相關文檔:

最後,附帶一張xmake的依賴包管理架構圖:

cmake

這塊我沒看到cmake有支持,不過cmake我用得並很少,若是有寫的不對的地方,你們能夠指正。

原文出處:tboox.org/cn/2019/05/…

相關文章
相關標籤/搜索