【问题标题】:How can i make a Makefile for a GMP project如何为 GMP 项目制作 Makefile
【发布时间】:2021-02-15 15:46:32
【问题描述】:

我在尝试为我的 C 项目生成 Makefile 时遇到问题。它包含 3 个文件 alea.c crypto.c 和 main.c。这是我的 Makefile :

SHELL = /bin/bash
CC = gcc
RM = rm -rf
TAR = tar
MKDIR = mkdir
CHMOD = chmod
CP = cp
MV = mv

PROGNAME = Crypto_ivsk
EXEC = Crypt
PACKAGE = $(PROGNAME)
VERSION = 0.3
DISTDIR = $(PACKAGE)-$(VERSION)
HEADERS = alea.h crypto.h  gmp.h
SOURCES = alea.c crypto.c main.c 

LDFLAGS = -lgmp 
CFLAGS = -Wall

OBJ = $(SOURCES:.c=.o) 
DISTFILES = $(SOURCES) Makefile $(HEADERS) 

all: $(EXEC)  

$(EXEC): $(OBJ)  
    $(CC) $(OBJ) -o $(LDFLAGS) $(EXEC)

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

dist: distdir
    $(CHMOD) -R a+r $(DISTDIR)
    $(TAR) zcvf $(DISTDIR).tar.gz $(DISTDIR)
    $(RM) $(DISTDIR)

distdir: $(DISTFILES)
    $(RM) $(DISTDIR)
    $(MKDIR) $(DISTDIR)
    $(CHMOD) 777 $(DISTDIR)
    $(CP) -rf $(DISTFILES) $(DISTDIR)
clean:
    $(RM) $(PROGNAME) $(OBJ) *~ $(DISTDIR).tar.gz

但是当我在 shell 中键入“make”时,会出现以下错误: "没有规则使 alea.o 停止所需的目标 gmp.h"

我的水平太低,对此无能为力,有人可以帮帮我吗?

谢谢你:)

【问题讨论】:

  • 嗯,你有一个叫 gmp.h 的文件吗?如果没有,您希望计算机如何创建它?
  • 是的,这是真的,但为什么 #include 有效呢?
  • 如果 gmp.h 发生变化,您是否希望计算机重新编译您的源文件?还是你不在乎?你认为 gmp.h 会改变吗?
  • gmp.h 位于库路径中,与您的 makefile 无关,请将其删除。
  • 谢谢它终于起作用了..真是太愚蠢了,非常感谢:)

标签: c makefile compilation gmp


【解决方案1】:

您说过您所有的%.o 文件都依赖于扩展名为.c 的同名文件以及它们包含的头文件。

您已将gmp.h 作为包含在此目录中,make 找不到(我想您指的是 GNU 多精度库包含文件),这是一个您不应该放在您的 $(HEADER) 变量中的文件。为什么?

很简单,因为你永远不会改变那个文件,所以依赖它的文件必须重新编译,因为它是一个系统文件。

我给你一些建议以避免将来出现问题。

  • 不要定义你不会使用的变量,或者你不打算改变的变量。变量在make 中作为常量工作。你在一个地方定义它们,但你在Makefile 上到处重复它们。这些是要使用的候选者。

  • make 有一堆已经定义的规则(实际上,从.c 文件构建对象.o 文件的规则已经包含在几乎所有实际使用的make 实现中。所以你最好尊重已安装的规则,而不是为您提供您的规则,因为此规则通常适用于您的系统,并且Makefile 的内容更便携。

  • 这同样适用于表示系统程序的变量,如CCRMLEXYACC 等。通常,当程序有特殊编译需求时重新定义它(这不是你的情况)

  • 您在 makefile 的最终链接阶段出现错误,因为您将选项 -o $(LDFLAGS) $(EXEC) 指定给链接器,而它应该是 $(LDFLAGS) -o $(EXEC)(最好将 $(LDFLAGS) 放在首位,因为将应用链接选项处理完所有目标文件后)

有了这个前提,这是为您的项目建议的Makefile

PACKAGE   = Crypto_ivsk
VERSION   = 0.3
DISTNAME = $(PACKAGE)-$(VERSION)

# don_t include system headers, because 1) you are never to
# modify them and 2) because they are in a different
# directory and make will not find them, and then it will
# try to create them in the local dir, if you put any in a
# dependency rule.
headers   = alea.h cripto.h main.h

# This variable is understood by the C source compilation rule.
CFLAGS = -Wall

# targets holds the list of programs we are to build.
targets   = Crypt

# toclean is a variable we initialize to the programs we are
# to build and for each program we add all the objects we
# compile of it.
toclean   = $(targets)

# put here programs that must be built before linking Crypt,
# e.g. program resource files, that are not used in the linking.  In this case we have none.
Crypt_deps =

# Put here things that must be built before linking Crypt,
# e.g. object files, that ***are*** used to link it.
Crypt_objs = alea.o cripto.o main.o

# Place for the libraries to build Crypt.
Crypt_libs = -lgmp

# For each program we add to toclean the object files that
# compose it, so we can erase just doing $(RM) $(toclean)
# Pay special attention to the += operator.
toclean += $(Crypt_objs)

# If we have more programs to build, add (prefixed) groups 
# of variables like the above.

DISTFILES = $(Cryp_objs:.o=.c) Makefile $(headers) 

# all should be a .PHONY target.
.PHONY: all clean dist

all: $(targets)
    @echo Build finished at: `date`

# repeat this for each file in $(targets)
# $@ is the target of the rule
Crypt: $(Crypt_deps) $(Crypt_objs)
    $(CC) $(LDFLAGS) $(Crypt_ldfl) -o $@ $(Crypt_objs) $(Crypt_libs)

dist: $(DISTNAME).tar.gz

# we link the files in $(DISTFILES) so we don_t consume
# disk space with the copies.
$(DISTNAME).tar.gz: $(DISTFILES)
    mkdir $(DISTNAME)
    ln $(DISTFILES) $(DISTNAME)/.
    tar cvfz $@ $(DISTNAME)
    $(RM) $(DISTNAME)

# this cleans everything built.
clean:
    $(RM) $(toclean)

# this can be written as
# alea.o cripto.o main.o: $(headers)
# but in case they include different lists of header is
# better to put it this way.
alea.o: $(headers)
cripto.o: $(headers)
main.o: $(headers)

Makefile 架构将为您提供更好的结果,并且可以轻松扩展以构建多个程序或库。

如您所见,目标文件的源没有编译规则。这是因为make 中有一个内置规则。 RM(在 GNU 中为 make)和 CC 还有一个默认定义。

请不要将CC 重新定义为gcc,这一点很重要,因为如果您不强迫每个人都使用gcc 构建您的程序,您的代码将更加可移植。

无论如何,如果你使用可选赋值,

CFLAGS       ?= -O -Wall -std=c98 -pedantic

相反,您将允许构建器在命令行中(或通过环境)为 CFLAGS 指定不同的值,这样您的脚本将更加灵活。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多