builtin_modules.html 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>xmake</title>
  6. <link rel="icon" href="/assets/img/favicon.ico">
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  8. <meta name="description" content="Description">
  9. <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  10. <link href="/assets/npm/github-markdown/github-markdown.min.css" rel="stylesheet">
  11. <style>
  12. .markdown-body {
  13. box-sizing: border-box;
  14. min-width: 200px;
  15. max-width: 980px;
  16. margin: 0 auto;
  17. padding: 45px;
  18. }
  19. @media (max-width: 767px) {
  20. .markdown-body {
  21. padding: 15px;
  22. }
  23. }
  24. </style>
  25. </head>
  26. <body>
  27. <article class="markdown-body">
  28. <h4>This is a mirror page, please see the original page: </h4><a href="https://xmake.io/#/manual/builtin_modules">https://xmake.io/#/manual/builtin_modules</a>
  29. <div id="wwads-panel" class="wwads-cn wwads-vertical wwads-sticky" data-id="239" style="max-width:180px;bottom:20px;right:20px;width:200px;height:260px;background:#fff;position:fixed"></div>
  30. </br>
  31. <script type="text/javascript" charset="UTF-8" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
  32. <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
  33. <style>
  34. #carbonads {
  35. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
  36. Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
  37. }
  38. #carbonads {
  39. display: flex;
  40. max-width: 330px;
  41. background-color: hsl(0, 0%, 98%);
  42. box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
  43. }
  44. #carbonads a {
  45. color: inherit;
  46. text-decoration: none;
  47. }
  48. #carbonads a:hover {
  49. color: inherit;
  50. }
  51. #carbonads span {
  52. position: relative;
  53. display: block;
  54. overflow: hidden;
  55. }
  56. #carbonads .carbon-wrap {
  57. display: flex;
  58. }
  59. .carbon-img {
  60. display: block;
  61. margin: 0;
  62. line-height: 1;
  63. }
  64. .carbon-img img {
  65. display: block;
  66. }
  67. .carbon-text {
  68. font-size: 13px;
  69. padding: 10px;
  70. line-height: 1.5;
  71. text-align: left;
  72. }
  73. .carbon-poweredby {
  74. display: block;
  75. padding: 8px 10px;
  76. background: repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4);
  77. text-align: center;
  78. text-transform: uppercase;
  79. letter-spacing: .5px;
  80. font-weight: 600;
  81. font-size: 9px;
  82. line-height: 1;
  83. }
  84. </style>
  85. <p>Used in script code such as custom scripts, plug-in scripts, task scripts, platform extensions, template extensions, etc., that is, in code blocks like the following, you can use these module interfaces:</p>
  86. <pre><code class="lang-lua">on_run(function (target)
  87. print("hello xmake!")
  88. end)
  89. </code></pre>
  90. <p>!> In order to ensure that the description scope of the outer layer is as simple and secure as possible, it is generally not recommended to use the interface and module operation api in this domain. Therefore, most module interfaces can only be used in the script domain to implement complex functions. </br><br>Of course, a small number of read-only built-in interfaces can still be used in the description scope, as shown in the following table:</p>
  91. <p>An example of using an interface call in a description scope is as follows, generally only for conditional control:</p>
  92. <pre><code class="lang-lua">-- Scan all subdirectories under the current xmake.lua directory, defining a task task with the name of each directory
  93. for _, taskname in ipairs(os.dirs("*"), path.basename) do
  94. task(taskname)
  95. on_run(function ()
  96. end)
  97. end
  98. </code></pre>
  99. <p>The script scope and description scope mentioned above mainly refer to:</p>
  100. <pre><code class="lang-lua">-- description scope
  101. target("test")
  102. -- description scope
  103. set_kind("static")
  104. add_files("src/*.c")
  105. on_run(function (target)
  106. -- Script domain
  107. end)
  108. -- description scope
  109. </code></pre>
  110. <h3 id="import">import</h3>
  111. <h4 id="importingextensionblocks">Importing extension blocks</h4>
  112. <p>Import is mainly used to import xmake&#39;s extension class library and some custom class library modules, generally used to:</p>
  113. <ul>
  114. <li>Custom script (<a href="/mirror/manual/project_target.html#targeton_build">on_build</a>, <a href="/mirror/manual/project_target.html#targeton_run">on_run</a> ..)</li>
  115. <li>Plugin development</li>
  116. <li>Template development</li>
  117. <li>Platform extension</li>
  118. <li>Custom task task</li>
  119. </ul>
  120. <p>The import mechanism is as follows:</p>
  121. <ol>
  122. <li>Import from the current script directory first</li>
  123. <li>Import from the extended class library</li>
  124. </ol>
  125. <p>Imported grammar rules:</p>
  126. <p>Class library path rules based on <code>.</code>, for example:</p>
  127. <p>Import core core extension module</p>
  128. <pre><code class="lang-lua">import("core.base.option")
  129. import("core.base.task")
  130. function main()
  131. -- Get parameter options
  132. print(option.get("version"))
  133. -- Run tasks and plugins
  134. task.run("hello")
  135. end
  136. </code></pre>
  137. <p>Import the custom module in the current directory:</p>
  138. <p>Directory Structure:</p>
  139. <pre><code>Plugin
  140. - xmake.lua
  141. - main.lua
  142. - modules
  143. - hello1.lua
  144. - hello2.lua
  145. </code></pre><p>Import modules in main.lua</p>
  146. <pre><code class="lang-lua">import("modules.hello1")
  147. import("modules.hello2")
  148. </code></pre>
  149. <p>After importing, you can directly use all the public interfaces inside. The private interface is marked with the <code>_</code> prefix, indicating that it will not be exported and will not be called externally. .</p>
  150. <p>In addition to the current directory, we can also import libraries in other specified directories, for example:</p>
  151. <pre><code class="lang-lua">import("hello3", {rootdir = "/home/xxx/modules"})
  152. </code></pre>
  153. <p>To prevent naming conflicts, you can also specify an alias after import:</p>
  154. <pre><code class="lang-lua">import("core.platform.platform", {alias = "p"})
  155. function main()
  156. -- So we can use p to call the plats interface of the platform module to get a list of all the platforms supported by xmake.
  157. utils.dump(p.plats())
  158. end
  159. </code></pre>
  160. <p>Import can not only import the class library, but also import and import as inheritance, realize the inheritance relationship between modules.</p>
  161. <pre><code class="lang-lua">import("xxx.xxx", {inherit = true})
  162. </code></pre>
  163. <p>This is not a reference to the module, but all the public interfaces of the module imported, so that it will be merged with the interface of the current module to achieve inheritance between modules.</p>
  164. <p>Version 2.1.5 adds two new properties: `import("xxx.xxx", {try = true, anonymous = true}).</p>
  165. <p>If the try is true, the imported module does not exist, only return nil, and will not interrupt xmake after throwing an exception.<br>If anonymous is true, the imported module will not introduce the current scope, only the imported object reference will be returned in the import interface.</p>
  166. <h4 id="customextensionmodule">Custom extension module</h4>
  167. <p>Through import, we can import not only many built-in extension modules of xmake, but also user-defined extension modules.</p>
  168. <p>Just put your own module in the project directory and import it according to the import method described above.</p>
  169. <p>So, what if you want to define a module? xmake has a set of convention rules for module writing specifications, and does not follow Lua&#39;s native require import mechanism, and there is no need to use return in the module to return it globally.</p>
  170. <p>If we have a module file foo.lua, its content is as follows:</p>
  171. <pre><code class="lang-lua">function _foo(a, b)
  172. return a + b
  173. end
  174. function add(a, b)
  175. _foo(a, b)
  176. end
  177. function main(a, b)
  178. add(a, b)
  179. end
  180. </code></pre>
  181. <p>Among them main is the entry function, optional, if set, the module foo can be called directly, for example:</p>
  182. <pre><code class="lang-lua">import("foo")
  183. foo(1, 2)
  184. </code></pre>
  185. <p>Or directly like this:</p>
  186. <pre><code class="lang-lua">import("foo")(1, 2)
  187. </code></pre>
  188. <p>Others without underscore are public module interface functions, such as add.</p>
  189. <pre><code class="lang-lua">import("foo")
  190. foo.add(1, 2)
  191. </code></pre>
  192. <p>The underscore prefixed <code>_foo</code> is a private function that is used internally by the module and is not exported, so users cannot call it outside.</p>
  193. <h3 id="inherit">inherit</h3>
  194. <h4 id="importandinheritbaseclassmodules">Import and inherit base class modules</h4>
  195. <p>This is equivalent to the <code>inherit</code> mode of the <a href="#import">import</a> interface, which is:</p>
  196. <pre><code class="lang-lua">import("xxx.xxx", {inherit = true})
  197. </code></pre>
  198. <p>With the <code>inherit</code> interface, it will be more concise:</p>
  199. <pre><code class="lang-lu">Inherit("xxx.xxx")
  200. </code></pre>
  201. <p>For an example, see the script in the xmake tools directory: <a href="#https://github.com/xmake-io/xmake/blob/master/xmake/tools/clang.lua">clang.lua</a></p>
  202. <p>This is part of the clang tool module that inherits gcc.</p>
  203. <h3 id="trycatchfinally">try-catch-finally</h3>
  204. <h4 id="exceptioncapture">Exception capture</h4>
  205. <p>Lua native does not provide try-catch syntax to catch exception handling, but provides interfaces such as <code>pcall/xpcall</code> to execute lua functions in protected mode.</p>
  206. <p>Therefore, the capture mechanism of the try-catch block can be implemented by encapsulating these two interfaces.</p>
  207. <p>We can look at the packaged try-catch usage first:</p>
  208. <pre><code class="lang-lua">try
  209. {
  210. -- try code block
  211. function ()
  212. error("error message")
  213. end,
  214. -- catch code block
  215. catch
  216. {
  217. -- After an exception occurs, it is executed
  218. function (errors)
  219. print(errors)
  220. end
  221. }
  222. }
  223. </code></pre>
  224. <p>In the above code, an exception is thrown inside the try block, and an error message is thrown, caught in the catch, and the error message is output.</p>
  225. <p>And finally processing, this role is for the <code>try{}</code> code block, regardless of whether the execution is successful, will be executed into the finally block</p>
  226. <p>In other words, in fact, the above implementation, the complete support syntax is: <code>try-catch-finally</code> mode, where catch and finally are optional, according to their actual needs.</p>
  227. <p>E.g:</p>
  228. <pre><code class="lang-lua">try
  229. {
  230. -- try code block
  231. function ()
  232. error("error message")
  233. end,
  234. -- catch code block
  235. catch
  236. {
  237. -- After an exception occurs, it is executed
  238. function (errors)
  239. print(errors)
  240. end
  241. },
  242. -- finally block
  243. finally
  244. {
  245. -- Finally will be executed here
  246. function (ok, errors)
  247. -- If there is an exception in try{}, ok is true, errors is the error message, otherwise it is false, and error is the return value in try
  248. end
  249. }
  250. }
  251. </code></pre>
  252. <p>Or only the finally block:</p>
  253. <pre><code class="lang-lua">try
  254. {
  255. -- try code block
  256. function ()
  257. return "info"
  258. end,
  259. -- finally block
  260. finally
  261. {
  262. -- Since there is no exception in this try code, ok is true and errors is the return value: "info"
  263. function (ok, errors)
  264. end
  265. }
  266. }
  267. </code></pre>
  268. <p>Processing can get the normal return value in try in finally, in fact, in the case of only try, you can also get the return value:</p>
  269. <pre><code class="lang-lua">-- If no exception occurs, result is the return value: "xxxx", otherwise nil
  270. local result = try
  271. {
  272. function ()
  273. return "xxxx"
  274. end
  275. }
  276. </code></pre>
  277. <p>In xmake&#39;s custom scripting and plugin development, it is also based entirely on this exception catching mechanism.</p>
  278. <p>This makes the development of the extended script very succinct and readable, eliminating the cumbersome <code>if err ~= nil then</code> return value judgment. When an error occurs, xmake will directly throw an exception to interrupt, and then highlight the detailed error. information.</p>
  279. <p>E.g:</p>
  280. <pre><code class="lang-lua">target("test")
  281. set_kind("binary")
  282. add_files("src/*.c")
  283. -- After the ios program is compiled, the target program is ldid signed
  284. after_build(function (target))
  285. os.run("ldid -S %s", target:targetfile())
  286. end
  287. </code></pre>
  288. <p>Only one line <code>os.run</code> is needed, and there is no need to return a value to determine whether it runs successfully. After the operation fails, xmake will automatically throw an exception, interrupt the program and prompt the error.</p>
  289. <p>If you want to run xmake without running interrupts directly after running, you can do it yourself.Add a try and you will be fine:</p>
  290. <pre><code class="lang-lua">target("test")
  291. set_kind("binary")
  292. add_files("src/*.c")
  293. after_build(function (target))
  294. try
  295. {
  296. function ()
  297. os.run("ldid -S %s", target:targetfile())
  298. end
  299. }
  300. end
  301. </code></pre>
  302. <p>If you want to capture the error message, you can add a catch:</p>
  303. <pre><code class="lang-lua">target("test")
  304. set_kind("binary")
  305. add_files("src/*.c")
  306. after_build(function (target))
  307. try
  308. {
  309. function ()
  310. os.run("ldid -S %s", target:targetfile())
  311. end,
  312. catch
  313. {
  314. function (errors)
  315. print(errors)
  316. end
  317. }
  318. }
  319. end
  320. </code></pre>
  321. <p>However, in general, write custom scripts in xmake, do not need to manually add try-catch, directly call a variety of api, after the error, let xmake default handler to take over, directly interrupted. .</p>
  322. <h3 id="pairs">pairs</h3>
  323. <h4 id="usedtotraversethedictionary">Used to traverse the dictionary</h4>
  324. <p>This is lua&#39;s native built-in api. In xmake, it has been extended in its original behavior to simplify some of the daily lua traversal code.</p>
  325. <p>First look at the default native notation:</p>
  326. <pre><code class="lang-lua">local t = {a = "a", b = "b", c = "c", d = "d", e = "e", f = "f"}
  327. for key, val in pairs(t) do
  328. print("%s: %s", key, val)
  329. end
  330. </code></pre>
  331. <p>This is sufficient for normal traversal operations, but if we get the uppercase for each of the elements it traverses, we can write:</p>
  332. <pre><code class="lang-lua">for key, val in pairs(t, function (v) return v:upper() end) do
  333. print("%s: %s", key, val)
  334. end
  335. </code></pre>
  336. <p>Even pass in some parameters to the second <code>function</code>, for example:</p>
  337. <pre><code class="lang-lua">for key, val in pairs(t, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
  338. print("%s: %s", key, val)
  339. end
  340. </code></pre>
  341. <h3 id="ipairs">ipairs</h3>
  342. <h4 id="fortraversingarrays">for traversing arrays</h4>
  343. <p>This is lua&#39;s native built-in api. In xmake, it has been extended in its original behavior to simplify some of the daily lua traversal code.</p>
  344. <p>First look at the default native notation:</p>
  345. <pre><code class="lang-lua">for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}) do
  346. print("%d %s", idx, val)
  347. end
  348. </code></pre>
  349. <p>The extension is written like the <a href="#pairs">pairs</a> interface, for example:</p>
  350. <pre><code class="lang-lua">for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v) return v:upper() end) do
  351. print("%d %s", idx, val)
  352. end
  353. for idx, val in ipairs({"a", "b", "c", "d", "e", "f"}, function (v, a, b) return v:upper() .. a .. b end, "a", "b") do
  354. print("%d %s", idx, val)
  355. end
  356. </code></pre>
  357. <p>This simplifies the logic of the <code>for</code> block code. For example, if I want to traverse the specified directory and get the file name, but not including the path, I can simplify the writing by this extension:</p>
  358. <pre><code class="lang-lua">for _, filename in ipairs(os.dirs("*"), path.filename) do
  359. -- ...
  360. end
  361. </code></pre>
  362. <h3 id="print">print</h3>
  363. <h4 id="wrappingprintterminallog">Wrapping print terminal log</h4>
  364. <p>This interface is also the native interface of lua. xmake is also extended based on the original behavior, and supports: formatted output, multivariable output.</p>
  365. <p>First look at the way native support:</p>
  366. <pre><code class="lang-lua">print("hello xmake!")
  367. print("hello", "xmake!", 123)
  368. </code></pre>
  369. <p>And also supports extended formatting:</p>
  370. <pre><code class="lang-lua">print("hello %s!", "xmake")
  371. print("hello xmake! %d", 123)
  372. </code></pre>
  373. <p>Xmake will support both types of writing at the same time, and the internal will automatically detect and select the output behavior.</p>
  374. <h3 id="printf">printf</h3>
  375. <h4 id="nolineprintingterminallog">No line printing terminal log</h4>
  376. <p>Like the <a href="#print">print</a> interface, the only difference is that it doesn&#39;t wrap.</p>
  377. <h3 id="cprint">cprint</h3>
  378. <h4 id="wrapcolorprintterminallog">Wrap color print terminal log</h4>
  379. <p>The behavior is similar to <a href="#print">print</a>, the difference is that this interface also supports color terminal output, and supports <code>emoji</code> character output.</p>
  380. <p>E.g:</p>
  381. <pre><code class="lang-lua"> cprint(&#39;${bright}hello xmake&#39;)
  382. cprint(&#39;${red}hello xmake&#39;)
  383. cprint(&#39;${bright green}hello ${clear}xmake&#39;)
  384. cprint(&#39;${blue onyellow underline}hello xmake${clear}&#39;)
  385. cprint(&#39;${red}hello ${magenta}xmake&#39;)
  386. cprint(&#39;${cyan}hello ${dim yellow}xmake&#39;)
  387. </code></pre>
  388. <p>The results are as follows:</p>
  389. <p><img src="https://tboox.org/static/img/xmake/cprint_colors.png" alt="cprint_colors"></p>
  390. <p>The color-related descriptions are placed in <code>${ }</code>, and you can set several different properties at the same time, for example:</p>
  391. <pre><code> ${bright red underline onyellow}
  392. </code></pre><p>Indicates: highlighted red, background yellow, and with a down line</p>
  393. <p>All of these descriptions will affect the entire entire line of characters. If you only want to display partial color text, you can insert <code>${clear}</code> at the end position to clear the previous color description.</p>
  394. <p>E.g:</p>
  395. <pre><code> ${red}hello ${clear}xmake
  396. </code></pre><p>In this case, only hello is displayed in red, and the others are still normal black display.</p>
  397. <p>Other colors belong to, I will not introduce them here, directly paste the list of attributes in the xmake code:</p>
  398. <pre><code class="lang-lua"> colors.keys =
  399. {
  400. -- Attributes
  401. reset = 0 -- reset attribute
  402. , clear = 0 -- clear attribute
  403. , default = 0 -- default property
  404. , bright = 1 -- highlight
  405. , dim = 2 -- dark
  406. , underline = 4 -- underline
  407. , blink = 5 -- flashing
  408. , reverse = 7 -- reverse color
  409. , hidden = 8 -- hidden text
  410. -- Foreground
  411. , black = 30
  412. , red = 31
  413. , green = 32
  414. , yellow = 33
  415. , blue = 34
  416. , magenta = 35
  417. , cyan = 36
  418. , white = 37
  419. -- Background color
  420. , onblack = 40
  421. , onred = 41
  422. , ongreen = 42
  423. , onyellow = 43
  424. , onblue = 44
  425. , onmagenta = 45
  426. , oncyan = 46
  427. , onwhite = 47
  428. </code></pre>
  429. <p>In addition to color highlighting, if your terminal is under macosx, lion above the system, xmake can also support the display of emoji expressions, for systems that do not support<br>Ignore the display, for example:</p>
  430. <pre><code class="lang-lua"> cprint("hello xmake${beer}")
  431. cprint("hello${ok_hand} xmake")
  432. </code></pre>
  433. <p>The above two lines of code, I printed a classic beer symbol in the homebrew, the following line printed an ok gesture symbol, is not very dazzling. .</p>
  434. <p><img src="https://tboox.org/static/img/xmake/cprint_emoji.png" alt="cprint_emoji"></p>
  435. <p>All emoji emoticons, as well as the corresponding keys in xmake, can be found in <a href="http://www.emoji-cheat-sheet.com/">emoji</a>. .</p>
  436. <p>Version 2.1.7 supports 24-bit true color output, if the terminal supports it:</p>
  437. <pre><code class="lang-lua">import("core.base.colors")
  438. if colors.truecolor() then
  439. cprint("${255;0;0}hello")
  440. cprint("${on;255;0;0}hello${clear} xmake")
  441. cprint("${bright 255;0;0 underline}hello")
  442. cprint("${bright on;255;0;0 0;255;0}hello${clear} xmake")
  443. end
  444. </code></pre>
  445. <p>Xmake&#39;s detection support for truecolor is implemented by the <code>$COLORTERM</code> environment variable. If your terminal supports truecolor, you can manually set this environment variable to tell xmake to enable truecolor support.</p>
  446. <p>It can be enabled and tested with the following command:</p>
  447. <pre><code class="lang-bash">$ export COLORTERM=truecolor
  448. $ xmake --version
  449. </code></pre>
  450. <p>The 2.1.7 version can disable color output with <code>COLORTERM=nocolor</code>.</p>
  451. <h3 id="cprintf">cprintf</h3>
  452. <h4 id="nolinefeedcolorprintterminallog">No line feed color print terminal log</h4>
  453. <p>This interface is similar to <a href="#cprint">cprint</a>, the difference is that it does not wrap the output.</p>
  454. <h3 id="format">format</h3>
  455. <h4 id="formattingastring">Formatting a string</h4>
  456. <p>If you just want to format the string and don&#39;t output it, you can use this interface. This interface is equivalent to the <a href="#stringformat">string.format</a> interface, just a simplified version of the interface name.</p>
  457. <pre><code class="lang-lua">local s = format("hello %s", xmake)
  458. </code></pre>
  459. <h3 id="vformat">vformat</h3>
  460. <h4 id="formattingstringssupportforbuiltinvariableescaping">Formatting strings, support for built-in variable escaping</h4>
  461. <p>This interface is followed by <a href="The #format">format</a> interface is similar, but adds support for the acquisition and escaping of built-in variables.</p>
  462. <pre><code class="lang-lua">local s = vformat("hello %s $(mode) $(arch) $(env PATH)", xmake)
  463. </code></pre>
  464. <h3 id="raise">raise</h3>
  465. <h4 id="throwinganabortprogram">Throwing an abort program</h4>
  466. <p>If you want to interrupt xmake running in custom scripts and plug-in tasks, you can use this interface to throw an exception. If the upper layer does not show the call to <a href="#try-catch-finally">try-catch</a>, xmake will be executed. An error message is displayed.</p>
  467. <pre><code class="lang-lua">if (errors) raise(errors)
  468. </code></pre>
  469. <p>If an exception is thrown in the try block, the error information is captured in catch and finally. See: <a href="#try-catch-finally">try-catch</a></p>
  470. <h3 id="os">os</h3>
  471. <p>The system operation module belongs to the built-in module. It can be called directly by the script scope without using <a href="#import">import</a> import.</p>
  472. <p>This module is also a native module of lua, and xmake has been extended to provide more practical interfaces.</p>
  473. <p>!> Only some readonly interfaces (for example: <code>os.getenv</code>, <code>os.arch</code>) in the os module can be used in the description scope. Other interfaces can only be used in the script domain, for example: <code>os.cp</code>, <code>os .rm</code>etc.</p>
  474. <table>
  475. <thead>
  476. <tr>
  477. <th>Interface</th>
  478. <th>Description</th>
  479. <th>Supported Versions</th>
  480. </tr>
  481. </thead>
  482. <tbody>
  483. <tr>
  484. <td><a href="#oscp">os.cp</a></td>
  485. <td>Copy files or directories</td>
  486. <td>>= 2.0.1</td>
  487. </tr>
  488. <tr>
  489. <td><a href="#osmv">os.mv</a></td>
  490. <td>Move Renamed File or Directory</td>
  491. <td>>= 2.0.1</td>
  492. </tr>
  493. <tr>
  494. <td><a href="#osrm">os.rm</a></td>
  495. <td>Delete files or directory tree</td>
  496. <td>>= 2.0.1</td>
  497. </tr>
  498. <tr>
  499. <td><a href="#ostrycp">os.trycp</a></td>
  500. <td>Try copying files or directories</td>
  501. <td>>= 2.1.6</td>
  502. </tr>
  503. <tr>
  504. <td><a href="#ostrymv">os.trymv</a></td>
  505. <td>Try moving the renamed file or directory</td>
  506. <td>>= 2.1.6</td>
  507. </tr>
  508. <tr>
  509. <td><a href="#ostryrm">os.tryrm</a></td>
  510. <td>Try deleting a file or directory tree</td>
  511. <td>>= 2.1.6</td>
  512. </tr>
  513. <tr>
  514. <td><a href="#oscd">os.cd</a></td>
  515. <td>Go to the specified directory</td>
  516. <td>>= 2.0.1</td>
  517. </tr>
  518. <tr>
  519. <td><a href="#osrmdir">os.rmdir</a></td>
  520. <td>Delete Directory Tree</td>
  521. <td>>= 2.0.1</td>
  522. </tr>
  523. <tr>
  524. <td><a href="#osmkdir">os.mkdir</a></td>
  525. <td>Create the specified directory</td>
  526. <td>>= 2.0.1</td>
  527. </tr>
  528. <tr>
  529. <td><a href="#osisdir">os.isdir</a></td>
  530. <td>Determine if the directory exists</td>
  531. <td>>= 2.0.1</td>
  532. </tr>
  533. <tr>
  534. <td><a href="#osisfile">os.isfile</a></td>
  535. <td>Determine if the file exists</td>
  536. <td>>= 2.0.1</td>
  537. </tr>
  538. <tr>
  539. <td><a href="#osexists">os.exists</a></td>
  540. <td>Determine if a file or directory exists</td>
  541. <td>>= 2.0.1</td>
  542. </tr>
  543. <tr>
  544. <td><a href="#osdirs">os.dirs</a></td>
  545. <td>Traversing to get all directories under the specified directory</td>
  546. <td>>= 2.0.1</td>
  547. </tr>
  548. <tr>
  549. <td><a href="#osfiles">os.files</a></td>
  550. <td>Traversing to get all the files in the specified directory</td>
  551. <td>>= 2.0.1</td>
  552. </tr>
  553. <tr>
  554. <td><a href="#osfiledirs">os.filedirs</a></td>
  555. <td>Traversing to get all files or directories under the specified directory</td>
  556. <td>>= 2.0.1</td>
  557. </tr>
  558. <tr>
  559. <td><a href="#osexit">os.exit</a></td>
  560. <td>Exit the program</td>
  561. <td>>= 2.3.1</td>
  562. </tr>
  563. <tr>
  564. <td><a href="#osisexec">os.isexec</a></td>
  565. <td>Test if a file is executable</td>
  566. <td>>= 2.0.1</td>
  567. </tr>
  568. <tr>
  569. <td><a href="#osrun">os.run</a></td>
  570. <td>Quiet running program</td>
  571. <td>>= 2.0.1</td>
  572. </tr>
  573. <tr>
  574. <td><a href="#osrunv">os.runv</a></td>
  575. <td>Quiet running program with parameter list</td>
  576. <td>>= 2.1.5</td>
  577. </tr>
  578. <tr>
  579. <td><a href="#osexec">os.exec</a></td>
  580. <td>Evoke Run Program</td>
  581. <td>>= 2.0.1</td>
  582. </tr>
  583. <tr>
  584. <td><a href="#osexecv">os.execv</a></td>
  585. <td>Echo running program with parameter list</td>
  586. <td>>= 2.1.5</td>
  587. </tr>
  588. <tr>
  589. <td><a href="#osiorun">os.iorun</a></td>
  590. <td>Run and get the program output</td>
  591. <td>>= 2.0.1</td>
  592. </tr>
  593. <tr>
  594. <td><a href="#osiorunv">os.iorunv</a></td>
  595. <td>Run and get the program output with parameter list</td>
  596. <td>>= 2.1.5</td>
  597. </tr>
  598. <tr>
  599. <td><a href="#ostmpdir">os.tmpdir</a></td>
  600. <td>Get Temp directory path</td>
  601. <td>>= 2.0.1</td>
  602. </tr>
  603. <tr>
  604. <td><a href="#ostmpfile">os.tmpfile</a></td>
  605. <td>Get Temporary File Path</td>
  606. <td>>= 2.0.1</td>
  607. </tr>
  608. <tr>
  609. <td><a href="#oscurdir">os.curdir</a></td>
  610. <td>Get current directory path</td>
  611. <td>>= 2.0.1</td>
  612. </tr>
  613. <tr>
  614. <td><a href="#osfilesize">os.filesize</a></td>
  615. <td>Get File Size</td>
  616. <td>>= 2.1.9</td>
  617. </tr>
  618. <tr>
  619. <td><a href="#osscriptdir">os.scriptdir</a></td>
  620. <td>Get script directory path</td>
  621. <td>>= 2.0.1</td>
  622. </tr>
  623. <tr>
  624. <td><a href="#osprogramdir">os.programdir</a></td>
  625. <td>Get xmake install main program script directory</td>
  626. <td>>= 2.1.5</td>
  627. </tr>
  628. <tr>
  629. <td><a href="#osprogramfile">os.programfile</a></td>
  630. <td>Get the path of the xmake executable</td>
  631. <td>>= 2.1.5</td>
  632. </tr>
  633. <tr>
  634. <td><a href="#osprojectdir">os.projectdir</a></td>
  635. <td>Get Project Home</td>
  636. <td>>= 2.1.5</td>
  637. </tr>
  638. <tr>
  639. <td><a href="#osarch">os.arch</a></td>
  640. <td>Get Current System Architecture</td>
  641. <td>>= 2.0.1</td>
  642. </tr>
  643. <tr>
  644. <td><a href="#oshost">os.host</a></td>
  645. <td>Get Current Host System</td>
  646. <td>>= 2.0.1</td>
  647. </tr>
  648. <tr>
  649. <td><a href="#ossubhost">os.subhost</a></td>
  650. <td>Get Subsystem host, e.g. msys, cygwin on windows</td>
  651. <td>>= 2.3.1</td>
  652. </tr>
  653. <tr>
  654. <td><a href="#ossubarch">os.subarch</a></td>
  655. <td>Get Subsystem host architecture</td>
  656. <td>>= 2.3.1</td>
  657. </tr>
  658. <tr>
  659. <td><a href="#osis_host">os.is_host</a></td>
  660. <td>Test if a given host is the current</td>
  661. <td>>= 2.3.1</td>
  662. </tr>
  663. <tr>
  664. <td><a href="#osis_arch">os.is_arch</a></td>
  665. <td>Test if a given arch is the current</td>
  666. <td>>= 2.3.1</td>
  667. </tr>
  668. <tr>
  669. <td><a href="#osis_subhost">os.is_subhost</a></td>
  670. <td>Test if a given sub host is the current</td>
  671. <td>>= 2.3.1</td>
  672. </tr>
  673. <tr>
  674. <td><a href="#osis_subarch">os.is_subarch</a></td>
  675. <td>Test if a given sub arch is the current</td>
  676. <td>>= 2.3.1</td>
  677. </tr>
  678. <tr>
  679. <td><a href="#osln">os.ln</a></td>
  680. <td>Link file or directory to the new symfile</td>
  681. <td>>= 2.2.2</td>
  682. </tr>
  683. <tr>
  684. <td><a href="#osreadlink">os.readlink</a></td>
  685. <td>Read the content of a symlink</td>
  686. <td>>= 2.2.2</td>
  687. </tr>
  688. <tr>
  689. <td><a href="#osraise">os.raise</a></td>
  690. <td>Raise an exception and abort the current script</td>
  691. <td>>= 2.2.8</td>
  692. </tr>
  693. <tr>
  694. <td><a href="#raiselevel">os.raiselevel</a></td>
  695. <td>Raise an exception and abort the current script</td>
  696. <td>>= 2.2.8</td>
  697. </tr>
  698. <tr>
  699. <td><a href="#osfeatures">os.features</a></td>
  700. <td>Get features</td>
  701. <td>>= 2.3.1</td>
  702. </tr>
  703. <tr>
  704. <td><a href="#osgetenvs">os.getenvs</a></td>
  705. <td>Get all current environment variables</td>
  706. <td>>= 2.2.6</td>
  707. </tr>
  708. <tr>
  709. <td><a href="#ossetenvs">os.setenvs</a></td>
  710. <td>Set environment variables</td>
  711. <td>>= 2.2.6</td>
  712. </tr>
  713. <tr>
  714. <td><a href="#osaddenvs">os.addenvs</a></td>
  715. <td>Add environment variables to current envs</td>
  716. <td>>= 2.5.6</td>
  717. </tr>
  718. <tr>
  719. <td><a href="#osjoinenvs">os.joinenvs</a></td>
  720. <td>Join environment variables</td>
  721. <td>>= 2.5.6</td>
  722. </tr>
  723. <tr>
  724. <td><a href="#osgetenv">os.getenv</a></td>
  725. <td>Get Environment Variables</td>
  726. <td>>= 2.0.1</td>
  727. </tr>
  728. <tr>
  729. <td><a href="#ossetenv">os.setenv</a></td>
  730. <td>Setting environment variables</td>
  731. <td>>= 2.0.1</td>
  732. </tr>
  733. <tr>
  734. <td><a href="#osaddenv">os.addenv</a></td>
  735. <td>Add values to one environment variable</td>
  736. <td>>= 2.1.5</td>
  737. </tr>
  738. <tr>
  739. <td><a href="#ossetenvp">os.setenvp</a></td>
  740. <td>Setting environment variables with a given separator</td>
  741. <td>>= 2.1.5</td>
  742. </tr>
  743. <tr>
  744. <td><a href="#osaddenvp">os.addenvp</a></td>
  745. <td>Add values to one environment variable with a given separator</td>
  746. <td>>= 2.1.5</td>
  747. </tr>
  748. <tr>
  749. <td><a href="#osworkingdir">os.workingdir</a></td>
  750. <td>Get the working directory</td>
  751. <td>>= 2.1.9</td>
  752. </tr>
  753. <tr>
  754. <td><a href="#osisroot">os.isroot</a></td>
  755. <td>Test if xmake is running as root</td>
  756. <td>>= 2.1.9</td>
  757. </tr>
  758. <tr>
  759. <td><a href="#osfscase">os.fscase</a></td>
  760. <td>Test if the os has a case sensitive filesystem</td>
  761. <td>>= 2.1.9</td>
  762. </tr>
  763. <tr>
  764. <td><a href="#osterm">os.term</a></td>
  765. <td>Get current terminal</td>
  766. <td>>= 2.7.3</td>
  767. </tr>
  768. <tr>
  769. <td><a href="#osshell">os.shell</a></td>
  770. <td>Get current shell</td>
  771. <td>>= 2.7.3</td>
  772. </tr>
  773. <tr>
  774. <td><a href="#oscpuinfo">os.cpuinfo</a></td>
  775. <td>Get cpu information</td>
  776. <td>>= 2.1.5</td>
  777. </tr>
  778. <tr>
  779. <td><a href="#osmeminfo">os.meminfo</a></td>
  780. <td>Get memory information</td>
  781. <td>>= 2.1.5</td>
  782. </tr>
  783. <tr>
  784. <td><a href="#osdefault_njob">os.default_njob</a></td>
  785. <td>Get default paralled jobs</td>
  786. <td>>= 2.5.8</td>
  787. </tr>
  788. </tbody>
  789. </table>
  790. <h4 id="oscp">os.cp</h4>
  791. <ul>
  792. <li>Copy files or directories</li>
  793. </ul>
  794. <p>The behavior is similar to the <code>cp</code> command in the shell, supporting path wildcard matching (using lua pattern matching), support for multi-file copying, and built-in variable support.</p>
  795. <p>e.g:</p>
  796. <pre><code class="lang-lua">os.cp("$(scriptdir)/*.h", "$(buildir)/inc")
  797. os.cp("$(projectdir)/src/test/**.h", "$(buildir)/inc")
  798. </code></pre>
  799. <p>The above code will copy all the header files in the current <code>xmake.lua</code> directory, the header files in the project source test directory to the <code>$(buildir)</code> output directory.</p>
  800. <p>Among them <code>$(scriptdir)</code>, <code>$(projectdir)</code> These variables are built-in variables of xmake. For details, see the related documentation of <a href="#built-in variables">built-in variables</a>.</p>
  801. <p>The matching patterns in <code>*.h</code> and <code>**.h</code> are similar to those in <a href="#targetadd_files">add_files</a>, the former is a single-level directory matching, and the latter is a recursive multi-level directory matching.</p>
  802. <p>This interface also supports `recursive replication&#39; of directories, for example:</p>
  803. <pre><code class="lang-lua">-- Recursively copy the current directory to a temporary directory
  804. os.cp("$(curdir)/test/", "$(tmpdir)/test")
  805. </code></pre>
  806. <p>The copy at the top will expand and copy all files to the specified directory, and lose the source directory hierarchy. If you want to copy according to the directory structure that maintains it, you can set the rootdir parameter:</p>
  807. <pre><code class="lang-lua">os.cp ("src/**.h", "/tmp/", {rootdir="src"})
  808. </code></pre>
  809. <p>The above script can press the root directory of <code>src</code> to copy all sub-files under src in the same directory structure.</p>
  810. <p>!> Try to use the <code>os.cp</code> interface instead of <code>os.run("cp ..")</code>, which will ensure platform consistency and cross-platform build description.</p>
  811. <p>Under 2.5.7, the parameter <code>{symlink = true}</code> is added to keep the symbolic link when copying files.</p>
  812. <pre><code class="lang-lua">os.cp("/xxx/foo", "/xxx/bar", {symlink = true})
  813. </code></pre>
  814. <h4 id="osmv">os.mv</h4>
  815. <ul>
  816. <li>Move to rename a file or directory</li>
  817. </ul>
  818. <p>Similar to the use of <a href="#oscp">os.cp</a>, it also supports multi-file move operations and pattern matching, for example:</p>
  819. <pre><code class="lang-lua">-- Move multiple files to a temporary directory
  820. os.mv("$(buildir)/test1", "$(tmpdir)")
  821. -- File movement does not support bulk operations, which is file renaming
  822. os.mv("$(buildir)/libtest.a", "$(buildir)/libdemo.a")
  823. </code></pre>
  824. <h4 id="osrm">os.rm</h4>
  825. <ul>
  826. <li>Delete files or directory trees</li>
  827. </ul>
  828. <p>Support for recursive deletion of directories, bulk delete operations, and pattern matching and built-in variables, such as:</p>
  829. <pre><code class="lang-lua">os.rm("$(buildir)/inc/**.h")
  830. os.rm("$(buildir)/lib/")
  831. </code></pre>
  832. <h4 id="ostrycp">os.trycp</h4>
  833. <ul>
  834. <li>Try copying files or directories</li>
  835. </ul>
  836. <p>Similar to <a href="#oscp">os.cp</a>, the only difference is that this interface operation will not throw an exception interrupt xmake, but the return value indicates whether the execution is successful.</p>
  837. <pre><code class="lang-lua">if os.trycp("file", "dest/file") then
  838. end
  839. </code></pre>
  840. <h4 id="ostrymv">os.trymv</h4>
  841. <ul>
  842. <li>Try moving a file or directory</li>
  843. </ul>
  844. <p>Similar to <a href="#osmv">os.mv</a>, the only difference is that this interface operation will not throw an exception interrupt xmake, but the return value indicates whether the execution is successful.</p>
  845. <pre><code class="lang-lua">if os.trymv("file", "dest/file") then
  846. end
  847. </code></pre>
  848. <h4 id="ostryrm">os.tryrm</h4>
  849. <ul>
  850. <li>Try deleting files or directories</li>
  851. </ul>
  852. <p>Similar to <a href="#osrm">os.rm</a>, the only difference is that this interface operation will not throw an exception interrupt xmake, but the return value indicates whether the execution is successful.</p>
  853. <pre><code class="lang-lua">if os.tryrm("file") then
  854. end
  855. </code></pre>
  856. <h4 id="oscd">os.cd</h4>
  857. <ul>
  858. <li>Enter the specified directory</li>
  859. </ul>
  860. <p>This operation is used for directory switching and also supports built-in variables, but does not support pattern matching and multi-directory processing, for example:</p>
  861. <pre><code class="lang-lua">-- Enter the temporary directory
  862. os.cd("$(tmpdir)")
  863. </code></pre>
  864. <p>If you want to leave the previous directory, there are several ways:</p>
  865. <pre><code class="lang-lua">-- Enter the parent directory
  866. os.cd("..")
  867. -- Enter the previous directory, equivalent to: cd -
  868. os.cd("-")
  869. -- Save the previous directory before entering the directory, then use it to cut back directly after the level
  870. local oldir = os.cd("./src")
  871. ...
  872. os.cd(oldir)
  873. </code></pre>
  874. <h4 id="osrmdir">os.rmdir</h4>
  875. <ul>
  876. <li>delete only the directory</li>
  877. </ul>
  878. <p>If it is not a directory, it cannot be deleted.</p>
  879. <h4 id="osmkdir">os.mkdir</h4>
  880. <ul>
  881. <li>Create a directory</li>
  882. </ul>
  883. <p>Support for batch creation and built-in variables, such as:</p>
  884. <pre><code class="lang-lua">os.mkdir("$(tmpdir)/test", "$(buildir)/inc")
  885. </code></pre>
  886. <h4 id="osisdir">os.isdir</h4>
  887. <ul>
  888. <li>Determine if it is a directory</li>
  889. </ul>
  890. <p>Return false if the directory does not exist</p>
  891. <pre><code class="lang-lua">if os.isdir("src") then
  892. -- ...
  893. end
  894. </code></pre>
  895. <h4 id="osisfile">os.isfile</h4>
  896. <ul>
  897. <li>Determine if it is a file</li>
  898. </ul>
  899. <p>Return false if the file does not exist</p>
  900. <pre><code class="lang-lua">if os.isfile("$(buildir)/libxxx.a") then
  901. -- ...
  902. end
  903. </code></pre>
  904. <h4 id="osexists">os.exists</h4>
  905. <ul>
  906. <li>Determine if a file or directory exists</li>
  907. </ul>
  908. <p>Return false if the file or directory does not exist</p>
  909. <pre><code class="lang-lua">-- Judging the existence of the directory
  910. if os.exists("$(buildir)") then
  911. -- ...
  912. end
  913. -- Judging the existence of the file
  914. if os.exists("$(buildir)/libxxx.a") then
  915. -- ...
  916. end
  917. </code></pre>
  918. <h4 id="osdirs">os.dirs</h4>
  919. <ul>
  920. <li>Traverse to get all the directories under the specified directory</li>
  921. </ul>
  922. <p>Supports pattern matching in <a href="#targetadd_files">add_files</a>, supports recursive and non-recursive mode traversal, and returns a table array. If not, returns an empty array, for example:</p>
  923. <pre><code class="lang-lua">-- Recursive traversal to get all subdirectories
  924. for _, dir in ipairs(os.dirs("$(buildir)/inc/**")) do
  925. print(dir)
  926. end
  927. </code></pre>
  928. <h4 id="osfiles">os.files</h4>
  929. <ul>
  930. <li>Traverse to get all the files in the specified directory</li>
  931. </ul>
  932. <p>Supports pattern matching in <a href="#targetadd_files">add_files</a>, supports recursive and non-recursive mode traversal, and returns a table array. If not, returns an empty array, for example:</p>
  933. <pre><code class="lang-lua">-- Non-recursive traversal to get all child files
  934. for _, filepath in ipairs(os.files("$(buildir)/inc/*.h")) do
  935. print(filepath)
  936. end
  937. </code></pre>
  938. <h4 id="osfiledirs">os.filedirs</h4>
  939. <ul>
  940. <li>Traverse to get all files and directories under the specified directory</li>
  941. </ul>
  942. <p>Supports pattern matching in <a href="#targetadd_files">add_files</a>, supports recursive and non-recursive mode traversal, and returns a table array. If not, returns an empty array, for example:</p>
  943. <pre><code class="lang-lua">-- Recursive traversal to get all child files and directories
  944. for _, filedir in ipairs(os.filedirs("$(buildir)/**")) do
  945. print(filedir)
  946. end
  947. </code></pre>
  948. <h4 id="osexit">os.exit</h4>
  949. <ul>
  950. <li>Exit the program</li>
  951. </ul>
  952. <h4 id="osisexec">os.isexec</h4>
  953. <ul>
  954. <li>Test if a file is executable</li>
  955. </ul>
  956. <pre><code class="lang-lua">if os.isexec("path/to/file.exe") then
  957. os.run("path/to/file.exe")
  958. end
  959. </code></pre>
  960. <h4 id="osrun">os.run</h4>
  961. <ul>
  962. <li>Quietly running native shell commands</li>
  963. </ul>
  964. <p>Used to execute third-party shell commands, but will not echo the output, only after the error, highlight the error message.</p>
  965. <p>This interface supports parameter formatting and built-in variables such as:</p>
  966. <pre><code class="lang-lua">-- Formatted parameters passed in
  967. os.run("echo hello %s!", "xmake")
  968. -- List build directory files
  969. os.run("ls -l $(buildir)")
  970. </code></pre>
  971. <p><p class="warn"><br>Using this interface to execute shell commands can easily reduce the cross-platform build. For <code>os.run("cp ..")</code>, try to use <code>os.cp</code> instead. <br><br>If you must use this interface to run the shell program, please use the <a href="#config-plat">config.plat</a> interface to determine the platform support.<br></p>
  972. </p>
  973. <p>For more advanced process operations and control, see the <a href="#process">process</a> module interface.</p>
  974. <h4 id="osrunv">os.runv</h4>
  975. <ul>
  976. <li>Quietly running native shell commands with parameter list</li>
  977. </ul>
  978. <p>Similar to <a href="#osrun">os.run</a>, just the way to pass parameters is passed through the parameter list, not the string command, for example:</p>
  979. <pre><code class="lang-lua">os.runv("echo", {"hello", "xmake!"})
  980. </code></pre>
  981. <h4 id="osexec">os.exec</h4>
  982. <ul>
  983. <li>Echo running native shell commands</li>
  984. </ul>
  985. <p>Similar to the <a href="#osrun">os.run</a> interface, the only difference is that when this interface executes the shell program, it has the output output, which is used in general debugging.</p>
  986. <h4 id="osexecv">os.execv</h4>
  987. <ul>
  988. <li>Echo running native shell commands with parameter list</li>
  989. </ul>
  990. <p>Similar to <a href="#osexec">os.exec</a>, just the way to pass parameters is passed through the parameter list, not the string command, for example:</p>
  991. <pre><code class="lang-lua">os.execv("echo", {"hello", "xmake!"})
  992. </code></pre>
  993. <p>In addition, this interface also supports an optional parameter for passing settings: redirect output, perform environment variable settings, for example:</p>
  994. <pre><code class="lang-lua">os.execv("echo", {"hello", "xmake!"}, {stdout = outfile, stderr = errfile, envs = {PATH = "xxx;xx", CFLAGS = "xx"}}
  995. </code></pre>
  996. <p>Among them, the stdout and stderr parameters are used to pass redirected output and error output. You can directly pass in the file path or the file object opened by io.open.</p>
  997. <p>After v2.5.1, we also support setting the stdin parameter to support redirecting input files.</p>
  998. <p>!> stdout/stderr/stdin can simultaneously support three types of values: file path, file object, and pipe object.</p>
  999. <p>In addition, if you want to temporarily set and rewrite some environment variables during this execution, you can pass the envs parameter. The environment variable settings inside will replace the existing settings, but will not affect the outer execution environment, only the current command.</p>
  1000. <p>We can also get all the current environment variables through the <code>os.getenvs()</code> interface, and then pass in the envs parameter after rewriting some parts.</p>
  1001. <h4 id="osiorun">os.iorun</h4>
  1002. <ul>
  1003. <li>Quietly running native shell commands and getting output</li>
  1004. </ul>
  1005. <p>Similar to the <a href="#osrun">os.run</a> interface, the only difference is that after executing the shell program, this interface will get the execution result of the shell program, which is equivalent to redirecting the output.</p>
  1006. <p>You can get the contents of <code>stdout</code>, <code>stderr</code> at the same time, for example:</p>
  1007. <pre><code class="lang-lua">local outdata, errdata = os.iorun("echo hello xmake!")
  1008. </code></pre>
  1009. <h4 id="osiorunv">os.iorunv</h4>
  1010. <ul>
  1011. <li>Run the native shell command quietly and get the output with a list of parameters</li>
  1012. </ul>
  1013. <p>Similar to <a href="#osiorun">os.iorun</a>, just the way to pass arguments is passed through the argument list, not the string command, for example:</p>
  1014. <pre><code class="lang-lua">local outdata, errdata = os.iorunv("echo", {"hello", "xmake!"})
  1015. local outdata, errdata = os.iorunv("echo", {"hello", "xmake!"}, {envs = {PATH="..."}})
  1016. </code></pre>
  1017. <h4 id="ostmpdir">os.tmpdir</h4>
  1018. <ul>
  1019. <li>Get temporary directory</li>
  1020. </ul>
  1021. <p>Consistent with the result of <a href="#var-tmpdir">$(tmpdir)</a>, it is just a direct return to return a variable that can be maintained with subsequent strings.</p>
  1022. <pre><code class="lang-lua">print(path.join(os.tmpdir(), "file.txt"))
  1023. </code></pre>
  1024. <p>Equivalent to:</p>
  1025. <pre><code class="lang-lua">print("$(tmpdir)/file.txt")
  1026. </code></pre>
  1027. <h4 id="ostmpfile">os.tmpfile</h4>
  1028. <ul>
  1029. <li>Get temporary file path</li>
  1030. </ul>
  1031. <p>Used to get a temporary file path, just a path, the file needs to be created by itself.</p>
  1032. <h4 id="oscurdir">os.curdir</h4>
  1033. <ul>
  1034. <li>Get the current directory path</li>
  1035. </ul>
  1036. <p>Consistent with the result of <a href="#var-curdir">$(curdir)</a>, it is just a direct return to return a variable that can be maintained with subsequent strings.</p>
  1037. <p>Usage reference: <a href="#ostmpdir">os.tmpdir</a>.</p>
  1038. <h4 id="osfilesize">os.filesize</h4>
  1039. <ul>
  1040. <li>Get file size</li>
  1041. </ul>
  1042. <pre><code class="lang-lua">print(os.filesize("/tmp/a"))
  1043. </code></pre>
  1044. <h4 id="osscriptdir">os.scriptdir</h4>
  1045. <ul>
  1046. <li>Get the path of the current description script</li>
  1047. </ul>
  1048. <p>Consistent with the result of <a href="#var-scriptdir">$(scriptdir)</a>, it is just a direct return to return a variable that can be maintained with subsequent strings.</p>
  1049. <p>Usage reference: <a href="#ostmpdir">os.tmpdir</a>.</p>
  1050. <h4 id="osprogramdir">os.programdir</h4>
  1051. <ul>
  1052. <li>Get the xmake installation main program script directory</li>
  1053. </ul>
  1054. <p>Consistent with the result of <a href="#var-programdir">$(programdir)</a>, it is just a direct get returned to a variable, which can be maintained with subsequent strings.</p>
  1055. <h4 id="osprogramfile">os.programfile</h4>
  1056. <ul>
  1057. <li>Get the path of the xmake executable</li>
  1058. </ul>
  1059. <h4 id="osprojectdir">os.projectdir</h4>
  1060. <ul>
  1061. <li>Get the project home directory</li>
  1062. </ul>
  1063. <p>Consistent with the result of <a href="#var-projectdir">$(projectdir)</a>, it is just a direct return to return a variable that can be maintained with subsequent strings.</p>
  1064. <h4 id="osarch">os.arch</h4>
  1065. <ul>
  1066. <li>Get current system architecture</li>
  1067. </ul>
  1068. <p>That is the default architecture of the current host system, for example, I execute xmake on <code>linux x86_64</code> to build, then the return value is: <code>x86_64</code></p>
  1069. <h4 id="oshost">os.host</h4>
  1070. <ul>
  1071. <li>Get the operating system of the current host</li>
  1072. </ul>
  1073. <p>Consistent with the result of <a href="#var-host">$(host)</a>, for example, if I execute xmake on <code>linux x86_64</code> to build, the return value is: <code>linux</code></p>
  1074. <h4 id="ossubhost">os.subhost</h4>
  1075. <ul>
  1076. <li>Get Subsystem host, e.g. msys, cygwin on windows</li>
  1077. </ul>
  1078. <h4 id="ossubarch">os.subarch</h4>
  1079. <ul>
  1080. <li>Get Subsystem host architecture</li>
  1081. </ul>
  1082. <h4 id="osis_host">os.is_host</h4>
  1083. <ul>
  1084. <li>Test if a given host is the current</li>
  1085. </ul>
  1086. <h4 id="osis_arch">os.is_arch</h4>
  1087. <ul>
  1088. <li>Test if a given arch is the current</li>
  1089. </ul>
  1090. <h4 id="osis_subhost">os.is_subhost</h4>
  1091. <ul>
  1092. <li>Test if a given sub host is the current</li>
  1093. </ul>
  1094. <h4 id="osis_subarch">os.is_subarch</h4>
  1095. <ul>
  1096. <li>Test if a given sub arch is the current</li>
  1097. </ul>
  1098. <h4 id="osln">os.ln</h4>
  1099. <ul>
  1100. <li>Create a symlink to a file or directory</li>
  1101. </ul>
  1102. <pre><code class="lang-lua">-- creates a symlink file "xxx.txt.ln" which is pointing to "xxx.txt"
  1103. os.ln("xxx.txt", "xxx.txt.ln")
  1104. </code></pre>
  1105. <h4 id="osreadlink">os.readlink</h4>
  1106. <ul>
  1107. <li>Read the content of a symlink</li>
  1108. </ul>
  1109. <h4 id="osraise">os.raise</h4>
  1110. <ul>
  1111. <li>Raise an exception and abort the current script</li>
  1112. </ul>
  1113. <pre><code class="lang-lua">-- Raise exception with message "an error occurred"
  1114. os.raise("an error occurred")
  1115. </code></pre>
  1116. <p>!> recommanded to use builtin function <code>raise</code> instead of <code>os.raise</code></p>
  1117. <h4 id="osraiselevel">os.raiselevel</h4>
  1118. <ul>
  1119. <li>Similar to <a href="#osraise">os.raise</a> but you can specify the level of the error</li>
  1120. </ul>
  1121. <pre><code class="lang-lua">-- Raise exception with message "an error occurred"
  1122. os.raiselevel(3,"an error occurred")
  1123. </code></pre>
  1124. <h4 id="osfeatures">os.features</h4>
  1125. <ul>
  1126. <li>Get features</li>
  1127. </ul>
  1128. <h4 id="osgetenvs">os.getenvs</h4>
  1129. <ul>
  1130. <li>Get all current environment variables</li>
  1131. </ul>
  1132. <pre><code class="lang-lua">local envs = os.getenvs()
  1133. --- home directory (on linux)
  1134. print(envs["HOME"])
  1135. </code></pre>
  1136. <h4 id="ossetenvs">os.setenvs</h4>
  1137. <ul>
  1138. <li>Set environment variables. Replace the current envs by a new one and return old envs</li>
  1139. </ul>
  1140. <h4 id="osaddenvs">os.addenvs</h4>
  1141. <ul>
  1142. <li>Add environment variables to current envs, return the all old envs</li>
  1143. </ul>
  1144. <pre><code class="lang-lua">os.setenvs({EXAMPLE = "a/path"}) -- add a custom variable to see addenvs impact on it
  1145. local oldenvs = os.addenvs({EXAMPLE = "some/path/"})
  1146. print(os.getenvs()["EXAMPLE"]) --got some/path/;a/path
  1147. print(oldenvs["EXAMPLE"]) -- got a/path
  1148. </code></pre>
  1149. <h4 id="osjoinenvs">os.joinenvs</h4>
  1150. <ul>
  1151. <li>Join environment variables. Similar to <a href="#osaddenvs">os.addenvs</a> but with two envs variable</li>
  1152. </ul>
  1153. <pre><code class="lang-lua">local envs = {CUSTOM = "a/path"}
  1154. local envs2 = {CUSTOM = "some/path/"}
  1155. print(os.joinenvs(envs, envs2))
  1156. </code></pre>
  1157. <p>The result is: <code>{ CUSTOM = "a/path;some/path/" }</code></p>
  1158. <h4 id="osgetenv">os.getenv</h4>
  1159. <ul>
  1160. <li>Get system environment variables</li>
  1161. </ul>
  1162. <pre><code class="lang-lua">print(os.getenv("PATH"))
  1163. </code></pre>
  1164. <h4 id="ossetenv">os.setenv</h4>
  1165. <ul>
  1166. <li>Set system environment variables</li>
  1167. </ul>
  1168. <pre><code class="lang-lua">os.setenv("HOME", "/tmp/")
  1169. </code></pre>
  1170. <h4 id="osaddenv">os.addenv</h4>
  1171. <ul>
  1172. <li>Add values to one environment variable</li>
  1173. </ul>
  1174. <pre><code class="lang-lua">-- Add &#39;bin&#39; to PATH
  1175. os.addenv("PATH", "bin")
  1176. </code></pre>
  1177. <h4 id="ossetenvp">os.setenvp</h4>
  1178. <ul>
  1179. <li>Setting environment variables with a given separator</li>
  1180. </ul>
  1181. <h4 id="osaddenvp">os.addenvp</h4>
  1182. <ul>
  1183. <li>Add values to one environment variable with a given separator</li>
  1184. </ul>
  1185. <h4 id="osworkingdir">os.workingdir</h4>
  1186. <ul>
  1187. <li>Get the working directory</li>
  1188. </ul>
  1189. <h4 id="osisroot">os.isroot</h4>
  1190. <ul>
  1191. <li>Test if xmake is running as root</li>
  1192. </ul>
  1193. <h4 id="osfscase">os.fscase</h4>
  1194. <ul>
  1195. <li>Test if the os has a case sensitive filesystem</li>
  1196. </ul>
  1197. <h4 id="osterm">os.term</h4>
  1198. <ul>
  1199. <li>Get current terminal (windows-terminal, vscode, ... )</li>
  1200. </ul>
  1201. <pre><code class="lang-lua">print(os.term())
  1202. -- got vscode
  1203. </code></pre>
  1204. <h4 id="osshell">os.shell</h4>
  1205. <ul>
  1206. <li>Get current shell (pwsh, cmd, ...)</li>
  1207. </ul>
  1208. <pre><code class="lang-lua">print(os.shell())
  1209. -- got pwsh
  1210. </code></pre>
  1211. <h4 id="oscpuinfo">os.cpuinfo</h4>
  1212. <ul>
  1213. <li>Get cpu information</li>
  1214. </ul>
  1215. <pre><code class="lang-lua">print(os.cpuinfo())
  1216. -- got {
  1217. -- ncpu = 8,
  1218. -- usagerate = 0.0,
  1219. -- model_name = "Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz",
  1220. -- march = "Kaby Lake",
  1221. -- vendor = "GenuineIntel",
  1222. -- model = 158,
  1223. -- family = 6
  1224. -- }
  1225. print(os.cpuinfo("march")) -- got "Kaby Lake"
  1226. </code></pre>
  1227. <h4 id="osmeminfo">os.meminfo</h4>
  1228. <ul>
  1229. <li>Get memory information</li>
  1230. </ul>
  1231. <pre><code class="lang-lua">print(os.meminfo())
  1232. -- got {
  1233. -- usagerate = 0.53490080822924,
  1234. -- totalsize = 16332,
  1235. -- availsize = 7596,
  1236. -- pagesize = 4096
  1237. -- }
  1238. </code></pre>
  1239. <h4 id="osdefault_njob">os.default_njob</h4>
  1240. <ul>
  1241. <li>Get default paralled jobs</li>
  1242. </ul>
  1243. <h3 id="winos">winos</h3>
  1244. <p>The windows system operation module is a built-in module, no need to use <a href="#import">import</a> to import, you can directly call its interface in the script domain.</p>
  1245. <table>
  1246. <thead>
  1247. <tr>
  1248. <th>Interface</th>
  1249. <th>Description</th>
  1250. <th>Support version</th>
  1251. </tr>
  1252. </thead>
  1253. <tbody>
  1254. <tr>
  1255. <td><a href="#winosversion">winos.version</a></td>
  1256. <td>Get windows system version</td>
  1257. <td>>= 2.3.1</td>
  1258. </tr>
  1259. <tr>
  1260. <td><a href="#winosregistry_keys">winos.registry_keys</a></td>
  1261. <td>Get the list of registry keys</td>
  1262. <td>>= 2.5.1</td>
  1263. </tr>
  1264. <tr>
  1265. <td><a href="#winosregistry_values">winos.registry_values</a></td>
  1266. <td>Get a list of registry value names</td>
  1267. <td>>= 2.5.1</td>
  1268. </tr>
  1269. <tr>
  1270. <td><a href="#winosregistry_query">winos.registry_query</a></td>
  1271. <td>Get the registry value</td>
  1272. <td>>= 2.3.1</td>
  1273. </tr>
  1274. </tbody>
  1275. </table>
  1276. <h4 id="winosversion">winos.version</h4>
  1277. <ul>
  1278. <li>Get windows system version</li>
  1279. </ul>
  1280. <p>The version returned is the semver semantic version object</p>
  1281. <pre><code class="lang-lua">if winos.version():ge("win7") then
  1282. - ...
  1283. end
  1284. if winos.version():ge("6.1") then
  1285. - ...
  1286. end
  1287. </code></pre>
  1288. <p>In addition, it can also support the direct judgment of the windows version name. The mapping rules are as follows:</p>
  1289. <pre><code>nt4 = "4.0"
  1290. win2k = "5.0"
  1291. winxp = "5.1"
  1292. ws03 = "5.2"
  1293. win6 = "6.0"
  1294. vista = "6.0"
  1295. ws08 = "6.0"
  1296. longhorn = "6.0"
  1297. win7 = "6.1"
  1298. win8 = "6.2"
  1299. winblue = "6.3"
  1300. win81 = "6.3"
  1301. win10 = "10.0"
  1302. </code></pre><h4 id="winosregistry_keys">winos.registry_keys</h4>
  1303. <ul>
  1304. <li>Get the list of registry builds</li>
  1305. </ul>
  1306. <p>Support through pattern matching, traverse to obtain the registry key path list, <code>*</code> is single-level path matching, <code>**</code> is recursive path matching.</p>
  1307. <pre><code class="lang-lua">local keypaths = winos.registry_keys("HKEY_LOCAL_MACHINE\\SOFTWARE\\*\\Windows NT\\*\\CurrentVersion\\AeDebug")
  1308. for _, keypath in ipairs(keypaths) do
  1309. print(winos.registry_query(keypath .. ";Debugger"))
  1310. end
  1311. </code></pre>
  1312. <h4 id="winosregistry_values">winos.registry_values</h4>
  1313. <ul>
  1314. <li>Get a list of registry value names</li>
  1315. </ul>
  1316. <p>Support to obtain the value name list of the specified key path through pattern matching, and the string after the <code>;</code> is the specified key name pattern matching string.</p>
  1317. <pre><code class="lang-lua">local valuepaths = winos.registry_values("HKEY_LOCAL_MACHINE\\SOFTWARE\\xx\\AeDebug;Debug*")
  1318. for _, valuepath in ipairs(valuepaths) do
  1319. print(winos.registry_query(valuepath))
  1320. end
  1321. </code></pre>
  1322. <h4 id="winosregistry_query">winos.registry_query</h4>
  1323. <ul>
  1324. <li>Get the registry value</li>
  1325. </ul>
  1326. <p>Get the value under the specified registry path, if the value name is not specified, then get the default value of the key path</p>
  1327. <pre><code class="lang-lua">local value, errors = winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug")
  1328. local value, errors = winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger")
  1329. </code></pre>
  1330. <h3 id="macos">macos</h3>
  1331. <p>The macOS system operation module is a built-in module, no need to use <a href="#import">import</a> to import, you can directly call its interface in the script domain.</p>
  1332. <table>
  1333. <thead>
  1334. <tr>
  1335. <th>Interface</th>
  1336. <th>Description</th>
  1337. <th>Support version</th>
  1338. </tr>
  1339. </thead>
  1340. <tbody>
  1341. <tr>
  1342. <td><a href="#macosversion">macos.version</a></td>
  1343. <td>Get macOS system version</td>
  1344. <td>>= 2.3.1</td>
  1345. </tr>
  1346. </tbody>
  1347. </table>
  1348. <h4 id="macosversion">macos.version</h4>
  1349. <ul>
  1350. <li>Get macOS system version</li>
  1351. </ul>
  1352. <p>The version returned is the semver semantic version object</p>
  1353. <pre><code class="lang-lua">if macos.version():ge("10.0") then
  1354. - ...
  1355. end
  1356. </code></pre>
  1357. <h3 id="linuxos">linuxos</h3>
  1358. <p>The linux system operation module is a built-in module, no need to use <a href="#import">import</a> to import, and its interface can be called directly in the script domain.</p>
  1359. <table>
  1360. <thead>
  1361. <tr>
  1362. <th>Interface</th>
  1363. <th>Description</th>
  1364. <th>Support version</th>
  1365. </tr>
  1366. </thead>
  1367. <tbody>
  1368. <tr>
  1369. <td><a href="#linuxosname">linuxos.name</a></td>
  1370. <td>Get the linux system release name</td>
  1371. <td>>= 2.5.2</td>
  1372. </tr>
  1373. <tr>
  1374. <td><a href="#linuxosversion">linuxos.version</a></td>
  1375. <td>Get linux system version</td>
  1376. <td>>= 2.5.2</td>
  1377. </tr>
  1378. <tr>
  1379. <td><a href="#linuxoskernelver">linuxos.kernelver</a></td>
  1380. <td>Get linux system kernel version</td>
  1381. <td>>= 2.5.2</td>
  1382. </tr>
  1383. </tbody>
  1384. </table>
  1385. <h4 id="linuxosname">linuxos.name</h4>
  1386. <ul>
  1387. <li>Get linux system name</li>
  1388. </ul>
  1389. <p>We can also quickly get the view through the following command</p>
  1390. <pre><code class="lang-bash">xmake l linuxos.name
  1391. </code></pre>
  1392. <p>Some names currently supported are:</p>
  1393. <ul>
  1394. <li>ubuntu</li>
  1395. <li>debian</li>
  1396. <li>archlinux</li>
  1397. <li>manjaro</li>
  1398. <li>linuxmint</li>
  1399. <li>centos</li>
  1400. <li>fedora</li>
  1401. <li>opensuse</li>
  1402. </ul>
  1403. <h4 id="linuxosversion">linuxos.version</h4>
  1404. <ul>
  1405. <li>Get linux system version</li>
  1406. </ul>
  1407. <p>The version returned is the semver semantic version object</p>
  1408. <pre><code class="lang-lua">if linux.version():ge("10.0") then
  1409. -- ...
  1410. end
  1411. </code></pre>
  1412. <h4 id="linuxoskernelver">linuxos.kernelver</h4>
  1413. <ul>
  1414. <li>Get linux system kernel version</li>
  1415. </ul>
  1416. <p>What is returned is also a semantic version object, you can also execute <code>xmake l linuxos.kernelver</code> to quickly view</p>
  1417. <h3 id="io">io</h3>
  1418. <p>The io operation module extends lua&#39;s built-in io module to provide more easy-to-use interfaces.</p>
  1419. <table>
  1420. <thead>
  1421. <tr>
  1422. <th>Interface</th>
  1423. <th>Description</th>
  1424. <th>Supported Versions</th>
  1425. </tr>
  1426. </thead>
  1427. <tbody>
  1428. <tr>
  1429. <td><a href="#ioopen">io.open</a></td>
  1430. <td>Open file for reading and writing</td>
  1431. <td>>= 2.0.1</td>
  1432. </tr>
  1433. <tr>
  1434. <td><a href="#ioload">io.load</a></td>
  1435. <td>De-serialize all table contents from the specified path file</td>
  1436. <td>>= 2.0.1</td>
  1437. </tr>
  1438. <tr>
  1439. <td><a href="#iosave">io.save</a></td>
  1440. <td>Serialize all table contents to the specified path file</td>
  1441. <td>>= 2.0.1</td>
  1442. </tr>
  1443. <tr>
  1444. <td><a href="#ioreadfile">io.readfile</a></td>
  1445. <td>Read everything from the specified path file</td>
  1446. <td>>= 2.1.3</td>
  1447. </tr>
  1448. <tr>
  1449. <td><a href="#iowritefile">io.writefile</a></td>
  1450. <td>Write everything to the specified path file</td>
  1451. <td>>= 2.1.3</td>
  1452. </tr>
  1453. <tr>
  1454. <td><a href="#iogsub">io.gsub</a></td>
  1455. <td>Full text replaces the contents of the specified path file</td>
  1456. <td>>= 2.0.1</td>
  1457. </tr>
  1458. <tr>
  1459. <td><a href="#iotail">io.tail</a></td>
  1460. <td>Read and display the tail of the file</td>
  1461. <td>>= 2.0.1</td>
  1462. </tr>
  1463. <tr>
  1464. <td><a href="#iocat">io.cat</a></td>
  1465. <td>Read and display all contents of a file</td>
  1466. <td>>= 2.0.1</td>
  1467. </tr>
  1468. <tr>
  1469. <td><a href="#ioprint">io.print</a></td>
  1470. <td>Formatting output with a line feed to a file</td>
  1471. <td>>= 2.0.1</td>
  1472. </tr>
  1473. <tr>
  1474. <td><a href="#ioprintf">io.printf</a></td>
  1475. <td>No line formatted output to file</td>
  1476. <td>>= 2.0.1</td>
  1477. </tr>
  1478. <tr>
  1479. <td><a href="#iolines">io.lines</a></td>
  1480. <td>Read all lines from file</td>
  1481. <td>>= 2.2.9</td>
  1482. </tr>
  1483. <tr>
  1484. <td><a href="#iostdfile">io.stdfile</a></td>
  1485. <td>Get std file</td>
  1486. <td>>= 2.2.9</td>
  1487. </tr>
  1488. <tr>
  1489. <td><a href="#ioopenlock">io.openlock</a></td>
  1490. <td>Open a lock of a file</td>
  1491. <td>>= 2.2.9</td>
  1492. </tr>
  1493. <tr>
  1494. <td><a href="#ioreplace">io.replace</a></td>
  1495. <td>Replace text of the given file and return the replaced data</td>
  1496. <td>>= 2.3.8</td>
  1497. </tr>
  1498. </tbody>
  1499. </table>
  1500. <h4 id="ioopen">io.open</h4>
  1501. <ul>
  1502. <li>Open file for reading and writing</li>
  1503. </ul>
  1504. <p>This is a native interface for lua. For detailed usage, see Lua&#39;s official documentation: <a href="https://www.lua.org/pil/21.2.html">The Complete I/O Model</a></p>
  1505. <p>If you want to read all the contents of the file, you can write:</p>
  1506. <pre><code class="lang-lua">local file = io.open("$(tmpdir)/file.txt", "r")
  1507. if file then
  1508. local data = file:read("*all")
  1509. file:close()
  1510. end
  1511. </code></pre>
  1512. <p>Or you can read it more quickly using <a href="#io.readfile">io.readfile</a>.</p>
  1513. <p>If you want to write a file, you can do this:</p>
  1514. <pre><code class="lang-lua">-- Open file: w is write mode, a is append write mode
  1515. local file = io.open("xxx.txt", "w")
  1516. if file then
  1517. -- Write data to file with native lua interface, does not support formatting, no line breaks, does not support built-in variables
  1518. file:write("hello xmake\n")
  1519. -- Write data to file with xmake extended interface, support formatting, no line breaks, no built-in variables
  1520. file:writef("hello %s\n", "xmake")
  1521. -- Use xmake extended formatted parameters to write to one line, with line breaks, and support for built-in variables
  1522. file:print("hello %s and $(buildir)", "xmake")
  1523. -- Write a line using the xmake extended formatted arguments, no line breaks, and support for built-in variables
  1524. file:printf("hello %s and $(buildir) \n", "xmake")
  1525. -- Close the file
  1526. file:close()
  1527. end
  1528. </code></pre>
  1529. <h4 id="ioload">io.load</h4>
  1530. <ul>
  1531. <li>Load all table contents from the specified path file deserialization</li>
  1532. </ul>
  1533. <p>You can load serialized table contents from a file, generally used with <a href="#iosave">io.save</a>, for example:</p>
  1534. <pre><code class="lang-lua">-- Load the contents of the serialized file to the table
  1535. local data = io.load("xxx.txt")
  1536. if data then
  1537. -- Dump prints the contents of the entire table in the terminal, formatting the output
  1538. utils.dump(data)
  1539. end
  1540. </code></pre>
  1541. <h4 id="iosave">io.save</h4>
  1542. <ul>
  1543. <li>Serialize all table contents to the specified path file</li>
  1544. </ul>
  1545. <p>You can serialize the contents of the table to the specified file, generally used in conjunction with <a href="#ioload">io.load</a>, for example:</p>
  1546. <pre><code class="lang-lua">io.save("xxx.txt", {a = "a", b = "b", c = "c"})
  1547. </code></pre>
  1548. <p>The result of the storage is:</p>
  1549. <pre><code>{
  1550. ["b"] = "b"
  1551. , ["a"] = "a"
  1552. , ["c"] = "c"
  1553. }
  1554. </code></pre><h4 id="ioreadfile">io.readfile</h4>
  1555. <ul>
  1556. <li>Read everything from the specified path file</li>
  1557. </ul>
  1558. <p>It is more convenient to directly read the contents of the entire file without opening the file, for example:</p>
  1559. <pre><code class="lang-lua">local data = io.readfile("xxx.txt")
  1560. </code></pre>
  1561. <h4 id="iowritefile">io.writefile</h4>
  1562. <ul>
  1563. <li>Write all content to the specified path file</li>
  1564. </ul>
  1565. <p>It is more convenient to directly write the contents of the entire file without opening the file, for example:</p>
  1566. <pre><code class="lang-lua">io.writefile("xxx.txt", "all data")
  1567. </code></pre>
  1568. <h4 id="iogsub">io.gsub</h4>
  1569. <ul>
  1570. <li>Full text replaces the contents of the specified path file</li>
  1571. </ul>
  1572. <p>Similar to the <a href="#stringgsub">string.gsub</a> interface, the full-text pattern matches the replacement content, but here is the direct operation file, for example:</p>
  1573. <pre><code class="lang-lua">-- Remove all whitespace characters from the file
  1574. io.gsub("xxx.txt", "%s+", "")
  1575. </code></pre>
  1576. <h4 id="iotail">io.tail</h4>
  1577. <ul>
  1578. <li>Read and display the tail content of the file</li>
  1579. </ul>
  1580. <p>Reads the data of the specified number of lines at the end of the file and displays a command like <code>cat xxx.txt | tail -n 10</code>, for example:</p>
  1581. <pre><code class="lang-lua">-- Display the last 10 lines of the file
  1582. io.tail("xxx.txt", 10)
  1583. </code></pre>
  1584. <h4 id="iocat">io.cat</h4>
  1585. <ul>
  1586. <li>read and display all contents of the file</li>
  1587. </ul>
  1588. <p>Read all the contents of the file and display it, similar to the <code>cat xxx.txt</code> command, for example:</p>
  1589. <pre><code class="lang-lua">io.cat("xxx.txt")
  1590. </code></pre>
  1591. <h4 id="ioprint">io.print</h4>
  1592. <ul>
  1593. <li>Formatted output content to file with newline</li>
  1594. </ul>
  1595. <p>Directly format the passed parameter to output a line of string to the file with a line break, for example:</p>
  1596. <pre><code class="lang-lua">io.print("xxx.txt", "hello %s!", "xmake")
  1597. </code></pre>
  1598. <h4 id="ioprintf">io.printf</h4>
  1599. <ul>
  1600. <li>Formatted output to file without line breaks</li>
  1601. </ul>
  1602. <p>Directly format the passed parameter to output a line of string to the file without a line break, for example:</p>
  1603. <pre><code class="lang-lua">io.printf("xxx.txt", "hello %s!\n", "xmake")
  1604. </code></pre>
  1605. <h3 id="iolines">io.lines</h3>
  1606. <ul>
  1607. <li>Read all lines from file</li>
  1608. </ul>
  1609. <p>Returns all lines from a given file name</p>
  1610. <pre><code class="lang-lua">local lines = io.lines("xxx.txt")
  1611. for line in lines do
  1612. print(line)
  1613. end
  1614. </code></pre>
  1615. <h3 id="iostdfile">io.stdfile</h3>
  1616. <ul>
  1617. <li>Get a std file</li>
  1618. </ul>
  1619. <p>Returns a file for a given std file name</p>
  1620. <pre><code class="lang-lua">-- returns stdin
  1621. io.stdin
  1622. -- returns stdout
  1623. io.stdout
  1624. -- returns stderr
  1625. io.stderr
  1626. </code></pre>
  1627. <h3 id="ioopenlock">io.openlock</h3>
  1628. <ul>
  1629. <li>Open a lock of a file</li>
  1630. </ul>
  1631. <p>Returns a file lock object when successfully locking the file</p>
  1632. <pre><code class="lang-lua">local lock = io.openlock("xxx.txt")
  1633. lock:lock()
  1634. lock:unlock()
  1635. lock:close()
  1636. </code></pre>
  1637. <h3 id="ioreplace">io.replace</h3>
  1638. <ul>
  1639. <li>Replace text of the given file and return the replaced data</li>
  1640. </ul>
  1641. <p>Replaces a given pattern in a file by a replacement string</p>
  1642. <pre><code class="lang-lua">-- replace string "Hello" in "xxx.txt" with "World"
  1643. io.replace("xxx.txt", "Hello", "World")
  1644. -- if you want to replace a string and not a pattern
  1645. io.replace("xxx.txt", "1+1=2", "2+2=4", {plain = true})
  1646. </code></pre>
  1647. <h3 id="path">path</h3>
  1648. <p>The path operation module implements cross-platform path operations, which is a custom module of xmake.</p>
  1649. <table>
  1650. <thead>
  1651. <tr>
  1652. <th>Interface</th>
  1653. <th>Description</th>
  1654. <th>Supported Versions</th>
  1655. </tr>
  1656. </thead>
  1657. <tbody>
  1658. <tr>
  1659. <td><a href="#pathnew">path.new</a></td>
  1660. <td>Create a new path instance</td>
  1661. <td>>= 2.0.1</td>
  1662. </tr>
  1663. <tr>
  1664. <td><a href="#pathjoin">path.join</a></td>
  1665. <td>Stitching Path</td>
  1666. <td>>= 2.0.1</td>
  1667. </tr>
  1668. <tr>
  1669. <td><a href="#pathtranslate">path.translate</a></td>
  1670. <td>Convert path to the path style of the current platform</td>
  1671. <td>>= 2.0.1</td>
  1672. </tr>
  1673. <tr>
  1674. <td><a href="#pathbasename">path.basename</a></td>
  1675. <td>Get the file name with no suffix at the end</td>
  1676. <td>>= 2.0.1</td>
  1677. </tr>
  1678. <tr>
  1679. <td><a href="#pathfilename">path.filename</a></td>
  1680. <td>Get the file name with the last suffix of the path</td>
  1681. <td>>= 2.0.1</td>
  1682. </tr>
  1683. <tr>
  1684. <td><a href="#pathextension">path.extension</a></td>
  1685. <td>Get the suffix of the path</td>
  1686. <td>>= 2.0.1</td>
  1687. </tr>
  1688. <tr>
  1689. <td><a href="#pathdirectory">path.directory</a></td>
  1690. <td>Get the directory name of the path</td>
  1691. <td>>= 2.0.1</td>
  1692. </tr>
  1693. <tr>
  1694. <td><a href="#pathrelative">path.relative</a></td>
  1695. <td>Convert to relative path</td>
  1696. <td>>= 2.0.1</td>
  1697. </tr>
  1698. <tr>
  1699. <td><a href="#pathabsolute">path.absolute</a></td>
  1700. <td>Convert to absolute path</td>
  1701. <td>>= 2.0.1</td>
  1702. </tr>
  1703. <tr>
  1704. <td><a href="#pathis_absolute">path.is_absolute</a></td>
  1705. <td>Determine if it is an absolute path</td>
  1706. <td>>= 2.0.1</td>
  1707. </tr>
  1708. <tr>
  1709. <td><a href="#pathsplit">path.split</a></td>
  1710. <td>Split by the separator</td>
  1711. <td>>= 2.0.1</td>
  1712. </tr>
  1713. <tr>
  1714. <td><a href="#pathsep">path.sep</a></td>
  1715. <td>Get the separator character</td>
  1716. <td>>= 2.0.1</td>
  1717. </tr>
  1718. <tr>
  1719. <td><a href="#pathislastsep">path.islastsep</a></td>
  1720. <td>Get if the last character is a separator</td>
  1721. <td>>= 2.0.1</td>
  1722. </tr>
  1723. <tr>
  1724. <td><a href="#pathsplitenv">path.splitenv</a></td>
  1725. <td>Split a environment variable value of an array of pathes</td>
  1726. <td>>= 2.2.7</td>
  1727. </tr>
  1728. <tr>
  1729. <td><a href="#pathjoinenv">path.joinenv</a></td>
  1730. <td>Concat environment variable with environment separator</td>
  1731. <td>>= 2.2.7</td>
  1732. </tr>
  1733. <tr>
  1734. <td><a href="#pathenvsep">path.envsep</a></td>
  1735. <td>Get the path seperator of environment variable</td>
  1736. <td>>= 2.2.7</td>
  1737. </tr>
  1738. <tr>
  1739. <td><a href="#pathcygwin_path">path.cygwin_path</a></td>
  1740. <td>Get the converted MSYS2/Cygwin style path</td>
  1741. <td>>= 2.2.7</td>
  1742. </tr>
  1743. <tr>
  1744. <td><a href="#pathpattern">path.pattern</a></td>
  1745. <td>Convert a path pattern to a lua pattern</td>
  1746. <td>>= 2.2.7</td>
  1747. </tr>
  1748. </tbody>
  1749. </table>
  1750. <h4 id="pathnew">path.new</h4>
  1751. <ul>
  1752. <li>Create a new path instance</li>
  1753. </ul>
  1754. <pre><code class="lang-lua">local p = path.new("/tmp/file.txt")
  1755. print(p:filename())
  1756. </code></pre>
  1757. <p>The result is: <code>file.txt</code></p>
  1758. <h4 id="pathjoin">path.join</h4>
  1759. <ul>
  1760. <li>Stitching path</li>
  1761. </ul>
  1762. <p>Adding multiple path items by splicing. Due to the path difference of <code>windows/unix</code> style, using api to append paths is more cross-platform, for example:</p>
  1763. <pre><code class="lang-lua">print(path.join("$(tmpdir)", "dir1", "dir2", "file.txt"))
  1764. </code></pre>
  1765. <p>The above splicing on Unix is equivalent to: <code>$(tmpdir)/dir1/dir2/file.txt</code>, and on Windows is equivalent to: <code>$(tmpdir)\\dir1\\dir2\\file.txt</code></p>
  1766. <p>If you find this cumbersome and not clear enough, you can use: <a href="#pathtranslate">path.translate</a> to format the conversion path string to the format supported by the current platform.</p>
  1767. <h4 id="pathtranslate">path.translate</h4>
  1768. <ul>
  1769. <li>Convert path to the path style of the current platform</li>
  1770. </ul>
  1771. <p>Formatting converts the specified path string to the path style supported by the current platform, and supports the path string parameter of the <code>windows/unix</code> format to be passed in, even mixed, such as:</p>
  1772. <pre><code class="lang-lua">print(path.translate("$(tmpdir)/dir/file.txt"))
  1773. print(path.translate("$(tmpdir)\\dir\\file.txt"))
  1774. print(path.translate("$(tmpdir)\\dir/dir2//file.txt"))
  1775. </code></pre>
  1776. <p>The path strings of the above three different formats, after being standardized by <code>translate</code>, will become the format supported by the current platform, and the redundant path separator will be removed.</p>
  1777. <h4 id="pathbasename">path.basename</h4>
  1778. <ul>
  1779. <li>Get the file name with no suffix at the end of the path</li>
  1780. </ul>
  1781. <pre><code class="lang-lua">print(path.basename("$(tmpdir)/dir/file.txt"))
  1782. </code></pre>
  1783. <p>The result is: <code>file</code></p>
  1784. <h4 id="pathfilename">path.filename</h4>
  1785. <ul>
  1786. <li>Get the file name with the last suffix of the path</li>
  1787. </ul>
  1788. <pre><code class="lang-lua">print(path.filename("$(tmpdir)/dir/file.txt"))
  1789. </code></pre>
  1790. <p>The result is: <code>file.txt</code></p>
  1791. <h4 id="pathextension">path.extension</h4>
  1792. <ul>
  1793. <li>Get the suffix of the path</li>
  1794. </ul>
  1795. <pre><code class="lang-lua">print(path.extensione("$(tmpdir)/dir/file.txt"))
  1796. </code></pre>
  1797. <p>The result is: <code>.txt</code></p>
  1798. <h4 id="pathdirectory">path.directory</h4>
  1799. <ul>
  1800. <li>Get the directory name of the path</li>
  1801. </ul>
  1802. <pre><code class="lang-lua">Print(path.directory("$(tmpdir)/dir/file.txt"))
  1803. </code></pre>
  1804. <p>The result is: <code>$(tmpdir)/dir</code></p>
  1805. <h4 id="pathrelative">path.relative</h4>
  1806. <ul>
  1807. <li>Convert to relative path</li>
  1808. </ul>
  1809. <pre><code class="lang-lua">print(path.relative("$(tmpdir)/dir/file.txt", "$(tmpdir)"))
  1810. </code></pre>
  1811. <p>The result is: <code>dir/file.txt</code></p>
  1812. <p>The second parameter is to specify the relative root directory. If not specified, the default is relative to the current directory:</p>
  1813. <pre><code class="lang-lua">os.cd("$(tmpdir)")
  1814. print(path.relative("$(tmpdir)/dir/file.txt"))
  1815. </code></pre>
  1816. <p>The result is the same.</p>
  1817. <h4 id="pathabsolute">path.absolute</h4>
  1818. <ul>
  1819. <li>Convert to absolute path</li>
  1820. </ul>
  1821. <pre><code class="lang-lua">print(path.absolute("dir/file.txt", "$(tmpdir)"))
  1822. </code></pre>
  1823. <p>The result is: <code>$(tmpdir)/dir/file.txt</code></p>
  1824. <p>The second parameter is to specify the relative root directory. If not specified, the default is relative to the current directory:</p>
  1825. <pre><code class="lang-lua">os.cd("$(tmpdir)")
  1826. print(path.absolute("dir/file.txt"))
  1827. </code></pre>
  1828. <p>The result is the same.</p>
  1829. <h4 id="pathis_absolute">path.is_absolute</h4>
  1830. <ul>
  1831. <li>Determine if it is an absolute path</li>
  1832. </ul>
  1833. <pre><code class="lang-lua">if path.is_absolute("/tmp/file.txt") then
  1834. -- if it is an absolute path
  1835. end
  1836. </code></pre>
  1837. <h4 id="pathsplit">path.split</h4>
  1838. <ul>
  1839. <li>Split the path by the separator </li>
  1840. </ul>
  1841. <pre><code class="lang-lua">print(path.split("/tmp/file.txt"))
  1842. </code></pre>
  1843. <p>The result is: <code>{ "tmp", "file.txt" }</code></p>
  1844. <h4 id="pathsep">path.sep</h4>
  1845. <ul>
  1846. <li>Return the current separator, usually <code>/</code> </li>
  1847. </ul>
  1848. <pre><code class="lang-lua">print(path.sep("/tmp/file.txt"))
  1849. </code></pre>
  1850. <p>The result is: <code>/</code></p>
  1851. <h4 id="pathislastsep">path.islastsep</h4>
  1852. <ul>
  1853. <li>Get if the last character is a separator</li>
  1854. </ul>
  1855. <pre><code class="lang-lua">if (path.islastsep("/tmp/dir/")) then
  1856. -- if the last character is a separator
  1857. end
  1858. </code></pre>
  1859. <h4 id="pathsplitenv">path.splitenv</h4>
  1860. <ul>
  1861. <li>Split a environment variable value of an array of pathes</li>
  1862. </ul>
  1863. <pre><code class="lang-lua">local pathes = path.splitenv(vformat("$(env PATH)"))
  1864. -- for windows
  1865. local pathes = path.splitenv("C:\\Windows;C:\\Windows\\System32")
  1866. -- got { "C:\\Windows", "C:\\Windows\\System32" }
  1867. -- for *nix
  1868. local pathes = path.splitenv("/usr/bin:/usr/local/bin")
  1869. -- got { "/usr/bin", "/usr/local/bin" }
  1870. </code></pre>
  1871. <p>The result is an array of strings, each item is a path in the input string.</p>
  1872. <h4 id="pathjoinenv">path.joinenv</h4>
  1873. <ul>
  1874. <li>Concat two environment variable by the environment separator</li>
  1875. </ul>
  1876. <pre><code class="lang-lua">print(path.joinenv({"/tmp/dir", "/tmp/dir2"}))
  1877. </code></pre>
  1878. <p>The result is: <code>/tmp/dir;/tmp/dir2</code> (on Windows)</p>
  1879. <h4 id="pathenvsep">path.envsep</h4>
  1880. <ul>
  1881. <li>Get the environment separator</li>
  1882. </ul>
  1883. <pre><code class="lang-lua">print(path.envsep())
  1884. </code></pre>
  1885. <p>The result is: <code>;</code></p>
  1886. <h4 id="pathcygwin_path">path.cygwin_path</h4>
  1887. <ul>
  1888. <li>Get the converted MSYS2/Cygwin style path </li>
  1889. </ul>
  1890. <pre><code class="lang-lua">print(path.cygwin_path("C:\\Windows"))
  1891. </code></pre>
  1892. <p>The result is: <code>/C/Windows</code></p>
  1893. <h4 id="pathpattern">path.pattern</h4>
  1894. <ul>
  1895. <li>Convert path pattern to lua pattern</li>
  1896. </ul>
  1897. <pre><code class="lang-lua">print(path.pattern("/tmp/file.txt"))
  1898. </code></pre>
  1899. <p>The result is: <code>/[tT][mM][pP]/[fF][iI][lL][eE]%.[tT][xX][tT]</code></p>
  1900. <h3 id="table">table</h3>
  1901. <p>Table belongs to the module provided by Lua native. For the native interface, you can refer to: <a href="https://www.lua.org/manual/5.1/manual.html#5.5">lua official document</a></p>
  1902. <p>It has been extended in xmake to add some extension interfaces:</p>
  1903. <table>
  1904. <thead>
  1905. <tr>
  1906. <th>Interface</th>
  1907. <th>Description</th>
  1908. <th>Supported Versions</th>
  1909. </tr>
  1910. </thead>
  1911. <tbody>
  1912. <tr>
  1913. <td><a href="#tablejoin">table.join</a></td>
  1914. <td>Merge multiple tables and return</td>
  1915. <td>>= 2.0.1</td>
  1916. </tr>
  1917. <tr>
  1918. <td><a href="#tablejoin2">table.join2</a></td>
  1919. <td>Merge multiple tables into the first table</td>
  1920. <td>>= 2.0.1</td>
  1921. </tr>
  1922. <tr>
  1923. <td><a href="#tableunique">table.unique</a></td>
  1924. <td>Deduplicate the contents of the table</td>
  1925. <td>>= 2.0.1</td>
  1926. </tr>
  1927. <tr>
  1928. <td><a href="#tableslice">table.slice</a></td>
  1929. <td>Get the slice of the table</td>
  1930. <td>>= 2.0.1</td>
  1931. </tr>
  1932. </tbody>
  1933. </table>
  1934. <h4 id="tablejoin">table.join</h4>
  1935. <ul>
  1936. <li>Merge multiple tables and return</li>
  1937. </ul>
  1938. <p>You can merge the elements in multiple tables and return to a new table, for example:</p>
  1939. <pre><code class="lang-lua">local newtable = table.join({1, 2, 3}, {4, 5, 6}, {7, 8, 9})
  1940. </code></pre>
  1941. <p>The result is: <code>{1, 2, 3, 4, 5, 6, 7, 8, 9}</code></p>
  1942. <p>And it also supports the merging of dictionaries:</p>
  1943. <pre><code class="lang-lua">local newtable = table.join({a = "a", b = "b"}, {c = "c"}, {d = "d"})
  1944. </code></pre>
  1945. <p>The result is: <code>{a = "a", b = "b", c = "c", d = "d"}</code></p>
  1946. <h4 id="tablejoin2">table.join2</h4>
  1947. <ul>
  1948. <li>Combine multiple tables into the first table</li>
  1949. </ul>
  1950. <p>Similar to <a href="#table.join">table.join</a>, the only difference is that the result of the merge is placed in the first argument, for example:</p>
  1951. <pre><code class="lang-lua">local t = {0, 9}
  1952. table.join2(t, {1, 2, 3})
  1953. </code></pre>
  1954. <p>The result is: <code>t = {0, 9, 1, 2, 3}</code></p>
  1955. <h4 id="tableunique">table.unique</h4>
  1956. <ul>
  1957. <li>Deduplicate the contents of the table</li>
  1958. </ul>
  1959. <p>To de-table elements, generally used in array tables, for example:</p>
  1960. <pre><code class="lang-lua">local newtable = table.unique({1, 1, 2, 3, 4, 4, 5})
  1961. </code></pre>
  1962. <p>The result is: <code>{1, 2, 3, 4, 5}</code></p>
  1963. <h4 id="tableslice">table.slice</h4>
  1964. <ul>
  1965. <li>Get the slice of the table</li>
  1966. </ul>
  1967. <p>Used to extract some elements of an array table, for example:</p>
  1968. <pre><code class="lang-lua">-- Extract all elements after the 4th element, resulting in: {4, 5, 6, 7, 8, 9}
  1969. table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4)
  1970. -- Extract the 4th-8th element and the result: {4, 5, 6, 7, 8}
  1971. table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8)
  1972. -- Extract the 4th-8th element with an interval of 2, resulting in: {4, 6, 8}
  1973. table.slice({1, 2, 3, 4, 5, 6, 7, 8, 9}, 4, 8, 2)
  1974. </code></pre>
  1975. <h4 id="tablecontains">table.contains</h4>
  1976. <ul>
  1977. <li>Determine that the table contains the specified value</li>
  1978. </ul>
  1979. <pre><code class="lang-lua">if table.contains(t, 1, 2, 3) then
  1980. - ...
  1981. end
  1982. </code></pre>
  1983. <p>As long as the table contains any value from 1, 2, 3, it returns true</p>
  1984. <h4 id="tableorderkeys">table.orderkeys</h4>
  1985. <ul>
  1986. <li>Get an ordered list of keys</li>
  1987. </ul>
  1988. <p>The order of the key list returned by <code>table.keys(t)</code> is random. If you want to get an ordered key list, you can use this interface.</p>
  1989. <h3 id="string">string</h3>
  1990. <p>The string module is a native module of lua. For details, see: <a href="https://www.lua.org/manual/5.1/manual.html#5.4">lua official manual</a></p>
  1991. <p>It has been extended in xmake to add some extension interfaces:</p>
  1992. <table>
  1993. <thead>
  1994. <tr>
  1995. <th>Interface</th>
  1996. <th>Description</th>
  1997. <th>Supported Versions</th>
  1998. </tr>
  1999. </thead>
  2000. <tbody>
  2001. <tr>
  2002. <td><a href="#stringstartswith">string.startswith</a></td>
  2003. <td>Determine if the beginning of the string matches</td>
  2004. <td>>= 1.0.1</td>
  2005. </tr>
  2006. <tr>
  2007. <td><a href="#stringendswith">string.endswith</a></td>
  2008. <td>Determine if the end of the string matches</td>
  2009. <td>>= 1.0.1</td>
  2010. </tr>
  2011. <tr>
  2012. <td><a href="#stringsplit">string.split</a></td>
  2013. <td>Split String</td>
  2014. <td>>= 1.0.1</td>
  2015. </tr>
  2016. <tr>
  2017. <td><a href="#stringtrim">string.trim</a></td>
  2018. <td>Remove the left and right whitespace characters</td>
  2019. <td>>= 1.0.1</td>
  2020. </tr>
  2021. <tr>
  2022. <td><a href="#stringltrim">string.ltrim</a></td>
  2023. <td>Remove the whitespace character to the left of the string</td>
  2024. <td>>= 1.0.1</td>
  2025. </tr>
  2026. <tr>
  2027. <td><a href="#stringrtrim">string.rtrim</a></td>
  2028. <td>Remove the whitespace character to the right of the string</td>
  2029. <td>>= 1.0.1</td>
  2030. </tr>
  2031. </tbody>
  2032. </table>
  2033. <h4 id="stringstartswith">string.startswith</h4>
  2034. <ul>
  2035. <li>Determine if the beginning of the string matches</li>
  2036. </ul>
  2037. <pre><code class="lang-lua">local s = "hello xmake"
  2038. if s:startswith("hello") then
  2039. print("match")
  2040. end
  2041. </code></pre>
  2042. <h4 id="stringendswith">string.endswith</h4>
  2043. <ul>
  2044. <li>Determine if the end of the string matches</li>
  2045. </ul>
  2046. <pre><code class="lang-lua">local s = "hello xmake"
  2047. if s:endswith("xmake") then
  2048. print("match")
  2049. end
  2050. </code></pre>
  2051. <h4 id="stringsplit">string.split</h4>
  2052. <p>pattern match and ignore empty string</p>
  2053. <pre><code class="lang-lua">("1\n\n2\n3"):split(&#39;\n&#39;) => 1, 2, 3
  2054. ("abc123123xyz123abc"):split(&#39;123&#39;) => abc, xyz, abc
  2055. ("abc123123xyz123abc"):split(&#39;[123]+&#39;) => abc, xyz, abc
  2056. </code></pre>
  2057. <p>plain match and ignore empty string</p>
  2058. <pre><code class="lang-lua">("1\n\n2\n3"):split(&#39;\n&#39;, {plain = true}) => 1, 2, 3
  2059. ("abc123123xyz123abc"):split(&#39;123&#39;, {plain = true}) => abc, xyz, abc
  2060. </code></pre>
  2061. <p>pattern match and contains empty string</p>
  2062. <pre><code class="lang-lua">("1\n\n2\n3"):split(&#39;\n&#39;, {strict = true}) => 1, , 2, 3
  2063. ("abc123123xyz123abc"):split(&#39;123&#39;, {strict = true}) => abc, , xyz, abc
  2064. ("abc123123xyz123abc"):split(&#39;[123]+&#39;, {strict = true}) => abc, xyz, abc
  2065. </code></pre>
  2066. <p>plain match and contains empty string</p>
  2067. <pre><code class="lang-lua">("1\n\n2\n3"):split(&#39;\n&#39;, {plain = true, strict = true}) => 1, , 2, 3
  2068. ("abc123123xyz123abc"):split(&#39;123&#39;, {plain = true, strict = true}) => abc, , xyz, abc
  2069. </code></pre>
  2070. <p>limit split count</p>
  2071. <pre><code class="lang-lua">("1\n\n2\n3"):split(&#39;\n&#39;, {limit = 2}) => 1, 2\n3
  2072. ("1.2.3.4.5"):split(&#39;%.&#39;, {limit = 3}) => 1, 2, 3.4.5
  2073. </code></pre>
  2074. <h4 id="stringtrim">string.trim</h4>
  2075. <ul>
  2076. <li>Remove the left and right whitespace characters of the string</li>
  2077. </ul>
  2078. <pre><code class="lang-lua">string.trim(" hello xmake! ")
  2079. </code></pre>
  2080. <p>The result is: "hello xmake!"</p>
  2081. <h4 id="stringltrim">string.ltrim</h4>
  2082. <ul>
  2083. <li>Remove the whitespace character to the left of the string</li>
  2084. </ul>
  2085. <pre><code class="lang-lua">string.ltrim(" hello xmake! ")
  2086. </code></pre>
  2087. <p>The result is: "hello xmake! "</p>
  2088. <h4 id="stringrtrim">string.rtrim</h4>
  2089. <ul>
  2090. <li>Remove the whitespace character to the right of the string</li>
  2091. </ul>
  2092. <pre><code class="lang-lua">string.rtrim(" hello xmake! ")
  2093. </code></pre>
  2094. <p>The result is: " hello xmake!"</p>
  2095. <h3 id="coroutine">coroutine</h3>
  2096. <p>The coroutine module is a native module of lua. For use, see: <a href="https://www.lua.org/manual/5.1/manual.html#5.2">lua official manual</a></p>
  2097. <h3 id="signal">signal</h3>
  2098. <p>2.9.1 adds a new signal registration interface. We can register signal processing functions such as SIGINT in the Lua layer to customize the response logic.</p>
  2099. <h4 id="signalregister">signal.register</h4>
  2100. <ul>
  2101. <li>Register signal handler</li>
  2102. </ul>
  2103. <p>Currently, it only supports SIGINT signal processing, and it also supports mainstream platforms such as windows.</p>
  2104. <pre><code class="lang-lua">import("core.base.signal")
  2105. function main()
  2106. signal.register(signal.SIGINT, function (signo)
  2107. print("signal.SIGINT(%d)", signo)
  2108. end)
  2109. io.read()
  2110. end
  2111. </code></pre>
  2112. <p>This is useful when some sub-processes internally shield SIGINT, causing them to freeze and not exit. Even if the user presses <code>Ctrl+C</code> to exit the xmake process, it does not exit.<br>We can force it out in this way.</p>
  2113. <pre><code class="lang-lua">import("core.base.process")
  2114. import("core.base.signal")
  2115. function main()
  2116. local proc
  2117. signal.register(signal.SIGINT, function (signo)
  2118. print("sigint")
  2119. if proc then
  2120. proc:kill()
  2121. end
  2122. end)
  2123. proc = process.open("./trap.sh")
  2124. if proc then
  2125. proc:wait()
  2126. proc:close()
  2127. end
  2128. end
  2129. </code></pre>
  2130. <p>For the background of this issue, please refer to: <a href="https://github.com/xmake-io/xmake/issues/4889">#4889</a></p>
  2131. <h4 id="signalignore">signal.ignore</h4>
  2132. <ul>
  2133. <li>Ignore a signal</li>
  2134. </ul>
  2135. <p>We can also ignore the processing of blocking a certain signal through the <code>signal.ignore</code> interface.</p>
  2136. <pre><code class="lang-lua">signal.ignore(signal.SIGINT)
  2137. </code></pre>
  2138. <h4 id="signalreset">signal.reset</h4>
  2139. <ul>
  2140. <li>Reset a signal</li>
  2141. </ul>
  2142. <p>We can also clear the processing function of a certain signal and fall back to the default processing logic.</p>
  2143. <pre><code class="lang-lua">signal.reset(signal.SIGINT)
  2144. </code></pre>
  2145. </article>
  2146. </body>
  2147. </html>