果然还是更喜欢vscode+ssh+Makefile的开发方式,
但是之前的Makefile不够成熟,进行了一些优化,并添加了注释
# 在main.cpp中添加代码 QResource::registerResource("resource.rcc");
# linux下使用/bin/dash,echo -e 会将 -e 输出,windows下可删除此行
SHELL = /bin/bash
# 根据CPU的核心数提升编译速度
MAKEFLAGS := -j $(shell nproc)
# 设置中间文件路径和目标文件名称
BUILD_DIR := ./build/
TARGET := ./execute
# 设置编译工具链路径和编译器路径
TOOLCHAIN_DIR := /usr/
COMPILER_PATH := $(TOOLCHAIN_DIR)bin/
# 设置编译器
CC := $(COMPILER_PATH)gcc
CX := $(COMPILER_PATH)g++
LD := $(COMPILER_PATH)g++
SZ := $(COMPILER_PATH)size
AR := $(COMPILER_PATH)ar
OBJCOPY := $(COMPILER_PATH)objcopy
# Qt相关工具
QT_TOOL_PATH := /root/workspace/code/third_party/Qt5.12.12/5.12.12/gcc_64/
RCC := $(QT_TOOL_PATH)bin/rcc
MOC := $(QT_TOOL_PATH)bin/moc
DUMMY := $(QT_TOOL_PATH)mkspecs/features/data/dummy.cpp
# 设置编译器标志
CC_MARK := .xc
CX_MARK := .xc++
DEFINES := -DQT_QML_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -D_REENTRANT
CC_FLAG := -xc -g $(DEFINES)
CX_FLAG := -xc++ -g -fPIC $(DEFINES)
LD_FLAG := -Wl,-rpath,$(QT_TOOL_PATH)lib
# 设置自定义源文件和路径列表
HEAD_PATH := -I$(QT_TOOL_PATH)include \
-I$(QT_TOOL_PATH)include/QtQuick \
-I$(QT_TOOL_PATH)include/QtGui \
-I$(QT_TOOL_PATH)include/QtQml \
-I$(QT_TOOL_PATH)include/QtNetwork \
-I$(QT_TOOL_PATH)include/QtCore \
-I$(QT_TOOL_PATH)mkspecs/linux-g++
LIB_PATH := -L$(TOOLCHAIN_DIR)lib/ \
-L$(QT_TOOL_PATH)lib/
LIB_FLAG := -lpthread -lGL -lQt5Quick -lQt5Gui -lQt5Qml -lQt5Network -lQt5Core
SRC_LIB :=
SRC_CC :=
SRC_CX :=
# 设置自动搜索源文件格式
HEAD_TYPE := .h .hpp .hh
LIB_TYPE := .a .so
CC_TYPE := .c
CX_TYPE := .cpp
EXCLUDE_FILES :=
HEAD_TYPE_SIFT := $(patsubst .%,%,$(subst $(empty) .,\|,$(HEAD_TYPE)))
LIB_TYPE_SIFT := $(patsubst .%,%,$(subst $(empty) .,\|,$(LIB_TYPE)))
CC_TYPE_SIFT := $(patsubst .%,%,$(subst $(empty) .,\|,$(CC_TYPE)))
CX_TYPE_SIFT := $(patsubst .%,%,$(subst $(empty) .,\|,$(CX_TYPE)))
LOCAL_HEAD := $(shell find . -type f -regex ".*\.\($(HEAD_TYPE_SIFT)\)" -printf "%P ")
LOCAL_LIB := $(shell find . -type f -regex ".*\.\($(LIB_TYPE_SIFT)\)" -printf "%P ")
LOCAL_CC := $(shell find . -type f -regex ".*\.\($(CC_TYPE_SIFT)\)" -printf "%P ")
LOCAL_CX := $(shell find . -type f -regex ".*\.\($(CX_TYPE_SIFT)\)" -printf "%P ")
# 搜索qml.qrc相关文件
QRC_TYPE := .qml .js .ttf .png
QRC_TYPE_SHIFT := $(patsubst .%,%,$(subst $(empty) .,\|,$(QRC_TYPE)))
QRC_FILES := $(shell find . -type f -regex ".*\.\($(QRC_TYPE_SHIFT)\)" -printf "%P ")
# 设置需要转换为moc文件的h文件
H_FILES := $(filter-out moc_predefs.h,$(shell find . -name "*.h" -type f -printf "%P "))
MOC_FILES := $(H_FILES:%.h=moc_%.cpp)
LOCAL_CX += $(MOC_FILES)
# 增加前缀并去重
HEAD_PATH += $(addprefix -I,$(sort $(dir $(filter-out $(EXCLUDE_FILES),$(LOCAL_HEAD)))))
SRC_LIB += $(sort $(filter-out $(EXCLUDE_FILES),$(LOCAL_LIB)))
SRC_CC += $(sort $(filter-out $(EXCLUDE_FILES),$(LOCAL_CC)))
SRC_CX += $(sort $(filter-out $(EXCLUDE_FILES),$(LOCAL_CX)))
# 生成中间文件列表
OBJ_CC := $(addprefix $(BUILD_DIR),$(notdir $(SRC_CC:%=%$(CC_MARK).o)))
OBJ_CX := $(addprefix $(BUILD_DIR),$(notdir $(SRC_CX:%=%$(CX_MARK).o)))
# 设置源文件查找路径
vpath % $(sort $(dir $(SRC_CC))) $(sort $(dir $(SRC_CX)))
# 定义all依赖
all : $(TARGET) resource.rcc
@echo " CHECK $<"
@$(SZ) $<
# 包含依赖文件
-include $(wildcard $(BUILD_DIR)*.d)
# 定义编译和链接命令和规则
$(TARGET) : $(OBJ_CC) $(OBJ_CX) $(SRC_LIB)
@echo " LN $^ -> $@"
@$(LD) $(LD_FLAG) -o $@ $^ $(LIB_PATH) $(LIB_FLAG) $(SRC_LIB)
# @$(AR) x $(SRC_LIB) --output=$(BUILD_DIR)
# @$(AR) $(AR_FLAG) rcs $@ $^
# 生成resource.rcc
resource.rcc: qml.qrc
@echo " RCC $@"
@$(RCC) -binary -name myresources $< -o $@
# 生成qml.qrc
qml.qrc : $(QRC_FILES)
@echo " GEN $@"
@rm -f $@
@echo "<RCC>" > $@
@echo " <qresource prefix=\"/\">" >> $@
@for file in $^; do \
echo " <file>$$file</file>" >>$@; \
done
@echo " </qresource>" >>$@
@echo "</RCC>" >> $@
# 生成moc_%.cpp
moc_%.cpp : moc_predefs.h %.h
@echo " MOC $@"
@$(MOC) $(DEFINES) $(HEAD_PATH) --include $^ -o $@
moc_predefs.h : $(DUMMY)
@echo " DM $@"
@$(CX) $(CX_FLAG) $(HEAD_PATH) -dM -E -c $< -o $@
# 定义隐式规则
$(BUILD_DIR)%$(CC_MARK).o : % | $(BUILD_DIR)
@echo " CC $<"
@$(CC) $(CC_FLAG) $(HEAD_PATH) -MMD -MP -MF"$(@:%.o=%.d)" -c $< -o $@
$(BUILD_DIR)%$(CX_MARK).o : % | $(BUILD_DIR)
@echo " CX $<"
@$(CX) $(CX_FLAG) $(HEAD_PATH) -MMD -MP -MF"$(@:%.o=%.d)" -c $< -o $@
# 生成build目录
$(BUILD_DIR) :
@echo " MK $@"
@mkdir $@
# 定义生成compile_commands.json文件的规则
json: $(SRC_CC) $(SRC_CX)
@echo "Generating compile_commands.json"
@rm -f compile_commands.json
@echo "[" > compile_commands.json
@for file in $(SRC_CC); do \
compile_cmd="$(CC) $(CC_FLAG) $(HEAD_PATH) -c $${file} -o $(addprefix $(BUILD_DIR),$$(basename $${file}$(CC_MARK).o))" \
command_json=" { \"arguments\": [ \"$$compile_cmd\" ], \"directory\": \"${PWD}\", \"file\": \"$$file\" },"; \
echo -e "$$command_json" >> compile_commands.json ; \
done
@for file in $(SRC_CX); do \
compile_cmd="$(CX) $(CX_FLAG) $(HEAD_PATH) -c $${file} -o $(addprefix $(BUILD_DIR),$$(basename $${file}$(CX_MARK).o))" \
command_json=" { \"arguments\": [ \"$$compile_cmd\" ], \"directory\": \"${PWD}\", \"file\": \"$$file\" },"; \
echo -e "$$command_json" >> compile_commands.json ; \
done
@sed -i '$$ s/,$$/\n]/' compile_commands.json
# 定义清理规则
clean:
rm -fR $(BUILD_DIR) $(TARGET) $(MOC_FILES) qml.qrc moc_predefs.h resource.rcc
# 定义伪目标
.PHONY: all clean json debug
# 定义调试输出
debug:
@echo "LOCAL_CX: $(LOCAL_CX)"
@echo "SRC_CX: $(SRC_CX)"