我知道有很多关于将.cpp和.c文件混合到一个makefile中的问题,但我还没有看到混合替换引用的问题。我遇到了问题。
我的makefile结构基于this answer:
LIB=mylib.so
CPPSRCS += hello.cpp
CSRCS += goodbye.c
OBJS = $(CSRCS:.c=.o) $(CPPSRCS:.cpp=.o)
# Separate rules for .cpp and .c files, link together to form library.
# All pretty standard stuff and I am sure it will work if we goodbye.o and
# hello.o are present.
这不起作用,我得到了旧的无规则来制造目标错误。我究竟做错了什么?如何将两种类型的文件替换引用到一个变量中?
答案 0 :(得分:1)
为了让makefile
同时适用于C和C ++,每种语言都需要单独的规则 - 尽管有些规则是相同的。
另一个问题是链接器。仅C项目将使用一个链接器而不是另一个链接器。
我在这里转储我的makefile(来自this project)。
从这个例子中可以看出,有两种不同的构建规则,一种用于使用C文件创建的对象,另一种用于使用C ++创建的对象。当第一个失败时,尝试第二个,因此可以共享对象列表。
此外,您可能会注意到C ++规则具有此行$(eval CCL = $(CPP))
,它将链接器变量(CCL
)设置为使用C ++的项目中的C ++链接器。这样,当调用构建规则时,它使用正确的链接器。
另一个需要注意的是此代码处理列表和扩展替换的方式。请注意foreach
,addsuffix
和basename
函数的使用......这比您建议的$(CSRCS:.c=.o)
要复杂得多。
我建议你添加一个显示make变量的规则,这样你就可以调试任何误入歧途的规则(参见演示),这是学习和解决问题的好方法。
关于makefile
我在这里粘贴的几句警告......
它适用于C和C ++(混合)项目,它几乎是“即插即用”,但您必须更改文件夹名称和目标文件以适合您的文件夹结构。
另外,请注意它将删除整个项目 如果 您将临时文件夹定义为项目文件夹(它定义为tmp
有一个原因,因为它使清理真的很容易)。
将来我可能会更新它,以便自动添加任何src
子文件夹,但目前我需要额外的控制来排除某些文件夹。
这个makefile主要是懒惰的工作......我讨厌一直更新makefile,所以我有一个低成本的makefile,主要计算它自己的一切...除非我改变项目的文件夹结构或需要不同库。
NAME=demo
OUT_ROOT=./tmp
TMP_ROOT=./tmp
SRC_ROOT=.
SRC_EXTRA_FOLDERS=src src/http
LIBS=-pthread -lssl -lcrypto
INCLUDE=/usr/local/include
CC=@gcc
CPP=@g++
DB=@lldb
OPTIMIZATION=O3
#auto computed values
BIN = $(OUT_ROOT)/$(NAME)
SRCDIR = $(SRC_ROOT) $(foreach dir, $(SRC_EXTRA_FOLDERS), $(addsuffix /,$(basename $(SRC_ROOT)))$(dir))
SRC = $(foreach dir, $(SRCDIR), $(wildcard $(addsuffix /, $(basename $(dir)))*.c*))
BUILDTREE =$(foreach dir, $(SRCDIR), $(addsuffix /, $(basename $(TMP_ROOT)))$(basename $(dir)))
OBJS = $(foreach source, $(SRC), $(addprefix $(TMP_ROOT)/, $(addsuffix .o, $(basename $(source)))))
CCL = $(CC)
# the C flags
CFLAGS=-Wall -g -$(OPTIMIZATION) -std=c11 $(foreach dir,$(INCLUDE),$(addprefix -I, $(dir))) $(foreach dir,$(SRCDIR),$(addprefix -I, $(dir)))
CPPFLAGS= -Wall -$(OPTIMIZATION) -std=c++11 $(foreach dir,$(INCLUDE),$(addprefix -I, $(dir))) $(foreach dir,$(SRCDIR),$(addprefix -I, $(dir)))
$(NAME): build
build: $(OBJS)
$(CCL) -o $(BIN) $^ -$(OPTIMIZATION) $(LIBS)
$(TMP_ROOT)/%.o: %.c
$(CC) -o $@ -c $^ $(CFLAGS)
$(TMP_ROOT)/%.o: %.cpp
$(CPP) -o $@ -c $^ $(CPPFLAGS)
$(eval CCL = $(CPP))
clean:
-@rm $(BIN)
-@rm -R $(TMP_ROOT)
-@mkdir -p $(BUILDTREE)
execute:
@$(BIN)
run: | clean build execute
db: | clean build
$(DB) $(BIN)
vars:
@echo "BIN: $(BIN)"
@echo ""
@echo "SRCDIR: $(SRCDIR)"
@echo ""
@echo "SRC: $(SRC)"
@echo ""
@echo "BUILDTREE: $(BUILDTREE)"
@echo ""
@echo "OBJS: $(OBJS)"
@echo ""
@echo "CFLAGS: $(CFLAGS)"
@echo ""
@echo "CPPFLAGS: $(CPPFLAGS)"
与Toby Speight的建议一样,我添加了管道标志(|
)来标记所有并发人员的有序先决条件。