练习1-编译调试teamtalk
TeamTalk 是一款蘑菇街开源的企业内部即时通讯软件,代码质量优秀,具有较高的学习价值。源码由张小方老师提供,在此表示感谢。
此次的任务仍然是在 Visual Studio 中将源码跑起来,这个过程碰到了许多编译和链接的问题,通过不断调整试错终于跑通了代码,实属不易!学习源码,往往就难在这第一步,只要将源码运行起来,我们就成功了一半。后续的代码细节直接边调试边理解,再爽不过!这个过程大大加深了我对编译与链接的理解,也熟悉了 Visual Studio 的开发环境。
勘误:文中图片的路径有时候为 TeamTalk,有时为 TeamTalk_test,前者是笔者为写此博客而重新开的项目,后者是之前的项目,由于本人疏忽不小心混淆了,大家直接将 TeamTalk_test 视作 TeamTalk 即可。
1)从 github 上拉取源码,然后打开客户端的 .sln
解决方案文件:
2)VS可能提示我们更新项目的编译工具集,默认即可:
3)配置 configuration manager,指定 Build Solution 时是将该方案下的所有项目进行编译。
4)点击 Build Solution,编译完成后报错如下:
我们一个一个来解决错误。
先看 <hash_map> 的报错。该错误出现在 network
项目中,提示 <hashmap> 已经被废弃,如果要使用它,请先定义指定的宏。 右击 侧边栏的 network
项目,点击最下方的 property 选项;然后在 C/C++ 栏目中找到 Preprocessor 预处理栏,然后打开 Preprocessor Definitions ,向其中添加提示的宏 _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
即可。Modules 和 teamtalk 项目也有此错误,相同操作。
之前的报错中还提示 ‘function’: is not a member of ‘std’ ,这个简单,直接在对应文件中添加头文件 <functional> 即可。
再次编译,报错如下:
mbstate_t
是结构体,无法直接赋值,应该使用初始化列表,将 0
改为 {0}
即可。
再次编译,报错如下:
先看后三个错误。在 utility 项目中无法打开 mfcs120ud.lib
文件,而在 Modules 和 teamtalk 项目中无法打开 utility.lib
。显然,是因为 mfcs120ud.lib
无法被打开导致 utility 项目无法生成 utility.lib
,继而使得 Modules 和 teamtalk 项目无法使用 utility.lib
。 所以我们必须先解决 mfcs120ud.lib
的问题。从这个静态链接库的名字我们可以知道,它不由任何项目生成,所以它应该是一个第三方库。打开文件夹,在整个 teamtalk 中搜索该文件,没有找到相关内容:
所以我们可以大胆猜测这个库应该是系统库或编译器自带库。让 chatgpt 来告诉我们:
ok,我们现在知道它是 MFC 的库,而且对应的版本是 Visual Studio 2013 。而当前我们的 VS 版本为 2022,所以极有可能是版本不匹配的原因。还是不确定,那让我们在 VS 的 VC 目录下搜索 mfcs 的相关内容:
因此可以推断,2022 版本的对应库为 mfcs140u.lib
而不是 mfcs120ud.lib
。所以我们修改 utility 项目的依赖库,如下:
然后再次编译:
果然,utility 的 mfcs120ud.lib
错误解决。Modules 也有相同问题,步骤如法炮制。
再次编译:
尼玛!问题又多了,头大!现在提示在 Modules 项目中的 libprotobuf-lite.lib
文件中有_MSC_VER
相关的错误。 _MSC_VER
是什么?chatgpt 告诉你:
真清晰!OK,现在我们大概知道报错是因为 libprotobuf-lite.lib
的编译版本较低造成的。同样,libprotobuf-lite.lib
依然不是我们的项目生成的库文件,让我们看看它在哪:
嗯,从路径中的 3rdParty(第三方)也可以看出这是第三方库,而不是我们自己编译的库。那么问题来了,我们应该如何将 libprotobuf-lite.lib
转换为高编译器版本呢?大多数第三方库都是知名库,可以直接从官方下载最新版本,比如这个库就可以在github下载。不过仔细搜寻后发现第三方库下有相关的压缩包(最下方的 protobuf):
解压后进入 vsprojects 目录,使用 VS 打开其中的 libprotobuf-lite.vcxproj
,这是工程文件:
打开后 Build 这个解决方案,编译成功,最新编译版本的 libprotobuf-lite.lib
的输出位置见图:
由于 Modules 项目的 linker 输入目录(Additional Library Directories)为 D:\VSProjects\TeamTalk\win-client\3rdParty\lib\debug
:
所以我们用新的 lib 将久版本的 lib 替换掉:
然后再次编译,该错误已经消失。teamwork 也有相同错误,同样加上前缀即可:
啊哦,出现了关于 security.lib
的新错误…还是关于编译版本的问题。不过这次和之前的 libprotobuf-lite.lib
不同,第三方库目录下没有相关的压缩包。不过我们在 3rdParty\src
下发现了 security.cpp
源文件,所以为什么不直接编译呢?将这个源文件作为一个项目引入到 solution 下:
发现有多个源文件找不到路径,搜索后发现它们位于 \TeamTalk\server\src\libsecurity\src
下,所以将此目录包含进项目的头文件搜寻范围:
现在头文件已经能够检测到,不过还有些类型报错:
小问题,typedef unsigned char uchar_t
即可。然后单独编译 security 项目,报错如下:
预编译头文件?这是什么?还是问问 chatgpt 吧:
我们无需使用预编译头文件,这里报错是因为项目默认开启了预编译头文件的功能,关闭即可:
再次编译 security 项目,报错如下:
好,我们在项目中添加 SECURITY_WIN32
宏:
于是 security 项目编译成功:
好,同样,我们用新生成的 security.lib
把之前的替换掉:
然后编译整个 solution,报错:
提示在 security.lib
中调用了一些没有定义的函数。回想一下,刚才我们是不是只为 security 项目引入了头文件目录以确保头文件能够找到,却没有把这些头文件对应的源文件包含进来,这样的话,如果 security.cpp
中调用了这些头文件声明的函数,只有声明而没有定义,就一定会导致上图所示的链接错误 。因此我们需要把头文件对应的源文件包含进 security 项目,它们仍位于 \TeamTalk\server\src\libsecurity\src
中:
ok,编译 security 项目,报错如下:
问题不大,定义该宏就行。然后再次编译,成功!然后把新的 security.lib
替换掉之前的即可。然后编译整个 solution,报错如下:
Please verify that you have sufficient right to run this command
,权限不够?那我们关闭 VS,以管理员身份重新运行:
哟呼!跑起来啦!!!!大功告成。
接下来我们就可以随意打断点,单步调试 teamtalk 了,这样来学习源码真是不要太爽!