cannot specify -s with -c or -S with multiple files

在修改一个Makefile时遇到了这个问题。
具体的情况为:

目录结构,其中liba1.c和liba1b.c都是含义一个函数的源文件,里面只有一个接口,显示内容为printf而已。

[zhang@zwfedora23 lib1]$ ls
liba1b.c  liba1b.h  liba1.c  liba1.h  Makefile
LIBA1_SRC:=$(wildcard *.c)
LIBA1_OBJ:=$(LIBA1_SRC:%.c=%.o)

LIBA1_STATIC:=liba1.a

CC=gcc
AR=ar

.PHONY: all clean


all: $(LIBA1_OBJ) $(LIBA1_STATIC)

$(LIBA1_OBJ):$(LIBA1_SRC)
  $(CC) -c $^ -o $@

$(LIBA1_STATIC):$(LIBA1_OBJ)
  $(AR) -rcv $@ $^

clean:
  @rm -f $(LIBA1_STATIC) 
  @rm -f $(LIBA1_OBJ)

执行make的结果:

[zhang@zwfedora23 lib1]$ make
gcc -c liba1.c liba1b.c -o liba1.o
gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files
compilation terminated.
Makefile:15: recipe for target 'liba1.o' failed
make: *** [liba1.o] Error 1
[zhang@zwfedora23 lib1]$

首先看到了那一句, cannot specify -o with -c ,-S or -E with multiple files.然后我就把目录中的liba1b.c和对应的liba1b.h修改了文件名后缀,为的是此目录只含有一个.c文件。

[zhang@zwfedora23 lib1]$ ls
liba1.a  liba1b-c  liba1b-h  liba1.c  liba1.h  liba1.o  Makefile
[zhang@zwfedora23 lib1]$

此时在执行make,即可以成功的生成.a文件,且这个.a文件中只包含一个.c文件。

[zhang@zwfedora23 lib1]$ make
gcc -c liba1.c -o liba1.o
ar -rcv liba1.a liba1.o
a - liba1.o
[zhang@zwfedora23 lib1]$ ls
liba1.a  liba1b-c  liba1b-h  liba1.c  liba1.h  liba1.o  Makefile
[zhang@zwfedora23 lib1]$ 

难道gcc -c 这样的参数不适合多个源文件使用?
那如果这个.a文件需要多个.c文件生成怎么办?这个问题好像太蠢了,因为我之前已经编译了无数个库了,现在才来问这个问题,可见当时使用makefile也是稀里糊涂的使用,根本没有研究明白,现在好了,全都需要花时间补上。
去网上查了一下,当需要有多个源文件生成一个.a文件时采用的方法是把每个源文件生成的自己对应的.o文件,然后再把多个.o文件使用ar组合为一个整体的.a文件。

废话不说了,赶快想解决办法。
我现在需要做的就是把每个c源文件都生成一个o文件,然后把这些个object文件私用ar组织起来形成一个真正的a文件。
为了实现这样的目的,我又去搜了一下《跟我一起写Makefile》这篇文档,当时刚学makefile时也是看的它,但是没有完全看进去,现在需要从里面找一些能够实现上面的目标的操作,这个文档都看完看懂需要至少2个小时,没办法,从头开始来吧。不过好在刚看到静态模式,就感觉好像就可以解决我目前的问题了。我把我当前的目录结构贴出来看看,基本跟上面的一样,这是文件名换了。

[zhang@zwfedora23 libs]$ ls
libs1.c  libs1.h  libs2.c  libs2.h  main.c  Makefile
[zhang@zwfedora23 libs]$ 
SRC:=$(wildcard *.c)
#OBJS:=$(wildcard *.o)
OBJS := $(patsubst %.c,%.o,$(wildcard *.c))
LIB_A := libs.a

CC:=gcc
CFLAGS:= -I./

.PNONY:all clean

all: $(LIB_A)


clean:
  @rm -f $(OBJS)
  @rm -f $(LIB_A) 



#$(OBJS):$(SRC)
# $(CC) -o $@ $^

$(OBJS):%.o:%.c
  $(CC) -c $(CFLAGS) $< -o $@


$(LIB_A):$(OBJS)
  $(AR) rcv $@ $^
  @echo '$$@' = $@
  @echo '$$^' = $^
  @echo SRC=$(SRC)
  @echo OBJS=$(OBJS)
  #$(CC) -o $(LIB_A) $(OBJS)

执行结果:

[zhang@zwfedora23 libs]$ make
gcc -c -I./ libs1.c -o libs1.o
gcc -c -I./ libs2.c -o libs2.o
gcc -c -I./ main.c -o main.o
ar rcv libs.a libs1.o libs2.o main.o
a - libs1.o
a - libs2.o
a - main.o
$@ = libs.a
$^ = libs1.o libs2.o main.o
SRC=libs1.c libs2.c main.c
OBJS=libs1.o libs2.o main.o
#gcc -o libs.a libs1.o libs2.o main.o
[zhang@zwfedora23 libs]$ ls
libs1.c  libs1.h  libs1.o  libs2.c  libs2.h  libs2.o  libs.a  main.c  main.o  Makefile
[zhang@zwfedora23 libs]$ 

这时已经生成了盼望的.o文件和.a文件,为了验证一下这个.a文件是否正确,我又写了一个简单的main.c,然后编译:

[zhang@zwfedora23 libs]$ gcc main.c -ls -L./ -o test
[zhang@zwfedora23 libs]$ ./test 
hello
hello,libs2

可以看到test的输出是正确的,至此我的问题也解决了。

最后再总结一下之前没有成功的原因。
主要是没有给出生成.o文件的生成规则,只给出了

OBJS:=$(wildcard %.o)

这个表达式,当时以为OBJS就是包含*.o的变量了。实际上,OBJS的值确实是libs1.o libs2.o,但是问题是我没有给出怎么生成这两个object文件的规则,然后就认为执行完它就已经有object文件了,这样的想法简直太错误了。静下心来,认真的读了《跟我一起写Makefile》才认识到自己的愚蠢思维,漏洞太多。

你可能感兴趣的:(linux)