2012-12-14 125 views
1

我有一个Makefile这样的:传递一个额外的参数,使

baud=19200 
src=dimmer 
avrType=attiny13 
programmerDev=/dev/ttyUSB003 
programmerType=stk500v1 

object: 
     avr-gcc -g -DF_CPU=$(avrFreq) -Wall -Os -mmcu=$(avrType) -c -o $(src).o $(src).cpp 

read: 
     @for memory in calibration eeprom efuse flash fuse hfuse lfuse lock signature application apptable boot prodsig usersig; do \ 
       avrdude -p $(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U $$memory:r:./$(avrType).$$memory.hex:i; \ 
     done 

如预期其中一期工程。当我输入make read时,几个文件从微控制器中提取出来。这可能需要一点时间,因为连接速度和数据量都很慢,所以我认为只需输入make read flash就可以了,但我不知道该怎么做。

当然,我可以让条目像read_flashread_hfuse ......但我有一种感觉,它可以做得更聪明。

我也希望能够运行一个像make read all这样的命令,它将依次从控制器执行每个文件。

现在我是创建Makfile的新手了,所以也许我一直在错误的轨道上。请随时解释应该如何完成。

我在Linux上。

回答

2

如果高度GNU特定的makefile是可以接受你(和我认为它是更好的使用便携式make,如GNU的,不是写便携式makefile文件),就可以比较容易地实现这一点:

ALL = calibration eeprom efuse flash fuse hfuse lfuse lock signature \ 
     application apptable boot prodsig usersig 

ifeq (read,$(firstword $(MAKECMDGOALS))) 
    WANT := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) 
    ifneq ($(WANT),) 
    $(eval $(WANT):;@:) 
    endif 
    UNKNOWN := $(filter-out $(ALL),$(WANT)) 
    ifneq ($(UNKNOWN),) 
    $(error Invalid arguments: $(UNKNOWN)) 
    endif 
endif 

read-one = avrdude -p $(avrType) -c$(programmerType) -P$(programmerDev) \ 
     -b$(baud) -v -U $1:r:./$(avrType).$1.hex:i 

.PHONY: read 
read: 
    $(foreach w,$(or $(WANT),$(ALL)),$(call read-one,$w) &&) : 

如果命令行中的第一个参数是“read”,则会将WANT变量设置为第一个参数后面的参数列表。然后它将这些名称变为空操作目标,并使read目标为每个名称调用read-one函数,如果未指定名称,则为$(ALL)

我经常使用这种变体,例如make print VARIABLE...,它只会打印$(VARIABLE)make help TOPIC来显示有关目标的信息。

+0

我不明白你的第一句话,你能澄清一下吗? “如果你可以接受一个高度GNU特定的makefile(我认为使用便携式make比GNU更好,而不是写入便携式makefile),” – jippie

+0

这个答案包含一个makefile,它只能在GNU make。从这个意义上说,它不是“便携”的。我也在说这不一定是件坏事,因为不是编写一个可移植的makefile,最好定位一个可移植的'make'程序。见[保罗的制造规则](http://mad-scientist.net/make/rules.html)中的第一个条目。 – Idelic

1

我会做:make flashmake hfusemake all与下面的Makefile:

baud=19200 
avrType=attiny13 
programmerDev=/dev/ttyUSB003 
programmerType=stk500v1 

all: calibration eeprom efuse flash fuse hfuse lfuse lock signature \ 
    application apptable boot prodsig usersig 

%: 
     avrdude -p $(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) \ 
     -v -U [email protected]:r:./$(avrType).$$memory.hex:i || rm ./$(avrType)[email protected]; 

这可能是不可移植作,但它在GNU工程化妆。这不允许任何其他规则,但您可以将此文件命名为read并执行make -f read flash。这将允许其他规则放置在其他make文件中。

请注意,这不是特别安全,因为它会在make foo上运行avrdude。为了更好地控制目标,你可以这样做:

.SUFFIXES: .ph 
.PHONY: efuse.ph eeprom.ph ... 
all: efuse eeprom ... 
.ph: 
     avrdude ... 

这样,只有列为PHONY的目标才是有效的目标。

+0

这绝对不是可移植的:任何包含'%'的目标的行为都是实现定义的。 –

+0

Thnx。问题在于,我在Makefile中实际上存在少数其他规则,为了便于阅读,我忽略了这些规则。我用那个更新了这个问题。我真的很想将所有规则放在一个Makefile中。 – jippie

+0

就可移植性而言,'for'循环也不是非常便携的; o)我希望能够使它在同一时间更具便携性。 – jippie

1

什么使得模块列表中选择一个配置列表有默认:

LIST = calibration eeprom efuse flash fuse \ 
     hfuse lfuse lock signature application \ 
     apptable boot prodsig usersig 

read: 
     @for memory in $(LIST); do \ 
      avrdude -p $(avrType) -c$(programmerType) -P$(programmerDev) \ 
       -b$(baud) -v -U $$memory:r:./$(avrType).$$memory.hex:i; \ 
     done 

然后打电话让无论是作为make默认,或make LIST="eeprom efuse"只是两个模块。