有时我需要我的项目使用普通的makefile,虽然它是一种不推荐用于任何用途的过时的构建技术,但是因为make几乎在任何地方都可用,它有时是有意义的。
但是我希望我的Makefile看起来像
Include "../buildexec.mk"
TARG = my_exec
CPPFILES = file1.cpp \
file2.cpp \
并且所有通用(和可怕)依赖关系跟踪代码都在buildexec.mk中。
是否有这样的“制作图书馆”?
在Go中,您可以包含一个标准的Makefile,并且您的Makefile看起来像this一样漂亮:
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这么小/以便编译完全没问题。我特别要求Make支持,而不是Make替代。
答案 0 :(得分:1)
我建议使用automake生成makefile。 Cmake还生成makefile,同时还能够为多个IDE生成项目文件。
问题是没有人make
。最基本的语法总是相同的,但是任何稍微复杂的东西(你需要这些包括)都不兼容,即使在 GNU make 和 BSD make 之间也是如此(不是试图提到 nmake )。但是,Automake可以处理几个版本的make,并提供自动依赖规则(只有一些编译器支持它们)。
答案 1 :(得分:0)
答案 2 :(得分:0)
这将满足您的要求(至少在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
...
但建议:不要诅咒你的工具。您可以使用它来学习如何使用它们或切换到您更喜欢的能量。
答案 3 :(得分:0)
有一个googlecode项目完全符合我的要求:
答案 4 :(得分:0)
我不知道。 make
确实存在很多问题,但它仍然是最常用的工具,一旦你让它正常运行,你应该专注于你的开发。
在那之前,你必须编写makefile。但是,不是寻找一个'make library',一个非常简单的解决方案(如果你实际上是在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)
ROOT
包含项目目录的路径(例如,存储库的工作副本),通常作为环境变量导出。您还需要在项目中添加几个目录(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
),但如果不这样做,则会得到合理的默认值。
以上内容是根据我的需求量身定制的,但应该很容易适应你的需求,同时保持事情就像你提到的例子一样简单。