首页 文章

Makefile基于子目录

提问于
浏览
-1

我有一个C项目程序,我想用makefile编译和管理:

./include: Headers 所在的位置

a.h,b.h,c.h

./obj: 将存储对象

./src: 源文件所在的位置

main.c,a.c,b.c,c.c

如何创建一个makefile来创建一个可执行文件 test ,并将目标文件放到obj文件夹中?

1 回答

  • 1

    您可以使用我为简单项目制作的模板 . 我不知道您使用的是哪个编译器,但您可以使用第一部分中的变量以及其他有用的配置来配置它:

    #=============================================================================
    # Project related variables
    EXENAME           = test
    FILEIDENTIFIER    = .c
    COMPFLAGS         = -pedantic -Wall
    COMPSTANDARD      = -std=c11
    EXELINKS          = -lm
    DBARGS            = -g
    
    BUILDDIR          = build/
    BINARY_OUTPUT_DIR = $(BUILDDIR)bin/
    OBJDIR            = obj/
    SOURCEDIRS        = src/
    INCLUDEDIRS       = include/
    LIBSDIRS          = /usr/lib/
    
    
    #=============================================================================
    # Commands variables
    COMPILER          = gcc
    LINKER            = ld -r
    
    DISPLAY           = printf
    MKDIR             = mkdir -p
    RMDIR             = rmdir
    RM                = rm -f
    
    
    #=============================================================================
    # Other
    VOIDECHO          = > /dev/null 2>&1
    
    
    #=============================================================================
    # Semi-automatic variables
    EXEFINALOBJ       = $(OBJDIR)$(EXENAME).o
    EXEFINAL          = $(BINARY_OUTPUT_DIR)$(EXENAME)
    INCLUDEARGS       = $(addprefix -I,$(INCLUDEDIRS))
    
    
    #=============================================================================
    # Automatic variables
    SOURCES           = $(foreach sourcedir,$(SOURCEDIRS),$(wildcard $(sourcedir)**/*$(FILEIDENTIFIER)) $(wildcard $(sourcedir)*$(FILEIDENTIFIER)))
    OBJECTS           = $(patsubst %$(FILEIDENTIFIER),%.o,$(foreach sourcedir,$(SOURCEDIRS),$(subst $(sourcedir),$(OBJDIR),$(wildcard $(sourcedir)**/*$(    FILEIDENTIFIER)) $(wildcard $(sourcedir)*$(FILEIDENTIFIER)))))
    GENERATED_FILES   = $(OBJECTS) $(EXEFINALOBJ) $(EXEFINAL)
    GENERATED_FOLDERS = $(OBJDIR) $(BINARY_OUTPUT_DIR) $(BUILDDIR)
    
    
    #=============================================================================
    # Special GNU make variables
    VPATH             = $(SOURCEDIRS)
    
    
    #=============================================================================
    # Rules: Phony Targets
    .PHONY: silent
    silent:
        @make --silent $(EXEFINAL)
    
    .PHONY: all
    all: $(EXEFINAL)
    
    .PHONY: debug
    debug: COMPFLAGS += $(DBARGS)
    debug: all
    
    .PHONY: clean
    clean:
        @$(DISPLAY) "\n-> Cleaning files...\n"
        @$(DISPLAY) " $(foreach file,$(GENERATED_FILES),$(if $(wildcard $(file)),- Removing file $(file)\n,\b))"
        @$(RM) $(GENERATED_FILES)
        @$(DISPLAY) "\n-> Cleaning folders...\n"
        @$(DISPLAY) " $(foreach folder,$(GENERATED_FOLDERS),$(if $(wildcard $(folder)),- Removing folder $(folder)\n,\b))"
        @$(RMDIR) $(GENERATED_FOLDERS) $(VOIDECHO) || true
        @$(DISPLAY) "\n"
    
    
    #=============================================================================
    # Rules: File Targets
    $(EXEFINAL): $(EXEFINALOBJ)
        @$(DISPLAY) "\n - Building $@ from $^...   "
        @$(MKDIR) $(BINARY_OUTPUT_DIR)
        $(COMPILER) $(EXEFINALOBJ) -o $@ $(LIBARGS) $(EXELINKS)
        @$(DISPLAY) "Done"
        @$(DISPLAY) "\n\n"
    
    $(EXEFINALOBJ): $(OBJECTS)
        @$(DISPLAY) "\n - Merging objects files into $@...   "
        $(LINKER) $(OBJECTS) -o $@
        @$(DISPLAY) "Done"
    
    $(OBJDIR)%.o: %$(FILEIDENTIFIER)
        @$(DISPLAY) "\n - Building $@ from $^...   "
        @$(MKDIR) $(OBJDIR)
        $(COMPILER) $(COMPFLAGS) $(COMPSTANDARD) $(INCLUDEARGS) -c $^ -o $@
        @$(DISPLAY) "Done"
    

    实际配置适用于Linux并使用gcc和ld . 它支持源的子文件夹,并定义了4个目标:

    • silent(默认):silent build

    • all:详细构建

    • debug:debug build

    • clean:删除makefile生成的文件和文件夹

    如果你想准确理解Makefile是如何工作的,就像MadScientist所写的那样,请看_991392_的GNU make手册

相关问题