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



我写了一个C代码,它由以下文件组成:main.Ckernel.Cfunzione.Cunzione.h和struttura.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;
}

内核.c

void pincopallo(void){  
printf("o.x=%fn",o.x);
printf("o.y=%fn",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=%fn",o.x);更改为printf("o.x=%dn",o.x);)并尝试再次编译,终端将显示以下消息:make: Nothing to be done for all.在这种情况下,我需要执行make clean并再次编译,以获得明显的错误消息:error: ‘struttura’ has no member named ‘z’ printf("o.x=%fn",o.z);

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

  • 我如何才能正确地得到结果?

  • 我应该如何修改makefile,以便每次我修改kernel.c中的内容时它都会编译

如果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

您永远不会调用funzione()函数。您需要调用它,并将一个指向o的指针传递给它。

此外,您真的不应该在C文件上使用#include,只应该在头文件上使用。

您需要从某个地方向funzione.c添加一个依赖项,这样Make就可以在需要时获取该依赖项并重新构建文件。类似于:

eseguibile: main.o funzione.o
  1. 修复错误:

    void funzione(struttura* a)

未调用,并且未为o.x分配值。在调用之前调用此函数

pincopallo();

大体上。c这样写:

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

#include "kernel.h"

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

void pincopallo(void);

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

最好像下面的一样组织make文件

并从主.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[ :]*,1.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

最新更新