Chinaunix首页 | 论坛 | 博客
  • 博客访问: 544924
  • 博文数量: 104
  • 博客积分: 2089
  • 博客等级: 大尉
  • 技术积分: 1691
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-29 08:48
文章分类

全部博文(104)

文章存档

2015年(1)

2013年(13)

2012年(31)

2011年(59)

分类: LINUX

2011-12-05 17:25:44

EMake 是一个 Make工具,用来从源文件输出可执行文件。EMake直接从源文件的注释中提取EMake宏指令,来确定这个工程有哪些源文件,他们该如何编译(编译参数,或者头文件路径),并且输出成什么格式(可执行,动态库,静态库,Windows下的窗口模式可执行)。

GNU Make是一个强大的工具,但大部分时候我不会去写一个非常大的需要用Makefile的工程,我经常写一些中小项目,代码在2万行以内,甚至更少(比如几百行)。为每个小工程都编写一个新的Makefile(或者修改一下旧的)是一件非常累的事情(当然你也可以写个足够强大的Makefile来应付我说的情况,但并非大多数人的用法)。

因此我所需要的是像Visual Studio工程管理一样简单直观的编译工具,让我简单的:增加源文件,然后编译他们。这这么简单,所有源代码依赖的头文件都会自动被分析出来,一旦更改,就需要编译他们,否则就跳过。所有繁琐的编译参数都有默认值,在大多数情况下你可以不去管他们,而当你需要时,你可以去定制。

EMake就是一个让你从繁重的Makefile维护中解放出来的工具,它并不是一个GNU Make的 Replacement,只是一个合理的补充,让你用代码中的注释宏来精简的描述工程信息,当你源代码改变的时候,你也可以随手改变工程信息,而且你可以用它指定各种详细的编译细节,真正做到简单,并且真切有力。

EMake 从你源代码的宏中得到工程信息。在C代码中使用 "//!" 或者 "/*!"作为注释的开头,Emake 就会提取并将该行注释看成 EMake的工程配置信息,比如你的main.c中一行这样的注释:

//! exe: file1.c, file2.c

当你使用 "emake.py main.c"时,Emake会知道该项目有三个源文件: file1.c, file2.c 和main.c 自己. 输出的模式是"exe" (还可以是"exe/dll/clib/win"). 接着 emake会分析所有源代码并指出,每个源文件总共使用过了哪些头文件(包括那些头文件又使用了哪些新的头文件). 然后比较它们和obj文件的时间,如果他们任何一个新于OBJ文件的时间戳,那么,这个对应的源代码就需要重新编译,否则跳过。

Emake会调用 gcc来编译工程中的所有文件,然后连接他们输出成指定的文件格式(可执行文件、动态库、静态库、Windows下窗口模式程序。。。)。

EMake is written with python in a single .py file. You can download the tarball and extract emake.py into current folder. Note, emake only supports gcc right now, so if you are under windows, you must download mingw to work with.

use "./emake.py -install" to install. The installation will copy itself into /usr/local/bin. It will search gcc in /usr/bin or /usr/local/bin.

copy emake.py into the root directory of mingw, in order to find gcc.exe in ".\bin\" directory. then you can execute as "c:\mingw\emake.py"

下载地址:

Documentation

testmain.c:

#include
#include "testsrc1.h"

//! mode: exe
//! flag: -O3
//! link: m
//! out: testmain
//! src: testmain.c, testsrc1.c
int main(void)
{
        foo
();
       
return 0;
}
  • The comment macro "//!" tells emake this is an EMake Macro,
  • mode tells emake the output format is an executable file (It can be 'exe', 'dll', 'lib').
  • out tells emake the output file's name
  • src tells emake there are two source files(testmain.c and testsrc1.c)
  • flag tells emake to send "-O3" to gcc parameters in compiling
  • link tells emake to send "-lm" to gcc parameters in linking

testsrc1.h:

#ifndef __TESTSRC1_H__
#define __TESTSRC1_H__

void foo(void);

#endif

testsrc1.c:

#include
#include "testsrc1.h"

void foo(void)
{
        printf
("This is foo\n");
}

Then you can use emake to build this project:

% python emake.py testmain.c
compiling
...
testmain
.c
testsrc1
.c
linking
...

Then you can run your executable file:

% ./testmain
This is foo

Actually EMake has done these things below for you:

gcc -O3 -c testmain.c -o testmain.o
gcc
-O3 -c testsrc1.c -o testsrc1.o
gcc testmain
.o testsrc1.o -o testmain -lm

Every time you call "emake.py testmain.c", it will check the timestamp of testmain.c and testsrc1.h (included by testmain.c) and timestamp of testmain.o, If they are earlier than testmain.o emake will skip compiling testmain.c.

It is that emake will parse the source file and find what header files it included and what header files the header files included, and so on, at last emake will find all the header files involved by the source file. Emake can check whether to compile the source by the timestamp of these files and the timestamp of the obj file.

If you add a emake macro with "//! int: PATH" in testmain.c, emake will output obj files and other intermediate files into PATH,eg:

//! mode: exe
//! int: obj
//! out: testmain
//! src: testmain.c
//! src: testsrc1.c

emake will do these thing below for you:

mkdir obj
gcc
-c testmain.c -o obj/testmain.o
gcc
-c testsrc1.c -o obj/testsrc1.o
gcc obj
/testmain.o obj/testsrc1.o -o testmain

Note: "src" keywords can be used many times, all the files followed by each "src" will be involved in the project.

There is a main.c which contains the following comment lines as emake macro:

//! exe: source1.c, source2.c

It is same as these three instructions:

//! mode: exe
//! int: obj
//! src: source1.c, source2.c

If you used the keywords exe/dll/clib/win and followed by a file list (the list can be nothing '//!exe :\n'), emake will do the three things:

  • set intermediate file folder to "obj"
  • set output mode to exe/dll/clib/win (note: use clib to avoid conflicting with another keyword lib)
  • set the source files to the project file list.

and then do the following jobs for you:

mkdir obj
gcc
-c source1.c -o obj/source1.o
gcc
-c source2.c -o obj/source2.o
gcc
-c main.c -o obj/main.o
gcc obj
/main.o obj/source1.o obj/source2.o -o main//! flags: -O3, -g
//! link: stdc++, pthread
//! exe: source1.c, source2.c

EMake will do these jobs below for you:

mkdir obj
gcc
-O3 -g -c source1.c -o obj/source1.o
gcc
-O3 -g -c source2.c -o obj/source2.o
gcc
-O3 -g -c main.c -o obj/main.o
gcc obj
/main.o obj/source1.o obj/source2.o -o main -lstdc++ -lpthread//! dll: src1.c, src2.c//! clib: src1.c, src2.c//! inc: ../ffmpeg/include
//! inc: ../ogg/include
//! lib: ../ffmpeg/lib
//! lib: ../ogg/lib
//! exe: src1, src2

EMake will do these jobs below for you:

mkdir obj
gcc
-I../ffmpeg/include -I../ogg/include -c src1.c -o obj/src1.o
gcc
-I../ffmpeg/include -I../ogg/include -c src2.c -o obj/src2.o
gcc
-I../ffmpeg/include -I../ogg/include -c main.c -o obj/main.o
gcc
-L../ffmpeg/lib -L../ogg/lib obj/src1.o obj/src2.o obj/main.o -o main

来自:
阅读(2028) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~