【问题标题】:Compiling any single C code using a Makefile使用 Makefile 编译任何单个 C 代码
【发布时间】:2020-11-08 02:46:46
【问题描述】:

我对 Makefiles 很陌生,所以我的问题可能很愚蠢。它将如下所示:我可以将另一个参数传递给make,以便我可以使用这个附加参数做一些事情吗? 更具体地说,如果可能的话,我想使用它来使用 Makefile 将任何单个 C 源代码编译成它的可执行文件。

例如,如果我有两个文件 foo.cbar.c,我希望能够使用相同的配方编译它们,因此可以做一些事情类似于 make compile foo.cmake compile bar.c,它们分别将它们编译成 foobar 可执行文件。

如果不可能,我可以为简单的 C 程序做一个替代方案吗?节省时间会很有用(每次我想编译刚创建的 C 文件时,不更新 Makefile 或不写 gcc -o name name.c)。

提前感谢您的耐心和时间。

【问题讨论】:

  • 听起来你想要目标?
  • 我不确定我理解你所说的目标是什么意思(对不起,我是新手……)。您是指任何 Makefile 配方中的 targets: dependencies 中的目标,还是其他什么?

标签: c makefile


【解决方案1】:

如果您正在处理单个主文件应用程序,bash 脚本听起来要简单得多,build.sh:

#!/bin/bash
SOURCE=$1
BIN=${SOURCE%.c}
if [[ -z "$SOURCE" || ! -s "$SOURCE" ]]; then
    echo "SOURCE is empty"
    exit 1
fi
gcc -o "$BIN" "$SOURCE"

然后像这样调用它:

./build.sh foo.c
./build.sh bar.c

【讨论】:

  • 应该是[[ -s $SOURCE ]]来检查文件是否存在且非空。 (你实际上想要两者,-z 确保 $SOURCE 不是空字符串,然后 -s 确保文件退出并且非空)但是是的,编译文件的单个脚本要简单得多而不是为每个编写一个makefile。
  • 对,这样会更安全,但我想知道它应该是-s 还是-f,第一个检查文件,它的大小大于零,第二个检查它是一个常规文件.
  • 我会使用-s,因为它包含-f,然后额外检查文件大小是否为非零。手册页说"True if file exists and has a size greater than zero."(当然gcc 将忽略空文件或抛出错误)这只是捕获gcc 调用之前的条件。
  • 我的意思是,你基本上只是在这里重新发明 make,所以你必须自己维护它并且你得到的功能更少。但如果它对你有用,那就去吧!
【解决方案2】:

为此,我使用下面的 makefile。 'make' 或'make all' 将目录中的每个.c(例如eg.c)文件编译为同一目录中的可执行文件(例如eg)。 'make eg' 仅将 eg.c 编译为 eg 。编译器标志——CFLAGS——或链接器标志——LFLAGS——没有什么特别之处——它们正是我习惯使用的。

CC  = gcc
CFLAGS  = -std=gnu11 -Wall -Wextra
LFLAGS  = -lm -lrt

OPATH   = ./
PROGS   += $(patsubst %.c,$(OPATH)%,$(wildcard *.c))


all: $(PROGS)
$(OPATH)% : %.c ; $(CC) $(CFLAGS) $< -o $@ $(LFLAGS)

clean:  
    \rm -f $(PROGS)

【讨论】:

    【解决方案3】:

    用这个怎么样:

    ================== 生成文件 =====================

    CC=gcc
    CCFLAGS=-ansi -pedantic -Wall
    
    all : clean foo bar
    
    foo : foo.c 
        $(CC) $(CCFLAGS) foo.c -o foo
    
    bar : bar.c
        $(CC) $(CCFLAGS) bar.c -o bar
    
    clean : 
        rm -f *.o *.*~ foo bar
    

    ======================= 结束makefile ======================

    make 调用make 将运行默认目标(在本例中为全部)删除所有中间文件和输出文件,然后重建foo 和bar

    make foo 调用make 只会运行make foo 的规则。

    make bar 调用make 只会运行制作bar 的规则。

    make clean 调用make 只会运行清理项目目录的规则——删除所有中间文件和输出文件。

    【讨论】:

    • 我希望在创建一个我想编译的新.c 文件后避免修改Makefile。换句话说,如果我创建一个新文件baz.c,我希望能够在不为baz 添加 Makefile 配方的情况下编译它。我想要的是一个适用于编译任何.c 文件的通用配方。
    • @benhauer 您可能需要查看隐式规则 (gnu.org/software/make/manual/html_node/…) 和模式 (gnu.org/software/make/manual/html_node/…) 来执行此操作。我自己从未尝试过 - 我的大多数构建规则都非常复杂,以至于我总是为项目创建自定义 makefile。
    【解决方案4】:

    Make 具有知道如何将源文件编译为可执行文件的内置规则。

    因此,您甚至根本不必编写 makefile(除非您想使用特殊的编译器选项)。这将起作用:

    $ ls
    bar.c   foo.c
    
    $ make foo
    cc -o foo foo.c
    
    $ make bar
    cc -o bar bar.c
    

    如果要修改编译器操作,请添加设置适当内置变量的makefile:

    $ ls
    bar.c   foo.c   Makefile
    
    $ cat Makefile
    CC = gcc
    CFLAGS = -O2 -g
    
    $ make foo
    gcc -O2 -g -o foo foo.c
    
    $ make bar
    gcc -O2 -g -o bar bar.c
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-05
      • 2011-09-21
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 2015-01-10
      • 1970-01-01
      相关资源
      最近更新 更多