Makefile的几则实用技巧

来源:互联网 发布:波动大的数据预测方法 编辑:程序博客网 时间:2024/06/02 07:06

转载时请注明出处和作者联系方式

作者联系方式:会飞的鱼 <parker30_liu at hotmail dot com>

GNUMakefile有强大的功能,我们一直都用Makefile控制整个项目的构建过程。在使用Makefile的过程中有些有时用了些技巧,记录在此,以备以后参考。

技巧一:根据Makefile的内容自动生成Makefile的变量

在我们的工程中有着众多的模块,根据我们的使用和分析,大部分的模块使用同样的优化参数即可,但有些模块需要用另外的优化参数。因此可以在Makefile中设定一个Makefile变量,该变量保存了缺省的优化参数,赋值给每个模块的CFLAGS变量,给少数的几个模块的CFLAGS变量单独赋值。但我们的模块时常会有增加和减少,若手工维护这些变量很容易出错,导致有些模块的优化参数设置不对,影响性能和系统测试的结果。若能依赖Makefile自己根据模块列表自动生成每个模块的CFLAGS变量,并赋值为缺省的优化参数,就省事了。

我查看了GNUMakefile手册,没有发现可以通过Makefile自身产生变量给自己用的方法。看来只好用文件的方法了,通过一个脚本文件根据模块生成变量及赋值表达式,将其写入一个新的Makefile中,然后在原来这个Makefile中通过include命令包含新的Makefile

Makefile中的实现如下所示。

BRONCHO_DEFAULT_OPTIM_FLAGS=-O2 -mthumb
 

GEN_MODULES_FLAGS
:=`. ./genmodflags.sh "$(ALL_MODULES)" > hw_defaultflags.mk`

include hw_defaultflags
.mk
include com
.mk

hw_defaultflags
.mk: hw.mk
    
@eval $(GEN_MODULES_FLAGS); 

脚本文件如下所示。

#!/bin/sh

for MODULE in $1do
    MODULE
=`echo $MODULE | tr [a-z]- [A-Z]_`
    echo 
"${MODULE}_OPTIM_FLAGS?=$(BRONCHO_DEFAULT_OPTIM_FLAGS)"
done

因为GNUMakefile具有两遍执行的特性,因此当第一遍执行时若没有hw_defaultflags.mk时,只是会报告错误,但仍然会根据规则产生hw_defaultflags.mk文件。在第二遍执行时将hw_defaultflags.mk包含进来,执行com.mk中的编译过程。

技巧二:使用Makefile的片断文件定制构建过程。

gcc的构建系统可以为多个目标构建gcc编译器,多种体系架构(ARMX86ALPHAPOWERSPARC)和操作系统(linuxunixBSDcygwinecossymbian)的目标现在都可以得到支持,具体的目标列表可以查看gcc的相关网站。每个目标的编译器都有一些和其他目标不同的构建过程的设置,如包含目标特定的文件、定义特定的编译条件等,这就需要有一个对各个目标的构建过程进行定制的方法。gcc 的构建系统是通过包含各个具体目标相关的Makefile片断文件的方法来实现的。

gcc的配置目录(gcc/config/)下保存了各个目标系统相关的Makefile片断文件,这些片断文件重新设置了构建过程的变量和独有的构建过程规则。下面是支持inteliwmmx指令的gcc构建的Makefile片断文件(gcc/config/arm/t-iwmmxt-elf),这里的$(T)crti.o的规则就是该目标独有的构建过程规则。

LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS 
= _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func 
    _call_via_rX _interwork_call_via_rX 

    _lshrdi3 _ashrdi3 _ashldi3 

    _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi 

    _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 

    _fixsfsi _fixunssfsi _floatdidf _floatdisf _floatundidf _floatundisf 

    _unwind

MULTILIB_OPTIONS    
+= mcpu=iwmmxt
MULTILIB_DIRNAMES   
+= iwmmxt
MULTILIB_REDUNDANT_DIRS 
+= interwork/thumb/iwmmxt=thumb
    
EXTRA_MULTILIB_PARTS 
= crtbegin.o crtend.o crti.o crtn.o
    
# If EXTRA_MULTILIB_PARTS is not defined above then define EXTRA_PARTS here
# EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o


LIBGCC 
= stmp-multilib
INSTALL_LIBGCC 
= install-multilib

# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.

TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
    
# Assemble startup files.
$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
    $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) 

    
--o $(T)crti.-x assembler-with-cpp $(srcdir)/config/arm/crti.asm
    
$(T)crtn
.o: $(srcdir)/config/arm/crtn.asm $(GCC_PASSES)
    $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) 
    --o $(T)crtn.-x assembler-with-cpp $(srcdir)/config/arm/crtn.asm

gccconfigure(路径是gcc/configure)会执行gcc/config.gcc收集目标系统的具体规格信息,在该shell文件中,将目标系统使用的Makefile片断文件名加入到变量tmake_file中。然后gccMakefileinclude指令将tmake_file中所有的Makefile片断文件包含进来,片断文件的变量设置和构建过程规则将在执行make命令时生效,从而构建出特定目标系统使用的gcc编译器。config.gccarmlinux目标系统的相关代码如下所示。

arm*-*-linux*)          # ARM GNU/Linux with ELF
    tm_file="dbxelf.h elfos.h linux.h arm/elf.h arm/linux-gas.h"
    case ${target} in 
        arm
*-iwmmxt-*)
            tmake_file
="${tmake_file} arm/t-iwmmxt-elf"
            tm_file
="${tm_file} arm/iwmmxt-linux-elf.h"
            ;;
        
*)
            tmake_file
="${tmake_file} arm/t-arm-elf"
            tm_file
="${tm_file} arm/linux-elf.h"
            ;;    esac
    tmake_file
="${tmake_file} t-linux arm/t-arm"
    case ${target} in
    arm
*-*-linux-gnueabi)
        tm_file
="$tm_file arm/bpabi.h arm/linux-eabi.h"
        tmake_file
="$tmake_file arm/t-bpabi arm/t-linux-eabi"
        
# The BPABI long long divmod functions return a 128-bit value in 
        # registers r0-r3.  Correctly modeling that requires the use of
        # TImode.

        need_64bit_hwint=yes
        
# The EABI requires the use of __cxa_atexit.
        default_use_cxa_atexit=yes
        ;;
    
*)
        tmake_file
="$tmake_file arm/t-linux"
        ;;
    esac
    tm_file
="$tm_file arm/aout.h arm/arm.h"
    ;;

 
原创粉丝点击