本帖最后由 waruqi 于 2017-01-09 21:54 编辑
最近给xmake增加了一个新特性,对于一份工程源码,可以不用编写makefile,也不用编写各种make相关的工程描述文件(例如:xmake.lua,makefile.am, cmakelist.txt等)
xmake就可以直接编译他们,这是如何做到的呢,简单来说下实现原理: - 首先扫描当前目录下,xmake所以支持的所有源代码文件
- 分析代码,检测哪些代码拥有main入口函数
- 所有没有main入口的代码编译成静态库
- 带有main入口的代码,编译成可执行程序,同时链接其他静态库程序
这种代码扫描和智能编译,非常简单,目前xmake还不支持多级目录扫描,只对单级目录的代码进行扫描编译。。
开源代码的移植和编译虽然这种方式,并不是非常智能,限制也不少,但是对于想临时写些代码进行编译运行,或者临时想交叉编译一些简单的开源库代码 这种方式已经足够使用了,下面看下一个实际的例子: 我下载了一份zlib-1.2.10的源码,想要编译它,只需要进入zlib的源码目录执行:
就行了,输出结果如下: - xmake.lua not found, scanning files ..
- target(zlib-1.2): static
- [+]: ./adler32.c
- [+]: ./compress.c
- [+]: ./crc32.c
- [+]: ./deflate.c
- [+]: ./gzclose.c
- [+]: ./gzlib.c
- [+]: ./gzread.c
- [+]: ./gzwrite.c
- [+]: ./infback.c
- [+]: ./inffast.c
- [+]: ./inflate.c
- [+]: ./inftrees.c
- [+]: ./trees.c
- [+]: ./uncompr.c
- [+]: ./zutil.c
- xmake.lua generated, scan ok!👌
- checking for the architecture ... x86_64
- checking for the Xcode SDK version for macosx ... 10.12
- checking for the target minimal version ... 10.12
- checking for the c compiler (cc) ... xcrun -sdk macosx clang
- checking for the c++ compiler (cxx) ... xcrun -sdk macosx clang
- checking for the objc compiler (mm) ... xcrun -sdk macosx clang
- checking for the objc++ compiler (mxx) ... xcrun -sdk macosx clang++
- checking for the swift compiler (sc) ... xcrun -sdk macosx swiftc
- checking for the assember (as) ... xcrun -sdk macosx clang
- checking for the linker (ld) ... xcrun -sdk macosx clang++
- checking for the static library archiver (ar) ... xcrun -sdk macosx ar
- checking for the static library extractor (ex) ... xcrun -sdk macosx ar
- checking for the shared library linker (sh) ... xcrun -sdk macosx clang++
- checking for the debugger (dd) ... xcrun -sdk macosx lldb
- checking for the golang compiler (go) ... go
- configure
- {
- ex = "xcrun -sdk macosx ar"
- , sh = "xcrun -sdk macosx clang++"
- , host = "macosx"
- , ar = "xcrun -sdk macosx ar"
- , buildir = "build"
- , as = "xcrun -sdk macosx clang"
- , plat = "macosx"
- , xcode_dir = "/Applications/Xcode.app"
- , arch = "x86_64"
- , mxx = "xcrun -sdk macosx clang++"
- , go = "go"
- , target_minver = "10.12"
- , ccache = "ccache"
- , mode = "release"
- , clean = true
- , cxx = "xcrun -sdk macosx clang"
- , cc = "xcrun -sdk macosx clang"
- , dd = "xcrun -sdk macosx lldb"
- , kind = "static"
- , ld = "xcrun -sdk macosx clang++"
- , xcode_sdkver = "10.12"
- , sc = "xcrun -sdk macosx swiftc"
- , mm = "xcrun -sdk macosx clang"
- }
- configure ok!
- clean ok!
- [00%]: ccache compiling.release ./adler32.c
- [06%]: ccache compiling.release ./compress.c
- [13%]: ccache compiling.release ./crc32.c
- [20%]: ccache compiling.release ./deflate.c
- [26%]: ccache compiling.release ./gzclose.c
- [33%]: ccache compiling.release ./gzlib.c
- [40%]: ccache compiling.release ./gzread.c
- [46%]: ccache compiling.release ./gzwrite.c
- [53%]: ccache compiling.release ./infback.c
- [60%]: ccache compiling.release ./inffast.c
- [66%]: ccache compiling.release ./inflate.c
- [73%]: ccache compiling.release ./inftrees.c
- [80%]: ccache compiling.release ./trees.c
- [86%]: ccache compiling.release ./uncompr.c
- [93%]: ccache compiling.release ./zutil.c
- [100%]: archiving.release libzlib-1.2.a
- build ok!👌
复制代码
通过输出结果,可以看到,xmake会去检测扫描当前目录下的所有.c代码,发现没有main入口,应该是静态库程序,因此执行xmake后,就直接编译成静态库libzlib-1.2.a了
连xmake.lua都没有编写,其实xmake在扫描完成后,会去自动在当前目录下生成一份xmake.lua,下次编译就不需要重新扫描检测了。 自动生成的xmake.lua内容如下:
- -- define target
- target("zlib-1.2")
- -- set kind
- set_kind("static")
- -- add files
- add_files("./adler32.c")
- add_files("./compress.c")
- add_files("./crc32.c")
- add_files("./deflate.c")
- add_files("./gzclose.c")
- add_files("./gzlib.c")
- add_files("./gzread.c")
- add_files("./gzwrite.c")
- add_files("./infback.c")
- add_files("./inffast.c")
- add_files("./inflate.c")
- add_files("./inftrees.c")
- add_files("./trees.c")
- add_files("./uncompr.c")
- add_files("./zutil.c")
复制代码
也许你会说,像这种开源库,直接configure; make不就好了吗,他们自己也有提供makefile来直接编译的,的确是这样,我这里只是举个例子而已。。 当然,很多开源库在交叉编译的时候,通过自带的configure,处理起来还是很繁琐的,用xmake进行交叉编译会更方便些。。
即时地代码编写和编译运行
xmake的这个扫描代码编译特性,主要的目的:还是为了让我们在临时想写些测试代码的时候,不用考虑太多东西,直接上手敲代码,然后快速执行xmake run 来调试验证结果。。
例如:
我想写了个简单的main.c的测试程序,打印hello world!,如果要写makefile或者直接通过gcc命令来,就很繁琐了,你需要:
最快速的方式,也需要执行两行命令,而如果用xmake,只需要执行:
就行了,它会自动检测到代码后,自动生成对应的xmake.lua,自动编译,自动运行,然后输出:
如果你有十几个代码文件,用手敲gcc的方式,或者写makefile的方式,这个差距就更明显了,用xmake还是只需要一行命令:
多语言支持
这种代码检测和即时编译,是支持多语言的,不仅支持c/c++,还支持objc/swift,后期还会支持golang(正在开发中) 例如我下载了一份fmdb的ios开源框架代码:
- .
- ├── FMDB.h
- ├── FMDatabase.h
- ├── FMDatabase.m
- ├── FMDatabaseAdditions.h
- ├── FMDatabaseAdditions.m
- ├── FMDatabasePool.h
- ├── FMDatabasePool.m
- ├── FMDatabaseQueue.h
- ├── FMDatabaseQueue.m
- ├── FMResultSet.h
- └── FMResultSet.m
复制代码
想要把它编译成ios的静态库,但是又不想写xmake.lua,或者makefile,那么只需要使用xmake的这个新特性,直接执行:
- <font color="#8f592">$ </font>xmake f -p iphoneos; xmake
复制代码
就行了,输出结果如下:
- xmake.lua not found, scanning files ..
- target(FMDB): static
- [+]: ./FMDatabase.m
- [+]: ./FMDatabaseAdditions.m
- [+]: ./FMDatabasePool.m
- [+]: ./FMDatabaseQueue.m
- [+]: ./FMResultSet.m
- xmake.lua generated, scan ok!👌
- checking for the architecture ... armv7
- checking for the Xcode SDK version for iphoneos ... 10.1
- checking for the target minimal version ... 10.1
- checking for the c compiler (cc) ... xcrun -sdk iphoneos clang
- checking for the c++ compiler (cxx) ... xcrun -sdk iphoneos clang
- checking for the objc compiler (mm) ... xcrun -sdk iphoneos clang
- checking for the objc++ compiler (mxx) ... xcrun -sdk iphoneos clang++
- checking for the assember (as) ... gas-preprocessor.pl xcrun -sdk iphoneos clang
- checking for the linker (ld) ... xcrun -sdk iphoneos clang++
- checking for the static library archiver (ar) ... xcrun -sdk iphoneos ar
- checking for the static library extractor (ex) ... xcrun -sdk iphoneos ar
- checking for the shared library linker (sh) ... xcrun -sdk iphoneos clang++
- checking for the swift compiler (sc) ... xcrun -sdk iphoneos swiftc
- configure
- {
- ex = "xcrun -sdk iphoneos ar"
- , ccache = "ccache"
- , host = "macosx"
- , ar = "xcrun -sdk iphoneos ar"
- , buildir = "build"
- , as = "/usr/local/share/xmake/tools/utils/gas-preprocessor.pl xcrun -sdk iphoneos clang"
- , arch = "armv7"
- , mxx = "xcrun -sdk iphoneos clang++"
- , cxx = "xcrun -sdk iphoneos clang"
- , target_minver = "10.1"
- , xcode_dir = "/Applications/Xcode.app"
- , clean = true
- , sh = "xcrun -sdk iphoneos clang++"
- , cc = "xcrun -sdk iphoneos clang"
- , ld = "xcrun -sdk iphoneos clang++"
- , mode = "release"
- , kind = "static"
- , plat = "iphoneos"
- , xcode_sdkver = "10.1"
- , sc = "xcrun -sdk iphoneos swiftc"
- , mm = "xcrun -sdk iphoneos clang"
- }
- configure ok!
- clean ok!
- [00%]: ccache compiling.release ./FMDatabase.m
- [20%]: ccache compiling.release ./FMDatabaseAdditions.m
- [40%]: ccache compiling.release ./FMDatabasePool.m
- [60%]: ccache compiling.release ./FMDatabaseQueue.m
- [80%]: ccache compiling.release ./FMResultSet.m
- [100%]: archiving.release libFMDB.a
- build ok!👌
复制代码
同时编译多个可执行文件
输出结果的开头部分,就是对代码的分析结果,虽然目前只支持单级目录结构的代码扫描,但是还是可以同时支持检测和编译多个可执行文件的 我们以libjpeg的开源库为例:
我们进入jpeg-6b目录后,执行: - <font color="#8f592">$ </font>xmake
复制代码
输出如下:
- xmake.lua not found, scanning files ..
- target(jpeg-6b): static
- [+]: ./cdjpeg.c
- [+]: ./example.c
- [+]: ./jcapimin.c
- [+]: ./jcapistd.c
- [+]: ./jccoefct.c
- [+]: ./jccolor.c
- [+]: ./jcdctmgr.c
- [+]: ./jchuff.c
- [+]: ./jcinit.c
- [+]: ./jcmainct.c
- [+]: ./jcmarker.c
- [+]: ./jcmaster.c
- [+]: ./jcomapi.c
- [+]: ./jcparam.c
- [+]: ./jcphuff.c
- [+]: ./jcprepct.c
- [+]: ./jcsample.c
- [+]: ./jctrans.c
- [+]: ./jdapimin.c
- [+]: ./jdapistd.c
- [+]: ./jdatadst.c
- [+]: ./jdatasrc.c
- [+]: ./jdcoefct.c
- [+]: ./jdcolor.c
- [+]: ./jddctmgr.c
- [+]: ./jdhuff.c
- [+]: ./jdinput.c
- [+]: ./jdmainct.c
- [+]: ./jdmarker.c
- [+]: ./jdmaster.c
- [+]: ./jdmerge.c
- [+]: ./jdphuff.c
- [+]: ./jdpostct.c
- [+]: ./jdsample.c
- [+]: ./jdtrans.c
- [+]: ./jerror.c
- [+]: ./jfdctflt.c
- [+]: ./jfdctfst.c
- [+]: ./jfdctint.c
- [+]: ./jidctflt.c
- [+]: ./jidctfst.c
- [+]: ./jidctint.c
- [+]: ./jidctred.c
- [+]: ./jmemansi.c
- [+]: ./jmemmgr.c
- [+]: ./jmemname.c
- [+]: ./jmemnobs.c
- [+]: ./jquant1.c
- [+]: ./jquant2.c
- [+]: ./jutils.c
- [+]: ./rdbmp.c
- [+]: ./rdcolmap.c
- [+]: ./rdgif.c
- [+]: ./rdppm.c
- [+]: ./rdrle.c
- [+]: ./rdswitch.c
- [+]: ./rdtarga.c
- [+]: ./transupp.c
- [+]: ./wrbmp.c
- [+]: ./wrgif.c
- [+]: ./wrppm.c
- [+]: ./wrrle.c
- [+]: ./wrtarga.c
- target(ansi2knr): binary
- [+]: ./ansi2knr.c
- target(cjpeg): binary
- [+]: ./cjpeg.c
- target(ckconfig): binary
- [+]: ./ckconfig.c
- target(djpeg): binary
- [+]: ./djpeg.c
- target(jpegtran): binary
- [+]: ./jpegtran.c
- target(rdjpgcom): binary
- [+]: ./rdjpgcom.c
- target(wrjpgcom): binary
- [+]: ./wrjpgcom.c
- xmake.lua generated, scan ok!👌
- checking for the architecture ... x86_64
- checking for the Xcode SDK version for macosx ... 10.12
- checking for the target minimal version ... 10.12
- checking for the c compiler (cc) ... xcrun -sdk macosx clang
- checking for the c++ compiler (cxx) ... xcrun -sdk macosx clang
- checking for the objc compiler (mm) ... xcrun -sdk macosx clang
- checking for the objc++ compiler (mxx) ... xcrun -sdk macosx clang++
- checking for the swift compiler (sc) ... xcrun -sdk macosx swiftc
- checking for the assember (as) ... xcrun -sdk macosx clang
- checking for the linker (ld) ... xcrun -sdk macosx clang++
- checking for the static library archiver (ar) ... xcrun -sdk macosx ar
- checking for the static library extractor (ex) ... xcrun -sdk macosx ar
- checking for the shared library linker (sh) ... xcrun -sdk macosx clang++
- checking for the debugger (dd) ... xcrun -sdk macosx lldb
- checking for the golang compiler (go) ... go
- configure
- {
- ex = "xcrun -sdk macosx ar"
- , sh = "xcrun -sdk macosx clang++"
- , host = "macosx"
- , ar = "xcrun -sdk macosx ar"
- , buildir = "build"
- , as = "xcrun -sdk macosx clang"
- , plat = "macosx"
- , xcode_dir = "/Applications/Xcode.app"
- , arch = "x86_64"
- , mxx = "xcrun -sdk macosx clang++"
- , go = "go"
- , target_minver = "10.12"
- , ccache = "ccache"
- , mode = "release"
- , clean = true
- , cxx = "xcrun -sdk macosx clang"
- , cc = "xcrun -sdk macosx clang"
- , dd = "xcrun -sdk macosx lldb"
- , kind = "static"
- , ld = "xcrun -sdk macosx clang++"
- , xcode_sdkver = "10.12"
- , sc = "xcrun -sdk macosx swiftc"
- , mm = "xcrun -sdk macosx clang"
- }
- configure ok!
- clean ok!
- [00%]: ccache compiling.release ./cdjpeg.c
- [00%]: ccache compiling.release ./example.c
- [00%]: ccache compiling.release ./jcapimin.c
- [00%]: ccache compiling.release ./jcapistd.c
- [00%]: ccache compiling.release ./jccoefct.c
- [00%]: ccache compiling.release ./jccolor.c
- [01%]: ccache compiling.release ./jcdctmgr.c
- [01%]: ccache compiling.release ./jchuff.c
- [01%]: ccache compiling.release ./jcinit.c
- [01%]: ccache compiling.release ./jcmainct.c
- [01%]: ccache compiling.release ./jcmarker.c
- [02%]: ccache compiling.release ./jcmaster.c
- [02%]: ccache compiling.release ./jcomapi.c
- [02%]: ccache compiling.release ./jcparam.c
- [02%]: ccache compiling.release ./jcphuff.c
- [02%]: ccache compiling.release ./jcprepct.c
- [03%]: ccache compiling.release ./jcsample.c
- [03%]: ccache compiling.release ./jctrans.c
- [03%]: ccache compiling.release ./jdapimin.c
- [03%]: ccache compiling.release ./jdapistd.c
- [03%]: ccache compiling.release ./jdatadst.c
- [04%]: ccache compiling.release ./jdatasrc.c
- [04%]: ccache compiling.release ./jdcoefct.c
- [04%]: ccache compiling.release ./jdcolor.c
- [04%]: ccache compiling.release ./jddctmgr.c
- [04%]: ccache compiling.release ./jdhuff.c
- [05%]: ccache compiling.release ./jdinput.c
- [05%]: ccache compiling.release ./jdmainct.c
- [05%]: ccache compiling.release ./jdmarker.c
- [05%]: ccache compiling.release ./jdmaster.c
- [05%]: ccache compiling.release ./jdmerge.c
- [06%]: ccache compiling.release ./jdphuff.c
- [06%]: ccache compiling.release ./jdpostct.c
- [06%]: ccache compiling.release ./jdsample.c
- [06%]: ccache compiling.release ./jdtrans.c
- [06%]: ccache compiling.release ./jerror.c
- [07%]: ccache compiling.release ./jfdctflt.c
- [07%]: ccache compiling.release ./jfdctfst.c
- [07%]: ccache compiling.release ./jfdctint.c
- [07%]: ccache compiling.release ./jidctflt.c
- [07%]: ccache compiling.release ./jidctfst.c
- [08%]: ccache compiling.release ./jidctint.c
- [08%]: ccache compiling.release ./jidctred.c
- [08%]: ccache compiling.release ./jmemansi.c
- [08%]: ccache compiling.release ./jmemmgr.c
- [08%]: ccache compiling.release ./jmemname.c
- [09%]: ccache compiling.release ./jmemnobs.c
- [09%]: ccache compiling.release ./jquant1.c
- [09%]: ccache compiling.release ./jquant2.c
- [09%]: ccache compiling.release ./jutils.c
- [09%]: ccache compiling.release ./rdbmp.c
- [10%]: ccache compiling.release ./rdcolmap.c
- [10%]: ccache compiling.release ./rdgif.c
- [10%]: ccache compiling.release ./rdppm.c
- [10%]: ccache compiling.release ./rdrle.c
- [10%]: ccache compiling.release ./rdswitch.c
- [11%]: ccache compiling.release ./rdtarga.c
- [11%]: ccache compiling.release ./transupp.c
- [11%]: ccache compiling.release ./wrbmp.c
- [11%]: ccache compiling.release ./wrgif.c
- [11%]: ccache compiling.release ./wrppm.c
- [12%]: ccache compiling.release ./wrrle.c
- [12%]: ccache compiling.release ./wrtarga.c
- [12%]: archiving.release libjpeg-6b.a
- [12%]: ccache compiling.release ./wrjpgcom.c
- [25%]: linking.release wrjpgcom
- [25%]: ccache compiling.release ./ansi2knr.c
- [37%]: linking.release ansi2knr
- [37%]: ccache compiling.release ./jpegtran.c
- [50%]: linking.release jpegtran
- [50%]: ccache compiling.release ./djpeg.c
- [62%]: linking.release djpeg
- [62%]: ccache compiling.release ./ckconfig.c
- [75%]: linking.release ckconfig
- [75%]: ccache compiling.release ./rdjpgcom.c
- [87%]: linking.release rdjpgcom
- [87%]: ccache compiling.release ./cjpeg.c
- [100%]: linking.release cjpeg
- build ok!👌
复制代码
可以看到,处理静态库,xmake还分析出了很多可执行的测试程序,剩下的代码统一编译成一个 libjpeg.a 的静态库,供哪些测试程序链接使用。。
- target(ansi2knr): binary
- [+]: ./ansi2knr.c
- target(cjpeg): binary
- [+]: ./cjpeg.c
- target(ckconfig): binary
- [+]: ./ckconfig.c
- target(djpeg): binary
- [+]: ./djpeg.c
- target(jpegtran): binary
- [+]: ./jpegtran.c
- target(rdjpgcom): binary
- [+]: ./rdjpgcom.c
- target(wrjpgcom): binary
- [+]: ./wrjpgcom.c
复制代码
遇到的一些问题和限制
当前xmake的这种自动分析检测还不是非常智能,对于: - 需要特殊的编译选项
- 需要依赖其他目录的头文件搜索
- 需要分条件编译不同源文件
- 同目录需要生成多个静态库
- 需要多级目录支持的源码库
以上这些情况,xmake暂时还没发自动化的智能处理,其中限制1,2还是可以解决的,通过半手动的方式,例如: - <font color="#8f592">$ </font>xmake f --cxflags<b>=</b><font color="#ff0ff">""</font> --ldflags<b>=</b><font color="#ff0ff">""</font> --includedirs<b>=</b><font color="#ff0ff">""</font> --linkdirs<b>=</b><font color="#ff0ff">""</font>; xmake
复制代码
在自动检测编译的时候,手动配置这个源码工程需要的特殊编译选项,就可以直接通过编译了
而限制3,暂时只能通过删源代码来解决了,就像刚才编译jpeg的代码,其实它的目录下面同时存在了:- <div><font color="rgb(51, 51, 51)"><font style="background-color:rgb(248, 248, 253)"><font face="" "=""><font style="font-size: 16px">jmemdos.c</font></font></font></font></div><div><font color="rgb(51, 51, 51)"><font style="background-color:rgb(248, 248, 253)"><font face="" "=""><font style="font-size: 16px">jmemmac.c</font></font></font></font></div><div><font color="rgb(51, 51, 51)"><font style="background-color:rgb(248, 248, 253)"><font face="" "=""><font style="font-size: 16px">jmemansi.c</font></font></font></font></div>
复制代码
其中两个是没法编译过的,需要删掉后才行。。
|