专利名称:一种编译程序的方法及装置的制作方法
技术领域:
本发明涉及编译技术领域,特别是涉及一种编译程序的方法及装置。
背景技术:
通常,在编写好程序代码之后,在Windows下使用IDE(IntegratedDevelop Environment,集成开发环境)工具对编写完成的代码进行编译时,大多数IDE会自动生成 Makefile文件,因此,程序员通常不需要关注如何写Makefile文件,只需要将代码编写好 后,运行IDE工具提供的"编译",IDE工具会自动生成Makefile文件,进行编译,得到最终结果。 但是,在li皿x下编程时,程序员就不得不直接面对Makefile文件了。例如,对于 一个简单的程序,只含有main.c,程序员编译时可以直接用gcc编译器,使用gcc-o test main, c命令即可得到最终可执行文件test。但是如果工程里面包含了大量的源文件,以及 依赖模块,则直接使用gcc输入命令显然是不合适的,所以,make工具解决了这个问题,该 工具通过读入符合Makefile规则的文件(默认文件名为Makefile或makefile,也可以通 过make_f ***来使用非标准文件名的Makefile文件),来推导各个源文件的依赖关系,调 用相应的编译指令来生成最终目标。 对于一个源文件较少的工程,直接按照Makefile规则编写一个Makefile文件 不是很难的一件事情,但是对于一个包含了大量的源文件,且依赖的模块有很多的工程, 写一个正确的Makefile文件就不是一件容易的事情了,对每一个工程都要写一个正确的 Makefile文件,常常需要耗费程序员很大的精力,并且容易出错,不便于维护及移植。
发明内容
本发明提供一种编译程序的方法及装置,能够提高程序编译的效率。
为实现上述目的,本发明提供了如下方案
—种编译程序的方法,包括 读入用户输入的环境参数,配置环境参数变量; 调用相关的shell脚本工具,生成编译规则临时文件; 引用所述编译规则临时文件,调用相应的编译器对程序进行编译。 优选的,还包括 调用相关的shell脚本工具,从预先保存的文件中获取依赖模块的相关信息,将 所述相关信息加入主模块的相关参数中。 优选的,当所述依赖模块为静态库模块时,所述依赖模块的相关信息包括所述依 赖模块本身。 优选的,当所述依赖模块为动态库模块时,所述依赖模块的相关信息包括所述依 赖模块所在的路径或者名称。
优选的,还包括
读入所述依赖模块的环境参数,编译所述依赖模块,并生成本次编译过程的缓存 文件。 优选的,还包括 判断依赖模块是否已经保存在缓存文件中,如果是,跳过编译所述依赖模块的步 骤。
—种编译程序的装置,包括 读入单元,用于读入用户输入的环境参数,配置环境参数变量; 生成单元,用于调用相关的shell脚本工具,生成编译规则临时文件; 编译单元,用于引用所述编译规则临时文件,调用相应的编译器对程序进行编译。 优选的,还包括 依赖模块获取单元,用于调用相关的shell脚本工具,从预先保存的文件中获取 依赖模块的相关信息,将所述相关信息加入主模块的相关参数中。 优选的,当所述依赖模块为静态库模块时,所述依赖模块的相关信息包括所述依 赖模块本身。 优选的,当所述依赖模块为动态库模块时,所述依赖模块的相关信息包括所述依 赖模块所在的路径或者名称。
优选的,还包括 缓存单元,用于读入所述依赖模块的环境参数,编译所述依赖模块,并生成本次编
译过程的缓存文件。 优选的,还包括 判断单元,用于判断依赖模块是否已经保存在缓存文件中,如果是,跳过编译所述 依赖模块的步骤。
根据本发明提供的具体实施例,本发明公开了以下技术效果 本发明能够通过读入用户输入的环境参数,配置环境参数变量;调用相关的 shell脚本工具,生成编译规则临时文件;引用所述编译规则临时文件,调用相应的编译器 对程序进行编译。因此,通过本发明,用户无须手动编写Makefile文件,只需要输入环境参 数,就可以调用本发明提供的shell脚本工具,生成编译规则临时文件,然后完成实现编译 过程。因此,能够方便、快捷地完成编译,并且易于维护和移植,能够提高编译速度。
此外,在进行跨平台或交叉编译时,只需要指定平台参数即可,而不需要专门针对 某个平台编写不同的Makefile文件。 最后,主模块和依赖模块可以同时编译,方便于同时开发主模块和依赖模块的情 况。
为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例中所 需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施 例,对于本领域普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这些附图 获得其他的附图。
图1是本发明实施例提供的方法的流程4
图2是本发明实施例提供的装置的示意图。
具体实施例方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完 整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于 本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他 实施例,都属于本发明保护的范围。
参见图l,本发明实施例提供的编译程序的方法包括以下步骤 S101 :读入用户输入的环境参数,配置环境参数变量; S102 :调用相关的shell脚本工具,生成编译规则临时文件; S103 :引用所述编译规则临时文件,调用相应的编译器对程序进行编译。 为了实现上述技术方案,本发明实施例提供了 Makefile模板以及一系列的shell
脚本工具。其中,shell脚本工具可以组成.rules文件,保存在与各工程的同级或上级目
录中,以便各工程都可以调用.rules文件中的Shell脚本工具。 用户仅需填写Makefile模板中所需的环境参数,然后点击make,本发明实施例提 供的编译工具就可以调用rules, gcc这一 shell脚本工具,读入用户编译时输入的参数,来 配置相关参数变量,调用相应的shell脚本工具,来生成编译规则文件进行编译,生成最终
目标,即整个过程中,无须生成通常意义上的Makefile文件,make之前,也不需要首先经过 "自动生成Makefile文件"等操作。 其中,Makefile模板主要是提供给用户,由用户填写一些环境参数,其中,环境参 数可以包括 A)平台名称PLATFORM
ifeq ($ (PLATFORM),)
PLATFORM = i 386-1 i皿x
Endif 即,如果make时没有指定PLATFORM,则默认是i386-li皿x类型
B)输出类型及名称
#MAKE_STATIC_LIB := 1
#MAKE_SHARED_LIB : = 1
EXECUTABLE := 即,如果输出时静态库,则MAKE_STATIC_LIB : = 1 ,如果是动态库,则MAKE_ SHARED_LIB : = 1 否则是可执行文件。目标名称为EXECUTABLE值。其中,MAKE—STATICJJB和MAKE_SHARED_LIB 二者最多只能设定一个,可执行文件
不能设定这两个选项的任何一个。 EXECUTABLE :=最终目标文件名。 C)头文件路径 INCLUDE—PATH : = $ (SYS—INCLUDE—PATH) \ 默认已经包含了系统头文件路径,只需把程序中依赖的所有头文件路径包含进来
5即可 D)用户自定义宏 DEFINES : = _DXP_UNIX_DOS_LINUX 如果是程序中固定的宏,可以直接写在这里,如果是可变的宏定义,可以灵活地通 过make参数加在这里。 E)包含路径设定 INCLUDE—PATH : = $ (SYS—INCLUDE—PATH) 如果程序依赖其他库,可以把库路径写在这里。 其中,INCLUDE—PATH是项目需要的include文件的目录,如广I. /-I. /include ; SYS_INCLUDE_PATH为系统包含文件路径的环境变量。 F)连接库包含路径设定 LIBRARY—PATH : = $ (SYS—LIBRARY—PATH) 其中,LIBRARY_PATH是项目在此路径下搜索包含的动态库,如_L. /_L. . / sourc6 j SYS_LIBRARY_PATH为系统lib文件路径的环境变量。 G)连接库设定 1JBS := _lpthread_lstdc++ USERLIBS := 其中,LIBS是一个需要连接的标准程序库列表,带-1前缀,例如pthread, stdc++
坐坐 寸寸; USERLIBS是需要连接的用户程序库列表,不带_1前缀; 对于li皿x下的动态库必须加在LIBS里面,并在LIBRARY_PATH里面加上动态库 所在的目录,其中,动态库必须以1 ib为前缀。
H)源文件设定 SOURCE : = $ (wildcard. /source/氺.c) $ (wi ldcard. /source/氺.cc) $ (wildcard. / source/承.cpp)
_S0URCE := 其中,默认SOURCE为makefile所在目录下的source目录下所有c/c++源文件;
源文件最终集合=[SOURCE集]-[_S0URCE集]。 用户仅需要将上述环境参数填写完毕,就可以输入make指令,然后,make工具就 会自动调用相关的shell脚本工具(make_0bj_rules),生成编译规则临时文件,该文件符 合Makefile规范,然后引用所述编译规则临时文件,调用相应的编译器对程序进行编译。
在实际应用中, 一个工程的主模块可能会存在大量的依赖模块,在现有技术中,需 要在Makefile文件中根据每个模块的类型(如动态库和静态库),在调用编译器的指令处 将依赖的模块的最终生成目标所在路径、模块名称等参数填写正确,,并且,主模块和依赖 模块间的编译是独立的,编译主模块时,必须确保倚赖模块最终生成目标已经被编译,才能 生成主模块的最终目标,这对于同时开发主模块和依赖模块的情况,由于经常会同时修改 依赖模块,并且可能模块间依赖关系比较复杂,如果每次都要先将依赖的模块全部编译好 之后再编译主模块,并且在全部编译好之后还要将依赖的所有动态库模块都拷贝到主模块目录下运行,则使用起来不方便,不能在编译时自动开始编译所依赖的工程,并且在编译后 自动安装(即拷贝所有依赖的动态库到主模块最终生成的可执行文件所在目录下),以能 够运行最终的可执行文件。 而在本发明实施例中,依赖关系可以写在一个单独的文件(modules, d印end)中,
并且同时提供了相应的shell脚本工具(kd印end),在编译主模块的过程中,可以调用
kd印end去获取依赖模块的目标名、目标路径等,并加入到主模块的相关参数中。 其中,如果MODULES_DEPEND中含静态库模块,则可以直接添加该依赖模块到
USERLIBS变量;如果MODULES_DEPEND中含动态库模块,则可以添加该动态库模块所在路径
或者名称到LIBRARY—PATH变量。 其中,依赖模块也具有子集的环境参数(也是由用户填写的),并且还可以有其所 依赖的模块。也就是说,在编译依赖模块时,其处理方法与编译主模块是一样的,同样需要 读入其环境参数,并配置环境参数变量,而且,也可以调用相关的shell脚本工具,生成编 译规则临时文件,对该依赖模块进行编译。因此,在本发明实施例中,依赖模块与主模块的 编译不是相互独立的,可以在编译主模块的过程中,编译依赖模块,因此,在编译主模块时, 就不再需要预先编译好依赖模块,主模块与依赖模块可以同时开发。 在实际应用中,可能会有多个模块都依赖于同一依赖模块,这样在对某依赖模块 编译过之后,在该依赖模块没有发生更新的情况下,其他模块再调用该依赖模块时,就可以 不用再进行编译。 为此,本发明实施例可以在编译所述依赖模块时,生成本次编译过程的缓存 (cache)文件。相应的,本发明实施例提供了另一种shell脚本工具mkcachefile,调用该 工具时,可以生成本次编译过程的cache文件,该文件用于保存本次编译过程中已经编译 过的模块,避免多模块依赖同一模块时对该模块的重复编译。然后,还可以调用put_int0_ cache工具,将已编译的依赖模块加入cache文件中 同时,还可以提供notjrucache脚本工具,调用该工具可以判断某依赖模块是否 存在cache文件中,如不存在则编译该依赖模块,否则表示已经编译过,跳过对该依赖模块 的编译过程。同时也可以判断某模块是否已经执行过拷贝到最终目标路径的过程。
除了 Makefile模板及shell脚本工具之外,本发明实施例还提供了平台相关配 置文件,该文件主要用来指明平台相关的工具,配置文件名格式为rules. (PLATFORM),如 mips平台下配置文件取名为rules, mipsel-li皿x, i386平台下配置文件取名为rules. i386-li皿x,平台配置文件主要设置该平台下编译工具的名称前缀,及平台相关的隐含规 则变量等,如rules, mipsel-li皿x内容。这样,在进行跨平台或交叉编译时,填写平台相关 配置文件即可,而不需要针对各个平台编写相应的Makefile文件。 其中,所述交叉编译指在一个平台上生成另一个平台上的可执行代码,在一些特 定环境下,例如目标机器由于资源问题不能运行编译器,或源程序太大不能拷贝到目标机 器进行编译时,都需要在另外一个平台上,安装目标平台的交叉编译工具链,来编译成能运 行在目标平台上的可执行文件。在现有技术中,当用户在开发程序时,可能想分别编译成目 标平台A和B(如X86和mips平台)上的代码以检查编译是否正确,则需要分别生成平台 A和B上的Makefile文件进行编译,而本发明实施例中则不需要分别针对平台生成相应的 Makefile文件,只需要在平台配置文件中进行配置即可。
为了更好地理解本发明实施例提供的方法,下面通过具体应用中的操作流程,对 本发明进行详细地介绍。( — )工程的目录结构需要遵循规则拷贝所有需要的shell脚本工具和平台配 置文件到.rules目录,并将.rules目录保存为与所有工程目录同级或更高一级;Makefile 模板文件和modules, d印end必须位于工程目录下。例如可建立如下目录结构 -project -------- rules ---------prjl -----------------source -----------------include -----------------Makefile -----------------modules, depend ---------prj2 -----------------source -----------------include -----------------Makefile -----------------modules, depend ( 二 )当建立一个新的工程进行编译时首先拷贝Makefile模板到工程目录下,
按照模板格式填写必要的参数,同时将工程依赖的模块路径写到modules, d印end文件中, 编译即可。(三)编译流程 1)用户输入make命令进行编译时,make工具开始解析Makefile模板文件,读取 该模板文件的参数变量; 2)通过Makefile模板中 的语句include$ (T0PDIR)/. rules/ rules. $ (PLATFORM) , make工具开始解析.rules目录下的rules. $ (PLATFORM)文件,读入 平台相关参数变量。其中,$ (PLATFORM)被替换为用户在make时指定的平台类型(不指定 时默认为i386-li皿x)。例如,makePLATF0RM = i386-li皿x表示编译成i386-li皿x平台 上的目标,makePLATFORM = mipsel—linux表示编译成mipsel—linux平台上的目标;
3)通过rules. ($PLATF0RM)文件中的语句include$ (T0PDIR)/ rules/rules. gcc, make工具开始解析 rules目录下的rules, gcc文件; 4)make工具解析rules, gcc过程中,对相关参数变量进行了赋值,并执行相关指 令,依次编译依赖的模块,生成本模块的编译规则临时文件,调用编译器进行编译,具体过 程如下 a)调用mkcachefile生成cache文件
b)相关环境参数设置,主要参数为
BUILDING_0UTPUT_DIR :目标输出路径。
INSTALL_DIR :目标安装全路径
CC:C编译器
0++<::0++编译器
LD:连接器MODULES_DEPEND :从.modules, d印end文件中获取依赖模块到该变量;USERLIBS :调用kd印end工具,如MODULES_DEPEND中含静态库模i央,则添加该模土央
到USERLIBS变量; LIBRARY_PATH :调用kd印end工具,如MODULES_DEPEND中含动态库模i央,则添加该 动态库模块所在路径到LIBRARY_PATH变量; LIBS :调用kd印end工具,如MODULES_DEPEND中含动态库模块,则添加该动态库模 块名到LIBS变量;CFLAGS, CXXFLAGS, DEFINES, LDFLAGS :隐含规则变量;
LDFLAGS :运行时lib寻找路径和连接时的lib路径;
OBJS, DEPS :编译工具编译时输入参数变量;
5)规则设置好后,执行编译过程 [O130] a)编译依赖模块 对每个依赖模块,调用notjn—cache检查该模块是否在cache文件中;如在 cache文件中,表示该模块已经被编译过,检查下一个模块,重复a);如没有在cache文件, 则调用make,并将参数传递,编译该依赖模块,编译过程与编译主模块相同;并将该模块的 名称加入cache中,表明该模块已经被编译; b)调用make_obj_rules生成本模块编译规则临时文件obj_rules. tmk ;
c)make命令工具引用obj_ruleS. tmk文件,调用相应编译器进行编译。
6)编译完成后,执行安装过程 a)如果本模块是静态库,拷贝本模块生成目标结果到INSTALL_DIR目录; b)如果本模块非静态库,则对每个依赖目标,调用notjn—cache判断该目标是否
已经被安装; c)如果已经被安装到INSTALL_DIR目录,则检查下一个模块; d)如果没有安装,则执行拷贝安装过程,并在cache文件中置已经安装标志。 总之,本发明实施例可以建立一套标准的Makefile模板,结合所提供的shell脚
本工具,使得对于每个工程,只需要按照Makefile模板格式填写一些相关的环境参数,即
可通过make工具进行编译;编译时自动编译依赖模块,且对该过程进行优化,避免多模块
依赖同一模块时对该依赖模块的重复编译和最终拷贝安装过程。 与本发明实施例提供的编译程序的方法相对应,本发明实施例还提供了一种编译 程序的装置,参见图2,该装置包括 读入单元U201,用于读入用户输入的环境参数,配置环境参数变量;
生成单元U202,用于调用相关的shell脚本工具,生成编译规则临时文件;
编译单元U203,用于引用所述编译规则临时文件,调用相应的编译器对程序进行 编译。
当一个工程存在多个依赖模块时,该装置还可以包括 依赖模块获取单元,用于调用相关的shell脚本工具,从预先保存的文件中获取 依赖模块的相关信息,将所述相关信息加入主模块的相关参数中。 其中,当所述依赖模块为静态库模块时,所述依赖模块的相关信息包括所述依赖
9模块本身。 当所述依赖模块为动态库模块时,所述依赖模块的相关信息包括所述依赖模块所 在的路径或者名称。
为了避免对同一依赖模块的重复编译,该装置还可以包括 缓存单元,用于读入所述依赖模块的环境参数,编译所述依赖模块,并生成本次编 译过程的缓存文件。
在此基础上,该装置还可以包括 判断单元,用于判断依赖模块是否已经保存在缓存文件中,如果是,跳过编译所述 依赖模块的步骤。 以上对本发明所提供的一种编译程序的方法及装置,进行了详细介绍,本文中应 用了具体个例对本发明的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理 解本发明的方法及其核心思想;同时,对于本领域的一般技术人员,依据本发明的思想,在具体实施方式
及应用范围上均会有改变之处。综上所述,本说明书内容不应理解为对本发 明的限制。
10
权利要求
一种编译程序的方法,其特征在于,包括读入用户输入的环境参数,配置环境参数变量;调用相关的shell脚本工具,生成编译规则临时文件;引用所述编译规则临时文件,调用相应的编译器对程序进行编译。
2. 根据权利要求l所述的方法,其特征在于,还包括调用相关的shell脚本工具,从预先保存的文件中获取依赖模块的相关信息,将所述 相关信息加入主模块的相关参数中。
3. 根据权利要求2所述的方法,其特征在于,当所述依赖模块为静态库模块时,所述依 赖模块的相关信息包括所述依赖模块本身。
4. 根据权利要求2所述的方法,其特征在于,当所述依赖模块为动态库模块时,所述依 赖模块的相关信息包括所述依赖模块所在的路径或者名称。
5. 根据权利要求2所述的方法,其特征在于,还包括读入所述依赖模块的环境参数,编译所述依赖模块,并生成本次编译过程的缓存文件。
6. 根据权利要求5所述的方法,其特征在于,还包括判断依赖模块是否已经保存在缓存文件中,如果是,跳过编译所述依赖模块的步骤。
7. —种编译程序的装置,其特征在于,包括读入单元,用于读入用户输入的环境参数,配置环境参数变量;生成单元,用于调用相关的shell脚本工具,生成编译规则临时文件;编译单元,用于引用所述编译规则临时文件,调用相应的编译器对程序进行编译。
8. 根据权利要求7所述的装置,其特征在于,还包括依赖模块获取单元,用于调用相关的shell脚本工具,从预先保存的文件中获取依赖 模块的相关信息,将所述相关信息加入主模块的相关参数中。
9. 根据权利要求8所述的装置,其特征在于,当所述依赖模块为静态库模块时,所述依 赖模块的相关信息包括所述依赖模块本身。
10. 根据权利要求8所述的装置,其特征在于,当所述依赖模块为动态库模块时,所述 依赖模块的相关信息包括所述依赖模块所在的路径或者名称。
11. 根据权利要求8所述的装置,其特征在于,还包括缓存单元,用于读入所述依赖模块的环境参数,编译所述依赖模块,并生成本次编译过 程的缓存文件。
12. 根据权利要求11所述的装置,其特征在于,还包括判断单元,用于判断依赖模块是否已经保存在缓存文件中,如果是,跳过编译所述依赖 模块的步骤。
全文摘要
本发明公开了一种编译程序的方法及装置,其中,所述方法包括读入用户输入的环境参数,配置环境参数变量;调用相关的shell脚本工具,生成编译规则临时文件;引用所述编译规则临时文件,调用相应的编译器对程序进行编译。通过本发明,能够方便、快捷地完成编译,并且易于维护和移植,能够提高编译速度。
文档编号G06F9/45GK101697135SQ20091023585
公开日2010年4月21日 申请日期2009年10月28日 优先权日2009年10月28日
发明者田海燕, 郭军 申请人:北京东方网力科技有限公司;