У меня есть текущие структуры каталогов:
- . / MyFolder /
- . / Common /
- Makefile
- error. c
- error.h
- . / Build /
/build/common
содержит файлы объектов и зависимостей, полученные при компиляции папки common
и эквивалент для build/myFolder
.
В основном /myFolder/
содержит программу, для которой требуется некоторая функция из common
. Таким образом, /myFolder/Makefile
вызывает также /common/Makefile
для компиляции.
./common/Makefile
- это следующее:
CC = gcc
CURRENT_DIR := $(shell basename $(CURDIR))
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR := ../build/$(CURRENT_DIR)
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
all: $(OBJECTS)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
-include $(DEPENDS)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $< -o $@
$(OBJDIR):
mkdir -p $(OBJDIR)
и ./myFolder/Makefile
- это следующее:
CC = gcc
INC_PATH := -I../common/
BUILD_DIR_NAME := build
BUILDDIR := ../$(BUILD_DIR_NAME)
CURR_DIR_NAME := $(shell basename $(CURDIR))
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR := $(BUILDDIR)/$(CURR_DIR_NAME)
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
COMMONDIR_NAME := common
COMMONDIR := ../$(COMMONDIR_NAME)
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON := $(BUILDDIR)/$(COMMONDIR_NAME)
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
EXECUTABLE := ../out_file
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
+$(MAKE) -C $(COMMONDIR) clean
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTS) $(OBJECTSCOMMON)
$(CC) $(WARNING) $^ -o $@
-include $(DEPENDS) $(DEPENDSCOMMON)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@
$(OBJDIRCOMMON):
mkdir -p $(OBJDIRCOMMON)
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/%.c $(COMMONDIR)/Makefile| $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
Если я войду в папку myFolder
и скомпилирую с make
в первый раз все ок. Если затем я попробую снова, я получу следующую ошибку:
make: *** No rule to make target `error.c', needed by `../build/common/error.o'. Stop.
Если я сделаю make clean
, а затем make
, это сработает.
Строка, вызывающая проблему, следующая:
-include $(DEPENDS) $(DEPENDSCOMMON)
особенно $(DEPENDSCOMMON)
. С -include $(DEPENDS)
вместо него он работает отлично.
Теперь -
говорит Makefile не жаловаться, если файлы не существуют. Если они существуют, они будут включены и перекомпилировать ваши источники в соответствии с зависимостями. По этой причине я ожидал, что не скомпилируется с первой попытки, но если он скомпилируется с первой попытки, также не будет генерировать такую ошибку (поскольку все файлы существуют).
Может кто-нибудь сказать, пожалуйста, кто я? отсутствует?
Для полноты вот другие файлы, которые являются только примерами:
main. c
#include "../common/error.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc<1) err_sys("some error");
printf("Hello world\n");
return 0;
}
ошибка . c
#include <stdio.h>
void err_sys(const char *fmt, ...)
{
printf("some err\n");
}
error.h
#ifndef _ERROR_H_
#define _ERROR_H_
#endif
/*Fatal error related to a system cal1.
* Print a message and terminate*/
void err_sys(const char *fmt,...);