使用Make构建C / C ++项目的“标准库”

|| 有时,我需要我的项目使用简单的makefile,尽管它不推荐用于任何用途的过时的构建技术,但是由于make几乎在任何地方都可用,因此有时是有意义的。 但是我希望我的Makefile看起来像
Include \"../buildexec.mk\"

TARG = my_exec

CPPFILES = file1.cpp \\
           file2.cpp \\
并在buildexec.mk中包含所有通用(且可怕的)依赖项跟踪代码。 是否有这样的“制作库”? 在Go中,可以包含一个标准的Makefile,并且Makefile看起来像这样漂亮:
include $(GOROOT)/src/Make.inc

TARG=irc
GOFILES=irc.go irc_struct.go irc_callback.go

include $(GOROOT)/src/Make.pkg 
与C ++类似吗? 澄清:我知道tup,cmake和scons /我知道waf和bjam等/,但是我希望我的deps很小/这样编译完全没有问题。我专门要求获得支持,而不是寻求替代。
已邀请:
我建议用automake代替生成makefile。 Cmake还可以生成makefile,同时还可以为多个IDE生成项目文件。 问题是没有one2ѭ。最基本的语法始终是相同的,但是稍微复杂一点的东西(您需要这样的东西)甚至在GNU make和BSD make之间也不兼容(更不用说nmake了)。但是,Automake可以处理make的多个版本,并在可用时提供自动依赖项规则(仅某些编译器支持它们)。
您可能想看看CMake或Premake。 对于大型C / C ++项目,您往往会有其他要求,例如特定于平台的API或需要自定义的库。
这将满足您的要求(至少在GNUMake中如此)。 makelib.mk:
$(TARG): $(CPPFILES:.cc=.o)
    $(CC) $^ -o $@

%.o : %.cc
    $(CC) -MD -o $@ $<                                               
    @cp $*.d $*.P; \\                                                        
      sed -e \'s/#.*//\' -e \'s/^[^:]*: *//\' -e \'s/ *\\\\$$//\' \\            
          -e \'/^$$/ d\' -e \'s/$$/ :/\' < $*.d >> $*.P; \\                 
      rm -f $*.d                                                       

-include $(CPPFILES:.cc=.P)
生成文件:
CPPFILES = foo.cc bar.cc
TARG = someTarget
include makelib.mk      # Note lower-case \"i\"

CPPFILES = baz.cc quartz.cc quince.cc
TARG = anotherTarget
include makelib.mk

...
但要提一个建议:不要过多地诅咒您的工具。您可能会用它的精力来学习如何使用它们,或者改用自己喜欢的。
确实有一个googlecode项目正在执行我想要的工作: http://code.google.com/p/nonrec-make/
我一无所知。
make
确实有很多问题,但是它仍然是周围最可用的工具,一旦使其正常运行,您应该专注于开发。 在那之前,您将不得不编写makefile。但是,而不是寻找“ make库”,一个真正简单的解决方案(如果您实际上是用Make语言启动的)通常被认为太过明显而被忽略了,而是实现自己的解决方案。创建一个make脚本,其中包含一组与项目makefile进行通信的默认模式规则和变量,并将此脚本包含在每个项目的makefile中。这并不困难,可能会花费一些时间,但是通常会得到很好的回报,特别是如果您要管理许多小型项目。 我使用这样的设计。我有几个经过精心设计的GNU make脚本,它们提供了一种几乎琐碎的机制来创建相当复杂的构建系统:自动依赖项生成,不同语言的处理,语言解析器的生成,不同的构建配置(调试或发行),构建日志的生成,等等。而且脚本也不麻烦:当前版本仅包含约250行的makefile代码,不包括注释。 我将为您提供此类系统的较旧版本的样本,仅处理C源代码,其中包含一些功能。它应该处理二进制和库的编译(静态和动态)。它还应通过
DEPS
变量帮助您跟踪项目间的依赖关系。 称此
$(ROOT)/project.mk
# Remove the default suffix rules.
.SUFFIXES:

# Turn on the delete-on-error feature.
.DELETE_ON_ERROR:

# Set up additional command variables.
STRIP ?= strip

# Set up a global search path to locate prerequisites.
VPATH := $(VPATH) $(shell find -type d)

# Locate all source files from the default locations in the project tree.
SRC := $(SRC) $(shell find src -name \'*.c\')

# Set up the default dependency files.
DEP := $(DEP) $(addprefix dep/,$(addsuffix .d,$(basename $(notdir $(filter %.c,$(SRC))))))

# Set up the default object files.
OBJ := $(OBJ) $(addprefix obj/,$(addsuffix .o,$(basename $(notdir $(filter %.c,$(SRC))))))

# Set up a set of default flags for all commands used.
STRIPFLAGS ?= -p
CPPFLAGS ?= -DNDEBUG
CFLAGS ?= -Wall -Wextra -Werror -pedantic -O3 -march=native -fomit-frame-pointer -ffast-math
LDFLAGS ?= --as-needed -O1
ARFLAGS ?= -scr

# Set up the default include and library search paths.
override INCLUDES := \\
    $(addprefix $(ROOT)/,$(addsuffix /include,$(DEPS))) \\
    $(INCLUDES)
override LIBRARIES := \\
    $(addprefix $(ROOT)/,$(addsuffix /lib,$(DEPS))) \\
    $(LIBRARIES) lib

# The default rule to build every target in the project.
.PHONY: all
all: deps $(DEP) $(OBJ) $(BIN) $(LIB)

# Phony rule to recursively build the library dependencies.
.PHONY: deps
deps:
    @for dep in $(DEPS); do cd $(ROOT)/lib/$$dep && $(MAKE); done

# Secondary expansion is used to properly locate prerequisites.
.SECONDEXPANSION:

# Rule for dependency file generation.
%.d: $$(notdir $$*).c
    $(CC) -M $(CPPFLAGS) $(CFLAGS) -iquote include $(addprefix -I ,$(INCLUDES)) $< -MM -MG -MP -MT \'$@ $(filter %/$(notdir $*).o,$(OBJ))\' > $@

# Rule for compiling object files.
%.o: $$(notdir $$*).c
    $(CC) -c $(CPPFLAGS) $(CFLAGS) -iquote include $(addprefix -I ,$(INCLUDES)) $< -o $@

# Rule for linking binaries.
%: $$(notdir $$*).c
    $(CC) $(CPPFLAGS) $(CFLAGS) $(addprefix -Xlinker ,$(LDFLAGS)) -iquote include $(addprefix -I ,$(INCLUDES)) $(addprefix -L ,$(LIBRARIES)) $(filter-out $<,$^) -o $@ $(addprefix -l,$(LDLIBS))
    $(STRIP) $(STRIPFLAGS) $@

# Rule for linking shared libraries.
%.so: $$(notdir $$*).c
    $(CC) $(CPPFLAGS) $(CFLAGS) $(addprefix -Xlinker ,$(LDFLAGS)) -iquote include $(addprefix -I ,$(INCLUDES)) $(addprefix -L ,$(LIBRARIES)) $(filter-out $<,$^) -o $@ -fpic -shared -Wl,-h,$(notdir $@) $(addprefix -l,$(LDLIBS))
    $(STRIP) $(STRIPFLAGS) $@

# Rule for generating static libraries.
%.a:
    $(AR) $(ARFLAGS) $@ $?

# Include all dependency files and remake them if necessary.
ifneq ($(MAKECMDGOALS),clean)
    include $(DEP)
endif

# Phony rule to clean the entire build tree.
.PHONY: clean
clean:
    @for dep in $(DEPS); do cd $(ROOT)/lib/$$dep && $(MAKE) clean; done
    $(RM) $(DEP) $(OBJ) $(BIN) $(LIB) $(CLEAN)
“ 9”包含项目目录的路径(例如,存储库的工作副本),通常以环境变量的形式导出。您的项目中还将需要几个目录(
bin
dep
obj
src
)。 使用此系统的示例Makefile可以是:
DEPS := mylib

BIN := bin/test
LIB := lib/libtest.a

include $(ROOT)/project.mk

bin/test: $(OBJ)
lib/libtest.a: obj/test1.o obj/test2.o
也就是说,您只需编写有关项目的最低要求,然后让构建系统完成其余工作。您总是可以显式指定给定变量的值(例如,
SRC
CFLAGS
),但是如果不指定,则它将获得合理的默认值。 上面的代码是根据我的需求量身定制的,但是应该很容易适应您的需求,同时让事情像您提到的示例一样简单。

要回复问题请先登录注册