【问题标题】:How to create a static library with a Makefile from C source code如何使用 C 源代码中的 Makefile 创建静态库
【发布时间】:2015-11-23 16:47:40
【问题描述】:

我正在尝试了解如何创建 Makefile。我有以下 Makefile:

DESTDIR=../../
PREFIX=../

STATIC=libdemo.a

CC = gcc
CFLAGS = -Wall -Winline -pipe

LDFLAGS = -L../../../lib
LIBS    = -lpthread 

SRC = demo1.c demo2.c

OBJ = $(SRC:.c=.o)

$(STATIC): $(OBJ)
        @echo "[Link (Static)]"
        @ar rcs $(STATIC) $(OBJ)

.c.o:
        @echo [Compile] $<
        @$(CC) -c $(CFLAGS) $< -o $@

clean:
        rm -f $(OBJ) *~ core tags *.bak Makefile.bak libgeniePi.*

.PHONEY:        install
install:        $(TARGET)
        @install -m 0755 libdemo.a  $(DESTDIR)$(PREFIX)/lib

all:
        gcc -g -Wall -o program program.c $(LDFLAGS) $(LIBS)

这几乎可以满足我的要求。使用make,我从文件demo1.cdemo2.c 中创建了一个静态库。使用make install,我将库放在正确的目录中,使用make all,我终于编译了使用这个库的程序,这一切都很好。

但是,库libdemo.a 是可执行的,我认为不应该是这样的,对吧?

其次,我怎样才能让所有命令(makemake installmake all)按顺序运行,而不是单独调用它们?

【问题讨论】:

  • 如果您删除libdemo.a 并重建它,它是否对新创建的文件具有可执行权限?
  • 通常,共享对象是读-执行的,而静态库是只读的。您可以通过将 0755 更改为 0644 在安装规则中控制这些权限。请查看 chmod 的手册页以了解这些值及其含义。
  • @Erik 啊,很好,我完全错过了通过install 设置的权限。
  • makemake all 相同
  • @RPGillespie 不,不是。 makemake &lt;first valid target&gt; 相同。在这种情况下,是libdemo.a(来自$(STATIC))。

标签: c makefile


【解决方案1】:

您通过先决条件链接目标。

要获得您想要的(并让 make 默认执行此操作),您需要添加 install 作为您的 all 目标的先决条件(尽管我们将在一分钟内重命名)并且要么在 assignment 和 target 行中将 install 先决条件中的 $(TARGET) 替换为 $(STATIC) 或将 STATIC 替换为 TARGET

类似这样的:

DESTDIR=../../
PREFIX=../

STATIC=libdemo.a

CC = gcc
CFLAGS = -Wall -Winline -pipe

LDFLAGS = -L../../../lib
LIBS    = -lpthread 

SRC = demo1.c demo2.c

OBJ = $(SRC:.c=.o)

$(STATIC): $(OBJ)
        @echo "[Link (Static)]"
        @ar rcs $@ $^

.c.o:
        @echo [Compile] $<
        @$(CC) -c $(CFLAGS) $< -o $@

clean:
        rm -f $(OBJ) *~ core tags *.bak Makefile.bak libgeniePi.*

.PHONY: install
install: $(STATIC)
        @install -m 0755 $< $(DESTDIR)$(PREFIX)/lib

all: install
        $(CC) -g -Wall -o program program.c $(LDFLAGS) $(LIBS)

另外请注意,我修正了您的 .PHONEY 拼写错误,并在某些食谱中使用 $@$^$&lt; 代替了明确的文件/变量名称。

也就是说,每次运行 make all 时,make all 仍然会从 program.c 重建 program

要解决您想要这样做的问题:

all: program

program: install program.c
    $(CC) -g -Wall -o $@ program.c $(LDFLAGS) $(LIBS)

而不是您当前的 all 目标。

请注意,由于install 先决条件,我不能在该配方中使用$&lt;$^ 来引用program.c。另请注意,这实际上并不能解决“始终重建”问题(同样是因为 install 先决条件)。

重建问题的解决方法是根本没有虚假目标。

您可以使用真正的目标来代替副本,也可以让-L 完成它的工作,而不用打扰libdemo.a 的本地副本。

all: program.c
    $(CC) -g -Wall -o $@ $< $(LDFLAGS) $(LIBS)

但话又说回来,您实际上并没有在此处的任何地方链接到 libdemo.a,所以我不确定您在用它做什么。 (要与它链接,您需要-ldemo 或在链接命令中列出libdemo.a。)

【讨论】:

  • 很好地重新工作,尽管all 规则仍然直接使用 gcc 而不是 CC 宏。一个小问题。
  • libdemo.a 会安装在LDFLAGS 然后链接到all 对吧?
  • @PaulBernhardWagner 它在all 的哪个位置链接? gcc 命令的哪一部分链接它?你在哪里告诉gcc它应该链接它?将参数展开为 gcc 或查看 make 运行的命令,看看是否可以找到它。当然,您可以找到lib 目录的路径。但是图书馆本身呢?
  • 我很想补充一句'总是安装软件通常不是一个好主意'。尤其是对于静态库,从本地重建的副本进行链接非常适合测试。
  • @EtanReisner,你说得对,对不起,它没有链接,应该在LIBS中列出
猜你喜欢
  • 2013-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 2014-05-28
  • 1970-01-01
  • 2015-09-29
相关资源
最近更新 更多