| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>xmake</title>
- <link rel="icon" href="/assets/img/favicon.ico">
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
- <meta name="description" content="Description">
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <link href="/assets/npm/github-markdown/github-markdown.min.css" rel="stylesheet">
- <style>
- .markdown-body {
- box-sizing: border-box;
- min-width: 200px;
- max-width: 980px;
- margin: 0 auto;
- padding: 45px;
- }
- @media (max-width: 767px) {
- .markdown-body {
- padding: 15px;
- }
- }
- </style>
- </head>
- <body>
- <article class="markdown-body">
- <h4>This is a mirror page, please see the original page: </h4><a href="https://xmake.io/#/zh-cn/manual/extension_modules">https://xmake.io/#/zh-cn/manual/extension_modules</a>
- <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>
- </br>
- <script type="text/javascript" charset="UTF-8" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
- <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
- <style>
- #carbonads {
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
- Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
- }
- #carbonads {
- display: flex;
- max-width: 330px;
- background-color: hsl(0, 0%, 98%);
- box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
- }
- #carbonads a {
- color: inherit;
- text-decoration: none;
- }
- #carbonads a:hover {
- color: inherit;
- }
- #carbonads span {
- position: relative;
- display: block;
- overflow: hidden;
- }
- #carbonads .carbon-wrap {
- display: flex;
- }
- .carbon-img {
- display: block;
- margin: 0;
- line-height: 1;
- }
- .carbon-img img {
- display: block;
- }
- .carbon-text {
- font-size: 13px;
- padding: 10px;
- line-height: 1.5;
- text-align: left;
- }
- .carbon-poweredby {
- display: block;
- padding: 8px 10px;
- 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);
- text-align: center;
- text-transform: uppercase;
- letter-spacing: .5px;
- font-weight: 600;
- font-size: 9px;
- line-height: 1;
- }
- </style>
- <p>所有扩展模块的使用,都需要通过<a href="/mirror/zh-cn/manual/builtin_modules.html#import">import</a>接口,进行导入后才能使用。</p>
- <h3 id="corebaseoption">core.base.option</h3>
- <p>一般用于获取xmake命令参数选项的值,常用于插件开发。</p>
- <h4 id="optionget">option.get</h4>
- <ul>
- <li>获取参数选项值</li>
- </ul>
- <p>在插件开发中用于获取参数选项值,例如:</p>
- <pre><code class="lang-lua">-- 导入选项模块
- import("core.base.option")
- -- 插件入口函数
- function main(...)
- print(option.get("info"))
- end
- </code></pre>
- <p>上面的代码获取hello插件,执行:<code>xmake hello --info=xxxx</code> 命令时候传入的<code>--info=</code>选项的值,并显示:<code>xxxx</code></p>
- <p>对于非main入口的task任务或插件,可以这么使用:</p>
- <pre><code class="lang-lua">task("hello")
- on_run(function ())
- import("core.base.option")
- print(option.get("info"))
- end)
- </code></pre>
- <h3 id="corebaseglobal">core.base.global</h3>
- <p>用于获取xmake全局的配置信息,也就是<code>xmake g|global --xxx=val</code> 传入的参数选项值。</p>
- <p>!> 2.1.5版本之前为<code>core.project.global</code>。</p>
- <h4 id="globalget">global.get</h4>
- <ul>
- <li>获取指定配置值</li>
- </ul>
- <p>类似<a href="#configget">config.get</a>,唯一的区别就是这个是从全局配置中获取。</p>
- <h4 id="globalload">global.load</h4>
- <ul>
- <li>加载配置</li>
- </ul>
- <p>类似<a href="#globalget">global.get</a>,唯一的区别就是这个是从全局配置中加载。</p>
- <h4 id="globaldirectory">global.directory</h4>
- <ul>
- <li>获取全局配置信息目录</li>
- </ul>
- <p>默认为<code>~/.config</code>目录。</p>
- <h4 id="globaldump">global.dump</h4>
- <ul>
- <li>打印输出所有全局配置信息</li>
- </ul>
- <p>输出结果如下:</p>
- <pre><code class="lang-lua">{
- clean = true
- , ccache = "ccache"
- , xcode_dir = "/Applications/Xcode.app"
- }
- </code></pre>
- <h3 id="corebasetask">core.base.task</h3>
- <p>用于任务操作,一般用于在自定义脚本中、插件任务中,调用运行其他task任务。</p>
- <p>!> 2.1.5版本之前为<code>core.project.task</code>。</p>
- <h4 id="taskrun">task.run</h4>
- <ul>
- <li>运行指定任务</li>
- </ul>
- <p>用于在自定义脚本、插件任务中运行<a href="#task">task</a>定义的任务或插件,例如:</p>
- <pre><code class="lang-lua">task("hello")
- on_run(function ()
- print("hello xmake!")
- end)
- target("demo")
- on_clean(function(target)
- -- 导入task模块
- import("core.base.task")
- -- 运行这个hello task
- task.run("hello")
- end)
- </code></pre>
- <p>我们还可以在运行任务时,增加参数传递,例如:</p>
- <pre><code class="lang-lua">task("hello")
- on_run(function (arg1, arg2)
- print("hello xmake: %s %s!", arg1, arg2)
- end)
- target("demo")
- on_clean(function(target)
- -- 导入task
- import("core.base.task")
- -- {} 这个是给第一种选项传参使用,这里置空,这里在最后面传入了两个参数:arg1, arg2
- task.run("hello", {}, "arg1", "arg2")
- end)
- </code></pre>
- <p>对于<code>task.run</code>的第二个参数,用于传递命令行菜单中的选项,而不是直接传入<code>function (arg, ...)</code>函数入口中,例如:</p>
- <pre><code class="lang-lua">-- 导入task
- import("core.base.task")
- -- 插件入口
- function main(...)
- -- 运行内置的xmake配置任务,相当于:xmake f|config --plat=iphoneos --arch=armv7
- task.run("config", {plat="iphoneos", arch="armv7"})
- emd
- </code></pre>
- <h3 id="corebasejson">core.base.json</h3>
- <p>xmake 提供了内置的 json 模块,基于 lua_cjson 实现,我们可以用它实现快速的在 json 和 lua table 直接相互操作。</p>
- <p>我们可以通过 <code>import("core.base.json")</code> 直接导入使用。</p>
- <p>这里也有一些例子:<a href="https://github.com/xmake-io/xmake/blob/master/tests/modules/json/test.lua">Jsom Examples</a></p>
- <h4 id="jsondecode">json.decode</h4>
- <p>直接从字符串解码 json 获取 lua table.</p>
- <pre><code class="lang-lua">import("core.base.json")
- local luatable = json.decode('[1,"2", {"a":1, "b":true}]')
- print(luatable)
- </code></pre>
- <pre><code>{
- 1.0,
- "2",
- {
- b = true,
- a = 1.0
- }
- }
- </code></pre><p>!> 如果里面有 null,可以用 <code>json.null</code> 来判断</p>
- <h4 id="jsonencode">json.encode</h4>
- <p>我们也可以直接对一个 lua table 进行编码。</p>
- <pre><code class="lang-lua">local jsonstr = json.encode({1, "2", {a = 1}}
- </code></pre>
- <p>需要注意的是,如果需要编码 null,需要使用 <code>json.null</code>,例如</p>
- <pre><code class="lang-lua">local jsonstr = json.encode({json.null, 1, "2", false, true})
- </code></pre>
- <h4 id="jsonloadfile">json.loadfile</h4>
- <p>直接加载 json 文件,并解析成 lua table。</p>
- <pre><code class="lang-lua">local luatable = json.loadfile("/tmp/xxx.json")
- </code></pre>
- <h4 id="jsonsavefile">json.savefile</h4>
- <p>保存 lua table 到指定 json 文件。</p>
- <pre><code class="lang-lua">json.savefile("/tmp/xxx.json", {1, {a = 1}})
- </code></pre>
- <h3 id="coretoollinker">core.tool.linker</h3>
- <p>链接器相关操作,常用于插件开发。</p>
- <h4 id="linkerlink">linker.link</h4>
- <ul>
- <li>执行链接</li>
- </ul>
- <p>针对target,链接指定对象文件列表,生成对应的目标文件,例如:</p>
- <pre><code class="lang-lua">linker.link("binary", "cc", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
- </code></pre>
- <p>其中<a href="#target">target</a>,为工程目标,这里传入,主要用于获取target特定的链接选项,具体如果获取工程目标对象,见:<a href="#core-project-project">core.project.project</a></p>
- <p>当然也可以不指定target,例如:</p>
- <pre><code class="lang-lua">linker.link("binary", "cc", {"a.o", "b.o", "c.o"}, "/tmp/targetfile")
- </code></pre>
- <p>第一个参数指定链接类型,目前支持:binary, static, shared<br>第二个参数告诉链接器,应该作为那种源文件对象进行链接,这些对象源文件使用什么编译器编译的,例如:</p>
- <table>
- <thead>
- <tr>
- <th>第二个参数值</th>
- <th>描述</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>cc</td>
- <td>c编译器</td>
- </tr>
- <tr>
- <td>cxx</td>
- <td>c++编译器</td>
- </tr>
- <tr>
- <td>mm</td>
- <td>objc编译器</td>
- </tr>
- <tr>
- <td>mxx</td>
- <td>objc++编译器</td>
- </tr>
- <tr>
- <td>gc</td>
- <td>go编译器</td>
- </tr>
- <tr>
- <td>as</td>
- <td>汇编器</td>
- </tr>
- <tr>
- <td>sc</td>
- <td>swift编译器</td>
- </tr>
- <tr>
- <td>rc</td>
- <td>rust编译器</td>
- </tr>
- <tr>
- <td>dc</td>
- <td>dlang编译器</td>
- </tr>
- </tbody>
- </table>
- <p>指定不同的编译器类型,链接器会适配最合适的链接器来处理链接,并且如果几种支持混合编译的语言,那么可以同时传入多个编译器类型,指定链接器选择支持这些混合编译语言的链接器进行链接处理:</p>
- <pre><code class="lang-lua">linker.link("binary", {"cc", "mxx", "sc"}, {"a.o", "b.o", "c.o"}, "/tmp/targetfile")
- </code></pre>
- <p>上述代码告诉链接器,a, b, c三个对象文件有可能分别是c, objc++, swift代码编译出来的,链接器会从当前系统和工具链中选择最合适的链接器去处理这个链接过程。</p>
- <h4 id="linkerlinkcmd">linker.linkcmd</h4>
- <ul>
- <li>获取链接命令行字符串</li>
- </ul>
- <p>直接获取<a href="#linkerlink">linker.link</a>中执行的命令行字符串,相当于:</p>
- <pre><code class="lang-lua">local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
- </code></pre>
- <p>注:后面<code>{target = target}</code>扩展参数部分是可选的,如果传递了target对象,那么生成的链接命令,会加上这个target配置对应的链接选项。</p>
- <p>并且还可以自己传递各种配置,例如:</p>
- <pre><code class="lang-lua">local cmdstr = linker.linkcmd("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {configs = {linkdirs = "/usr/lib"}})
- </code></pre>
- <h4 id="linkerlinkargv">linker.linkargv</h4>
- <ul>
- <li>获取链接命令行参数列表</li>
- </ul>
- <p>跟<a href="#linkerlinkcmd">linker.linkcmd</a>稍微有点区别的是,此接口返回的是参数列表,table表示,更加方便操作:</p>
- <pre><code class="lang-lua">local program, argv = linker.linkargv("static", "cxx", {"a.o", "b.o", "c.o"}, target:targetfile(), {target = target})
- </code></pre>
- <p>其中返回的第一个值是主程序名,后面是参数列表,而<code>os.args(table.join(program, argv))</code>等价于<code>linker.linkcmd</code>。</p>
- <p>我们也可以通过传入返回值给<a href="#os-runv">os.runv</a>来直接运行它:<code>os.runv(linker.linkargv(..))</code></p>
- <h4 id="linkerlinkflags">linker.linkflags</h4>
- <ul>
- <li>获取链接选项</li>
- </ul>
- <p>获取<a href="#linkerlinkcmd">linker.linkcmd</a>中的链接选项字符串部分,不带shellname和对象文件列表,并且是按数组返回,例如:</p>
- <pre><code class="lang-lua">local flags = linker.linkflags("shared", "cc", {target = target})
- for _, flag in ipairs(flags) do
- print(flag)
- end
- </code></pre>
- <p>返回的是flags的列表数组。</p>
- <h4 id="linkerhas_flags">linker.has_flags</h4>
- <ul>
- <li>判断指定链接选项是否支持</li>
- </ul>
- <p>虽然通过<a href="detect-has_flags">lib.detect.has_flags</a>也能判断,但是那个接口更加底层,需要指定链接器名称<br>而此接口只需要指定target的目标类型,源文件类型,它会自动切换选择当前支持的链接器。</p>
- <pre><code class="lang-lua">if linker.has_flags(target:targetkind(), target:sourcekinds(), "-L/usr/lib -lpthread") then
- -- ok
- end
- </code></pre>
- <h3 id="coretoolcompiler">core.tool.compiler</h3>
- <p>编译器相关操作,常用于插件开发。</p>
- <h4 id="compilercompile">compiler.compile</h4>
- <ul>
- <li>执行编译</li>
- </ul>
- <p>针对target,链接指定对象文件列表,生成对应的目标文件,例如:</p>
- <pre><code class="lang-lua">compiler.compile("xxx.c", "xxx.o", "xxx.h.d", {target = target})
- </code></pre>
- <p>其中<a href="#target">target</a>,为工程目标,这里传入主要用于获取taeget的特定编译选项,具体如果获取工程目标对象,见:<a href="#core-project-project">core.project.project</a></p>
- <p>而<code>xxx.h.d</code>文件用于存储为此源文件的头文件依赖文件列表,最后这两个参数都是可选的,编译的时候可以不传他们:</p>
- <pre><code class="lang-lua">compiler.compile("xxx.c", "xxx.o")
- </code></pre>
- <p>来单纯编译一个源文件。</p>
- <h4 id="compilercompcmd">compiler.compcmd</h4>
- <ul>
- <li>获取编译命令行</li>
- </ul>
- <p>直接获取<a href="#compilercompile">compiler.compile</a>中执行的命令行字符串,相当于:</p>
- <pre><code class="lang-lua">local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {target = target})
- </code></pre>
- <p>注:后面<code>{target = target}</code>扩展参数部分是可选的,如果传递了target对象,那么生成的编译命令,会加上这个target配置对应的链接选项。</p>
- <p>并且还可以自己传递各种配置,例如:</p>
- <pre><code class="lang-lua">local cmdstr = compiler.compcmd("xxx.c", "xxx.o", {configs = {includedirs = "/usr/include", defines = "DEBUG"}})
- </code></pre>
- <p>通过target,我们可以导出指定目标的所有源文件编译命令:</p>
- <pre><code class="lang-lua">import("core.project.project")
- for _, target in pairs(project.targets()) do
- for sourcekind, sourcebatch in pairs(target:sourcebatches()) do
- for index, objectfile in ipairs(sourcebatch.objectfiles) do
- local cmdstr = compiler.compcmd(sourcebatch.sourcefiles[index], objectfile, {target = target})
- end
- end
- end
- </code></pre>
- <h4 id="compilercompargv">compiler.compargv</h4>
- <ul>
- <li>获取编译命令行列表</li>
- </ul>
- <p>跟<a href="#compilercompcmd">compiler.compcmd</a>稍微有点区别的是,此接口返回的是参数列表,table表示,更加方便操作:</p>
- <pre><code class="lang-lua">local program, argv = compiler.compargv("xxx.c", "xxx.o")
- </code></pre>
- <h4 id="compilercompflags">compiler.compflags</h4>
- <ul>
- <li>获取编译选项</li>
- </ul>
- <p>获取<a href="#compilercompcmd">compiler.compcmd</a>中的编译选项字符串部分,不带shellname和文件列表,例如:</p>
- <pre><code class="lang-lua">local flags = compiler.compflags(sourcefile, {target = target})
- for _, flag in ipairs(flags) do
- print(flag)
- end
- </code></pre>
- <p>返回的是flags的列表数组。</p>
- <h4 id="compilerhas_flags">compiler.has_flags</h4>
- <ul>
- <li>判断指定编译选项是否支持</li>
- </ul>
- <p>虽然通过<a href="detect-has_flags">lib.detect.has_flags</a>也能判断,但是那个接口更加底层,需要指定编译器名称。<br>而此接口只需要指定语言类型,它会自动切换选择当前支持的编译器。</p>
- <pre><code class="lang-lua">-- 判断c语言编译器是否支持选项: -g
- if compiler.has_flags("c", "-g") then
- -- ok
- end
- -- 判断c++语言编译器是否支持选项: -g
- if compiler.has_flags("cxx", "-g") then
- -- ok
- end
- </code></pre>
- <h4 id="compilerfeatures">compiler.features</h4>
- <ul>
- <li>获取所有编译器特性</li>
- </ul>
- <p>虽然通过<a href="detect-features">lib.detect.features</a>也能获取,但是那个接口更加底层,需要指定编译器名称。<br>而此接口只需要指定语言类型,它会自动切换选择当前支持的编译器,然后获取当前的编译器特性列表。</p>
- <pre><code class="lang-lua">-- 获取当前c语言编译器的所有特性
- local features = compiler.features("c")
- -- 获取当前c++语言编译器的所有特性,启用c++11标准,否则获取不到新标准的特性
- local features = compiler.features("cxx", {configs = {cxxflags = "-std=c++11"}})
- -- 获取当前c++语言编译器的所有特性,传递工程target的所有配置信息
- local features = compiler.features("cxx", {target = target, configs = {defines = "..", includedirs = ".."}})
- </code></pre>
- <p>所有c编译器特性列表:</p>
- <table>
- <thead>
- <tr>
- <th>特性名</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>c_static_assert</td>
- </tr>
- <tr>
- <td>c_restrict</td>
- </tr>
- <tr>
- <td>c_variadic_macros</td>
- </tr>
- <tr>
- <td>c_function_prototypes</td>
- </tr>
- </tbody>
- </table>
- <p>所有c++编译器特性列表:</p>
- <table>
- <thead>
- <tr>
- <th>特性名</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>cxx_variable_templates</td>
- </tr>
- <tr>
- <td>cxx_relaxed_constexpr</td>
- </tr>
- <tr>
- <td>cxx_aggregate_default_initializers</td>
- </tr>
- <tr>
- <td>cxx_contextual_conversions</td>
- </tr>
- <tr>
- <td>cxx_attribute_deprecated</td>
- </tr>
- <tr>
- <td>cxx_decltype_auto</td>
- </tr>
- <tr>
- <td>cxx_digit_separators</td>
- </tr>
- <tr>
- <td>cxx_generic_lambdas</td>
- </tr>
- <tr>
- <td>cxx_lambda_init_captures</td>
- </tr>
- <tr>
- <td>cxx_binary_literals</td>
- </tr>
- <tr>
- <td>cxx_return_type_deduction</td>
- </tr>
- <tr>
- <td>cxx_decltype_incomplete_return_types</td>
- </tr>
- <tr>
- <td>cxx_reference_qualified_functions</td>
- </tr>
- <tr>
- <td>cxx_alignof</td>
- </tr>
- <tr>
- <td>cxx_attributes</td>
- </tr>
- <tr>
- <td>cxx_inheriting_constructors</td>
- </tr>
- <tr>
- <td>cxx_thread_local</td>
- </tr>
- <tr>
- <td>cxx_alias_templates</td>
- </tr>
- <tr>
- <td>cxx_delegating_constructors</td>
- </tr>
- <tr>
- <td>cxx_extended_friend_declarations</td>
- </tr>
- <tr>
- <td>cxx_final</td>
- </tr>
- <tr>
- <td>cxx_nonstatic_member_init</td>
- </tr>
- <tr>
- <td>cxx_override</td>
- </tr>
- <tr>
- <td>cxx_user_literals</td>
- </tr>
- <tr>
- <td>cxx_constexpr</td>
- </tr>
- <tr>
- <td>cxx_defaulted_move_initializers</td>
- </tr>
- <tr>
- <td>cxx_enum_forward_declarations</td>
- </tr>
- <tr>
- <td>cxx_noexcept</td>
- </tr>
- <tr>
- <td>cxx_nullptr</td>
- </tr>
- <tr>
- <td>cxx_range_for</td>
- </tr>
- <tr>
- <td>cxx_unrestricted_unions</td>
- </tr>
- <tr>
- <td>cxx_explicit_conversions</td>
- </tr>
- <tr>
- <td>cxx_lambdas</td>
- </tr>
- <tr>
- <td>cxx_local_type_template_args</td>
- </tr>
- <tr>
- <td>cxx_raw_string_literals</td>
- </tr>
- <tr>
- <td>cxx_auto_type</td>
- </tr>
- <tr>
- <td>cxx_defaulted_functions</td>
- </tr>
- <tr>
- <td>cxx_deleted_functions</td>
- </tr>
- <tr>
- <td>cxx_generalized_initializers</td>
- </tr>
- <tr>
- <td>cxx_inline_namespaces</td>
- </tr>
- <tr>
- <td>cxx_sizeof_member</td>
- </tr>
- <tr>
- <td>cxx_strong_enums</td>
- </tr>
- <tr>
- <td>cxx_trailing_return_types</td>
- </tr>
- <tr>
- <td>cxx_unicode_literals</td>
- </tr>
- <tr>
- <td>cxx_uniform_initialization</td>
- </tr>
- <tr>
- <td>cxx_variadic_templates</td>
- </tr>
- <tr>
- <td>cxx_decltype</td>
- </tr>
- <tr>
- <td>cxx_default_function_template_args</td>
- </tr>
- <tr>
- <td>cxx_long_long_type</td>
- </tr>
- <tr>
- <td>cxx_right_angle_brackets</td>
- </tr>
- <tr>
- <td>cxx_rvalue_references</td>
- </tr>
- <tr>
- <td>cxx_static_assert</td>
- </tr>
- <tr>
- <td>cxx_extern_templates</td>
- </tr>
- <tr>
- <td>cxx_func_identifier</td>
- </tr>
- <tr>
- <td>cxx_variadic_macros</td>
- </tr>
- <tr>
- <td>cxx_template_template_parameters</td>
- </tr>
- </tbody>
- </table>
- <h4 id="compilerhas_features">compiler.has_features</h4>
- <ul>
- <li>判断指定的编译器特性是否支持</li>
- </ul>
- <p>虽然通过<a href="detect-has-features">lib.detect.has_features</a>也能获取,但是那个接口更加底层,需要指定编译器名称。<br>而此接口只需要指定需要检测的特姓名称列表,就能自动切换选择当前支持的编译器,然后判断指定特性在当前的编译器中是否支持。</p>
- <pre><code class="lang-lua">if compiler.has_features("c_static_assert") then
- -- ok
- end
- if compiler.has_features({"c_static_assert", "cxx_constexpr"}, {languages = "cxx11"}) then
- -- ok
- end
- if compiler.has_features("cxx_constexpr", {target = target, defines = "..", includedirs = ".."}) then
- -- ok
- end
- </code></pre>
- <p>具体特性名有哪些,可以参考:<a href="#compilerfeatures">compiler.features</a>。</p>
- <h3 id="coreprojectconfig">core.project.config</h3>
- <p>用于获取工程编译时候的配置信息,也就是<code>xmake f|config --xxx=val</code> 传入的参数选项值。</p>
- <h4 id="configget">config.get</h4>
- <ul>
- <li>获取指定配置值</li>
- </ul>
- <p>用于获取<code>xmake f|config --xxx=val</code>的配置值,例如:</p>
- <pre><code class="lang-lua">target("test")
- on_run(function (target)
- -- 导入配置模块
- import("core.project.config")
- -- 获取配置值
- print(config.get("xxx"))
- end)
- </code></pre>
- <h4 id="configload">config.load</h4>
- <ul>
- <li>加载配置</li>
- </ul>
- <p>一般用于插件开发中,插件任务中不像工程的自定义脚本,环境需要自己初始化加载,默认工程配置是没有被加载的,如果要用<a href="#configget">config.get</a>接口获取工程配置,那么需要先:</p>
- <pre><code class="lang-lua">
- -- 导入配置模块
- import("core.project.config")
- function main(...)
- -- 先加载工程配置
- config.load()
- -- 获取配置值
- print(config.get("xxx"))
- end
- </code></pre>
- <h4 id="configarch">config.arch</h4>
- <ul>
- <li>获取当前工程的架构配置</li>
- </ul>
- <p>也就是获取<code>xmake f|config --arch=armv7</code>的平台配置,相当于<code>config.get("arch")</code>。</p>
- <h4 id="configplat">config.plat</h4>
- <ul>
- <li>获取当前工程的平台配置</li>
- </ul>
- <p>也就是获取<code>xmake f|config --plat=iphoneos</code>的平台配置,相当于<code>config.get("plat")</code>。</p>
- <h4 id="configmode">config.mode</h4>
- <ul>
- <li>获取当前工程的编译模式配置</li>
- </ul>
- <p>也就是获取<code>xmake f|config --mode=debug</code>的平台配置,相当于<code>config.get("mode")</code>。</p>
- <h4 id="configbuildir">config.buildir</h4>
- <ul>
- <li>获取当前工程的输出目录配置</li>
- </ul>
- <p>也就是获取<code>xmake f|config -o /tmp/output</code>的平台配置,相当于<code>config.get("buildir")</code>。</p>
- <h4 id="configdirectory">config.directory</h4>
- <ul>
- <li>获取当前工程的配置信息目录</li>
- </ul>
- <p>获取工程配置的存储目录,默认为:<code>projectdir/.config</code></p>
- <h4 id="configdump">config.dump</h4>
- <ul>
- <li>打印输出当前工程的所有配置信息</li>
- </ul>
- <p>输出结果例如:</p>
- <pre><code class="lang-lua">{
- sh = "xcrun -sdk macosx clang++"
- , xcode_dir = "/Applications/Xcode.app"
- , ar = "xcrun -sdk macosx ar"
- , small = true
- , object = false
- , arch = "x86_64"
- , xcode_sdkver = "10.12"
- , ex = "xcrun -sdk macosx ar"
- , cc = "xcrun -sdk macosx clang"
- , rc = "rustc"
- , plat = "macosx"
- , micro = false
- , host = "macosx"
- , as = "xcrun -sdk macosx clang"
- , dc = "dmd"
- , gc = "go"
- , openssl = false
- , ccache = "ccache"
- , cxx = "xcrun -sdk macosx clang"
- , sc = "xcrun -sdk macosx swiftc"
- , mm = "xcrun -sdk macosx clang"
- , buildir = "build"
- , mxx = "xcrun -sdk macosx clang++"
- , ld = "xcrun -sdk macosx clang++"
- , mode = "release"
- , kind = "static"
- }
- </code></pre>
- <h3 id="coreprojectproject">core.project.project</h3>
- <p>用于获取当前工程的一些描述信息,也就是在<code>xmake.lua</code>工程描述文件中定义的配置信息,例如:<a href="#target">target</a>、<a href="#option">option</a>等。</p>
- <h4 id="projectload">project.load</h4>
- <ul>
- <li>加载工程描述配置</li>
- </ul>
- <p>仅在插件中使用,因为这个时候还没有加载工程配置信息,在工程目标的自定义脚本中,不需要执行此操作,就可以直接访问工程配置。</p>
- <pre><code class="lang-lua">-- 导入工程模块
- import("core.project.project")
- -- 插件入口
- function main(...)
- -- 加载工程描述配置
- project.load()
- -- 访问工程描述,例如获取指定工程目标
- local target = project.target("test")
- end
- </code></pre>
- <p>!> 2.1.5版本后,不在需要,工程加载会自动在合适时机延迟加载。</p>
- <h4 id="projectdirectory">project.directory</h4>
- <ul>
- <li>获取工程目录</li>
- </ul>
- <p>获取当前工程目录,也就是<code>xmake -P xxx</code>中指定的目录,否则为默认当前<code>xmake</code>命令执行目录。</p>
- <p>!> 2.1.5版本后,建议使用<a href="#os-projectdir">os.projectdir</a>来获取。</p>
- <h4 id="projecttarget">project.target</h4>
- <ul>
- <li>获取指定工程目标对象</li>
- </ul>
- <p>获取和访问指定工程目标配置,例如:</p>
- <pre><code class="lang-lua">local target = project.target("test")
- if target then
- -- 获取目标名
- print(target:name())
- -- 获取目标目录, 2.1.9版本之后才有
- print(target:targetdir())
- -- 获取目标文件名
- print(target:targetfile())
- -- 获取目标类型,也就是:binary, static, shared
- print(target:targetkind())
- -- 获取目标名
- print(target:name())
- -- 获取目标源文件
- local sourcefiles = target:sourcefiles()
- -- 获取目标安装头文件列表
- local srcheaders, dstheaders = target:headerfiles()
- -- 获取目标依赖
- print(target:get("deps"))
- end
- </code></pre>
- <h4 id="projecttargets">project.targets</h4>
- <ul>
- <li>获取工程目标对象列表</li>
- </ul>
- <p>返回当前工程的所有编译目标,例如:</p>
- <pre><code class="lang-lua">for targetname, target in pairs(project.targets())
- print(target:targetfile())
- end
- </code></pre>
- <h4 id="projectoption">project.option</h4>
- <ul>
- <li>获取指定选项对象</li>
- </ul>
- <p>获取和访问工程中指定的选项对象,例如:</p>
- <pre><code class="lang-lua">local option = project.option("test")
- if option:enabled() then
- option:enable(false)
- end
- </code></pre>
- <h4 id="projectoptions">project.options</h4>
- <ul>
- <li>获取工程所有选项对象</li>
- </ul>
- <p>返回当前工程的所有编译目标,例如:</p>
- <pre><code class="lang-lua">for optionname, option in pairs(project.options())
- print(option:enabled())
- end
- </code></pre>
- <h4 id="projectname">project.name</h4>
- <ul>
- <li>获取当前工程名</li>
- </ul>
- <p>也就是获取<a href="#set_project">set_project</a>的工程名配置。</p>
- <pre><code class="lang-lua">print(project.name())
- </code></pre>
- <h4 id="projectversion">project.version</h4>
- <ul>
- <li>获取当前工程版本号</li>
- </ul>
- <p>也就是获取<a href="#set_version">set_version</a>的工程版本配置。</p>
- <pre><code class="lang-lua">print(project.version())
- </code></pre>
- <h3 id="corelanguagelanguage">core.language.language</h3>
- <p>用于获取编译语言相关信息,一般用于代码文件的操作。</p>
- <h4 id="languageextensions">language.extensions</h4>
- <ul>
- <li>获取所有语言的代码后缀名列表</li>
- </ul>
- <p>获取结果如下:</p>
- <pre><code class="lang-lua">{
- [".c"] = cc
- , [".cc"] = cxx
- , [".cpp"] = cxx
- , [".m"] = mm
- , [".mm"] = mxx
- , [".swift"] = sc
- , [".go"] = gc
- }
- </code></pre>
- <h4 id="languagetargetkinds">language.targetkinds</h4>
- <ul>
- <li>获取所有语言的目标类型列表</li>
- </ul>
- <p>获取结果如下:</p>
- <pre><code class="lang-lua">{
- binary = {"ld", "gcld", "dcld"}
- , static = {"ar", "gcar", "dcar"}
- , shared = {"sh", "dcsh"}
- }
- </code></pre>
- <h4 id="languagesourcekinds">language.sourcekinds</h4>
- <ul>
- <li>获取所有语言的源文件类型列表</li>
- </ul>
- <p>获取结果如下:</p>
- <pre><code class="lang-lua">{
- cc = ".c"
- , cxx = {".cc", ".cpp", ".cxx"}
- , mm = ".m"
- , mxx = ".mm"
- , sc = ".swift"
- , gc = ".go"
- , rc = ".rs"
- , dc = ".d"
- , as = {".s", ".S", ".asm"}
- }
- </code></pre>
- <h4 id="languagesourceflags">language.sourceflags</h4>
- <ul>
- <li>加载所有语言的源文件编译选项名列表</li>
- </ul>
- <p>获取结果如下:</p>
- <pre><code class="lang-lua">{
- cc = {"cflags", "cxflags"}
- , cxx = {"cxxflags", "cxflags"}
- , ...
- }
- </code></pre>
- <h4 id="languageload">language.load</h4>
- <ul>
- <li>加载指定语言</li>
- </ul>
- <p>从语言名称加载具体语言对象,例如:</p>
- <pre><code class="lang-lua">local lang = language.load("c++")
- if lang then
- print(lang:name())
- end
- </code></pre>
- <h4 id="languageload_sk">language.load_sk</h4>
- <ul>
- <li>从源文件类型加载指定语言</li>
- </ul>
- <p>从源文件类型:<code>cc, cxx, mm, mxx, sc, gc, as ..</code>加载具体语言对象,例如:</p>
- <pre><code class="lang-lua">local lang = language.load_sk("cxx")
- if lang then
- print(lang:name())
- end
- </code></pre>
- <h4 id="languageload_ex">language.load_ex</h4>
- <ul>
- <li>从源文件后缀名加载指定语言</li>
- </ul>
- <p>从源文件后缀名:<code>.cc, .c, .cpp, .mm, .swift, .go ..</code>加载具体语言对象,例如:</p>
- <pre><code class="lang-lua">local lang = language.load_sk(".cpp")
- if lang then
- print(lang:name())
- end
- </code></pre>
- <h4 id="languagesourcekind_of">language.sourcekind_of</h4>
- <ul>
- <li>获取指定源文件的源文件类型</li>
- </ul>
- <p>也就是从给定的一个源文件路径,获取它是属于那种源文件类型,例如:</p>
- <pre><code class="lang-lua">print(language.sourcekind_of("/xxxx/test.cpp"))
- </code></pre>
- <p>显示结果为:<code>cxx</code>,也就是<code>c++</code>类型,具体对应列表见:<a href="#languagesourcekinds">language.sourcekinds</a></p>
- <h3 id="libdetect">lib.detect</h3>
- <p>此模块提供了非常强大的探测功能,用于探测程序、编译器、语言特性、依赖包等。</p>
- <p>!> 此模块的接口分散在多个模块目录中,尽量通过导入单个接口来使用,这样效率更高。</p>
- <h4 id="detectfind_file">detect.find_file</h4>
- <ul>
- <li>查找文件</li>
- </ul>
- <p>这个接口提供了比<a href="#os-files">os.files</a>更加强大的工程, 可以同时指定多个搜索目录,并且还能对每个目录指定附加的子目录,来模式匹配查找,相当于是<a href="#os-files">os.files</a>的增强版。</p>
- <p>例如:</p>
- <pre><code class="lang-lua">import("lib.detect.find_file")
- local file = find_file("ccache", { "/usr/bin", "/usr/local/bin"})
- </code></pre>
- <p>如果找到,返回的结果是:<code>/usr/bin/ccache</code></p>
- <p>它同时也支持模式匹配路径,进行递归查找,类似<code>os.files</code>:</p>
- <pre><code class="lang-lua">local file = find_file("test.h", { "/usr/include", "/usr/local/include/**"})
- </code></pre>
- <p>不仅如此,里面的路径也支持内建变量,来从环境变量和注册表中获取路径进行查找:</p>
- <pre><code class="lang-lua">local file = find_file("xxx.h", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
- </code></pre>
- <p>如果路径规则比较复杂多变,还可以通过自定义脚本来动态生成路径传入:</p>
- <pre><code class="lang-lua">local file = find_file("xxx.h", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name"):match("\"(.-)\"") end})
- </code></pre>
- <p>大部分场合下,上面的使用已经满足各种需求了,如果还需要一些扩展功能,可以通过传入第三个参数,自定义一些可选配置,例如:</p>
- <pre><code class="lang-lua">local file = find_file("test.h", { "/usr", "/usr/local"}, {suffixes = {"/include", "/lib"}})
- </code></pre>
- <p>通过指定suffixes子目录列表,可以扩展路径列表(第二个参数),使得实际的搜索目录扩展为:</p>
- <pre><code>/usr/include
- /usr/lib
- /usr/local/include
- /usr/local/lib
- </code></pre><p>并且不用改变路径列表,就能动态切换子目录来搜索文件。</p>
- <p>!> 我们也可以通过<code>xmake lua</code>插件来快速调用和测试此接口:<code>xmake lua lib.detect.find_file test.h /usr/local</code></p>
- <h4 id="detectfind_path">detect.find_path</h4>
- <ul>
- <li>查找路径</li>
- </ul>
- <p>这个接口的用法跟<a href="#detectfind_file">lib.detect.find_file</a>类似,唯一的区别是返回的结果不同。<br>此接口查找到传入的文件路径后,返回的是对应的搜索路径,而不是文件路径本身,一般用于查找文件对应的父目录位置。</p>
- <pre><code class="lang-lua">import("lib.detect.find_path")
- local p = find_path("include/test.h", { "/usr", "/usr/local"})
- </code></pre>
- <p>上述代码如果查找成功,则返回:<code>/usr/local</code>,如果<code>test.h</code>在<code>/usr/local/include/test.h</code>的话。</p>
- <p>还有一个区别就是,这个接口传入不只是文件路径,还可以传入目录路径来查找:</p>
- <pre><code class="lang-lua">local p = find_path("lib/xxx", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"})
- </code></pre>
- <p>同样,此接口也支持模式匹配和后缀子目录:</p>
- <pre><code class="lang-lua">local p = find_path("include/*.h", { "/usr", "/usr/local/**"}, {suffixes = "/subdir"})
- </code></pre>
- <h4 id="detectfind_library">detect.find_library</h4>
- <ul>
- <li>查找库文件</li>
- </ul>
- <p>此接口用于指定的搜索目录中查找库文件(静态库,动态库),例如:</p>
- <pre><code class="lang-lua">import("lib.detect.find_library")
- local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"})
- </code></pre>
- <p>在macosx上运行,返回的结果如下:</p>
- <pre><code class="lang-lua">{
- filename = libcrypto.dylib
- , linkdir = /usr/lib
- , link = crypto
- , kind = shared
- }
- </code></pre>
- <p>如果不指定是否需要静态库还是动态库,那么此接口会自动选择一个存在的库(有可能是静态库、也有可能是动态库)进行返回。</p>
- <p>如果需要强制指定需要查找的库类型,可以指定kind参数为(<code>static/shared</code>):</p>
- <pre><code class="lang-lua">local library = find_library("crypto", {"/usr/lib", "/usr/local/lib"}, {kind = "static"})
- </code></pre>
- <p>此接口也支持suffixes后缀子目录搜索和模式匹配操作:</p>
- <pre><code class="lang-lua">local library = find_library("cryp*", {"/usr", "/usr/local"}, {suffixes = "/lib"})
- </code></pre>
- <h4 id="detectfind_program">detect.find_program</h4>
- <ul>
- <li>查找可执行程序</li>
- </ul>
- <p>这个接口比<a href="#detectfind_tool">lib.detect.find_tool</a>较为原始底层,通过指定的参数目录来查找可执行程序。</p>
- <pre><code class="lang-lua">import("lib.detect.find_program")
- local program = find_program("ccache")
- </code></pre>
- <p>上述代码犹如没有传递搜索目录,所以它会尝试直接执行指定程序,如果运行ok,那么直接返回:<code>ccache</code>,表示查找成功。</p>
- <p>指定搜索目录,修改尝试运行的检测命令参数(默认是:<code>ccache --version</code>):</p>
- <pre><code class="lang-lua">local program = find_program("ccache", {paths = {"/usr/bin", "/usr/local/bin"}, check = "--help"})
- </code></pre>
- <p>上述代码会尝试运行:<code>/usr/bin/ccache --help</code>,如果运行成功,则返回:<code>/usr/bin/ccache</code>。</p>
- <p>如果<code>--help</code>也没法满足需求,有些程序没有<code>--version/--help</code>参数,那么可以自定义运行脚本,来运行检测:</p>
- <pre><code class="lang-lua">local program = find_program("ccache", {paths = {"/usr/bin", "/usr/local/bin"}, check = function (program) os.run("%s -h", program) end})
- </code></pre>
- <p>同样,搜索路径列表支持内建变量和自定义脚本:</p>
- <pre><code class="lang-lua">local program = find_program("ccache", {paths = {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}})
- local program = find_program("ccache", {paths = {"$(env PATH)", function () return "/usr/local/bin" end}})
- </code></pre>
- <p><p class="tip"><br>为了加速频发查找的效率,此接口是默认自带cache的,所以就算频繁查找相同的程序,也不会花太多时间。<br>如果要禁用cache,可以在工程目录执行<code>xmake f -c</code>清除本地cache。<br></p>
- </p>
- <p>我们也可以通过<code>xmake lua lib.detect.find_program ccache</code> 来快速测试。</p>
- <h4 id="detectfind_programver">detect.find_programver</h4>
- <ul>
- <li>查找可执行程序版本号</li>
- </ul>
- <pre><code class="lang-lua">import("lib.detect.find_programver")
- local programver = find_programver("ccache")
- </code></pre>
- <p>返回结果为:3.2.2</p>
- <p>默认它会通过<code>ccache --version</code>尝试获取版本,如果不存在此参数,可以自己指定其他参数:</p>
- <pre><code class="lang-lua">local version = find_programver("ccache", {command = "-v"})
- </code></pre>
- <p>甚至自定义版本获取脚本:</p>
- <pre><code class="lang-lua">local version = find_programver("ccache", {command = function () return os.iorun("ccache --version") end})
- </code></pre>
- <p>对于版本号的提取规则,如果内置的匹配模式不满足要求,也可以自定义:</p>
- <pre><code class="lang-lua">local version = find_programver("ccache", {command = "--version", parse = "(%d+%.?%d*%.?%d*.-)%s"})
- local version = find_programver("ccache", {command = "--version", parse = function (output) return output:match("(%d+%.?%d*%.?%d*.-)%s") end})
- </code></pre>
- <p>!> 为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行<code>xmake f -c</code>清除本地cache。</p>
- <p>我们也可以通过<code>xmake lua lib.detect.find_programver ccache</code> 来快速测试。</p>
- <h4 id="detectfind_package">detect.find_package</h4>
- <ul>
- <li>查找包文件</li>
- </ul>
- <p>2.6.x 之后,这个接口不推荐直接使用(仅供内部使用),库集成,请尽量使用 <code>add_requires()</code> 和 <code>add_packages()</code>。</p>
- <h4 id="detectfind_tool">detect.find_tool</h4>
- <ul>
- <li>查找工具</li>
- </ul>
- <p>此接口也是用于查找可执行程序,不过比<a href="#detectfind_program">lib.detect.find_program</a>更加的高级,功能也更加强大,它对可执行程序进行了封装,提供了工具这个概念:</p>
- <ul>
- <li>toolname: 工具名,可执行程序的简称,用于标示某个工具,例如:<code>gcc</code>, <code>clang</code>等</li>
- <li>program: 可执行程序命令,例如:<code>xcrun -sdk macosx clang</code></li>
- </ul>
- <p>其对应关系如下:</p>
- <table>
- <thead>
- <tr>
- <th>toolname</th>
- <th>program</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>clang</td>
- <td><code>xcrun -sdk macosx clang</code></td>
- </tr>
- <tr>
- <td>gcc</td>
- <td><code>/usr/toolchains/bin/arm-linux-gcc</code></td>
- </tr>
- <tr>
- <td>link</td>
- <td><code>link.exe -lib</code></td>
- </tr>
- </tbody>
- </table>
- <p><a href="#detectfind_program">lib.detect.find_program</a>只能通过传入的原始program命令或路径,去判断该程序是否存在。<br>而<code>find_tool</code>则可以通过更加一致的toolname去查找工具,并且返回对应的program完整命令路径,例如:</p>
- <pre><code class="lang-lua">import("lib.detect.find_tool")
- local tool = find_tool("clang")
- </code></pre>
- <p>返回的结果为:<code>{name = "clang", program = "clang"}</code>,这个时候还看不出区别,我们可以手动指定可执行的命令:</p>
- <pre><code class="lang-lua">local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"})
- </code></pre>
- <p>返回的结果为:<code>{name = "clang", program = "xcrun -sdk macosx clang"}</code></p>
- <p>而在macosx下,gcc就是clang,如果我们执行<code>gcc --version</code>可以看到就是clang的一个马甲,我们可以通过<code>find_tool</code>接口进行智能识别:</p>
- <pre><code class="lang-lua">local tool = find_tool("gcc")
- </code></pre>
- <p>返回的结果为:<code>{name = "clang", program = "gcc"}</code></p>
- <p>通过这个结果就可以看的区别来了,工具名实际会被标示为clang,但是可执行的命令用的是gcc。</p>
- <p>我们也可以指定<code>{version = true}</code>参数去获取工具的版本,并且指定一个自定义的搜索路径,也支持内建变量和自定义脚本哦:</p>
- <pre><code class="lang-lua">local tool = find_tool("clang", {version = true, paths = {"/usr/bin", "/usr/local/bin", "$(env PATH)", function () return "/usr/xxx/bin" end}})
- </code></pre>
- <p>返回的结果为:<code>{name = "clang", program = "/usr/bin/clang", version = "4.0"}</code></p>
- <p>这个接口是对<code>find_program</code>的上层封装,因此也支持自定义脚本检测:</p>
- <pre><code class="lang-lua">local tool = find_tool("clang", {check = "--help"})
- local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end})
- </code></pre>
- <p>最后总结下,<code>find_tool</code>的查找流程:</p>
- <ol>
- <li>优先通过<code>{program = "xxx"}</code>的参数来尝试运行和检测。</li>
- <li>如果在<code>xmake/modules/detect/tools</code>下存在<code>detect.tools.find_xxx</code>脚本,则调用此脚本进行更加精准的检测。</li>
- <li>尝试从<code>/usr/bin</code>,<code>/usr/local/bin</code>等系统目录进行检测。</li>
- </ol>
- <p>我们也可以在工程<code>xmake.lua</code>中<code>add_moduledirs</code>指定的模块目录中,添加自定义查找脚本,来改进检测机制:</p>
- <pre><code>projectdir
- - xmake/modules
- - detect/tools/find_xxx.lua
- </code></pre><p>例如我们自定义一个<code>find_7z.lua</code>的查找脚本:</p>
- <pre><code class="lang-lua">import("lib.detect.find_program")
- import("lib.detect.find_programver")
- function main(opt)
- -- init options
- opt = opt or {}
- -- find program
- local program = find_program(opt.program or "7z", opt.pathes, opt.check or "--help")
- -- find program version
- local version = nil
- if program and opt and opt.version then
- version = find_programver(program, "--help", "(%d+%.?%d*)%s")
- end
- -- ok?
- return program, version
- end
- </code></pre>
- <p>将它放置到工程的模块目录下后,执行:<code>xmake l lib.detect.find_tool 7z</code>就可以查找到了。</p>
- <p>!> 为了加速频发查找的效率,此接口是默认自带cache的,如果要禁用cache,可以在工程目录执行<code>xmake f -c</code>清除本地cache。</p>
- <p>我们也可以通过<code>xmake lua lib.detect.find_tool clang</code> 来快速测试。</p>
- <h4 id="detectfind_toolname">detect.find_toolname</h4>
- <ul>
- <li>查找工具名</li>
- </ul>
- <p>通过program命令匹配对应的工具名,例如:</p>
- <table>
- <thead>
- <tr>
- <th>program</th>
- <th>toolname</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>xcrun -sdk macosx clang</code></td>
- <td>clang</td>
- </tr>
- <tr>
- <td><code>/usr/bin/arm-linux-gcc</code></td>
- <td>gcc</td>
- </tr>
- <tr>
- <td><code>link.exe -lib</code></td>
- <td>link</td>
- </tr>
- <tr>
- <td><code>gcc-5</code></td>
- <td>gcc</td>
- </tr>
- <tr>
- <td><code>arm-android-clang++</code></td>
- <td>clangxx</td>
- </tr>
- <tr>
- <td><code>pkg-config</code></td>
- <td>pkg_config</td>
- </tr>
- </tbody>
- </table>
- <p>toolname相比program,更能唯一标示某个工具,也方便查找和加载对应的脚本<code>find_xxx.lua</code>。</p>
- <h4 id="detectfind_cudadevices">detect.find_cudadevices</h4>
- <ul>
- <li>查找本机的 CUDA 设备</li>
- </ul>
- <p>通过 CUDA Runtime API 枚举本机的 CUDA 设备,并查询其属性。</p>
- <pre><code class="lang-lua">import("lib.detect.find_cudadevices")
- local devices = find_cudadevices({ skip_compute_mode_prohibited = true })
- local devices = find_cudadevices({ min_sm_arch = 35, order_by_flops = true })
- </code></pre>
- <p>返回的结果为:<code>{ { ['$id'] = 0, name = "GeForce GTX 960M", major = 5, minor = 0, ... }, ... }</code></p>
- <p>包含的属性依据当前 CUDA 版本会有所不同,可以参考 <a href="https://docs.nvidia.com/cuda/cuda-runtime-api/structcudaDeviceProp.html#structcudaDeviceProp">CUDA 官方文档</a>及其历史版本。</p>
- <h4 id="detectfeatures">detect.features</h4>
- <ul>
- <li>获取指定工具的所有特性</li>
- </ul>
- <p>此接口跟<a href="#compilerfeatures">compiler.features</a>类似,区别就是此接口更加的原始,传入的参数是实际的工具名toolname。</p>
- <p>并且此接口不仅能够获取编译器的特性,任何工具的特性都可以获取,因此更加通用。</p>
- <pre><code class="lang-lua">import("lib.detect.features")
- local features = features("clang")
- local features = features("clang", {flags = "-O0", program = "xcrun -sdk macosx clang"})
- local features = features("clang", {flags = {"-g", "-O0", "-std=c++11"}})
- </code></pre>
- <p>通过传入flags,可以改变特性的获取结果,例如一些c++11的特性,默认情况下获取不到,通过启用<code>-std=c++11</code>后,就可以获取到了。</p>
- <p>所有编译器的特性列表,可以见:<a href="#compilerfeatures">compiler.features</a>。</p>
- <h4 id="detecthas_features">detect.has_features</h4>
- <ul>
- <li>判断指定特性是否支持</li>
- </ul>
- <p>此接口跟<a href="#compilerhas_features">compiler.has_features</a>类似,但是更加原始,传入的参数是实际的工具名toolname。</p>
- <p>并且此接口不仅能够判断编译器的特性,任何工具的特性都可以判断,因此更加通用。</p>
- <pre><code class="lang-lua">import("lib.detect.has_features")
- local features = has_features("clang", "cxx_constexpr")
- local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = {"-g", "-O0"}, program = "xcrun -sdk macosx clang"})
- local features = has_features("clang", {"cxx_constexpr", "c_static_assert"}, {flags = "-g"})
- </code></pre>
- <p>如果指定的特性列表存在,则返回实际支持的特性子列表,如果都不支持,则返回nil,我们也可以通过指定flags去改变特性的获取规则。</p>
- <p>所有编译器的特性列表,可以见:<a href="#compilerfeatures">compiler.features</a>。</p>
- <h4 id="detecthas_flags">detect.has_flags</h4>
- <ul>
- <li>判断指定参数选项是否支持</li>
- </ul>
- <p>此接口跟<a href="#compilerhas_flags">compiler.has_flags</a>类似,但是更加原始,传入的参数是实际的工具名toolname。</p>
- <pre><code class="lang-lua">import("lib.detect.has_flags")
- local ok = has_flags("clang", "-g")
- local ok = has_flags("clang", {"-g", "-O0"}, {program = "xcrun -sdk macosx clang"})
- local ok = has_flags("clang", "-g -O0", {toolkind = "cxx"})
- </code></pre>
- <p>如果检测通过,则返回true。</p>
- <p>此接口的检测做了一些优化,除了cache机制外,大部分场合下,会去拉取工具的选项列表(<code>--help</code>)直接判断,如果选项列表里获取不到的话,才会通过尝试运行的方式来检测。</p>
- <h4 id="detecthas_cfuncs">detect.has_cfuncs</h4>
- <ul>
- <li>判断指定c函数是否存在</li>
- </ul>
- <p>此接口是<a href="#detectcheck_cxsnippets">lib.detect.check_cxsnippets</a>的简化版本,仅用于检测函数。</p>
- <pre><code class="lang-lua">import("lib.detect.has_cfuncs")
- local ok = has_cfuncs("setjmp")
- local ok = has_cfuncs({"sigsetjmp((void*)0, 0)", "setjmp"}, {includes = "setjmp.h"})
- </code></pre>
- <p>对于函数的描述规则如下:</p>
- <table>
- <thead>
- <tr>
- <th>函数描述</th>
- <th>说明</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>sigsetjmp</code></td>
- <td>纯函数名</td>
- </tr>
- <tr>
- <td><code>sigsetjmp((void*)0, 0)</code></td>
- <td>函数调用</td>
- </tr>
- <tr>
- <td><code>sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}</code></td>
- <td>函数名 + {}块</td>
- </tr>
- </tbody>
- </table>
- <p>在最后的可选参数中,除了可以指定<code>includes</code>外,还可以指定其他的一些参数用于控制编译检测的选项条件:</p>
- <pre><code class="lang-lua">{ verbose = false, target = [target|option], includes = .., configs = {linkdirs = .., links = .., defines = ..}}
- </code></pre>
- <p>其中verbose用于回显检测信息,target用于在检测前追加target中的配置信息, 而config用于自定义配置跟target相关的编译选项。</p>
- <h4 id="detecthas_cxxfuncs">detect.has_cxxfuncs</h4>
- <ul>
- <li>判断指定c++函数是否存在</li>
- </ul>
- <p>此接口跟<a href="#detecthas_cfuncs">lib.detect.has_cfuncs</a>类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++函数。</p>
- <h4 id="detecthas_cincludes">detect.has_cincludes</h4>
- <ul>
- <li>判断指定c头文件是否存在</li>
- </ul>
- <p>此接口是<a href="#detectcheck_cxsnippets">lib.detect.check_cxsnippets</a>的简化版本,仅用于检测头文件。</p>
- <pre><code class="lang-lua">import("lib.detect.has_cincludes")
- local ok = has_cincludes("stdio.h")
- local ok = has_cincludes({"stdio.h", "stdlib.h"}, {target = target})
- local ok = has_cincludes({"stdio.h", "stdlib.h"}, {configs = {defines = "_GNU_SOURCE=1", languages = "cxx11"}})
- </code></pre>
- <h4 id="detecthas_cxxincludes">detect.has_cxxincludes</h4>
- <ul>
- <li>判断指定c++头文件是否存在</li>
- </ul>
- <p>此接口跟<a href="#detecthas_cincludes">lib.detect.has_cincludess</a>类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++头文件。</p>
- <h4 id="detecthas_ctypes">detect.has_ctypes</h4>
- <ul>
- <li>判断指定c类型是否存在</li>
- </ul>
- <p>此接口是<a href="#detectcheck_cxsnippets">lib.detect.check_cxsnippets</a>的简化版本,仅用于检测函数。</p>
- <pre><code class="lang-lua">import("lib.detect.has_ctypes")
- local ok = has_ctypes("wchar_t")
- local ok = has_ctypes({"char", "wchar_t"}, {includes = "stdio.h"})
- local ok = has_ctypes("wchar_t", {includes = {"stdio.h", "stdlib.h"}, configs = {"defines = "_GNU_SOURCE=1", languages = "cxx11"}})
- </code></pre>
- <h4 id="detecthas_cxxtypes">detect.has_cxxtypes</h4>
- <ul>
- <li>判断指定c++类型是否存在</li>
- </ul>
- <p>此接口跟<a href="#detecthas_ctypes">lib.detect.has_ctypess</a>类似,请直接参考它的使用说明,唯一区别是这个接口用于检测c++类型。</p>
- <h4 id="detectcheck_cxsnippets">detect.check_cxsnippets</h4>
- <ul>
- <li>检测c/c++代码片段是否能够编译通过</li>
- </ul>
- <p>通用的c/c++代码片段检测接口,通过传入多个代码片段列表,它会自动生成一个编译文件,然后常识对它进行编译,如果编译通过返回true。</p>
- <p>对于一些复杂的编译器特性,连<a href="#compilerhas_features">compiler.has_features</a>都无法检测到的时候,可以通过此接口通过尝试编译来检测它。</p>
- <pre><code class="lang-lua">import("lib.detect.check_cxsnippets")
- local ok = check_cxsnippets("void test() {}")
- local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
- </code></pre>
- <p>此接口是<a href="#detecthas_cfuncs">detect.has_cfuncs</a>, <a href="#detecthas_cincludes">detect.has_cincludes</a>和<a href="detect-has_ctypes">detect.has_ctypes</a>等接口的通用版本,也更加底层。</p>
- <p>因此我们可以用它来检测:types, functions, includes 还有 links,或者是组合起来一起检测。</p>
- <p>第一个参数为代码片段列表,一般用于一些自定义特性的检测,如果为空,则可以仅仅检测可选参数中条件,例如:</p>
- <pre><code class="lang-lua">local ok = check_cxsnippets({}, {types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}})
- </code></pre>
- <p>上面那个调用,会去同时检测types, includes和funcs是否都满足,如果通过返回true。</p>
- <p>还有其他一些可选参数:</p>
- <pre><code class="lang-lua">{ verbose = false, target = [target|option], sourcekind = "[cc|cxx]"}
- </code></pre>
- <p>其中verbose用于回显检测信息,target用于在检测前追加target中的配置信息, sourcekind 用于指定编译器等工具类型,例如传入<code>cxx</code>强制作为c++代码来检测。</p>
- <h3 id="nethttp">net.http</h3>
- <p>此模块提供http的各种操作支持,目前提供的接口如下:</p>
- <h4 id="httpdownload">http.download</h4>
- <ul>
- <li>下载http文件</li>
- </ul>
- <p>这个接口比较简单,就是单纯的下载文件。</p>
- <pre><code class="lang-lua">import("net.http")
- http.download("https://xmake.io", "/tmp/index.html")
- </code></pre>
- <h3 id="privilegesudo">privilege.sudo</h3>
- <p>此接口用于通过<code>sudo</code>来运行命令,并且提供了平台一致性处理,对于一些需要root权限运行的脚本,可以使用此接口。</p>
- <p>!> 为了保证安全性,除非必须使用的场合,其他情况下尽量不要使用此接口。</p>
- <h4 id="sudohas">sudo.has</h4>
- <ul>
- <li>判断sudo是否支持</li>
- </ul>
- <p>目前仅在<code>macosx/linux</code>下支持sudo,windows上的管理员权限运行暂时还不支持,因此建议使用前可以通过此接口判断支持情况后,针对性处理。</p>
- <pre><code class="lang-lua">import("privilege.sudo")
- if sudo.has() then
- sudo.run("rm /system/file")
- end
- </code></pre>
- <h4 id="sudorun">sudo.run</h4>
- <ul>
- <li>安静运行原生shell命令</li>
- </ul>
- <p>具体用法可参考:<a href="#os-run">os.run</a>。</p>
- <pre><code class="lang-lua">import("privilege.sudo")
- sudo.run("rm /system/file")
- </code></pre>
- <h4 id="sudorunv">sudo.runv</h4>
- <ul>
- <li>安静运行原生shell命令,带参数列表</li>
- </ul>
- <p>具体用法可参考:<a href="#os-runv">os.runv</a>。</p>
- <h4 id="sudoexec">sudo.exec</h4>
- <ul>
- <li>回显运行原生shell命令</li>
- </ul>
- <p>具体用法可参考:<a href="#os-exec">os.exec</a>。</p>
- <h4 id="sudoexecv">sudo.execv</h4>
- <ul>
- <li>回显运行原生shell命令,带参数列表</li>
- </ul>
- <p>具体用法可参考:<a href="#os-execv">os.execv</a>。</p>
- <h4 id="sudoiorun">sudo.iorun</h4>
- <ul>
- <li>安静运行原生shell命令并获取输出内容</li>
- </ul>
- <p>具体用法可参考:<a href="#os-iorun">os.iorun</a>。</p>
- <h4 id="sudoiorunv">sudo.iorunv</h4>
- <ul>
- <li>安静运行原生shell命令并获取输出内容,带参数列表</li>
- </ul>
- <p>具体用法可参考:<a href="#os-iorunv">os.iorunv</a>。</p>
- <h3 id="develgit">devel.git</h3>
- <p>此接口提供了git各种命令的访问接口,相对于直接调用git命令,此模块提供了更加上层易用的封装接口,并且提供对git的自动检测和跨平台处理。</p>
- <p>!> 目前windows上,需要手动安装git包后,才能检测到,后续版本会提供自动集成git功能,用户将不用关心如何安装git,就可以直接使用。</p>
- <h4 id="gitclone">git.clone</h4>
- <ul>
- <li>clone代码库</li>
- </ul>
- <p>此接口对应<code>git clone</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- git.clone("[email protected]:tboox/xmake.git")
- git.clone("[email protected]:tboox/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"})
- </code></pre>
- <h4 id="gitpull">git.pull</h4>
- <ul>
- <li>拉取代码库最新提交</li>
- </ul>
- <p>此接口对应<code>git pull</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- git.pull()
- git.pull({remote = "origin", tags = true, branch = "master", repodir = "/tmp/xmake"})
- </code></pre>
- <h4 id="gitclean">git.clean</h4>
- <ul>
- <li>清理代码库文件</li>
- </ul>
- <p>此接口对应<code>git clean</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- git.clean()
- git.clean({repodir = "/tmp/xmake", force = true})
- </code></pre>
- <h4 id="gitcheckout">git.checkout</h4>
- <ul>
- <li>签出指定分支版本</li>
- </ul>
- <p>此接口对应<code>git checkout</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- git.checkout("master", {repodir = "/tmp/xmake"})
- git.checkout("v1.0.1", {repodir = "/tmp/xmake"})
- </code></pre>
- <h4 id="gitrefs">git.refs</h4>
- <ul>
- <li>获取所有引用列表</li>
- </ul>
- <p>此接口对应<code>git ls-remote --refs</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- local refs = git.refs(url)
- </code></pre>
- <h4 id="gittags">git.tags</h4>
- <ul>
- <li>获取所有标记列表</li>
- </ul>
- <p>此接口对应<code>git ls-remote --tags</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- local tags = git.tags(url)
- </code></pre>
- <h4 id="gitbranches">git.branches</h4>
- <ul>
- <li>获取所有分支列表</li>
- </ul>
- <p>此接口对应<code>git ls-remote --heads</code>命令</p>
- <pre><code class="lang-lua">import("devel.git")
- local branches = git.branches(url)
- </code></pre>
- <h3 id="utilsarchive">utils.archive</h3>
- <p>此模块用于压缩和解压文件。支持大部分常用压缩格式的解压缩,它会自动检测系统提供了哪些压缩工具,然后会使用最合适的压缩工具进行操作。</p>
- <h4 id="archivearchive">archive.archive</h4>
- <ul>
- <li>压缩文件</li>
- </ul>
- <pre><code class="lang-lua">import("utils.archive")
- archive.archive("/tmp/a.zip", "/tmp/outputdir")
- archive.archive("/tmp/a.7z", "/tmp/outputdir")
- archive.archive("/tmp/a.gzip", "/tmp/outputdir")
- archive.archive("/tmp/a.tar.bz2", "/tmp/outputdir")
- </code></pre>
- <p>还可以添加一些配置选项,如递归目录,压缩质量,排除文件等。</p>
- <pre><code class="lang-lua">import("utils.archive")
- local options = {}
- options.curdir = "/tmp"
- options.recurse = true
- options.compress = "fastest|faster|default|better|best"
- options.excludes = {"*/dir/*", "dir/*"}
- archive.archive("/tmp/a.zip", "/tmp/outputdir", options)
- </code></pre>
- <h4 id="archiveextract">archive.extract</h4>
- <ul>
- <li>解压文件</li>
- </ul>
- <pre><code class="lang-lua">import("utils.archive")
- archive.extract("/tmp/a.zip", "/tmp/outputdir")
- archive.extract("/tmp/a.7z", "/tmp/outputdir")
- archive.extract("/tmp/a.gzip", "/tmp/outputdir")
- archive.extract("/tmp/a.tar.bz2", "/tmp/outputdir")
- </code></pre>
- <h3 id="utilsplatform">utils.platform</h3>
- <p>此模块用于一些平台相关的辅助操作接口</p>
- <h4 id="utilsplatformgnu2mslib">utils.platform.gnu2mslib</h4>
- <ul>
- <li>将 mingw 的 libxxxdll.a 转换成 msvc 的 xxx.lib 库</li>
- </ul>
- <p>这个功能对 Fortran & C++ 混合项目特别有帮助,因为 VS 不提供fortran编译器,只能用MinGW的gfortran来编译fortran部分,然后和VS的项目链接。<br>往往这样的项目同时有一些其他的库以vs格式提供,因此纯用MinGW编译也不行,只能使用这个功能来混合编译。</p>
- <p>而 cmake 也有个类似的 <a href="https://cmake.org/cmake/help/latest/prop_tgt/GNUtoMS.html">GNUtoMS</a>。</p>
- <p>相关 issues 见:<a href="https://github.com/xmake-io/xmake/issues/1181">#1181</a></p>
- <pre><code class="lang-lua">import("utils.platform.gnu2mslib")
- gnu2mslib("xxx.lib", "xxx.dll.a")
- gnu2mslib("xxx.lib", "xxx.def")
- gnu2mslib("xxx.lib", "xxx.dll.a", {dllname = "xxx.dll", arch = "x64"})
- </code></pre>
- <p>支持从 def 生成 xxx.lib ,也支持从 xxx.dll.a 自动导出 .def ,然后再生成 xxx.lib</p>
- <p>如果不想自动从dll.a生成 def,想借用 gnu linker 生成的 def,那就自己通过 add_shflags("-Wl,--output-def,xxx.def") 配置,生成 def,然后传入 def 到这个接口。。</p>
- <p><code>{dllname = xxx, arch = "xxx"}</code> 这些是可选的,根据自己的需求而定。。</p>
- <p>也可以直接 xmake l utils.platform.gnu2mslib xxx.lib xxx.dll.a 快速测试验证</p>
- <h3 id="cli">cli</h3>
- <h4 id="cliamalgamate">cli.amalgamate</h4>
- <ul>
- <li>合并成单源码文件</li>
- </ul>
- <p>这是一个小工具模块,主要用于快速合并指定 target 里面的所有 c/c++ 和 头文件源码到单个源文件。</p>
- <p>合并会将内部 includes 头文件全部展开,并生成 DAG,通过拓扑排序引入。</p>
- <p>默认它会处理所有 target 的合并,例如:</p>
- <pre><code class="lang-bash">$ xmake l cli.amalgamate
- build/tbox.c generated!
- build/tbox.h generated!
- </code></pre>
- <p>我们也可以指定合并需要的目标:</p>
- <pre><code class="lang-bash">$ xmake l cli.amalgamate tbox
- build/tbox.c generated!
- build/tbox.h generated!
- </code></pre>
- <p>也可以在合并每个源文件时候,指定一个自定义的 unique ID 的宏定义,来处理符号冲突问题。</p>
- <pre><code class="lang-bash">$ xmake l cli.amalgamate -u MY_UNIQUEU_ID
- build/tbox.c generated!
- build/tbox.h generated!
- </code></pre>
- <p>如果多个源文件内部有重名符号,就可以判断这个 <code>MY_UNIQUEU_ID</code> 宏是否被定义,如果定义了,说明是在单文件中,就自己在源码中处理下重名符号。</p>
- <pre><code class="lang-c">#ifdef MY_UNIQUEU_ID
- // do some thing
- #endif
- </code></pre>
- <p>我们也可以指定输出位置:</p>
- <pre><code class="lang-bash">$ xmake l cli.amalgamate -o /xxx
- /xxx/tbox.c generated!
- /xxx/tbox.h generated!
- </code></pre>
- </article>
- </body>
- </html>
|