我有一个目录结构如下的项目:
$projectroot
|
+---------------+----------------+
| | |
part1/ part2/ part3/
| | |
+------+-----+ +---+----+ +---+-----+
| | | | | | |
data/ src/ inc/ src/ inc/ src/ inc/
Run Code Online (Sandbox Code Playgroud)
我应该如何编写部分/ src(或其他任何地方)的makefile,它可以补充/链接部分?/ src中的c/c ++源文件?
我可以做一些像-I $ projectroot/part1/src -I $ projectroot/part1/inc -I $ projectroot/part2/src ...
如果这样可行,是否有更简单的方法.我看过每个相应部分都有makefile的项目?文件夹.[在这篇文章中我使用了像bash语法中的问号]
小智 104
传统的方法是有一个Makefile在每个子目录(中part1,part2等),使您能够独立构建它们.此外,Makefile在项目的根目录中有一个构建一切的东西."root" Makefile看起来如下所示:
all:
+$(MAKE) -C part1
+$(MAKE) -C part2
+$(MAKE) -C part3
Run Code Online (Sandbox Code Playgroud)
由于make目标中的每一行都在自己的shell中运行,因此无需担心遍历目录树或其他目录.
我建议看看GNU make手册第5.7节 ; 这非常有帮助.
dav*_*420 84
如果一个子目录中的代码依赖于另一个子目录中的代码,那么最好使用顶级的单个makefile.
请参阅Recursive Make Considered Harmful的完整原理,但基本上你希望make获得它所需的全部信息来决定是否需要重建文件,如果你只告诉它大约三分之一,那就不会有.你的项目.
上面的链接似乎无法访问.这里可以访问相同的文档:
Cod*_*oat 33
VPATH选项可能派上用场,它告诉make要查找源代码的目录.但是,对于每个包含路径,您仍然需要-I选项.一个例子:
CXXFLAGS=-Ipart1/inc -Ipart2/inc -Ipart3/inc
VPATH=part1/src:part2/src:part3/src
OutputExecutable: part1api.o part2api.o part3api.o
Run Code Online (Sandbox Code Playgroud)
这将自动在任何VPATH指定目录中找到匹配的partXapi.cpp文件并进行编译.但是,当您的src目录分解为子目录时,这会更有用.正如你所描述的那样,正如其他人所说,你可能最好使用每个部分的makefile,特别是如果每个部分都可以独立存在.
RC.*_*RC. 23
您可以向根Makefile添加规则,以便在其他目录中编译必要的cpp文件.下面的Makefile示例应该是一个很好的开始,让您到达您想要的位置.
CC=g++
TARGET=cppTest
OTHERDIR=../../someotherpath/in/project/src
SOURCE = cppTest.cpp
SOURCE = $(OTHERDIR)/file.cpp
## End sources definition
INCLUDE = -I./ $(AN_INCLUDE_DIR)
INCLUDE = -I.$(OTHERDIR)/../inc
## end more includes
VPATH=$(OTHERDIR)
OBJ=$(join $(addsuffix ../obj/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.o)))
## Fix dependency destination to be ../.dep relative to the src dir
DEPENDS=$(join $(addsuffix ../.dep/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.d)))
## Default rule executed
all: $(TARGET)
@true
## Clean Rule
clean:
@-rm -f $(TARGET) $(OBJ) $(DEPENDS)
## Rule for making the actual target
$(TARGET): $(OBJ)
@echo "============="
@echo "Linking the target $@"
@echo "============="
@$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
@echo -- Link finished --
## Generic compilation rule
%.o : %.cpp
@mkdir -p $(dir $@)
@echo "============="
@echo "Compiling $<"
@$(CC) $(CFLAGS) -c $< -o $@
## Rules for object files from cpp files
## Object file for each file is put in obj directory
## one level up from the actual source directory.
../obj/%.o : %.cpp
@mkdir -p $(dir $@)
@echo "============="
@echo "Compiling $<"
@$(CC) $(CFLAGS) -c $< -o $@
# Rule for "other directory" You will need one per "other" dir
$(OTHERDIR)/../obj/%.o : %.cpp
@mkdir -p $(dir $@)
@echo "============="
@echo "Compiling $<"
@$(CC) $(CFLAGS) -c $< -o $@
## Make dependancy rules
../.dep/%.d: %.cpp
@mkdir -p $(dir $@)
@echo "============="
@echo Building dependencies file for $*.o
@$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^../obj/$*.o^" > $@'
## Dependency rule for "other" directory
$(OTHERDIR)/../.dep/%.d: %.cpp
@mkdir -p $(dir $@)
@echo "============="
@echo Building dependencies file for $*.o
@$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^$(OTHERDIR)/../obj/$*.o^" > $@'
## Include the dependency files
-include $(DEPENDS)
das*_*esy 19
如果源代码分布在许多文件夹中,并且按照之前的建议建立单独的Makefile是有意义的,递归make是一种很好的方法,但对于较小的项目,我发现使用它们的相对路径列出Makefile中的所有源文件更容易像这样的Makefile:
# common sources
COMMON_SRC := ./main.cpp \
../src1/somefile.cpp \
../src1/somefile2.cpp \
../src2/somefile3.cpp \
Run Code Online (Sandbox Code Playgroud)
然后我可以这样设置VPATH:
VPATH := ../src1:../src2
Run Code Online (Sandbox Code Playgroud)
然后我构建对象:
COMMON_OBJS := $(patsubst %.cpp, $(ObjDir)/%$(ARCH)$(DEBUG).o, $(notdir $(COMMON_SRC)))
Run Code Online (Sandbox Code Playgroud)
现在规则很简单:
# the "common" object files
$(ObjDir)/%$(ARCH)$(DEBUG).o : %.cpp Makefile
@echo creating $@ ...
$(CXX) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
Run Code Online (Sandbox Code Playgroud)
构建输出更容易:
# This will make the cbsdk shared library
$(BinDir)/$(OUTPUTBIN): $(COMMON_OBJS)
@echo building output ...
$(CXX) -o $(BinDir)/$(OUTPUTBIN) $(COMMON_OBJS) $(LFLAGS)
Run Code Online (Sandbox Code Playgroud)
甚至可以VPATH通过以下方式使生成自动化:
VPATH := $(dir $(COMMON_SRC))
Run Code Online (Sandbox Code Playgroud)
或者使用sort删除重复的事实(尽管它应该无关紧要):
VPATH := $(sort $(dir $(COMMON_SRC)))
Run Code Online (Sandbox Code Playgroud)
我认为最好指出使用Make(递归或非递归)通常是你可能想要避免的,因为与今天的工具相比,它很难学习,维护和扩展.
这是一个很棒的工具,但直接使用应该在2010年以后被认为是过时的.
当然,除非您在特殊环境中工作,例如遗留项目等.
使用IDE,CMake,或者,如果你是硬盘,使用Autotools.
(由于downvotes编辑,ty Honza指出)
我一直在寻找这样的东西,经过一番尝试和失败后,我创建了自己的 makefile,我知道这不是“惯用的方式”,但这是理解 make 的开始,这对我有用,也许你可以在你的项目中尝试。
PROJ_NAME=mono
CPP_FILES=$(shell find . -name "*.cpp")
S_OBJ=$(patsubst %.cpp, %.o, $(CPP_FILES))
CXXFLAGS=-c \
-g \
-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!
Run Code Online (Sandbox Code Playgroud)
我知道这很简单,对于某些人来说,我的标志是错误的,但正如我所说,这是我在多个目录中编译我的项目的第一个 Makefile,并将所有这些链接在一起以创建我的 bin。
我接受建议 :D
| 归档时间: |
|
| 查看次数: |
211117 次 |
| 最近记录: |