如何使用makefile编译不同平台的目标文件(makefile的参数传递)
2017-10-08 14:50
1481 查看
最近在研究一个嵌入式开发项目,在编写实际的项目代码时,需要临时写一些测试代码对部分功能进行预测试。编写的这些代码,有时候需要在PC机(x86)的平台上运行,有时候则需要在A嵌入式平台(arm端)i.mx6的平台上运行,而还有时候则需要在B嵌入式平台(arm端)mini2440的平台上运行,需要能随时进行切换,编译出对应平台所需要的可执行文件。
为了解决这个问题,最土的办法自然就是写三份makefile,需要编译某一个平台时,拷贝对应的makefile,然后再make。可是这样效率很低,而且很low,自然不予考虑。稍微好一点的办法,则是在makefile中,定义三套编译规则,通过输入make x86,以及make imx6,以及make mini2440这样的目标选择命令,来指示编译器选择某一套编译规则并运行。但是,这样的方法,会导致makefile的文件很冗余,存在多套几乎一模一样的编译规则。如下所示:
为了简单起见,上述makefile中,只列举了其中两套编译规则,第三套并没有写上。尽管如此,仍然可以看出整个文件很冗长,虽然整个make的过程很简单,但是makefile的可读性却不怎么高,代码看上去不舒服。而且,最大的问题是,可扩展性很差,当我要再增加第三个平台甚至第四个平台时,代码量是呈倍数增长的,显然不适合。
那么,有没有更好的办法呢?答案显然是有的。
通过一番搜索,我找到了以下的思路:
在makefile中可以预先使用一个未定义的变量, 这个变量可以在make执行时传递给它。换句话说,就是可以向make命令传递参数,告诉它怎么去解释makefile这个文件。
网上关于这个思路最多的例子,就是如何使用同一份代码、同一份makefile,却通过给make命令传入不同的参数来编译出debug版本和release版本,直接去百度一抓一大把【可参见其他博主的博文:如何给Make命令来传递参数,如何给Makefile 传入参数,make传递给Makefile参数,等等】,这里就不再赘述。
于是,根据这个思路,我对上述的makefile文件进行了精简和修改,最终的效果如下所示:
可以看出,修改后的makefile,代码明显精简了,可读性也提高了,最关键的是,扩展性大大提升,日后如果我再需要更换或者增加目标平台时,只需要在文件头处加以修改就搞定!
使用起来的话,只需要输入“make target=x86”命令,或者“make target=imx6”命令,或者“make target=2440”命令,系统就会自动编译出对应平台下的可执行目标文件,而无需对makefile文件本身进行其他多余的操作,大大提升了调试和修改的效率。
为了解决这个问题,最土的办法自然就是写三份makefile,需要编译某一个平台时,拷贝对应的makefile,然后再make。可是这样效率很低,而且很low,自然不予考虑。稍微好一点的办法,则是在makefile中,定义三套编译规则,通过输入make x86,以及make imx6,以及make mini2440这样的目标选择命令,来指示编译器选择某一套编译规则并运行。但是,这样的方法,会导致makefile的文件很冗余,存在多套几乎一模一样的编译规则。如下所示:
# 强制用bash,有的系统/bin/sh默认是用dash的,用dash会导致echo -e显示时多出一个-e SHELL = /bin/bash # syspath & tools COMPILE_x86 = gcc COMPILE_arm = arm-poky-linux-gnueabi-gcc # build target TARGET_x86 := test_x86 TARGET_arm := test_arm # compile option LIBS += -lpthread CFLAGS += -rdynamic -Wall -O2 -Wno-uninitialized LDFLAGS += $(LIBS) # sources path SOURCES += ${wildcard *.c} # build dir BUILDDIR_x86 ?= _build_x86 BUILDDIR_arm ?= _build_arm TEMPDIR_x86 ?= $(BUILDDIR_x86)/temp TEMPDIR_arm ?= $(BUILDDIR_arm)/temp # object files OBJECTS_x86 := $(patsubst %.c,$(TEMPDIR_x86)/%.o,$(filter %.c, $(SOURCES))) DEPENDS_x86 := $(patsubst %.c,$(TEMPDIR_x86)/%.d,$(filter %.c, $(SOURCES))) OBJECTS_arm := $(patsubst %.c,$(TEMPDIR_arm)/%.o,$(filter %.c, $(SOURCES))) DEPENDS_arm := $(patsubst %.c,$(TEMPDIR_arm)/%.d,$(filter %.c, $(SOURCES))) # build command .PHONY: x86 arm clean x86: mngdir_x86 $(TARGET_x86) mngdir_x86: @mkdir -pv $(TEMPDIR_x86) @mkdir -pv $(BUILDDIR_x86) $(TEMPDIR_x86)/%.o: %.c @mkdir -pv $(@D) $(COMPILE_x86) $(CFLAGS) -c -o $@ $< $(TEMPDIR_x86)/%.d: %.c @echo "$@: $<:$(notdir $*)" @mkdir -pv $(@D) @set -e; rm -f $@; \ $(COMPILE_x86) -MM $(CFLAGS) $< > $@.$$$$; \ sed 's,$(notdir $*)\.o[ :]*,$(TEMPDIR_x86)/$*\.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ $(TARGET_x86): $(OBJECTS_x86) $(DEPENDS_x86) $(COMPILE_x86) $(CFLAGS) -o $(BUILDDIR_x86)/$@ $(OBJECTS_x86) $(LDFLAGS) @echo "********************* Bulid $(TARGET_x86) complete ************************" arm: mngdir_arm $(TARGET_arm) mngdir_arm: @mkdir -pv $(TEMPDIR_arm) @mkdir -pv $(BUILDDIR_arm) $(TEMPDIR_arm)/%.o: %.c @mkdir -pv $(@D) $(COMPILE_arm) $(CFLAGS) -c -o $@ $< $(TEMPDIR_arm)/%.d: %.c @echo "$@: $<:$(notdir $*)" @mkdir -pv $(@D) @set -e; rm -f $@; \ $(COMPILE_arm) -MM $(CFLAGS) $< > $@.$$$$; \ sed 's,$(notdir $*)\.o[ :]*,$(TEMPDIR)/$*\.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ $(TARGET_arm): $(OBJECTS_arm) $(DEPENDS) $(COMPILE_arm) $(CFLAGS) -o $(BUILDDIR_arm)/$@ $(OBJECTS_arm) $(LDFLAGS) @echo "********************* Bulid $(TARGET_arm) complete ************************" clean: -@rm -fv $(TARGET_x86) -@rm -fv $(OBJECTS_x86) -@rm -fv $(DEPENDS_x86) -@rm -rfv $(TEMPDIR_x86) -@rm -rfv $(BUILDDIR_x86) -@rm -fv $(TARGET_arm) -@rm -fv $(OBJECTS_arm) -@rm -fv $(DEPENDS_arm) -@rm -rfv $(TEMPDIR_arm) -@rm -rfv $(BUILDDIR_arm) @echo "********************* clean all targets complete ************************"
为了简单起见,上述makefile中,只列举了其中两套编译规则,第三套并没有写上。尽管如此,仍然可以看出整个文件很冗长,虽然整个make的过程很简单,但是makefile的可读性却不怎么高,代码看上去不舒服。而且,最大的问题是,可扩展性很差,当我要再增加第三个平台甚至第四个平台时,代码量是呈倍数增长的,显然不适合。
那么,有没有更好的办法呢?答案显然是有的。
通过一番搜索,我找到了以下的思路:
在makefile中可以预先使用一个未定义的变量, 这个变量可以在make执行时传递给它。换句话说,就是可以向make命令传递参数,告诉它怎么去解释makefile这个文件。
网上关于这个思路最多的例子,就是如何使用同一份代码、同一份makefile,却通过给make命令传入不同的参数来编译出debug版本和release版本,直接去百度一抓一大把【可参见其他博主的博文:如何给Make命令来传递参数,如何给Makefile 传入参数,make传递给Makefile参数,等等】,这里就不再赘述。
于是,根据这个思路,我对上述的makefile文件进行了精简和修改,最终的效果如下所示:
# 强制用bash,有的系统/bin/sh默认是用dash的,用dash会导致echo -e显示时多出一个-e SHELL = /bin/bash # avalible targets target_x86 = x86 target_imx6 = imx6 target_2440 = 2440 # build target TARGET_ARCH = $(target) TARGET_OBJT := temptest_$(TARGET_ARCH) # syspath & tools ifeq ($(TARGET_ARCH), $(target_x86)) COMPILE = gcc else ifeq ($(TARGET_ARCH), $(target_imx6)) COMPILE = arm-poky-linux-gnueabi-gcc else ifeq ($(TARGET_ARCH), $(target_2440)) COMPILE = arm-linux-gcc endif # compile option LIBS += -lpthread CFLAGS += -rdynamic -Wall -O2 -Wno-uninitialized LDFLAGS += $(LIBS) # sources path SOURCES += ${wildcard *.c} # build dir BUILDDIR ?= _build OBJCTDIR ?= $(BUILDDIR)/object_$(TARGET_ARCH) # object files OBJECTS := $(patsubst %.c,$(OBJCTDIR)/%.o,$(filter %.c, $(SOURCES))) DEPENDS := $(patsubst %.c,$(OBJCTDIR)/%.d,$(filter %.c, $(SOURCES))) # build command .PHONY: all useage help clean all: mngdir $(TARGET_OBJT) mngdir: @mkdir -pv $(OBJCTDIR) @mkdir -pv $(BUILDDIR) $(OBJCTDIR)/%.o: %.c @mkdir -pv $(@D) $(COMPILE) $(CFLAGS) -c -o $@ $< $(OBJCTDIR)/%.d: %.c @echo "$@: $<:$(notdir $*)" @mkdir -pv $(@D) @set -e; rm -f $@; \ $(COMPILE) -MM $(CFLAGS) $< > $@.$$$$; \ sed 's,$(notdir $*)\.o[ :]*,$(TEMPDIR_x86)/$*\.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ $(TARGET_OBJT): $(OBJECTS) $(DEPENDS) $(COMPILE) $(CFLAGS) -o $(BUILDDIR)/$@ $(OBJECTS) $(LDFLAGS) @echo "********************* Bulid $(TARGET_OBJT) complete ************************" useage help: @echo "Build Help Info" @echo " make target=$(target_x86) -- build $(target_x86) arch target" @echo " make target=$(target_imx6) -- build $(target_imx6) arch target" @echo " make target=$(target_2440) -- build $(target_2440) arch target" clean: -@rm -rfv $(BUILDDIR) @echo "********************* clean all targets complete ************************"
可以看出,修改后的makefile,代码明显精简了,可读性也提高了,最关键的是,扩展性大大提升,日后如果我再需要更换或者增加目标平台时,只需要在文件头处加以修改就搞定!
使用起来的话,只需要输入“make target=x86”命令,或者“make target=imx6”命令,或者“make target=2440”命令,系统就会自动编译出对应平台下的可执行目标文件,而无需对makefile文件本身进行其他多余的操作,大大提升了调试和修改的效率。
相关文章推荐
- Makefile中使用 for 控制结构编译多个目标文件
- android如何编译出适用于不同平台的库文件
- 使用OpenCV-2.4.0.exe文件编译x86或x64平台Visual Studio 2005/2008/2010目标文件
- 使用makefile编译多个目标文件的方法
- 使用OpenCV-2.4.0.exe文件编译x86或x64平台Visual Studio 2005/2008/2010目标文件
- 如何编写Build对文件手机软件的编译--使用antenna和ant
- 如何正确使用不同类型的WSDL文件
- Win32平台如何编译使用Google test编写的单元测试?
- [技巧靠点点滴滴的积累] Linux平台下如何将make编译的所有信息保存至文件?
- (转)如何让一个动态链接库文件debug和release编译的时候生成不同的文件名
- 请求帮助:如何解决烦人的VS.NET2003编译时“无法将程序集复制到文件,另一个程序正在使用,进程无法访问”的问题?
- Linux内核Makefile编译生成内核目标文件的过程
- Linux内核Makefile编译生成内核目标文件的过程
- 如何将驱动编译进内核 修改Kconfig 和Makefile 文件
- 如何使用IAR软件来调试和下载编译文件到MSP430 LaunchPad!
- 如何由.c或.cpp文件建立 与Qt相关的不同IDE平台的项目文件(.pro 和 .vcproj)和 中间文件夹 放置Generated Files
- 如何在XCode中使用gcc编译生成的.a库文件?
- 不同平台下,库文件的编译和应用原理
- Eclipse如何使用不同的语言平台
- [技巧靠点点滴滴的积累] Linux平台下如何将make编译的所有信息保存至文件?