V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
codechaser
V2EX  ›  C

请教一个关于 makefile 的问题

  •  
  •   codechaser · 2018-11-20 16:17:51 +08:00 · 2491 次点击
    这是一个创建于 2201 天前的主题,其中的信息可能已经有所发展或是发生改变。
    objects = display.o main.o
    
    display : $(objects)
    	@gcc -o display $(objects)
    
    $(objects) : display.h
    	@echo 正在编译程序
    
    .PHONY : clean
    clean :
    	@-rm $(objects) display
    	@-rm *.h.gch
    

    同一个文件夹下面有main.c

    #include "display.h"
    #include <stdio.h>
    
    
    int main(void){
        display();
        return 0;
    }
    

    display.h:

    #ifndef DISPLAY_H_
    #define DISPLAY_H_
    #define TEST_STRING "I love you three times!"
    void display(void);
    
    #endif
    

    display.c:

    #include <stdio.h>
    #include "display.h"
    
    void display(void) {
        printf("Now %s is displayed.\n",__FILE__);
    }
    

    为什么像上面那样写 makefile 会报错?求教。

    gcc: error: display.o: 没有那个文件或目录
    gcc: error: main.o: 没有那个文件或目录
    gcc: fatal error: no input files
    compilation terminated.
    make: *** [display] 错误 4
    

    刚开始学 makefile,见谅。另外想问一下 makefile 有学的必要吗?

    15 条回复    2018-11-21 09:12:51 +08:00
    jasonyang9
        1
    jasonyang9  
       2018-11-20 16:23:58 +08:00
    纯乱改的:

    ```
    objects = display.c main.c

    display : $(objects)
    @gcc -o display $(objects)

    $(objects) : display.h
    @echo 正在编译程序

    .PHONY : clean
    clean :
    @-rm $(objects) display
    @-rm *.h.gch
    ```
    jasonyang9
        2
    jasonyang9  
       2018-11-20 16:30:29 +08:00
    以上是乱改的,不要跑`make clean`啊!!
    shylockhg
        3
    shylockhg  
       2018-11-20 16:49:27 +08:00
    你没有编译.o 吧,还是这是隐式规则
    shylockhg
        4
    shylockhg  
       2018-11-20 16:51:05 +08:00
    $(objects): 等价 main.o display.o : ,目标可以同时定义多个?
    tmy
        5
    tmy  
       2018-11-20 16:58:39 +08:00
    display : $(objects)
    @gcc -o display $(objects) 这里相当与 gcc -o display display.o 而不是 display.c,已经有这样的错误提示了,没有指定源代码
    codechaser
        6
    codechaser  
    OP
       2018-11-20 17:16:42 +08:00
    @tmy 按教程上说法是没有`display.o`它就会生成 display.o
    codechaser
        7
    codechaser  
    OP
       2018-11-20 17:17:07 +08:00
    @shylockhg 是隐式规则
    codechaser
        8
    codechaser  
    OP
       2018-11-20 17:17:52 +08:00
    @jasonyang9 这样是可以的,但我想知道为什么像上面那样写不行
    codechaser
        9
    codechaser  
    OP
       2018-11-20 17:21:19 +08:00
    @jasonyang9 这样写就没问题
    ```c
    objects = display.o main.o

    display : $(objects)
    @gcc -o display $(objects)

    main.o : main.c display.h
    @gcc -c main.c
    display.o : display.c display.h
    @gcc -c display.c
    ```
    ccpp132
        10
    ccpp132  
       2018-11-20 17:22:13 +08:00 via Android
    这是你自己指定了.o 生成的规则,命令执行成功了却不会产出对应的文件
    Machard
        11
    Machard  
       2018-11-20 17:35:04 +08:00
    ```sh
    sources = display.c main.c
    objects = $(sources:.c=.o)

    display : $(objects)
    @gcc -o display $(objects)

    $(objects) : .o:.c
    @gcc -c $< -o $@
    @echo 正在编译程序

    .PHONY : clean
    clean :
    @-rm $(objects) display
    @-rm *.h.gch
    ```
    Machard
        12
    Machard  
       2018-11-20 17:37:03 +08:00
    将 clean 中删除.h 语句删除。。。。。
    jqin4
        13
    jqin4  
       2018-11-20 17:58:34 +08:00
    jqin4
        14
    jqin4  
       2018-11-20 18:00:35 +08:00
    我学 c 时一节课,现在忘光了,参考一下

    # Makefile sample illustrating separate compilation and dependencies.

    # Students are welcome to use this as a starter or model, but be sure
    # to replace these comments with comments relevant to YOUR assignment
    # (including your name and cats login!). If the reader has to wade
    # through "junk comments" you will lose credit.

    # Explanatory comments follow the ``real code.''
    # Everything after the # on any line is a comment

    # ===================================================================
    # Here we define a few important "make" variables.
    # CFLAGS is platform dependent. This one is for Linux.

    CC = gcc
    CFLAGS = -g -Wall -O0 -std=c99 -D_SVID_SOURCE

    # The next line has the first target. Typing "make" without any names
    # causes "make" to default to this target.
    # A common first target would read "all: hex shuffle" but this is omitted
    # because shuffle.c is not in this directory.
    #
    hex: hex.o readline.o
    ${CC} -o hex ${CFLAGS} hex.o readline.o

    hex.o: hex.c readline.h
    ${CC} -c ${CFLAGS} hex.c

    readline.o: readline.c readline.h
    ${CC} -c ${CFLAGS} readline.c

    shuffle: shuffle.o readline.o
    ${CC} -o shuffle ${CFLAGS} shuffle.o readline.o

    shuffle.o: shuffle.c readline.h
    ${CC} -c ${CFLAGS} shuffle.c

    # ===================================================================
    #
    # The rest of this file is a tutorial and should not be submitted.
    #
    # Makefiles are used by the Unix "make" command. Do "man make" for
    # (too much) information. A brief summary:

    # A "make statement" goes on one or more lines.
    # The first of these lines begins in the left margin.
    # Subsequent lines of the same "statement" must be indented by
    # one tab character (NOT spaces).
    # Finally, put a blank line after the whole "statement".
    # Make sure you do not have any blanks or tabs at the end of a line.

    # THE ABOVE IS VERY IMPORTANT TO FOLLOW STRICTLY ON SOME PLATFORMS.
    # READ IT AGAIN.


    # Line 1 (the one that is not indented):
    # The format is target_name, colon, dependency_names.
    # White space is flexible. If this line needs to be continued
    # due to a large number of dependencies, end it with backslash (\).
    # Lines 2-n:
    # The format is tab, unix_command (with make variables, maybe).
    # WHAT IT MEANS:
    # A "make statement" is like a recursive procedure. It says:
    # To update target_name
    # first update any of the dependency_name files that are
    # not up to date (use them as recursive target_names).
    #
    # Now, if any dependency_name file is NEWER than the
    # target_name file, execute the unix_commands on lines 2-n.
    #
    # Being a recursive procedure, it better have a base case.
    # The base cases are dependency_names that do not exist as targets
    # in the Makefile, AND do not conventionally require ``making'',
    # because you, the programmer, create them, often with an editor.
    # Their mere existence makes them up to date.
    #
    # Object (.o) files DO require making.
    # Even if you do not include a .o file as a target name,
    # "make" will try (probably not successfully, unless you are a
    # "make" wizard) to make the .o file with a default unix_command,
    # if it does not exist in the current directory.
    #
    # Normal make commands to issue for this Makefile are "make hex" and
    # "make shuffle", because these are executable programs as opposed to
    # modules. "make" figures out which modules, if any, need to be
    # recompiled. If you want to see what make WOULD do, without actually
    # having it do anything, type "make -n hex", etc.

    # However, if you want to be sure readline.c compiles correctly, before
    # you try to use it as a module in another program, do "make readline.o".
    # That is not a typo. Re-read the previous sentence.

    # Running "make" can generate many error messages. Do
    # make hex >& make.log
    # to cause the errors to go into the file make.log.
    # When "make" finishes you can read the file with "view", "more", or "less".
    #
    # Many later error messages can be meaningless because they were caused
    # by an earlier error. Always try to correct errors in order.
    shylockhg
        15
    shylockhg  
       2018-11-21 09:12:51 +08:00
    @Machard 这个好像有道理
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2824 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 87ms · UTC 06:55 · PVG 14:55 · LAX 22:55 · JFK 01:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.