简体   繁体   English

如何使我的 makefile 以我需要的方式将我的项目组合在一起?

[英]How can I make my makefile put my project together the way I need it?

I've been through probably 20 different webpages about makefile but I still can't seem to get it to work for my project.我已经浏览了大约 20 个关于 makefile 的不同网页,但我似乎仍然无法让它为我的项目工作。 A project with all the files in one folder works, but I can't get it to work with my specific project which has everything in different folders.在一个文件夹中包含所有文件的项目可以工作,但我无法让它与我的特定项目一起使用,该项目在不同文件夹中包含所有文件。

Example structure示例结构

Here is an example project that has all the necessary features and distinctions to be structurally identical to my project yet obviously smaller:这是一个示例项目,它具有所有必要的功能和区别,在结构上与我的项目相同,但明显更小:

.
|-- bin
|   |-- apple (executable 1)   // needs apple's .o files (C++)
|   |-- banana (executable 2)  // needs banana's .o files + .so file (C/C++)
|-- include
|   |-- format
|   |   |-- format.h
|   |-- apple
|   |   |-- foo.h
|   |-- banana
|       |-- bar.h
|-- lib
|   |-- apple
|   |   |-- apple_main.o
|   |   |-- apple_one.o
|   |-- banana
|   |   |-- banana_main.o
|   |   |-- banana_one.o
|   |   |-- banana_two.o
|   |-- archive_apple
|   |   |-- libapple_one.a
|   |-- archive_banana
|   |   |-- libbanana_one.a
|   |   |-- libbanana_two.a
|   |-- external
|   |   |-- foo.so
|-- makefile
|-- src
    |-- drivers
    |   |-- apple_main.cpp       // needs format.h
    |   |-- banana_main.cpp    // needs format.h,
    |-- apple
    |   |-- apple_one.cpp        // needs format.h, foo.h
    |-- banana
        |-- banana_one.c       // needs format.h, bar.h
        |-- banana_two.cpp     // needs format.h, bar.h

I've been reading about things online about automatic makefile generation, where you type in certain things into the makefile that goes through the folders and uses substitutions and other things to eliminate the need to list every single rule explicitly, but none of them worked.我一直在网上阅读有关自动生成文件生成的内容,您可以在生成文件中输入某些内容,这些内容会遍历文件夹并使用替换和其他内容来消除明确列出每条规则的需要,但它们都不起作用。 I must be doing something wrong, but I don't know what it is.我一定是做错了什么,但我不知道是什么。

What I need我需要的

I want to put the correct things into my makefile that creates what you see above.我想将正确的东西放入我的生成文件中,以创建您在上面看到的内容。

As you can see, some parts of the project are necessarily written in C. (I guess I could change everything to be C++ but I don't want to if I don't have to).如您所见,该项目的某些部分必须用 C 编写。(我想我可以将所有内容更改为 C++,但如果我不需要,我不想这样做)。

My compilers and flags will be:我的编译器和标志将是:

CC := gcc
CXX := g++
C_FLAGS := -Wall -std=c17
CXX_FLAGS := -Wall -std=c++17

My directories will use -I to avoid things like我的目录将使用-I来避免类似的事情

// #include "../../include/format/format.h"
// instead:
#include <format/format.h>

I'll also be using -L , if that helps, because I want to create those .a files.如果有帮助,我也会使用-L ,因为我想创建那些.a文件。 As far as I can see, it's something like:据我所知,它是这样的:

libsomething.a: something.o
    ar rvs ./lib/archive/libsomething.a ./lib/foo/something.o

What do I need in my makefile in order to put this project together and generate my executables, object files, and libraries?为了将这个项目放在一起并生成我的可执行文件、目标文件和库,我的 makefile 中需要什么?

Note: I understand the basics of makefile, like how a rule works and how to put together a makefile manually for a small and simple project, but I'm only just starting to understand the built-in functions and wildcards and other complex things.注意:我了解 makefile 的基础知识,例如规则如何工作以及如何为一个小而简单的项目手动组合一个 makefile,但我才刚刚开始了解内置函数和通配符以及其他复杂的东西。

And of course, since my project is much larger than this, though structurally identical, I need the answer to be something either generic or easy to modify, like those examples of makefiles I saw online that for some reason don't work on my project.当然,由于我的项目比这个大得多,虽然结构相同,但我需要答案是通用的或易于修改的,就像我在网上看到的那些 makefile 示例由于某种原因不适用于我的项目. That way, I can adapt this to future projects without unnecessary manual work.这样,我可以将其适应未来的项目,而无需进行不必要的手动工作。

Preferably (unless it is bad practice to do so), I would like for the executables to be built from the libraries, something along the lines of:最好(除非这样做是不好的做法),我希望从库中构建可执行文件,类似于:

executable: something_main.o libfoo.a libbar.a
    $(CXX_BUILD) -o ./bin/executable \
    ./lib/something_main.o \
    -L./lib/something \
    -lfoo -lbar

May Help.可以帮助。

The Structure of the project:项目结构:

    xc
        inc
        src
    test
        inc
        src
    obj
        xc
        test
    bin

Makefile生成文件

PNAME = xc
OBJS_DIR=obj
BIN_DIR=bin
INC_SUB_DIR=inc
SRC_SUB_DIR=src

CPP = gcc
#CPP += -m32

#LIBPATH = -Llib
LIBLIST += -lz
LDFLAGS += $(LIBPATH) $(LIBLIST) 

UTILS_DIR = xc
UTILS_SRCS  = $(wildcard $(UTILS_DIR)/$(SRC_SUB_DIR)/*.c)
UTILS_INCS  = $(wildcard $(UTILS_DIR)/$(INC_SUB_DIR)/*.h)
UTILS_SLIST = $(UTILS_SRCS) $(UTILS_INCS)
UTILS_OLIST = $(wildcard $(OBJS_DIR)/$(UTILS_DIR)/*.o)
UTILS_OBJS  = $(patsubst $(UTILS_DIR)/$(SRC_SUB_DIR)/%.c,$(OBJS_DIR)/$(UTILS_DIR)/%.o,$(UTILS_SRCS))

BASE_DIR = test
BASE_SRCS  = $(wildcard $(BASE_DIR)/$(SRC_SUB_DIR)/*.c)
BASE_INCS  = $(wildcard $(BASE_DIR)/$(INC_SUB_DIR)/*.h)
BASE_SLIST = $(BASE_SRCS) $(BASE_INCS)
BASE_OLIST = $(wildcard $(OBJS_DIR)/$(BASE_DIR)/*.o)
BASE_OBJS  = $(patsubst $(BASE_DIR)/$(SRC_SUB_DIR)/%.c,$(OBJS_DIR)/$(BASE_DIR)/%.o,$(BASE_SRCS))

SLIST += $(UTILS_SLIST) $(BASE_SLIST)
OLIST += $(UTILS_OLIST) $(BASE_OLIST)
OBJS += $(UTILS_OBJS) $(BASE_OBJS)

INCPATH = -I$(UTILS_DIR)/$(INC_SUB_DIR) -I$(BASE_DIR)/$(INC_SUB_DIR)
CPPFLAGS += -c -Wall -Wextra
#CPPFLAGS += -O2
CPPFLAGS += $(INCPATH)
#CPPFLAGS += -g 

# target
.PHONY = all

all: $(PNAME)

packsrc:
    tar zcvf $(PNAME)-src-`date +%Y%m%d%H%M%S`.tgz $(SLIST) doc Makefile 

slib:
    $(AR) rcs $(PNAME)-`date +%Y%m%d%H%M%S`.a $(OBJS)

clean:
    $(RM) $(OLIST) $(BIN_DIR)/$(PNAME)
 
$(PNAME): $(OBJS) 
    @ mkdir -p $(BIN_DIR)
    @ mkdir -p $(OBJS_DIR)
    @ mkdir -p $(OBJS_DIR)/$(UTILS_DIR)
    @ mkdir -p $(OBJS_DIR)/$(BASE_DIR)
    $(CPP) $^ -o $(BIN_DIR)/$@ $(LDFLAGS)

$(OBJS_DIR)/$(UTILS_DIR)/%.o:$(UTILS_DIR)/$(SRC_SUB_DIR)/%.c
    $(CPP) $(CPPFLAGS) $< -o $@

$(OBJS_DIR)/$(BASE_DIR)/%.o:$(BASE_DIR)/$(SRC_SUB_DIR)/%.c
    $(CPP) $(CPPFLAGS) $< -o $@

dos2unix:
    dos2unix $(SLIST)  

Ad 1 and 2: The filenames can safely include directories and % matches / as necessary.广告 1 和 2:文件名可以根据需要安全地包含目录和%匹配/ So you can easily have:因此,您可以轻松拥有:

$(wildcard subdir/*.c) $(wildcard anotherdir/*.c)

or even甚至

$(wildcard */*.c)

... or as suggested by keltar in comment ...或如keltar在评论中所建议的那样

$(shell find . -name '*.c')

which is recursive.这是递归的。

Ad 3: You are doing it.广告 3:你正在做。

Ad 4: Create a target with $(OBJ) as dependencies and use the automatic variable just as you do for compilation:广告 4:创建一个以$(OBJ)作为依赖项的目标,并像编译一样使用自动变量:

main : $(OBJ)
        $(LD) $(LDFLAGS) -o $@ $< $(LIBS)

Original answer by @Jan Hudec: make for compiling — all *.c files in folders & subfolders in project @Jan Hudec 的原始答案: 编译 - 项目中文件夹和子文件夹中的所有 *.c 文件

Maybe the makemymakefile.com web site would help.也许makemymakefile.com网站会有所帮助。 It asks a number of questions like what directory you have your source files in, what directories do you want to have as include paths.它询问了许多问题,例如您的源文件在哪个目录中,您希望将哪些目录作为包含路径。 After you have answered the questions you hit generate and it writes a makefile for you.在您回答了您点击生成的问题后,它会为您编写一个生成文件。

The generated makefile expects to build only one target so it won't build your libraries.生成的 makefile 预计只构建一个目标,因此它不会构建您的库。 You can make a different makefile for each library and have a "master" makefile that builds the final output and uses the other makefiles a dependencies.您可以为每个库制作不同的 makefile,并拥有一个“主”makefile 来构建最终输出并使用其他 makefile 作为依赖项。

So in the master makefile you add a target:因此,在主 makefile 中添加一个目标:

lib/archive_apple/libapple_one.a:
    echo "Making libapple_one"
    $(MAKE) -f libapple_one.mk

and then add it as a target to the final binary:然后将其作为目标添加到最终二进制文件中:

$(BIN) : PreBuild lib/archive_apple/libapple_one.a $(OBJ)

A different option would be to copy/paste the sections to make each of your libraries all in one big makefile.另一种选择是复制/粘贴这些部分以使您的每个库都在一个大的 makefile 中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM