原文转自:http://blog.sina.com.cn/s/blog_87c063060101c9yp.html

1、在写 多目录下makefile的时候,碰到一个错误提示,让我纠结许久,后面还是解决了,这个错误不容易被发现。

2、错误提示如下:

Makefile:8: *** missing separator (did you mean TAB instead of 8 spaces?).  Stop.

3、先来说一下我想干什么,有些什么?

想干什么: 搭建一个Linux  LCD的裸机开发环境,注意是多目录下面的,想写 一个比较通用的makefile。

有什么:父目录①←子目录①(build目录)、子目录①(code目录)

子目录①(build目录)←Makefile  make.rule

子目录①(code目录)← 子目录②(startup)、子目录②(lib)、子目录②(foo)、子目录②(huge)

如下图:

1.工程目录下:

2.build 目录下

3.code目录下

4.code目录下的子目录都有2个子目录: src目录(存放.c文件) 、 include目录(存放.h文件)

5、下面贴一下makefile的内容

a.  build下面的make.rule:

.PHONY:all clean

CC = arm-linux-gcc
LD = arm-linux-ld
AR = arm-linux-ar
ARFLAGS = crs
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump
CFLAGS := -Wall -O2

RM  = rm
RMFLAGS = -fr

export CC LD AR  RM RMFLAGS ARFLAGS OBJCOPY OBJDUMP CFLAGS

SRCS  = $(wildcard *.c)
ASS  = $(wildcard *.S)

OBJS := $(SRCS:.c=.o)
ASMS := $(ASS:.S=.o )
DEPS := $(SRCS:.c=.dep)

ifneq ("$(EXE)","")
EXE  := $(EXE)
RMS  += $(EXE)
endif

ifneq ("$(LIB)","")
LIB  := $(LIB)
RMS  += $(LIB)
endif

ifneq ($(INCLUDE_DIRS), "")
INCLUDE_DIRS := $(strip $(INCLUDE_DIRS))
INCLUDE_DIRS := $(addprefix -I, $(INCLUDE_DIRS))
endif

ifneq ($(LINK_LIBS), "")
LINK_LIBS := $(strip $(LINK_LIBS))

LIB_ALL := $(notdir $(wildcard $(DIR_LIB)/*))
LIB_FILTERED := $(addsffix %,$(addprefix lib, $(LINK_LIBS)))
$(evel DEP_LIBS = $(filter $(LIB_FILTERED), $(LIB_ALL) ) )
DEP_LIBS := $(addprefix $(DIR_LIBS)/, $(DEP_LIBS))

LINK_LIBS := $(addprefix -l, $(LINK_LIBS))
endif

all: $(EXE) $(LIB)

$(EXE):$(OBJS) $(LIB)
 $(CC) $(CFLAGS) $(INCLUDE_DIRS) -o $@ $^

$(LIB):$(ASMS) $(OBJS)   
 $(AR) -$(ARFLAGS) $@  $^

%.o : %.c
 $(CC) $(CFLAGS) $(INCLUDE_DIRS) -o $@ -c $<</P>

%.o : %.S
 $(CC) $(CFLAGS) $(INCLUDE_DIRS) -o $@ -c $<</P>

%.dep: %.c
 @echo "Creating $@ ..."
 @set -e;\
 $(RM) $(RMFLAGS) $@.tmp ;\
 $(CC) $(INCLUDE_DIRS) -E -MM $(filter %.c, $^) > $@.tmp ; \
 sed 's,\(. *\)\.o[ :]*,objs/\1.o $@: ,g' < $@.tmp > $@ ; \
 $(RM) $(RMFLAGS) $@.tmp

clean:
 $(RM) $(RMFLAGS) *.bin  *.bak *.o *.dep  *.a

b.  build下面的 Makefile:

.PHONY: all clean  touch

ROOT = $(realpath ..)

#注意:因为 huge目录下 是编译 可执行文件(最终目标).所以对于 foo bar huge 这三个目录,huge 需要放到 最后编译。
DIRS = $(ROOT)/code/startup/src \
       $(ROOT)/code/lib/src     \
       $(ROOT)/code/foo/src     \
       $(ROOT)/code/huge/src
      
RM = rm
RMFLAGS = -fr
RMS = $(ROOT)/build/exes  $(ROOT)/build/libs

all clean:
 @set -e; \
 for dir in $(DIRS); \
 do \
 cd $$dir && $(MAKE) ROOT=$(ROOT) $@; \
 done
 
 @set -e;\
 if ["$(MAKECMDGOALS)" = "clean" ]; \
 then $(RM) $(RMFLAGS) $(RMS); fi
 @echo ""
 @echo ":-) Completed"
 @echo ""

touch:
 @echo "Processing ......"
 @find $(ROOT) -exec touch {} \;
 @echo ""
 @echo ":-)  Completed"
 @echo ""

c.huge/src  下面的 makefile:

正确的写法如下:

EXE = huge.bin

LIB =

INCLUDE_DIRS = $(ROOT)/code/huge/include    \
               $(ROOT)/code/startup/include \
               $(ROOT)/code/lib/include     \
               $(ROOT)/code/foo/include
                                          
                                          
LINK_LIBS = startup lib foo

include $(ROOT)/build/make.rule

d. startup/src 目录下面Makefile的写法:

#2012-10-21
EXE =

LIB = libstartup.a

INCLUDE_DIRS = $(ROOT)/code/startup/include \
               $(ROOT)/code/foo/include
LINK_LIBS =

include $(ROOT)/build/make.rule

e.  foo/src 目录下的Makefile :

#2012-10-21
EXE =

LIB = libfoo.a

INCLUDE_DIRS = $(ROOT)/code/foo/include
LINK_LIBS =

include $(ROOT)/build/make.rule

f. lib/src 目录下的Makefile :

#2012-10-21
EXE =

LIB = liblib.a

INCLUDE_DIRS = $(ROOT)/code/lib/include
LINK_LIBS =

include $(ROOT)/build/make.rule

PS:我们重点注意 我们标色的 地方,其它地方不用看。

INCLUDE_DIRS = $(ROOT)/code/huge/include \
$(ROOT)/code/startup/include \
$(ROOT)/code/lib/include \
$(ROOT)/code/foo/include

PS:在 huge目录下的 C文件 包含了其它目录下面的头文件时(如 foo/include 下面的 2440addr.h),

main.c(假设在 huge/src下):

#include"2440addr.h"

#include"stdio.h"

............

像这样子的 程序,头文件 在 "别人的目录下面" 你想用它  就必须 用 INCLUDE_DIRS =  去选择它的 路径,但是 它($(ROOT)/code/lib/include ) 必须写在  $(ROOT)/code/huge/include   的后面。
如果 将 上面改成 下面这样,就会出现 "文章开始的错误了" :

INCLUDE_DIRS =$(ROOT)/code/lib/include \
$(ROOT)/code/startup/include \

$(ROOT)/code/huge/include \
$(ROOT)/code/foo/include

错误提示:Makefile:8: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.

同理下面也是一样的.

INCLUDE_DIRS = $(ROOT)/code/startup/include \
$(ROOT)/code/foo/include

makefile的一个错误:*** missing separator的更多相关文章

  1. makefile:4: *** missing separator. Stop.

    今天在编写蜂鸣器的驱动程序时,makefile文件是这样: CROSS=arm-linux- all: beep beep: beep.c $(CROSS)gcc -o beep beep.c $(C ...

  2. [ASM C/C++] C makefile:2: *** missing separator. Stop. 问题

    在利用make编译代码时,makefile文件的目标代码前面要用tab而不能用空格来代替. 要不然就会提示: makefile:2: *** missing separator.  Stop. 要注意 ...

  3. Makefile:130: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.

    修改了snmp里面的包Makefile,出现了如下问题: Makefile:130: *** missing separator (did you mean TAB instead of 8 spac ...

  4. makefile:n: *** missing separator. Stop

    makefile has a very stupid relation with tabs, all actions of every rule are identified by tabs .... ...

  5. Linux C编程学习之开发工具3---多文件项目管理、Makefile、一个通用的Makefile

    GNU Make简介 大型项目的开发过程中,往往会划分出若干个功能模块,这样可以保证软件的易维护性. 作为项目的组成部分,各个模块不可避免的存在各种联系,如果其中某个模块发生改动,那么其他的模块需要相 ...

  6. C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”

    Q: 在反序列化 Xml 字符串为 Xml 对象时,抛出如下异常. 即在 XML文档(0, 0)中有一个错误:缺少根元素. A: 首先看下代码: StringBuilder sb = new Stri ...

  7. 处理程序“ExtensionlessUrlHandler-Integrated-4.0”在其模块列表中有一个错误模块“ManagedPipelineHandler”

    新服务器安装完开发环境后,还需要注册framework4.0到IIS.不然会报错:   HTTP 错误 500.21 - Internal Server Error 处理程序“Extensionles ...

  8. 关于Java中的继承和组合的一个错误使用的例子

    [TOC] 关于Java中的继承和组合的一个错误使用的例子 相信绝大多数人都比较熟悉Java中的「继承」和「组合」这两个东西,本篇文章就主要就这两个话题谈论一下.如果我某些地方写的不对,或者比较幼稚, ...

  9. HTTP 错误 500.21 - Internal Server Error 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”

    HTTP 错误 500.21 - Internal Server Error 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipe ...

随机推荐

  1. POJ 2506 Tiling(递推+大整数加法)

    http://poj.org/problem?id=2506 题意: 思路:递推.a[i]=a[i-1]+2*a[i-2]. 计算的时候是大整数加法.错了好久,忘记考虑1了...晕倒. #includ ...

  2. MKAnnotationView和MKPinAnnotationView的区别

    如果想创建以静态图片作为大头针图片的话,可以通过创建MKAnnotationView是实例.如果想使用apple自带的大头针则创建MKPinAnnotationView

  3. Codeforces 483B - Friends and Presents(二分+容斥)

    483B - Friends and Presents 思路:这个博客写的不错:http://www.cnblogs.com/windysai/p/4058235.html 代码: #include& ...

  4. 雷林鹏分享:Ruby 语法

    Ruby 语法 让我们编写一个简单的 Ruby 程序.所有的 Ruby 文件扩展名都是 .rb.所以,把下面的源代码放在 test.rb 文件中. #!/usr/bin/ruby -w puts &q ...

  5. 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(二)

      五.Graphics layer 1.新增Graphics layer Graphics layer用于显示用户自定义绘制的点.线.面图形.使用时确保xaml文件中Graphics layer定义 ...

  6. Ultimate Weirdness of an Array CodeForces - 671C (gcd,线段树)

    大意: 定义一个数列的特征值为两个数gcd的最大值, $f(l,r)$表示数列删除区间$[l,r]$的元素后剩余元素的特征值, 求$\sum_{i=1}^n\sum_{j=i}^n{f(i,j)}$ ...

  7. Leetcode 22

    //这题感觉不如前两题回溯清楚,还要再看看class Solution { public: vector<string> generateParenthesis(int n) { vect ...

  8. M爷的线段树

    M爷的线段树 - BUCTOJ 3305 一个长度为n的数列A.修改m次,每次给区间[L,R]中的每一个数加X.查询k次,每次查询第i个元素的值并输出.1<=n<=1e5 ,1<=m ...

  9. 数据库操作——SQL

    ()修改数据表内容 UPDATE t_com_staffinfo set upnative = '河南省郑州市金水区' WHERE id = 1082

  10. java容器——Collection接口

    Collection是Set,List接口的父类接口,用于存储集合类型的数据. 2.方法 int size():返回集合的长度 void clear():清除集合里的所有元素,将集合长度变为0 Ite ...