源文件位于不同目录中的 Makefile

2024-10-12 10:28:00
admin
原创
237
摘要:问题描述:我有一个项目,其目录结构如下: $projectroot | +---------------+----------------+ | ...

问题描述:

我有一个项目,其目录结构如下:

                         $projectroot
                              |
              +---------------+----------------+
              |               |                |
            part1/          part2/           part3/
              |               |                |
       +------+-----+     +---+----+       +---+-----+
       |      |     |     |        |       |         |
     data/   src/  inc/  src/     inc/   src/       inc/

我应该如何编写一个位于 part/src(或实际上任何地方)的 makefile,以便可以完成/链接 part?/src 中的 c/c++ 源文件?

我可以执行类似 -I$projectroot/part1/src -I$projectroot/part1/inc -I$projectroot/part2/src 的操作吗...

如果这样可行,有没有更简单的方法。我见过一些项目,每个相应的部分都有一个 makefile?文件夹。[在这篇文章中,我使用了问号,就像 bash 语法一样]


解决方案 1:

Makefile传统方法是在每个子目录(part1、等)中创建一个,part2以便您独立构建它们。此外,Makefile在项目的根目录中创建一个,用于构建所有内容。“根”Makefile看起来类似于以下内容:

all:
    +$(MAKE) -C part1
    +$(MAKE) -C part2
    +$(MAKE) -C part3

由于 make 目标中的每一行都在其自己的 shell 中运行,因此无需担心遍历目录树或其他目录。

我建议看一下GNU make 手册第 5.7 节;它非常有帮助。

解决方案 2:

如果一个子目录中的代码依赖于另一个子目录中的代码,那么最好在顶层使用一个 makefile。

请参阅“递归 Make 被视为有害”以了解完整原理,但基本上您希望 make 拥有所需的全部信息来决定是否需要重建文件,而如果您只告诉它项目的三分之一,它就不会拥有这些信息。

上面的链接似乎无法访问。 同一文档可在此处访问:

  • aegis.sourceforge.net (已存档)

  • lcgapp.cern.ch

解决方案 3:

VPATH 选项可能会派上用场,它告诉 make 在哪些目录中查找源代码。不过,您仍然需要为每个包含路径添加 -I 选项。例如:

CXXFLAGS=-Ipart1/inc -Ipart2/inc -Ipart3/inc
VPATH=part1/src:part2/src:part3/src

OutputExecutable: part1api.o part2api.o part3api.o

这将自动在 VPATH 指定的任何目录中找到匹配的 partXapi.cpp 文件并对其进行编译。但是,当您的 src 目录被分成子目录时,这更有用。对于您所描述的,正如其他人所说,您可能最好为每个部分使用一个 makefile,特别是如果每​​个部分都可以独立存在的话。

解决方案 4:

您可以向根 Makefile 添加规则,以便编译其他目录中所需的 cpp 文件。下面的 Makefile 示例应该是一个很好的开始,可以帮助您实现目标。

抄送=g++
目标=cpp测试
OTHERDIR=../../someotherpath/in/project/src

源文件 = cppTest.cpp
源 = $(OTHERDIR)/file.cpp

## 结束源定义
包括 = -I./ $(AN_INCLUDE_DIR)  
包括 = -I.$(OTHERDIR)/../inc
## 结束更多包含

VPATH=$(其他目录)
OBJ=$(加入$(addsuffix../obj/,$(dir $(SOURCE))),$(notdir $(SOURCE:.cpp=.o)))

## 修复依赖目标为相对于 src 目录的 ../.dep
DEPENDS=$(加入$(addsuffix../.dep/,$(dir $(SOURCE))),$(notdir $(SOURCE:.cpp=.d)))

## 执行默认规则
全部:$(TARGET)
        @真的

## 清洁规则
干净的:
        @-rm -f $(目标) $(对象) $(取决于)


## 制定实际目标的规则
$(目标): $(对象)
        @echo "=============="
        @echo "链接目标 $@"
        @echo "=============="
        @$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
        @echo -- 链接完成 --

## 通用编译规则
%.o : %.cpp
        @mkdir -p $(目录 $@)
        @echo "=============="
        @echo "编译 $<"
        @$(CC) $(CFLAGS) -c $< -o $@


## 来自 cpp 文件的目标文件的规则
## 每个文件的目标文件都放在 obj 目录中
## 比实际源目录高一级。
../obj/%.o:%.cpp
        @mkdir -p $(目录 $@)
        @echo "=============="
        @echo "编译 $<"
        @$(CC) $(CFLAGS) -c $< -o $@

# “其他目录”规则每个“其他”目录都需要一个
$(OTHERDIR)/../obj/%.o:%.cpp
        @mkdir -p $(目录 $@)
        @echo "=============="
        @echo "编译 $<"
        @$(CC) $(CFLAGS) -c $< -o $@

## 制定依赖规则
../.dep/%.d: %.cpp
        @mkdir -p $(目录 $@)
        @echo "=============="
        @echo 为 $*.o 构建依赖文件
        @$(SHELL) -ec'$(CC) -M $(CFLAGS) $< | sed"s^$*.o^../obj/$*.o^" > $@'

## “其他”目录的依赖规则
$(OTHERDIR)/../.dep/%.d: %.cpp
        @mkdir -p $(目录 $@)
        @echo "=============="
        @echo 为 $*.o 构建依赖文件
        @$(SHELL) -ec'$(CC) -M $(CFLAGS) $< | sed"s^$*.o^$(OTHERDIR)/../obj/$*.o^" > $@'

## 包含依赖文件
-包括 $(取决于)

解决方案 5:

如果源代码分布在许多文件夹中,并且有单独的 Makefile 是有意义的,那么如前所述,递归 make 是一种很好的方法,但对于较小的项目,我发现在 Makefile 中列出所有源文件及其相对于Makefile的相对路径更容易,如下所示:

# common sources
COMMON_SRC := ./main.cpp \ n              ../src1/somefile.cpp \ n              ../src1/somefile2.cpp \ n              ../src2/somefile3.cpp \ n

然后我可以VPATH这样设置:

VPATH := ../src1:../src2

然后我构建对象:

COMMON_OBJS := $(patsubst %.cpp, $(ObjDir)/%$(ARCH)$(DEBUG).o, $(notdir $(COMMON_SRC)))

现在规则很简单:

# the "common" object files
$(ObjDir)/%$(ARCH)$(DEBUG).o : %.cpp Makefile
    @echo creating $@ ...
    $(CXX) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<

并且构建输出甚至更加简单:

# This will make the cbsdk shared library
$(BinDir)/$(OUTPUTBIN): $(COMMON_OBJS)
    @echo building output ...
    $(CXX) -o $(BinDir)/$(OUTPUTBIN) $(COMMON_OBJS) $(LFLAGS)

甚至可以VPATH通过以下方式实现自动化生成:

VPATH := $(dir $(COMMON_SRC))

或者使用删除重复项的事实sort(尽管这并不重要):

VPATH := $(sort  $(dir $(COMMON_SRC)))

解决方案 6:

我认为最好指出的是,通常你可能想要避免使用 Make(递归或非递归),因为与今天的工具相比,它很难学习、维护和扩展。

这是一个非常棒的工具,但是在 2010 年以后直接使用应该被认为是过时的。

当然,除非你在特殊环境中工作,例如,有一个遗留项目等等。

使用 IDE、CMake,或者如果您很执着,也可以使用Autotools。

(由于投票反对而进行了编辑,感谢 Honza 指出)

解决方案 7:

我一直在寻找这样的东西,经过几次尝试和失败后,我创建了自己的 makefile,我知道这不是“惯用的方式”,但这是一个理解 make 的开始,而且这对我有用,也许你可以在你的项目中尝试。

PROJ_NAME=mono

CPP_FILES=$(shell find . -name "*.cpp")

S_OBJ=$(patsubst %.cpp, %.o, $(CPP_FILES))

CXXFLAGS=-c \ n         -g \ n        -Wall

all: $(PROJ_NAME)
    @echo Running application
    @echo
    @./$(PROJ_NAME)

$(PROJ_NAME): $(S_OBJ)
    @echo Linking objects...
    @g++ -o $@ $^

%.o: %.cpp %.h
    @echo Compiling and generating object $@ ...
    @g++ $< $(CXXFLAGS) -o $@

main.o: main.cpp
    @echo Compiling and generating object $@ ...
    @g++ $< $(CXXFLAGS)

clean:
    @echo Removing secondary things
    @rm -r -f objects $(S_OBJ) $(PROJ_NAME)
    @echo Done!

我知道这很简单,而且对于某些人来说我的标志是错误的,但正如我所说,这是我的第一个 Makefile,用于在多个目录中编译我的项目并将它们全部链接在一起以创建我的 bin。

我接受建议 :D

解决方案 8:

RC 的帖子超级有用。我从来没有想过使用 $(dir $@) 函数,但它确实满足了我的需求。

在 parentDir 中,有一堆包含源文件的目录:dirA、dirB、dirC。各种文件都依赖于其他目录中的目标文件,因此我希望能够在一个目录中创建一个文件,并通过调用与该依赖项关联的 makefile 来创建该依赖项。

本质上,我在 parentDir 中创建了一个 Makefile,它具有(以及许多其他内容)类似于 RC 的通用规则:

%.o : %.cpp
        @mkdir -p $(dir $@)
        @echo "============="
        @echo "Compiling $<"
        @$(CC) $(CFLAGS) -c $< -o $@

每个子目录都包含此上级 makefile,以便继承此通用规则。在每个子目录的 Makefile 中,我为每个文件编写了一个自定义规则,以便可以跟踪每个单个文件所依赖的所有内容。

每当我需要创建文件时,我都会使用(本质上)此规则以递归方式创建任何/所有依赖项。完美!

注意:有一个名为“makepp”的实用程序似乎可以更直观地完成这项任务,但为了可移植性并且不依赖于其他工具,我选择以这种方式进行。

希望这有帮助!

解决方案 9:

递归使用 Make

all:
    +$(MAKE) -C part1
    +$(MAKE) -C part2
    +$(MAKE) -C part3

这允许make拆分作业并使用多个核心

解决方案 10:

我建议使用autotools

//##将生成的目标文件(.o)放入与其源文件相同的目录中,以避免在使用非递归 make 时发生冲突。

AUTOMAKE_OPTIONS = subdir-objects

Makefile.am只是将其与其他相当简单的东西包括在内。

这是教程。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1553  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   27  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   22  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   19  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用