首页 > 解决方案 > 如何正确设置项目的 make 文件?

问题描述

Vulkan SDK 托管一个仅包含C++ 标头的 C 包装库。问题是,它确实是一个沉重的头文件,所以它浪费了大量的编译时间。

所以我考虑为我的 Vulkan 项目使用 make 文件,这是我以前从未做过的。我决定以编程方式生成所有依赖项。可能我也搞砸了这部分,使其难以理解。

它确实有效,可能有一种更简单的方法来做同样的事情。这是我无法真正解决的部分:

  1. 我为我的项目生成了所有.o(对象)文件以及.gch(预编译头文件)
  2. 然后我对 vulkan.hpp 和 glfw3.h 做了同样的事情。(请记住,这是我大部分编译时间的所在)。

...这是我对此过程有几个问题的地方:

我正在使用 MSYS2 MINGW_64 版本,如果它有所作为的话。如果有人能给我关于制作文件的一两个提示,我会很高兴,特别是如果我对编译过程有什么完全误解的话。

# Methods

define uniq =
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
  ${seen}
endef

# Compilation flags
_COMPILER := g++ -std=c++17
_FLAGS_WARNING := -Wall -Wextra -Wshadow
_FLAGS_COMPILE := -g -O0
_FLAGS_VULKAN := -lglfw3 -lvulkan

# Custom Flags
_FLAGS_DEBUG := -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0

# Output
_OUTPUT_NAME := test

# Directories
_TMP_DIR := _tmp
_O_DIR := ${_TMP_DIR}\.o
_GCH_DIR := ${_TMP_DIR}\.gch

_SOURCE_DIR := src
_BUILD_DIR := build
_DEBUG_DIR := ${_BUILD_DIR}\debug
_RELEASE_DIR := ${_BUILD_DIR}\release

# Files
_VULKAN_HPP := C:/VulkanSDK/1.2.148.1/Include/vulkan/vulkan.hpp
_GLFW_HPP := C:/msys64/mingw64/include/GLFW/glfw3.h

# Grouping Files
# .cpp & .o
_CPP_LIST := ${wildcard ${_SOURCE_DIR}/*.cpp ${_SOURCE_DIR}/*/*.cpp}
_CPP_LIST_NAME := ${notdir ${_CPP_LIST}}
_O_LIST := ${addprefix ${_O_DIR}/, ${patsubst %.cpp, %.o, ${_CPP_LIST_NAME}}}

# .hpp & .gch
_HPP_LIST := ${wildcard ${_SOURCE_DIR}/*.hpp ${_SOURCE_DIR}/*/*.hpp} ${_VULKAN_HPP}
_HPP_LIST_NAME := ${notdir ${_HPP_LIST}}
_GCH_LIST := ${addprefix ${_GCH_DIR}/, ${patsubst %.hpp, %.gch, ${_HPP_LIST_NAME}}}

# .h & .gch
_H_LIST := ${_GLFW_HPP}
_H_LIST_NAME := ${notdir ${_H_LIST}}
_C_GCH_LIST := ${addprefix ${_GCH_DIR}/, ${patsubst %.h, %.gch, ${_H_LIST_NAME}}}

_COMPILATION_BUNDLE_CPP = ${_FLAGS_WARNING} ${_FLAGS_COMPILE} ${_FLAGS_VULKAN} ${_FLAGS_DEBUG} -I ${_GCH_DIR} 
_COMPILATION_BUNDLE_HPP = ${_FLAGS_COMPILE} -x c++-header ${_FLAGS_DEBUG} -I ${_GCH_DIR}

${_DEBUG_DIR}/${_OUTPUT_NAME}: ${_GCH_LIST} ${_C_GCH_LIST} ${_O_LIST} 
    ${_COMPILER} ${_COMPILATION_BUNDLE_CPP} ${_O_LIST} ${addprefix -include , ${_GCH_LIST}} ${addprefix -include , ${_C_GCH_LIST}} -o $@ 

vpath %.cpp $(call uniq, ${dir ${_CPP_LIST}})
${_O_DIR}/%.o: %.cpp 
    ${_COMPILER} ${_COMPILATION_BUNDLE_CPP} -c $< -o $@ 

vpath %.hpp $(call uniq, ${dir ${_HPP_LIST}})
${_GCH_DIR}/%.gch: %.hpp 
    ${_COMPILER} ${_COMPILATION_BUNDLE_HPP} $< -o $@

vpath %.h $(call uniq, ${dir ${_H_LIST}})
${_GCH_DIR}/%.gch: %.h
    ${_COMPILER} ${_COMPILATION_BUNDLE_HPP} $< -o $@

在一个干净的项目上执行(因此更容易遵循):

g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch src/helper/helper.hpp -o _tmp\.gch/helper.gch
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch src/renderer/renderer.hpp -o _tmp\.gch/renderer.gch
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch C:/VulkanSDK/1.2.148.1/Include/vulkan/vulkan.hpp -o _tmp\.gch/vulkan.gch
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch C:/msys64/mingw64/include/GLFW/glfw3.h -o _tmp\.gch/glfw3.gch 
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch  -c src/main.cpp -o _tmp\.o/main.o  
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch  -c src/helper/helper.cpp -o _tmp\.o/helper.o
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch  -c src/renderer/renderer.cpp -o _tmp\.o/renderer.o
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch  _tmp\.o/main.o _tmp\.o/helper.o _tmp\.o/renderer.o -include _tmp\.gch/helper.gch -include _tmp\.gch/renderer.gch -include _tmp\.gch/vulkan.gch -include _tmp\.gch/glfw3.gch -o build\debug/test

标签: c++makefileg++

解决方案


使用预编译的头文件实际上是相当直接的。将其分解为手动步骤可能是最简单的。您甚至可以很容易地对现有项目进行改造。步骤可能是:

  • 创建一个 PCH 文件,包括一堆标准库或您要预编译的其他头文件。注意:使用与编译其他 c++ 代码相同的标志编译 PCH,否则可能无法正常工作。
  • 在你的makefile中添加PCH的包含标志......基本上就是这样。

所以让我们尝试一个实际的例子:

  1. 从源文件 src1.cpp 开始并编译它:g++ -I. <other flags> src1.cpp -o src1.o
  2. 创建您的 pch 文件,调用它pch.hpp(或其他)
  3. 编译您的 PCH 文件:(g++ -I. <other flags> pch.hpp与之前编译的标志相同)。这将生成 pch.hpp.gch 文件。
  4. 现在您可以在原始编译行中使用您的 PCH 文件:g++ -I. <other flags> src1.cpp -o src1.o -Winvalid-pch -include pch.hpp

需要注意的几点:

  • 如果您使用 -Winvalid-pch 警告标志,这通常会为您提供足够的信息来找出不使用 pch 的原因(例如其丢失、错误路径、错误选项等......)。
  • -include pch.hpp不要使用-include pch.hpp.gch,因为 g++ 会解决这个问题。您可以看到改装很容易 - 因为您只需将包含标志附加到编译器行。
  • 如果您的 .gch 文件未生成,则代码仍应直接使用 pch.hpp 标头进行编译...

推荐阅读