如何正确设置 makefile 并在此 C 程序中获得正确的结果

How to set up correctly makefile and get the right results in this C program

我写了一个由这些文件组成的 C 代码:main.c, kernel.c, funzione.cfunzione.hstruttura.h。以下是文件:

main.c:

#include <math.h>
#include "stdio.h"

#include "struttura.h"
#include "funzione.h"

struttura o;

#include "kernel.c"

int main(void){

  pincopallo();
  return 0;
}

kernel.c

void pincopallo(void){  
printf("o.x=%f\n",o.x);
printf("o.y=%f\n",o.y);
}

funzione.cu

#include "struttura.h"

void funzione(struttura* a){
  (*a).x  = 450;
  (*a).y  = 150;
}

funzione.h

#include "struttura.h"
void funzione(struttura* a);

struttura.h

#ifndef STRUTTURA_H
#define STRUTTURA_H

typedef struct{
  float x;
  float y;  
}struttura;

#endif /* STRUTTURA_H */

我的目标是显示 funzione.c 文件中包含的值(我根本不想修改 struttura.h)。然而,当我用我自己写的 makefile 编译它时,我得到以下结果:

o.x=0.000000
o.y=0.000000

而不是值 450 和 150。

这是生成文件:

enter CC=gcc
CFLAGS=-Wall
OBJS = main.o funzione.o 

all: eseguibile

eseguibile: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o eseguibile -lm

main.o: main.c funzione.h struttura.h
    $(CC) -c $(CFLAGS) main.c

funzione.o: funzione.c funzione.h struttura.h
    $(CC) -c $(CFLAGS) funzione.c

clean:
    rm -rf *.o eseguibilecode here

(注意标签)。我确信 makefile 并不完全正确:事实上,如果 运行 它是第一次,它会一直编译。但是,如果我修改 kernel.c 中的某些内容(例如,我将 printf("o.x=%f\n",o.x); 更改为 printf("o.x=%d\n",o.x);)并尝试再次编译,终端将显示以下消息:make: Nothing to be done for all. 在这种情况下,我需要执行 make clean 并再次编译以获得明显的错误消息: error: ‘struttura’ has no member named ‘z’ printf("o.x=%f\n",o.z);

所以基本上我的问题是 2:

您永远不会调用 funzione() 函数。您需要调用它并向其传递指向 o 某处的指针。

另外,你真的不应该在 C 文件上使用 #include,只能在头文件上使用。

您需要从某处向 funzione.c 添加依赖项,以便 Make 可以选择它并在需要时重新构建文件。类似于:

eseguibile: main.o funzione.o
如果 kernel.c 改变,

main.c 应该重新编译,因为你 #include kernel.c 在里面,但是 make 不知道依赖关系。您也可以将其添加到 main.o,如下所示:

main.o: main.c funzione.h struttura.h kernel.c
    $(CC) -c $(CFLAGS) main.c
  1. 修复错误:

    void funzione(struttura* a)

未被调用并且 o.x 的值未被分配。在调用

之前调用这个函数
pincopallo();

在main.c 像这样写:

funzione(&o);
pincopallo();
return 0;
  1. include *.c 文件不是很好的做法。 *.h 文件用于包含。 创建 kernel.h 文件并添加到 main.c 和 kernel.c

#include "kernel.h"

写入 pincopallo() 的 kernel.h 声明:

void pincopallo(void);

注意:在 .c 文件中包含 .c 文件是一种非常糟糕的做法

像下面这样组织make文件会好很多

并从 main.c 文件中删除 #include "kernel.c"

除此之外,这将是很好的,尤其是当项目得到 更大,也生成依赖文件 请参阅最后的注释以了解执行此操作的方法。

name = eseguibile
CC=gcc
CFLAGS :=-Wall
LIBS := -lm

SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
HDR := $(wildcard *.h)

.PHONY: all clean

all: $(name)

$(name): $(OBJ)
    #
    # ======= $(name) Link Start =========
    $(CC) -o $@ $(OBJ) $(LIBS)
    # ======= $(name) Link Done ==========
    #

%.o: %.c $(HDR)
    #
    # ========= START $< TO $@ =========
    $(CC) $(CCFLAGS) -c $< -o $@ -I.
    # ========= END $< TO $@ =========
    #

clean:
    rm -rf *.o $(name)



dependency notes:  only use the following after understanding it

#
#create dependancy files -- inference rule
# (gcc has parameters that do not require the sed utility)
#
%.d: %.c
    #
    # ========= START $< TO $@ =========
    $(CC) -M $(CPPFLAGS) $< > $@.$$$$;                      \
    sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@;     \
    rm -f $@.$$$$
    # ========= END $< TO $@ =========


#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d makefile
    #
    # ========= START $< TO $@ =========
    $(CC) $(CCFLAGS) -c $< -o $@ -I.
    # ========= END $< TO $@ =========
    #

清洁: rm -rf *.o *.d $(名称)

# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif