首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
宝塔
V2EX  ›  程序员

无需手写任何 make 文件,智能扫描代码进行自动编译

  •  
  •   waruqi · 2017-01-09 18:06:57 +08:00 · 2260 次点击
    这是一个创建于 1043 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近给xmake增加了一个新特性,对于一份工程源码,可以不用编写 makefile ,也不用编写各种 make 相关的工程描述文件(例如: xmake.lua , makefile.am, cmakelist.txt 等)

    xmake 就可以直接编译他们,这是如何做到的呢,简单来说下实现原理:

    1. 首先扫描当前目录下, xmake 所以支持的所有源代码文件
    2. 分析代码,检测哪些代码拥有 main 入口函数
    3. 所有没有 main 入口的代码编译成静态库
    4. 带有 main 入口的代码,编译成可执行程序,同时链接其他静态库程序

    这种代码扫描和智能编译,非常简单,目前 xmake 还不支持多级目录扫描,只对单级目录的代码进行扫描编译。。

    开源代码的移植和编译

    虽然这种方式,并不是非常智能,限制也不少,但是对于想临时写些代码进行编译运行,或者临时想交叉编译一些简单的开源库代码

    这种方式已经足够使用了,下面看下一个实际的例子:

    我下载了一份 zlib-1.2.10 的源码,想要编译它,只需要进入 zlib 的源码目录执行:

    $ cd zlib-1.2.10
    $ xmake
    

    就行了,输出结果如下:

    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 命令来,就很繁琐了,你需要:

    gcc ./main.c -o demo
    ./demo
    

    最快速的方式,也需要执行两行命令,而如果用 xmake ,只需要执行:

    xmake run
    

    就行了,它会自动检测到代码后,自动生成对应的 xmake.lua ,自动编译,自动运行,然后输出:

    hello world!
    

    如果你有十几个代码文件,用手敲 gcc 的方式,或者写 makefile 的方式,这个差距就更明显了,用 xmake 还是只需要一行命令:

    xmake run
    

    多语言支持

    这种代码检测和即时编译,是支持多语言的,不仅支持 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 的这个新特性,直接执行:

    $ 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 目录后,执行:

    $ 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 的这种自动分析检测还不是非常智能,对于:

    1. 需要特殊的编译选项
    2. 需要依赖其他目录的头文件搜索
    3. 需要分条件编译不同源文件
    4. 同目录需要生成多个静态库
    5. 需要多级目录支持的源码库

    以上这些情况, xmake 暂时还没发自动化的智能处理,其中限制 1 , 2 还是可以解决的,通过半手动的方式,例如:

    $ xmake f --cxflags="" --ldflags="" --includedirs="" --linkdirs=""; xmake
    

    在自动检测编译的时候,手动配置这个源码工程需要的特殊编译选项,就可以直接通过编译了

    而限制 3 ,暂时只能通过删源代码来解决了,就像刚才编译 jpeg 的代码,其实它的目录下面同时存在了:

    jmemdos.c
    jmemmac.c
    jmemansi.c
    

    其中两个是没法编译过的,需要删掉后才行。。


    个人主页:TBOOX 开源工程 原文出处:http://tboox.org/cn/2017/01/07/build-without-makefile/

    17 回复  |  直到 2017-01-10 21:30:39 +08:00
        1
    skydiver   2017-01-09 18:19:07 +08:00
    > 最快速的方式,也需要执行两行命令

    并不需要。你写一个 main.c 直接输入 make main 就出来可执行文件了
        2
    waruqi   2017-01-09 18:40:46 +08:00
    @skydiver 这样确实也可以。赞一个。
        3
    waruqi   2017-01-09 18:43:37 +08:00
    @skydiver 但是我说的是加上运行:

    gcc ./main.c -o demo
    ./demo

    改成:

    make main
    ./main

    还是需要两条命令,用; 合并后为: make main; ./main 这是最简的了。。

    如果用 xmake ,只需要执行:

    xmake run

    或者其缩写: xmake r 就行了
        4
    firefox12   2017-01-09 19:29:03 +08:00 via iPad
    赞,我也想做一个这个。关键是选择哪些文件被用到了。选最小集合。这个比较麻烦
        5
    waruqi   2017-01-09 19:40:29 +08:00 via Android
    @firefox12 这个确实很难完美处理 所以我现在只处理单级目录。仅用于一些小模块的快速编译。。 里面的源代码都作为可编译对象 。。里面通过检测 main 入口 来支持多 target 。。多级目录就复杂了 复杂工程 我暂时还是通过写 xmake.lua 文件来维护
        6
    codehz   2017-01-09 19:46:30 +08:00
    要是能识别常见构建系统的配置文件并转换就更好了。。。这样,所有软件都可以统一了
        7
    waruqi   2017-01-09 19:48:17 +08:00 via Android
    @codehz 这个我以后也会考虑做进去 不过最近还是重点
        8
    thomaspaine   2017-01-10 11:01:10 +08:00
    >> 用 xmake 进行交叉编译会更方便些
    怎么个方便法?有参数可以指定不同版本的编译环境么?
        9
    waruqi   2017-01-10 11:56:28 +08:00
    @thomaspaine 可以参考下这篇文档: http://tboox.org/cn/2016/07/22/how-to-compile-on-cross-toolchains/

    对于交叉 toolchains ,会自动检测工具链结构,通常情况下,只需要只需要指定整个 toolchains 的 rootdir :

    xmake f -p linux --sdk=/home/toolchains_sdkdir

    就行了, xmake 会去自动探测 toolchains 的结构,找到编译器,以及自动检测 arm-linux- 等前缀。。然后直接编译。。

    只有很少情况下,才需要额外参数设置。。大部分情况下,所有都是自动检测的。。
        10
    zhidian   2017-01-10 14:05:24 +08:00
    如果只是为了偷懒,用 1 楼那种就很好了。如果想稍微工程化一点,用 qt 的 qmake 也是极好的。
    基本步骤是, 1 )写好你的源码; 2 )用 qmake 分析你的源码,生成 .pro 文件; 3 )生成 Makefile 文件; 4 ) make 。而且还支持多层目录啊……


    ```
    # 来看看 qmake 有多方便
    $ pwd
    /tmp/tmp

    # 随手写了一个 main 文件,一个 header 文件:
    $ ls
    main.cpp header.h
    $ cat main.cpp
    #include <iostream>
    #include "header.h"

    int main() {
    echo();
    }
    $ cat header.h
    int echo() {
    std::cout << "Echo is here\n";
    }

    # 先用 qmake 生成 qt 的 pro 工程文件
    $ qmake -project
    # 再用 qmake 生成 Makefile 工程文件
    $ qmake

    # 文件夹下:
    $ ls
    header.h main.cpp Makefile tmn p.pro

    # 编译
    ➜ tmp make
    g++ -c -pipe -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I. -I. -I/opt/Qt5.7.1/5.7/gcc_64/include -I/opt/Qt5.7.1/5.7/gcc_64/include/QtGui -I/opt/Qt5.7.1/5.7/gcc_64/include/QtCore -I. -I/opt/Qt5.7.1/5.7/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
    In file included from main.cpp:2:0:
    header.h: In function ‘ int echo()’:
    header.h:3:1: warning: no return statement in function returning non-void [-Wreturn-type]
    }
    ^
    g++ -Wl,-O1 -Wl,-rpath,/opt/Qt5.7.1/5.7/gcc_64/lib -o tmp main.o -L/opt/Qt5.7.1/5.7/gcc_64/lib -lQt5Gui -L/usr/lib64 -lQt5Core -lGL -lpthread

    # 运行
    ➜ tmp ./tmp
    Echo is here
    ```
        11
    waruqi   2017-01-10 14:42:42 +08:00
    @zhidian xmake 这个特性既可以给偷懒的人用,并且它会自动生成 xmake.lua 。。

    你也可以进一步对其工程化处理, xmake.lua 完全支持复杂工程维护的,也支持多级目录。。

    并且完全不依赖 make ,不需要生成 makefile ,当然也提供了插件,来生成: makefile , vsproj 等第三方工程文件。。
        12
    waruqi   2017-01-10 14:46:15 +08:00
    而且 xmake 提供了各种工程默认,不需要手动创建 main.c ,只需要执行:

    xmake create -P ./test

    就可以创建一个简单的 console 工程,可以直接编译运行:

    xmake run

    各种 static/console/shared 工程,以及 c/c++/objc/swift 工程模板,都有提供( golang 的工程创建以及编译也在支持中。。)
        13
    waruqi   2017-01-10 14:49:42 +08:00
    编译工程也不需要,额外的 像 qmake 那样,还要执行命令去生成 pro 工程文件,一般情况,只需要执行:

    xmake

    就可以直接编译,完全不依赖 makefile 和 make 工具。。

    第三方 IDE 的工程文件生成,通过插件方式提示,只有在你需要生成 vsproj, makefile 的情况下(例如需要打开 vs 进行代码编辑),你再去生成就行了,通常情况下,只需要直接一键快速编译。。

    并且直接编译的效率,也是优化过的,自动多任务编译。。
        14
    waruqi   2017-01-10 14:54:07 +08:00   ♥ 1
    并且同时支持: ios, android, windows, linux , mingw, 交叉编译等各种编译平台和模式

    之间只需要在配置的时候,快速换平台就行:

    xmake -p android
    xmake -p iphoneos
    xmake -p watchos
    xmake -p linux
    xmake -p windows
    xmake -p mingw

    只要代码跨平台,编译切平台、切 arch 都非常方便
        15
    thomaspaine   2017-01-10 16:33:28 +08:00
    @waruqi 点赞!
        16
    leitwolf   2017-01-10 18:21:29 +08:00
    支持支持,目前在用。
        17
    waruqi   2017-01-10 21:30:39 +08:00 via Android
    @leitwolf 嗯嗯 感谢支持。。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4230 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 32ms · UTC 01:40 · PVG 09:40 · LAX 17:40 · JFK 20:40
    ♥ Do have faith in what you're doing.