xcode学习glfw 的 custom project template

最近在看learn opengl,每次都要配置opengl的项目有点烦,例如,需要添加framework,需要增加search path等,然后发现xcode可以支持项目模板。但是有一点比较烦就是每次升级系统或者升级xcode配置都不见了,所以记个笔记。这个也是自己摸索和找参考资料写的,部分是自己的理解,可能存在错误和遗漏。

xcode的project template位置在

/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/

opengl学习项目一般是mac OS系统的命令行项目,所以在上述的文件夹下面的macOS文件夹下添加OpenGL文件夹。

cd macOS
sudo mkdir OpenGL

copy Application/Command Line Tool.xctemplate到OpenGL目录下,修改项目名字为Base OpenGL.xctemplate。
Base OpenGL.xctemplate里面此时有三个文件

TemplateIcon.png
TemplateIcon@2x.png
TemplateInfo.plist

两个png文件是用来做项目的图标的,是不是修改随意。
主要考虑TemplateInfo.plist文件,如果在原文件夹不能修改,可以复制到别的文件夹,例如Desktop,修改完再覆盖回去。一般来说,TemplateInfo.plist如下

Kind是模板类型,不需要修改
Identifier是模板的唯一标志符,自己新加的,必须修改
Ancestors 用来表明继承自某些模板,不需要修改
Concrete 必须是1或者YES,表示不是抽象的模板,需要在创建时展示。
SortOrder 应该是用来设置排序
Description 模板描述,可以改成自己需要的文案
Targets 我的理解是用来创建项目的产品类型和文件夹配置之类的,一般不用修改。因为opengl学习一般需要读取相对目录(例如Resources)下的shader或者图片文件,可以修改CopyFiles如下

DstSubfolderSpec 设置成7,RunOnlyForDeploymentPostprocessing 设置成NO,体现在项目文件中应该是类似如下

Options 语言类型以及项目配置

因为opengl我一般都是c++,所以不需要oc,swift,c的语言类型可以删掉。
第一,Values删除Object-c,swift,c
第二,Default 默认语言改成需要的C++
第三,Units也删除oc,swift,c的选项
另外,因为openGL配置一般需要添加search path,可以在如上图的Units/C++/Project/SharedSettings下添加 LIBRARY_SEARCH_PATHS 和 HEADER_SEARCH_PATHS,增加自己对应项目的库文件夹地址和header文件夹地址。我配置的glfw_lib和glfw_include分别在Preferences下的custom path配置好了。
frameworks和dylib也可以在这里配置,在如上图的Units/C++/Targets/Item 0/Frameworks添加 Cocoa,IOKit,CoreVideo,OpenGL这4个framework。在Units/C++/Targets/Item 0/Libraries下添加自己对应的glfw和glew的lib库,可以在/usr/local/lib/这个文件夹下找到具体的dylib的名字,例如我的版本是libglfw.3.3.dylib 和 libGLEW.2.1.0.dylib



第四,Nodes和Definitions,这里主要是定义模板里的文件和文件夹,以及main文件。Nodes是Array类型,Defintions是Dictionary类型。
这里可以分为三类,第一类是文件或者文件夹,第二类是main.cpp文件里的最顶部的注释、头文件、还有function的声明等,第三类是main.cpp里文件的functions。
文件或者文件夹一般是在Nodes里添加一个item,例如为ResourcesShader.cpp,在Definitions里一般添加一个key为上面item名字的Dictionary,添加一个key为Path的string,value为实际的相对目录。
注释和头文件等也就是Nodes里添加一个item,例如main.cpp:comments或者main.cpp:include,注意comments一般都是自动生成,不需要在Definitions额外定义了。main.cpp:include在Definitions里添加String,内容自己定义即可。
main.cpp里的function,在Nodes里声明为main.cpp:function_name:content,在Definitions里定义实际的main.cpp:function_name:content的内容,还有main.cpp:function_name对应方法的的Beginning 和 End,还有Indent。
举个🌰,类似下面的一个function

void processInput(GLFWwindow* window) {
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);
}

在Nodes里添加一个 item,格式为string
main.cpp:processInput:content
在Definitions里添加一个key为main.cpp:processInput:content的string,value为

    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);

在Definitions里添加一个Dictionary,key为main.cpp:processInput,实际一般如下

Definitions 我的理解是全局的一些定义,例如Options里如果有C和C++,有部分main的定义可以放至此处,可以参考xcode自带的Command Line Tool.xctemplate

参考:
https://medium.com/overapp-ios/create-xcode-templates-c968d4b43f7b