Linux C/C++工程中可生成 ELF、动/静态库文件的通用 Makefile(二)
今天对之前写的 Linux C/C++工程中可生成ELF、动/静态库文件的通用Makefile - TypeCodes 文章里面的 Makefile 进行了优化,增加了在当前目录生成单个可执行文件的功能。
1 功能说明
之前已有的功能不再赘述,这次主要是在包含多个 cpp 文件的项目中生成一个可执行文件(之前只能一个 cpp 或者 c 文件生成对应的一个可执行文件)。
如上图所示,我的一个 myRedisSentinel 目录中包含了多个 cpp 文件,然后只要在 SINGLE_BIN
里面配置想要输出的可执行文件名称,最后执行 make -j4
命令即可生成。
2 附录:Makefile 文件源码
已将下面的 Makefile 源文件托管到 github仓库中:
1、GitHub: https://github.com/vfhky/General_Makefile ;
##################################################################
#
# FILENAME : Makefile
# DESCRIPT : A general makefile to generate an ELF or a
# dynamic or a static library for C/C++ project.
# AUTHOR : vfhky 2015.08.07
# URI : https://typecodes.com/cseries/cppgeneralmakefile.html
#
##################################################################
.PHONY: all clean help
all:
# Some important on-off settings. You can not be too careful about them.
DEBUG := y
# Flag of generate a dynamic lib or a static lib: y means yes. If the target is a excutable file, it should be blank!
GEN_LIBS := y
# Flag of generate a dynamic lib: y means yes. It should be blank unless you want to generate a dynamic lib!
GEN_DYN_LIB := y
# generate a single target bin file.Please let it be blank unless the target is a excutable file.
SINGLE_BIN :=
# generate mutil target bin files.Please let it be blank unless the target is a excutable file.
MUTIL_BIN :=
# Name of the static lib. It should be blank unless the target is a static lib, then the GEN_LIBS is y and GEN_DYN_LIB is blank.
# STATIC_LIBS := libsrcpbl.a
# Name of the dynamic lib. It should be blank unless the target is a dynamic lib, then the GEN_LIBS is y and GEN_DYN_LIB is y.
DYNAMIC_LIBS := libsrcpbl.so
# Environment settings. The value of PROJECT_DIR shoule be set in the *nix system as the the absolute dir path of your project.
# PROJECT_DIR := /home/test_usr
#CURDIR := $(PROJECT_DIR)/src/pbl
CURDIR := $(shell pwd)
PRG_BIN_DIR := $(PROJECT_DIR)/bin
PRG_LIB_DIR := $(PROJECT_DIR)/lib
PRG_INC_DIR := $(PROJECT_DIR)/include
# Cross compile tools defined. You needn't modify these vars below generally.
AS := as
LD := ld
CC := gcc
CXX := g++
CPP := $(CC) -E
AR := ar rcs
NM := nm
STRIP := strip
RANLIB := ranlib
STD_OPT := -D_GNU_SOURCE
CC += -std=c99 $(STD_OPT)
CXX += $(STD_OPT)
# *nix system tools defined. You needn't modify these vars below generally.
BLACK = "\e[33;0m"
RED = "\e[31;1m"
GREEN = "\e[32;1m"
YELLOW = "\e[33;3m"
BLUE = "\e[34;1m"
PURPLE = "\e[35;1m"
CYAN = "\e[36;1m"
WHITE = "\e[37;1m"
CP := cp
SED := sed
FIND := find
MKDIR := mkdir -p
XARGS := xargs
MV := mv
RM := rm -rf
# Get .c, .cpp source files by searching from current directory.
CUR_SRC_DIR = $(shell ls -AxR $(CURDIR)|grep ":"|tr -d ':')
CUR_SRC := $(foreach subdir,$(CUR_SRC_DIR),$(wildcard $(subdir)/*.c $(subdir)/*.cpp))
#CUR_SRC := $(shell find . -name "*.c" -o -name "*.cpp"|sed -e 's,./,,')
CUR_C := $(filter %.c, $(CUR_SRC))
CUR_CPP := $(filter %.cpp, $(CUR_SRC))
# Get the include files, object files, dependent files by searching from PRG_INC_DIR.
CUR_INC_DIR = $(shell ls -AxR $(PRG_INC_DIR)|grep ":"|tr -d ':')
CUR_INC := $(foreach subdir,$(CUR_INC_DIR),$(subdir)/*.h)
SRC_H := $(filter %.h, $(CUR_INC))
#CUR_OBJ := $(addprefix $(PRG_BIN_DIR)/,$(strip $(CUR_CPP:.cpp=.o) $(CUR_C:.c=.o)))
#CUR_OBJ := $(addprefix $(PRG_BIN_DIR)/,$(notdir $(CUR_CPP:.cpp=.o) $(CUR_C:.c=.o)))
CUR_OBJ := $(strip $(CUR_CPP:.cpp=.o) $(CUR_C:.c=.o))
#CUR_DEP := $(addprefix $(PRG_BIN_DIR)/,$(notdir $(CUR_CPP:.cpp=.d) $(CUR_C:.c=.d)))
CUR_DEP := $(strip $(CUR_CPP:.cpp=.d) $(CUR_C:.c=.d))
# Create directory in the header files, bin and library directory.
$(foreach dirname,$(sort $(PRG_INC_DIR) $(PRG_BIN_DIR) $(PRG_LIB_DIR)),\
$(shell $(MKDIR) $(dirname)))
# Complie and link variables. LD_LIBS means the dynamic or static library needed for the object file.
CFLAGS := $(if $(DEBUG),-g -Wall, -O2 -Wall)
CFLAGS += $(if $(GEN_DYN_LIB), $(addprefix -fPIC -I ,$(sort $(dir $(SRC_H)))), $(addprefix -I ,$(sort $(dir $(SRC_H)))))
CXXFLAGS = $(CFLAGS)
LDFLAGS :=
LD_LIB_DIR := #-L $(PRG_LIB_DIR)
LD_LIBS := #-lsrcpbl -lmysqlclient
XLD_FLG := -Xlinker "-(" $(LDFLAGS) -Xlinker "-)"
# Add vpath.
vpath %.h $(sort $(dir $(SRC_H)))
vpath %.c $(sort $(dir $(CUR_C)))
vpath %.cpp $(sort $(dir $(CUR_CPP)))
# Generate depend files.
ifneq "$(MAKECMDGOALS)" "clean"
sinclude $(CUR_DEP)
endif
# Gen_depend(depend-file,source-file,object-file,cc). This command-package is used to generate a depend file with a postfix of .d.
define gen_depend
@set -e; \
$(RM) $1; \
$4 $(CFLAGS) -MM $2 | \
$(SED) 's,\($(notdir $3)\): ,$3: ,' > $1.tmp; \
$(SED) -e 's/#.*//' \
-e 's/^[^:]*: *//' \
-e 's/ *\\$$//' \
-e '/^$$/ d' \
-e 's/$$/ :/' < $1.tmp >> $1.tmp; \
$(MV) $1.tmp $1;
endef
# Rules to generate objects file(.o) from .c or .cpp files.
$(CURDIR)/%.o: $(CURDIR)/%.c
@$(call gen_depend,$(patsubst %.o,%.d,$@),$<,$@,$(CC))
$(CC) $(CFLAGS) -o $@ -c $<
$(CURDIR)/%.o: $(CURDIR)/%.cpp
@$(call gen_depend,$(patsubst %.o,%.d,$@),$<,$@,$(CXX))
$(CXX) $(CXXFLAGS) -o $@ -c $<
# Gen_excbin(target,CUR_OBJ,cc). This command-package is used to generate a excutable file.
define gen_single_excbin
ULT_SINGLE_BIN += $(PRG_BIN_DIR)/$1
$(PRG_BIN_DIR)/$1: $2
$3 $(LDFLAGS) $$^ $(LD_LIB_DIR) $(LD_LIBS) $(XLD_FLG) -o $$@
@echo -e $(YELLOW)"========================Success========================"$(BLACK)
endef
# Gen_excbin(target,CUR_OBJ,cc). This command-package is used to generate a excutable file.
define gen_mutil_bin
ULT_MUTIL_BIN += $(PRG_BIN_DIR)/$1
$(PRG_BIN_DIR)/$1: $2
$3 $(LDFLAGS) $$^ $(LD_LIB_DIR) $(LD_LIBS) $(XLD_FLG) -o $$@
@echo -e $(YELLOW)"========================Success========================"$(BLACK)
endef
# Gen_libs(libs,CUR_OBJ,cc). This command-package is used to generate a dynamic lib or a static lib.
define gen_libs
ULT_LIBS += $(PRG_LIB_DIR)/$1
$(PRG_LIB_DIR)/$1: $2
$3 $(if $(GEN_DYN_LIB),-shared $$^ $(CXXFLAGS) $(LD_LIB_DIR) $(LD_LIBS) $(XLD_FLG) -o $$@,$$@ $$^)
@echo -e $(YELLOW)"========================Success========================"$(BLACK)
endef
# Call gen_single_excbin to generate an excutale file.
$(foreach bin,$(SINGLE_BIN),$(eval $(call gen_single_excbin,$(bin),$(CUR_OBJ),$(CXX))))
# Call gen_mutil_bin to generate mutil excutale files.
$(foreach bin,$(MUTIL_BIN),$(eval $(call gen_mutil_bin,$(bin),$(CURDIR)/$(bin).o,$(CXX))))
# Call gen_libs to generate a dynamic lib.
$(foreach lib,$(DYNAMIC_LIBS),$(eval $(call gen_libs,$(lib),$(CUR_OBJ),$(CXX))))
# Call gen_libs to generate a static lib.
$(foreach lib,$(STATIC_LIBS),$(eval $(call gen_libs,$(lib),$(CUR_OBJ),$(AR))))
all: $(ULT_SINGLE_BIN) $(ULT_MUTIL_BIN) $(ULT_LIBS)
clean:
-$(FIND) $(CURDIR) -name "*.o" -o -name "*.d" | $(XARGS) $(RM)
-$(RM) $(ULT_SINGLE_BIN) $(ULT_MUTIL_BIN) $(ULT_LIBS)
help:
@echo CC=[$(CC)]
@echo CXX=[$(CXX)]
@echo CFLAGS=[$(CFLAGS)]
@echo CXXFLAGS=[$(CXXFLAGS)]
@echo PROJECT_DIR=[$(PROJECT_DIR)]
@echo CURDIR=[$(CURDIR)]
@echo PRG_BIN_DIR=[$(PRG_BIN_DIR)]
@echo PRG_LIB_DIR=[$(PRG_LIB_DIR)]
@echo PRG_INC_DIR=[$(PRG_INC_DIR)]
@echo CUR_SRC_DIR=[$(CUR_SRC_DIR)]
@echo CUR_SRC=[$(CUR_SRC)]
@echo CUR_C=[$(CUR_C)]
@echo CUR_CPP=[$(CUR_CPP)]
@echo CUR_OBJ=[$(CUR_OBJ)]
@echo CUR_DEP=[$(CUR_DEP)]
@echo STATIC_LIBS=[$(STATIC_LIBS)]
@echo DYNAMIC_LIBS=[$(DYNAMIC_LIBS)]
打赏支持
Comments »