不想看废话的话,直接上github:https://github.com/zhangping312/VSCode-Premake5-Example
说实话,上一篇VSCode配置编译和调试C++程序已经全部结束了,引用第3方库的功能其实是通过premake5中配置的,这篇是讲述在premake5在XCode上的踩的坑, Windows上没有任何问题。先描述一下自己遇到的问题:Mac上我不想安装SFML库,或者将SFML库拷贝到Library/Framework目录中,因为这些库我不常用。
先去SFML官网下载,需要下载3个文件,VS2017 32位和64位的,和Mac的。在Game同级目录中创建Third文件夹,把下载好的SFML-2.5.1-windows-vc15-32-bit.zip,SFML-2.5.1-windows-vc15-64-bit.zip和SFML-2.5.1-macOS-clang.tar.gz解压到Third文件夹中。
在Third文件夹中创建SFML-2.5.1文件夹,从之前解压好的3个文件夹中随便选一个include文件夹,拷贝至Third/SFML-2.5.1/中,并新建一个lib文件夹,在Third/SFML-2.5.1/lib文件夹中创建Macosx和Windows文件夹,在Third/SFML-2.5.1/lib/Windows文件夹中创建x86和x86_64文件夹,并将相对应的lib库中的内容全部拷贝过来, 与lib文件夹一样继续对bin文件夹进行处理,bin文件夹中都是运行需要的dll文件。前期工作先做Windows上的,Mac等会再说。
开始写SFML的代码,代码可以从SFML官网上拷贝一份,但是发现#include好像出错,这里也需要配置,就是之前一直没说的c_cpp_properties.json,Ctrl + Shift + P后输入C/C++: Edit Configuration(Json),会自动创建c_cpp_properties.json文件,修改成如下:
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}\\..\\Third\\SFML-2.5.1\\include"
],
"defines": [],
"windowsSdkVersion": "10.0.18362.0",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "${default}"
}
],
"version": 4
}
主要就关心inincludePath,其他的先不管,现在就有代码提示了,开始敲代码,对之前的Application.h和Application.cpp进行修改:
Application.h:
#include <iostream>
#include <exception>
#include <SFML/Graphics.hpp>
class Application
{
public:
Application(const std::string& title, unsigned int width, unsigned int height);
Application(const Application& other) = delete;
Application& operator=(const Application& other) = delete;
virtual ~Application();
void Run();
private:
sf::RenderWindow* m_WindowHandle = nullptr;
};
Application.cpp:
#include "Application.h"
Application::Application(const std::string& title, unsigned int width, unsigned int height)
{
m_WindowHandle = new sf::RenderWindow(sf::VideoMode(width, height), title.c_str());
if (!m_WindowHandle) throw std::runtime_error("Failed to create SFML window!");
}
Application::~Application()
{
if (m_WindowHandle) delete m_WindowHandle;
m_WindowHandle = nullptr;
}
void Application::Run()
{
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
while (m_WindowHandle->isOpen())
{
sf::Event event;
while (m_WindowHandle->pollEvent(event))
{
if (event.type == sf::Event::Closed)
m_WindowHandle->close();
}
m_WindowHandle->clear();
m_WindowHandle->draw(shape);
m_WindowHandle->display();
}
}
好了,代码就就到这。如果你现在编译肯定失败的,还需要修改premake5.lua配置。找到SFML/premake5.lua文件,对此修改如下:
IncludeDirs = {}
IncludeDirs["SFML"] = g_WorkspaceFolder .. "/../Third/SFML-2.5.1/include"
project "SFML"
kind "ConsoleApp"
language "C++"
cppdialect "C++17"
-- Place where build files will be generated
location (g_BuildFolder .. "/%{prj.name}")
-- Place where compiled binary target
targetdir (g_WorkspaceFolder .. "/../bin/%{prj.name}")
-- Place where object and other intermediate files
objdir (g_WorkspaceFolder .. "/../bin-int/%{prj.name}")
-- Specify script files for the project
files
{
g_WorkspaceFolder .. "/%{prj.name}/Source/**.h",
g_WorkspaceFolder .. "/%{prj.name}/Source/**.cpp",
}
-- Window configuration
filter "system:windows"
-- Specify the include file search path
includedirs
{
g_WorkspaceFolder .. "/%{prj.name}/Source/",
"%{IncludeDirs.SFML}"
}
-- Specify the library file search path
libdirs { g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/%{cfg.architecture}" }
-- Copy dlls
prebuildcommands
{
("{COPY} \"%{wks.location}../Third/SFML-2.5.1/bin/%{cfg.system}/%{cfg.architecture}/*.dll\" \"%{cfg.buildtarget.directory}\""),
}
filter { "system:windows", "configurations:Debug" }
links { "sfml-system-d.lib", "sfml-window-d.lib", "sfml-graphics-d.lib" }
filter { "system:windows", "configurations:Release" }
links { "sfml-system.lib","sfml-window.lib", "sfml-graphics.lib" }
-- Mac configuration
filter "system:macosx"
systemversion "10.14" -- 我的Mac版本是10.14.5,低于development target的10.15, 为了避免手动修改,改成10.14
includedirs { g_WorkspaceFolder .. "/%{prj.name}/Source/" }-- Xcode: User Header Search Paths
这次修改的内容主要有设置SFML头文件和库文件路径,并拷贝dll到可执行文件处。现在可以通过VSCode进行调试代码,也可以通过bat文件生成或者VSCode执行任务生成VS2019工程,在VS2019上进行编译和调试。
现在开始配置XCode的设置了。先贴出修改后的SFML/premake5.lua文件:
IncludeDirs = {}
IncludeDirs["SFML"] = g_WorkspaceFolder .. "/../Third/SFML-2.5.1/include"
project "SFML"
kind "ConsoleApp"
language "C++"
cppdialect "C++17"
-- Place where build files will be generated
location (g_BuildFolder .. "/%{prj.name}")
-- Place where compiled binary target
targetdir (g_WorkspaceFolder .. "/../bin/%{prj.name}")
-- Place where object and other intermediate files
objdir (g_WorkspaceFolder .. "/../bin-int/%{prj.name}")
-- Specify script files for the project
files
{
g_WorkspaceFolder .. "/%{prj.name}/Source/**.h",
g_WorkspaceFolder .. "/%{prj.name}/Source/**.cpp",
}
-- Window configuration
filter "system:windows"
-- Specify the include file search path
includedirs
{
g_WorkspaceFolder .. "/%{prj.name}/Source/",
"%{IncludeDirs.SFML}"
}
-- Specify the library file search path
libdirs { g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/%{cfg.architecture}" }
-- Copy dlls
prebuildcommands
{
("{COPY} \"%{wks.location}../Third/SFML-2.5.1/bin/%{cfg.system}/%{cfg.architecture}/*.dll\" \"%{cfg.buildtarget.directory}\"")
}
filter { "system:windows", "configurations:Debug" }
links { "sfml-system-d.lib", "sfml-window-d.lib", "sfml-graphics-d.lib" }
filter { "system:windows", "configurations:Release" }
links { "sfml-system.lib","sfml-window.lib", "sfml-graphics.lib" }
-- Mac configuration
filter "system:macosx"
systemversion "10.14" -- 我的Mac版本是10.14.5,低于development target的10.15, 为了避免手动修改,改成10.14
includedirs { g_WorkspaceFolder .. "/%{prj.name}/Source/" }-- Xcode: User Header Search Paths
sysincludedirs { "%{IncludeDirs.SFML}" }--Xcode: Header Search Paths
links { "sfml-system.framework", "sfml-window.framework", "sfml-graphics.framework", "freetype.framework" }
linkoptions
{
"-F" .. g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks",
"-Xlinker -rpath -Xlinker " .. g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks"
}
--syslibdirs { g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks" }
--libdirs { g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks" }
-- runpathdirs
-- {
-- g_WorkspaceFolder .. "/../bin/%{prj.name}",
-- g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks",
-- g_WorkspaceFolder .. "/../Third/SFML-2.5.1/lib/%{cfg.system}/extlibs"
-- }
-- prebuildcommands
-- {
-- ("{COPY} \"%{wks.location}/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks/sfml-system.framework\" \"%{cfg.buildtarget.directory}\""),
-- ("{COPY} \"%{wks.location}/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks/sfml-window.framework\" \"%{cfg.buildtarget.directory}\""),
-- ("{COPY} \"%{wks.location}/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks/sfml-graphics.framework\" \"%{cfg.buildtarget.directory}\""),
-- ("{COPY} \"%{wks.location}/../Third/SFML-2.5.1/lib/%{cfg.system}/Frameworks/freetype.framework\" \"%{cfg.buildtarget.directory}\"")
-- }
这里坑超级多,premake5的wiki上好多设置感觉在XCode上都是无效的。一个个来说,首先是sysincludedirs值是Header Search Paths表示可以#include <>,不然使用#include <SFML/Graphics.hpp>会报错,includedirs指的是User Header Search Paths,用的是#include "", 这些可以通过google查找学习。
linkoptions这个参数是后面经过多个坑踩出来的最后结果,下面所有的注释都是自己踩过留下来的。先来说下情况,因为SFML库不常用,不想安装也不想拷贝Framework到/Library/Framework目录中,其实更加重要的原因是我自己编译出来的库,我难道还得放到/Library/Framework目录中吗。我先测试了prebuildcommands拷贝到可执行程序目录中,可以编译,XCode也可编译执行,但可执行文件会报错,Library not loaded,然后这个方法弃之。第2个方法指定frameworkpath,但premake5没有提供这个功能,测试了libdirs和syslibdirs,发现没有用。第3个方法,回到拷贝framework,运行的时候指定runpath,但发现runpathdirs这个值无效,看链接的输出时候没有。本来打算放弃了,不死心,对着build出来的xcode工程修改,自己添加framework和设置runpath,直接执行可执行程序,可以,就说明之前想的方法可行。疯狂google如何通过xcodebuild设置runpath和frameworkpath。没有找到,只好通过XCode拷贝链接指令,一个个看过来,发现通过xcodebuild的有漏了2个参数。
查看链接指令的方式:
发现自己漏了这2条:
//用于编译
-Xlinker -no_deduplicate -F/Users/zhangping/Documents/ZP/VSCode-Premake5-Example/Game/../Third/SFML-2.5.1/lib/macosx/Frameworks
//用于运行
-Xlinker -rpath -Xlinker /Users/zhangping/Documents/ZP/VSCode-Premake5-Example/Game/../Third/SFML-2.5.1/lib/macosx/Frameworks
然后通过linkoptions补上了这2个参数,编译运行OK,VSCode也可以编译和调试了。这边得吐槽SFML的framework,好逗比,freetype.framework必须在../Frameworks中,不就是表示将freetype.framework放在Frameworks目录中和sfml-system.framework等同级吗?
代码和SFML库都已经上传到github上的,Mac和Windows目录下的库文件都删除了一部分,不然太大,而且还用不上。