xmake的簡易學習

文章目錄

      • 1. xmake是什么
      • 2. 一個可執行程序
      • 3. 一個庫文件
      • 4. 遍歷文件用法
      • 5. 第三方庫
        • 3.1 系統安裝庫
        • 3.2 獨立庫
      • 6. 后續

由于前一篇博客的最后說要做一些rknn的優化,其實這個工作很早就完成了,但是我是使用 xmake這個來做我的工程的構建的,不管是出于對之后的博客的鋪墊,還是對 xmake的欣賞和喜歡,我覺得有必要寫這么一篇博客。

1. xmake是什么

相信我們寫C/C++的更多的都知道CMake,也大致知道這個東西在當前跨平臺編譯的地位。或者還會了解其他的,比如:makefileninjia等等。

但是不知道你有沒有像我一樣,在寫CMakeLists.txt的時候,總是吐槽這凌亂的語法,不關心大小寫就算了,然后各種東西又臭又長,尤其是寫面向對象多了以后,就更討厭CMake這丑陋的語法。尤其是看到gopython這些語言中,特別好用方便的包管理的時候,就更嫌棄了。

我也是偶然間看到了xmake的,有中文的文檔,簡潔的語法(如果你有lua語言的基礎,就更喜歡這樣的語法),還有一個特別方便的包管理,我是就自個兒看著文檔學了起來。

后來我自己的github上一些小代碼也都使用xmake進行構建,還有自己本地的gitlab的代碼也都使用xmake了,可能寫的水平不是很高,但帶來的方便是讓我很受用的。

OK,廢話說完,真心希望大家可以看看xmake,也許你也會喜歡上用這個工具。

2. 一個可執行程序

由于xmake官方的文檔已經非常詳細了,而且還有中文的文檔,非常適合我們自學和使用,我就不賣弄知識,就簡單根據自己的使用,寫幾個很簡單的demo來介紹一下xmake的基礎用法。

首先就是一個可執行程序,我還是用最經典的HELLO WORLD來說。

有這樣一個目錄結構:

- src
-- main.cpp
- xmake.lua

就這樣的一個簡單的示例,注意到這里有一個xmake.lua,這個就是我們進行構建的核心。那么我們這個xmake.lua怎么寫?我直接給一個很簡單的demo

-- 設置項目名稱,可有可無
set_project("xmake_exec")
-- 設置支持的編譯模式
add_rules("mode.debug", "mode.release")-- 配置 debug 下的一些編譯選項
if is_mode("debug") then    -- 啟用 debug 時的調試符號set_symbols("debug")-- 禁用優化set_optimize("none")
end-- 配置 release 下的一些編譯選項
if is_mode("release") then-- 隱藏調試符號set_symbols("hidden")-- 設置優化set_optimize("fastest")-- 刪除所有的調試符號set_strip("all")
end-- 將所有的警告都視為錯誤
set_warnings("all", "error")-- 設置 c99 c++11
set_languages("c99", "c++11") -- cxx11-- 添加一些宏定義
-- add_defines("NDEBUG", "_GNU_SOURCE=1")-- 設置包含目錄
-- add_includedirs("/usr/include", "/usr/local/include")-- 設置依賴的庫和目錄
-- add_links("tbox")
-- add_linkdirs("/usr/local/lib", "/usr/lib")-- 添加系統鏈接庫
-- add_syslinks("z", "pthread")-- 添加編譯鏈接的參數
-- add_cxflags("-stdnolib", "-fno-strict-aliasing")
-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true})target("xmake_exec")set_kind("binary")add_files("src/*.cpp")

這里面寫了很多注釋的東西,都是一些暫時沒用上的,可以供后續使用的時候添加。這里的各種“函數”,其實都可以在xmake官方文檔中有詳細的介紹和demo,我肯定沒有作者寫的深入和詳細,所以如果想要了解每一個“函數”的作用,還請認真看一下。

我這里直接說target這個部分。

顧名思義,target就是目標,也就是我們當前這個xmake.lua所要構建的目標,只需要上述那么簡單的三行就可以搞定,我們可以對應的理解CMake中的:

add_executable(xmake_exec src/main.cpp)

當然,如果你的文件特別多的時候,你就只能使用CMakefile(GLOB ...)來實現了,但是xmake就是上述簡單的add_files("src/*.cpp)來實現,是不是很優雅,尤其是你在Linux下使用shell命令習慣了之后的寫法?

題外話,我覺得xmake使用的特別舒服的一點就是,它能讓你覺得“就應該是這樣的嘛”,而不是CMake那樣很繁瑣且難用的方式。

3. 一個庫文件

如果只是寫一個可執行程序,那也太沒水平了,只能用來做做測試,那么如何生成一個庫文件?

在這里插入圖片描述

OK,這樣一個目錄結構,有頭文件,有源文件,然后還有我們的xmake.lua,那我們的xmake.lua也很簡單:

-- 設置項目名稱
set_project("xmake_lib")-- 設置版本
set_version("1.0.0")-- 設置xmake的最低要求版本
set_xmakever("2.6.9")-- 設置支持的編譯模式
add_rules("mode.debug", "mode.release")-- 配置 debug 下的一些編譯選項
if is_mode("debug") then    -- 啟用 debug 時的調試符號set_symbols("debug")-- 禁用優化set_optimize("none")
end-- 配置 release 下的一些編譯選項
if is_mode("release") then-- 隱藏調試符號set_symbols("hidden")-- 設置優化set_optimize("fastest")-- 刪除所有的調試符號set_strip("all")
end-- 將所有的警告都視為錯誤
set_warnings("all", "error")-- 設置 c99 c++11
set_languages("c99", "c++11") -- cxx11-- 添加一些宏定義
add_defines("DREAMSKY_EXPORTS")-- 設置包含目錄
-- add_includedirs("/usr/include", "/usr/local/include")-- 設置依賴的庫和目錄
-- add_links("tbox")
-- add_linkdirs("/usr/local/lib", "/usr/lib")-- 添加系統鏈接庫
-- add_syslinks("z", "pthread")-- 添加編譯鏈接的參數
-- add_cxflags("-stdnolib", "-fno-strict-aliasing")
-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true})target("xmake_lib")    -- 這樣可以在外部直接傳參,從而構建需要的set_kind("$(kind)")-- set_kind("shared")-- set_kind("static")-- 如果需要外部配置是否需要進行傳參,比如 --var=val 的時候,可以使用-- add_defines("-DTEST=$(var)")add_includedirs("include", {public = true})-- 如果頭文件的目錄比較復雜,那么就需要這樣進行處理-- 通配符include/**.h匹配include目錄及其子目錄的所有.h后綴文件。-- 對于add_headerfiles語句,如果不加括號,則所有文件都會被直接安裝到include文件夾下,-- 目錄結構將會丟失;而括號的作用在于保持括號內的目錄結構。-- 例如a/(b/c.h)安裝后會變成include/b/c.h。-- 而在設置中的prefixdir選項則將所有頭文件放在include的子目錄中。-- 如對于上述設置{prefixdir = "mylib"},a/(b/c.h)安裝后會變成include/mylib/b/c.h-- add_headerfiles("include/(**.h)", {prefixdir = "DreamSky"})add_headerfiles("include/*.h")add_files("src/*.cpp")-- 有時候使用xmake構建的庫需要導出給使用其他構建系統的項目使用,-- 這就需要對應構建工具的配置文件。xmake提供pkg-config配置文件和cmake配置文件的生成。-- 對于需要導出的target,使用如下語句:add_rules("utils.install.pkgconfig_importfiles")add_rules("utils.install.cmake_importfiles")-- 對于頭文件之外的安裝文件,xmake提供了類似的接口add_installfiles,-- 它與add_headerfiles的區別在于,prefixdir將直接放在安裝目錄下而不是include文件夾下。-- 例如文檔安裝可以寫-- add_installfiles("doc/*.md", {prefixdir = "share/doc"})if is_plat("windows") and is_kind("shared") thenprint("windows shared")end-- 有時候,項目生成的庫和二進制不要按約定的bin和lib目錄存放,甚至不需要被安裝。-- 還有時候,安裝的文件需要根據安裝目錄做一定的更改。-- 這時可以使用on_install語句來重載target的安裝過程。例如,將生成的庫文件安裝到xmake_lib文件夾:-- on_install(function (target)--     local libdir = path.join(target:installdir(), "xmake_lib")--     os.mkdir(libdir)--     os.cp(target:targetfile(), libdir)--     local includedir = path.join(target:installdir(), "xmake_lib_include")--     os.mkdir(includedir)--     for _, headerfile in ipairs(target:headerfiles()) do--         os.cp(headerfile, includedir)--     end-- end)-- 編譯安裝命令示例:
-- 清除編譯配置: xmake clean
-- 清除所有:     xmake clean --all
-- 指定編譯器:   xmake f -p mingw       xmake f -p windows
-- 指定編譯模式: xmake f -m debug       xmake f -m release
-- 指定庫類型:   xmake f -k shared      xmake f -k static
-- 指定安裝目錄:  xmake install -o "D:/install/xmake_lib"-- 簡短示例:
-- xmake f -p mingw -m debug -k shared
-- xmake
-- xmake install -o "D:/install/xmake_lib"

我也是加了一些注釋,我覺得似乎都不需要額外的說明了,就很清晰了。

當然新版本的xmake已經支持給so文件加上版本號了,也就是很簡單的:

set_version("1.0.0", {soname = true})

4. 遍歷文件用法

很多時候我們需要寫很小的demo來驗證某個函數,或者某個小算法,好吧,總不能每個文件寫一個xmake工程吧?不僅要新建工程,還得寫xmake.lua,就很麻煩。

能不能我隨意添加文件,然后又能夠根據我的文件名自動生成對應的target,然后每次只需要在工程中新建一個.cpp文件就可以了呢?

當然可以!

假設,有這樣的目錄:

在這里插入圖片描述

以后我要是再隨便增加test_04.cpp,不用改xmake.lua可不可以做到?答案是肯定的。

那這里的xmake.lua就可以這樣寫:

-- 遍歷和生成部分參考:
-- https://github.com/idealvin/coost/blob/master/test/xmake.lua-- 設置項目名稱
set_project("xmake_foreach")-- 設置版本
set_version("1.0.0")-- 設置xmake的最低要求版本
set_xmakever("2.6.9")-- 設置支持的編譯模式
add_rules("mode.debug", "mode.release")-- 配置 debug 下的一些編譯選項
if is_mode("debug") then    -- 啟用 debug 時的調試符號set_symbols("debug")-- 禁用優化set_optimize("none")
end-- 配置 release 下的一些編譯選項
if is_mode("release") then-- 隱藏調試符號set_symbols("hidden")-- 設置優化set_optimize("fastest")-- 刪除所有的調試符號set_strip("all")
end-- 將所有的警告都視為錯誤
set_warnings("all", "error")-- 設置 c99 c++11
set_languages("c99", "c++11") -- cxx11-- 使用函數來遍歷cpp文件夾,后續根據遍歷的結果來處理
function all_tests()local res = {}for _, x in ipairs(os.files("**.cpp")) dolocal item = {}local s = path.filename(x)table.insert(item, s:sub(1, #s - 4))       -- 取文件名來作為target的名字table.insert(item, path.relative(x, "."))  -- 利用path.relative來轉換相對路徑,即將 x 轉換為相對于 . 的相對路徑table.insert(res, item)endreturn res
endfor _, test in ipairs(all_tests()) do
target(test[1])set_kind("binary")-- set_default(false)add_files(test[2])
end

這是直接參考xmake作者的coost來進行實現的,額外說一句,作者的coost庫也很強,而且沒有Boost那么龐大復雜,如果想學習一些編程的思路,可以閱讀這個源碼,還是很容易看明白的。

5. 第三方庫

當然xmake有一個特別好用的倉庫,你添加opencv這些依賴的時候,只需要:

add_requires("opencv")target("test")add_files("src/*.cpp")add_packages("opencv")

就可以了,而且可以自動從網絡上下載相關的庫文件。

3.1 系統安裝庫

當然,如果你系統上已經安裝了這個opencv庫,你就是不想用xmake repo的庫,也是可以的。

add_requires("cmake::OpenCV", {alias = "opencv", system = true})target("test")add_files("src/*.cpp")add_packages("opencv")

是不是很簡單,可以調用cmake的庫,當然xmake支持的可多了,具體的參考官方文檔。

3.2 獨立庫

這些都是安裝的,那么對于我們使用rknn來說,他就是提供了頭文件和庫文件,我們怎么來加入到編譯呢?當然你可以直接將頭文件和庫文件加到target的編譯中來,可是那也太不優雅了,而且工程多了起來就亂。所以我們需要一個優雅的使用方法,有沒有呢?有!

我們可以通過創建一個本地的xmake repo來實現,將他們按照xmake的語法來進行描述,然后就可以在我們的工程中直接使用了,下一篇寫rknn的優化的時候將詳細說如何將rknnrtrga來優雅地寫到我們的xmake repo中。

假設我們已經能將rknnrt按照xmake語法寫好了,并且我們的xmake repo地址是/home/xxx/xmake_repo,那么我們工程中直接就可以:

add_repositories("local-repo /home/xxx/xmake_repo")
add_requires("rknnrt", "librga")target("rknn_engine")add_includedirs("include", {public = true})add_headerfiles("include/(**.h)")add_files("src/**.cpp")add_packages("rknnrt", "librga")

是不是很優雅了?

6. 后續

xmake的官方文檔已經足夠詳細了,我覺得沒有那個水平能超過作者的文檔,只是在自己的使用過程中有一些心得體會,也在自己的githubgitlab和工作中使用了xmake,水平也不算高,如果你也恰好是入門,有一些我也恰好知道的問題,歡迎一起交流。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85573.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85573.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85573.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【ArcGIS微課1000例】0147:Geographic Imager6.2下載安裝教程

文章目錄 一、軟件功能二、下載地址三、安裝教程Geographic Imager地圖工具使Adobe Photoshop空間圖像可以快速高效地工作。它增加了導入,編輯,操作和導出地理空間圖像的工具,例如航空和衛星圖像。Geographic Imager Mac功能非常強大,擁有柵格數據輸出、投影信息修改、基于…

【 java 集合知識 第一篇 】

1.概念 1.1.集合與數組的區別 集合:長度不固定,動態的根據數據添加刪除改變長度,并且只能存入引用類型,讀取采用迭代器或其他方法 數組:長度固定,不可改變,既可以存入基本類型也可以存入引用…

嵌入式開發學習日志(linux系統編程--系統編程之 進程間通信IPC)Day32

一、引言 空間獨立,需要一些操作; 分為三大類: 1、古老的通信方式 無名管道 有名管道 信號 2、IPC對象通信 system v BSD suse fedora kernel.org 消息隊列(用的相對少,這里不討論) …

metersphere不同域名的參數在鏈路測試中如何傳遞?

域名1:https://api.domain1.com 域名2:https://api.domain2.com 域名1的返回參數stteid會作為域名2的入參 步驟: 1)先在metersphere—接口測試—接口定義中創建域名1和域名2的接口 2)接口創建好后,在接口測…

使用Process Explorer、System Informer(Process Hacker)和Windbg工具排查軟件高CPU占用問題

目錄 1、問題現象 2、使用Process Explorer和System Informer(該工具原先叫Process Hacker)查看占用CPU高的線程 3、使用System Informer工具時發現了一個關鍵細節 4、將Windbg附加到軟件進程上,根據System Informer中顯示的線程id到Wind…

Linux(線程概念)

目錄 一 虛擬地址到物理地址的轉換 1. 操作系統如何管理物理內存: 2. 下面來談談虛擬地址如何轉換到物理地址: 3. 補充字段: 二 Linux中的線程 1. 先來說說進程: 2. 線程: 3. 線程相比較于進程的優缺點&#x…

阿里云為何,一個郵箱綁定了兩個賬號

阿里云“幽靈賬號”之謎:同一個郵箱注銷后仍有兩個賬號?深度揭秘成因與終極解決方案! 你是否曾在阿里云上使用同一個郵箱注冊過多個賬號,明明已經**“徹底”注銷了其中一個**,卻驚愕地發現系統里依然**“幽靈般”掛著…

動態規劃-數位DP

今天開始做關于數位DP的問題,首先對于數位DP來說,這類問題難度較大,比較難理解,所以博主也會盡量講的更加詳細一些,來幫助大家更好地理解這里的相關知識。 前置知識: 1.首先對于數位DP來說,主…

總覽四級考試

別被“四級”這個龐然大物嚇到!我們一起拆解它:?? 📍 ??核心認知:四級是一場策略性考試!?? 它不考智商,考的是??基礎英語能力 考試技巧 時間管理??。基礎可以通過努力補,技巧可以…

BSRR對比BRR對比ODR

? 三種操作方式的本質區別 寄存器功能原子操作特點BSRR同時支持置位(1)和復位(0)?? 是單指令完成任意位操作,無競爭風險ODR直接讀寫輸出狀態? 否需"讀-改-寫",多線程/中斷中需關中斷保護BRR只能復位(0)?? 是僅清零功能,無置…

職坐標精選嵌入式AI物聯網開源項目

隨著嵌入式、AI與物聯網技術的深度融合,開源生態已成為開發者構建智能硬件解決方案的核心驅動力。本文將從嵌入式實時操作系統、多模態AI數據集及物聯網接入平臺三大維度切入,系統性梳理技術選型要點與實踐路徑。在嵌入式領域,重點解析低功耗…

Ubuntu系統 | 本地部署ollama+deepseek

1、Ollama介紹 Ollama是由Llama開發團隊推出的開源項目,旨在為用戶提供高效、靈活的本地化大型語言模型(LLM)運行環境。作為Llama系列模型的重要配套工具,Ollama解決了傳統云服務對計算資源和網絡連接的依賴問題,讓用戶能夠在個人電腦或私有服務器上部署和運行如Llama 3等…

【數據庫】關系數據庫標準語言-SQL(金倉)下

4、數據查詢 語法&#xff1a; SELECT [ALL | DISTINCT] <目標列表達式> [,<目標列表達式>] … FROM <表名或視圖名>[, <表名或視圖名> ] … [ WHERE <條件表達式> ] [ GROUP BY <列名1> [ HAVING <條件表達式> ] ] [ ORDER BY <…

基于YOLO-NAS-Pose的無人機象群姿態估計:群體行為分析的突破

【導讀】 應對氣候變化對非洲象的生存威脅&#xff0c;本研究創新采用無人機航拍結合AI姿態分析技術&#xff0c;突破傳統觀測局限。團隊在肯尼亞桑布魯保護區對比測試DeepLabCut與YOLO-NAS-Pose兩種模型&#xff0c;首次將后者引入野生動物研究。通過檢測象群頭部、脊柱等關鍵…

8.RV1126-OPENCV 視頻中添加LOGO

一.視頻中添加 LOGO 圖像大體流程 首先初始化VI,VENC模塊并使能&#xff0c;然后創建兩個線程&#xff1a;1.把LOGO灰度化&#xff0c;然后獲取VI原始數據&#xff0c;其次把VI數據Mat化并創建一個感興趣區域&#xff0c;最后把LOGO放感興趣區域里并把數據發送給VENC。2.專門獲…

AI+3D 視覺重塑塑料袋拆垛新范式:遷移科技解鎖工業自動化新高度

在工業自動化浪潮席卷全球的當下&#xff0c;倉儲物流環節的效率與精準度成為企業降本增效的關鍵戰場。其中&#xff0c;塑料袋拆垛作為高頻、高重復性的作業場景&#xff0c;傳統人工或機械臂操作面臨著諸多挑戰。遷移科技&#xff0c;作為行業領先的 3D 工業相機和 3D 視覺系…

MATLAB實戰:視覺伺服控制實現方案

以下是一個基于MATLAB的視覺伺服控制項目實現方案&#xff0c;結合實時圖像處理、目標跟蹤和控制系統設計。我們將使用模擬環境進行演示&#xff0c;但代碼結構可直接應用于真實硬件。 系統架構 圖像采集 → 目標檢測 → 誤差計算 → PID控制器 → 執行器控制 完整代碼實現 …

RequestRateLimiterGatewayFilterFactory

一、功能說明 RequestRateLimiterGatewayFilterFactory 是 Spring Cloud Gateway 的流量控制組件&#xff0c;用于實現 API 請求速率限制&#xff0c;核心功能包括&#xff1a; 限制單位時間內的請求數量&#xff08;如每秒10次&#xff09;防止服務被突發流量擊垮&#xff0…

鴻蒙倉頡語言開發實戰教程:購物車頁面

大家上午好&#xff0c;倉頡語言商城應用的開發進程已經過半&#xff0c;不知道大家通過這一系列的教程對倉頡開發是否有了進一步的了解。今天要分享的購物車頁面&#xff1a; 看到這個頁面&#xff0c;我們首先要對它簡單的分析一下。這個頁面一共分為三部分&#xff0c;分別是…

AXURE安裝+漢化-Windows

安裝網站&#xff1a;https://www.axure.com/release-history/rp9 Axure中文漢化包下載地址 鏈接:https://pan.baidu.com/s/1U62Azk8lkRPBqWAcrJMFew?pwd5418 提取碼:5418 下載完成之后&#xff0c;crtlc lang文件夾 到下載的Axure路徑下 雙擊點進這個目錄里面。ctrlv把lan…