4

为了编译两个文件,我创建了一个 makefile,用于提及对象名称,或者我可以使用 patsubst 的模式规则。

# ----------------------------------------------------------------------------
# Makefile for building tapp
#
# Copyright 2010 FriendlyARM (http://www.arm9.net/)
#

ifndef DESTDIR
DESTDIR            ?= /opt/FriendlyARM/tiny6410/linux/rootfs_qtopia_qt4
endif

#CFLAGS              = -c -Wall -O2  # wall is for warning show and 02 is optiminisation level 2
CFLAGS              = -c -O2  # wall is for warning show and 02 is optiminisation level 2
#CC                    = arm-linux-gcc   # compiler name
CC                    = gcc   # compiler name
LD                    = ld

INSTALL             = install         # 

TARGET              = led_player_project

#OBJ = led-player_backup.o led-player.o
OBJ := $(patsubst %.c,%.o,$(wildcard *.c */*.c))

#OBJ = $(shell find . -name '*.c')

all: $(TARGET) 
#all: $(OBJ)

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

%.o : %.c
    $(CC) $(CFLAGS) $< -o $@

#$< -o $@


install: $(TARGET)
    $(INSTALL) $^ $(DESTDIR)/usr/bin

clean :
    rm -rf *.o $(TARGET) $(OBJ)


# ----------------------------------------------------------------------------

.PHONY: $(PHONY) install clean

# End of file
# vim: syntax=make

#EOF

现在,如果我的项目包含文件夹包含子文件夹并且它们包含更多文件。那么我可以编写模式规则来编译每个文件并创建一个通用的可执行文件吗?

1>我是否必须在每个子文件夹中创建makefile,以便我可以从主makefile调用该makefile,例如将静态驱动程序集成到linux内核每个驱动程序都有各自的makefile?
2> 或者完整项目的通用makefile?
3> 我可以使用 patsubst 编译每个文件而不提及名称吗?
4> 我如何结合每个 *.o 来创建名为main.

在此处输入图像描述

编辑:---
@Jan Hudec 我已根据您的评论修改了我的生成文件(我已在上面发布)。现在我只是尝试在我的主文件夹中使用两个文件夹。我收到以下错误文件夹结构:-

main Folder  ----> one Folder 
             ----> two Folder 

文件夹主要包含:--

main.c 
main.h
Makefile

文件夹一包含:--

one.c
one.h

文件夹二包含:--

two.c
two.h

main.c 内容:--

#include <stdio.h>
#include <stdlib.h>

#include "main.h"

int main()
{
  char *p;

  printf("\n\n main \n");

  one();
  two();

  return 0;
}

main.h 内容:---

#include "one/one.h"
#include "two/two.h"

one.c 内容:---

    #include <stdio.h>
    #include <stdlib.h>

#include "one.h"

    void one()
    {

      printf("\n one \n");

    }

one.h 内容:---

void one();

二.c内容:---

#include <stdio.h>
#include <stdlib.h>

#include "two.h"

void two()
{

  printf("\n two \n");

}

二.h内容:---

void two();

我在制作时遇到的错误:----

ignite@ignite:~/testing/main$ make
gcc    -c -O2   main.c -o main.o
gcc    -c -O2   one/one.c -o one/one.o
gcc    -c -O2   two/two.c -o two/two.o
ld  -o led_player_project main.o one/one.o two/two.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080
main.o: In function `main':
main.c:(.text.startup+0x11): undefined reference to `puts'
one/one.o: In function `one':
one.c:(.text+0xb): undefined reference to `puts'
two/two.o: In function `two':
two.c:(.text+0xb): undefined reference to `puts'
make: *** [led_player_project] Error 1
ignite@ignite:~/testing/main$ 
4

2 回答 2

9

广告 1 和 2:文件名可以根据需要安全地包含目录和%匹配/项。因此,您可以轻松拥有:

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

甚至

$(wildcard */*.c)

...或如keltar在评论中所建议的那样

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

这是递归的。

广告 3:你正在做。

广告 4:创建一个$(OBJ)作为依赖项的目标,并像编译一样使用自动变量:

main : $(OBJ)
        $(LD) $(LDFLAGS) -o $@ $< $(LIBS)
于 2013-10-23T10:48:29.910 回答
2

也许还有另一种解决方案。我的项目目录中有一个源目录,其中包含子目录。而且我不想在每个子目录或其他东西中都有一个 Makefile。而且我只想在项目的rootdir中使用一个makefile来构建所有东西:所以对于我在c++中的静态库,我做了这个makefile。也许它也可以成为您的解决方案。但是我没有通过“make -j4”左右的并行构建对其进行很好的测试。

BUILDCXX=g++-10
CHECKCXX=clang++-12

CXXFLAGS=-std=c++17 -Wall -Werror -Wextra -g -pg -O0 -I. -DDEBUG
CXXFLREL=-std=c++17 -Wall -Werror -Wextra -O3 -s -I. -DNDEBUG
CXXFLAGSLIB=$(CXXFLAGS)
CXXFLAGSTST=$(CXXFLAGS) -DRLOG_COMPONENT="clbc"

LDFLAGS=
LDFLAGSLIB=$(LDFLAGS)
LDFLAGSTST=$(LDFLAGS) -L./target/lib -lUnitTest++ -lclbc

OUTDIR=target
OUTDIRLIB=$(OUTDIR)/lib
OUTDIRTST=$(OUTDIR)/bin
OUTDIROBJ=$(OUTDIR)/obj
OUTFILELIB=libclbc.a
OUTFILETST=runtests

SRCDIR=source
SRCDIRLIB=$(SRCDIR)/lib
SRCDIRTST=$(SRCDIR)/test
SRCDIRSLIBR := $(shell find $(SRCDIRLIB) -maxdepth 3 -type d)
SRCFILESLIB := $(foreach dir,$(SRCDIRSLIBR),$(wildcard $(dir)/*.cpp))
OBJFILESLIB := $(addprefix $(OUTDIROBJ)/,$(notdir $(patsubst %.cpp,%.o,$(SRCFILESLIB))))
SRCDIRSTSTR := $(shell find $(SRCDIRTST) -maxdepth 3 -type d)
SRCFILESTST := $(foreach dir,$(SRCDIRSTSTR),$(wildcard $(dir)/*.cpp))
OBJFILESTST := $(addprefix $(OUTDIROBJ)/,$(notdir $(patsubst %.cpp,%.o,$(SRCFILESTST))))


.PHONY: all


all: clean lib


check-syntax:
    $(CHECKCXX) $(CXXFLAGS) -s -o /dev/null -S $(CHK_SOURCES)


clean:
    @rm -rf $(OUTDIR)


lib:$(OBJFILESLIB)
    @mkdir -p $(OUTDIRLIB)
    @echo " TargetLib :" $(OUTDIRLIB)/$(OUTFILELIB) 
    @ ar rcs $(OUTDIRLIB)/$(OUTFILELIB) $^


test:$(OBJFILESTST)
    @mkdir -p $(OUTDIRTST)
    @echo "TargetTest :" $(OUTDIRTST)/$(OUTFILETST)
    @ $(BUILDCXX) $(OBJFILESTST) -o $(OUTDIRTST)/$(OUTFILETST) $(LDFLAGSTST)


release: CXXFLAGSLIB=$(CXXFLREL)
release:$(OBJFILESLIB)   
    @mkdir -p $(OUTDIRLIB)
    @echo "RTargetLib :" $(OUTDIRLIB)/$(OUTFILELIB) 
    @ ar rcs $(OUTDIRLIB)/$(OUTFILELIB) $^


define set_real_src_file
    $(eval REAL_SRC_FILE=$(strip $(1)))
endef

define set_nothing
endef

define get_real_src_file
    $(if $(strip $(findstring $(strip $(1)),$(strip $(2)))),$(call set_real_src_file,$(2)),$(call set_nothing))
endef

define get_source_file
    @echo ObjectFile : $(1)
    $(eval REAL_SRC_SEARCH=$(notdir $(patsubst %.o,%.cpp,$(1))))
    $(eval REAL_SRC_FILE=)
    $(foreach word,$(2), $(call get_real_src_file, $(REAL_SRC_SEARCH),$(word)))
endef


$(OBJFILESLIB): $(SRCFILESLIB)
    @mkdir -p $(OUTDIROBJ)
    $(call get_source_file,$@,$^,$<)
    @ $(BUILDCXX) $(CXXFLAGSLIB) -c $(REAL_SRC_FILE) -o $@


$(OBJFILESTST): $(SRCFILESTST)
    @mkdir -p $(OUTDIROBJ)
    $(call get_source_file,$@,$^,$<)
    @ $(BUILDCXX) $(CXXFLAGSTST) -c $(REAL_SRC_FILE) -o $@

但我猜它只能与 GNUMake 一起运行,而没有其他 make 实现。

于 2021-11-28T19:08:42.913 回答