0%

从零开始建立PuTTY工程

PuTTY的源码下载之后,里面已经带有Visual Studio 2010和Visual Studio 2012的解决方案,但是惊奇的发现,用这个两个解决方案编译出来的putty居然是xp风格的,和官网下载到的不一样。(如果只是要单纯的解决这个xp风格,可以参考MANIFEST)

所以,从零开始建立putty的Viusal Studio2017解决方案。

首先,建立一个空项目(记得勾选为解决方案创建目录)

这个时候,在你的putty源码目录的windows文件夹内会有一个putty文件夹,里面会有一个putty.sln和一个putty文件夹,将windows文件夹内的putty文件夹更名为VS2017(仅仅是为了与已有的解决方案统一风格而已,名字随意),这个时候,你可以对着解决方案的putty项目,点击右键,移动到添加,然后点击添加现有现有项,或者可以直接按下Shift + Alt +A,对着原本就有的PuTTY项目,分别添加源文件、头文件、资源文件:

添加完成之后,putty项目看起来应该是这个样子的

无法打开包括文件: “unix.h”

按下Ctrl+Shift+B,你就会看到这样的画面:

错误

1
2
严重性	代码	说明	项目	文件	行	禁止显示状态
错误 C1083 无法打开包括文件: “unix.h”: No such file or directory putty d:\desktop\putty-en\puttyps.h 14

原因很明显,它们找不到头文件在哪儿,右击项目,点击属性,选中C/C++,在附加包含目录内填入..\..\..\./;..\..\..\unix/;..\..\..\charset/;..\..\..\windows/;

这个是用来指定编译器搜索头文件的目录的,这里用的是相对路径(相对于putty解决方案内putty项目的路径,也就是putty源码的根目录,unix目录,charset目录和windows目录),这个附加目录也可以在VC++目录的包含目录里面填写,如下图

库目录在putty项目的建立过程中不用填写,putty没有用到第三方库,这里不用填写。

无法打开包括文件: “dlfcn.h”

再次生成解决方案,你会遇到第二个问题

1
2
严重性	代码	说明	项目	文件	行	禁止显示状态
错误 C1083 无法打开包括文件: “dlfcn.h”: No such file or directory putty d:\desktop\putty-en\unix\unix.h 11

依旧打开项目属性,点击C/C++,预处理器,预处理器定义

点击右边的下拉箭头,点击编辑,填入以下内容:

1
2
3
WIN32
_WINDOWS
_CRT_SECURE_NO_WARNINGS

这个时候,看起来应该是这个样子的(“dlfcn.h”是Linux系统的头文件,猜测加预处理参数是为了让编译器知道不去试图查找这个文件)

case 表达式不是常量

再次生成解决方案,你会遇到第三个问题

1
2
严重性	代码	说明	项目	文件	行	禁止显示状态
错误 C2051 case 表达式不是常量 putty d:\desktop\putty-en\ssh.c 1372

打开项目属性,选中C/C++,将调试信息格式更改为“程序数据库”,

使用了可能未初始化的本地指针变量

再次生成解决方案,你会遇到第四个问题

1
2
严重性	代码	说明	项目	文件	行	禁止显示状态
错误 C4703 使用了可能未初始化的本地指针变量“oev” putty d:\desktop\putty-en\windows\winhandl.c 342

打开项目属性,选中C/C++,将SDL检查改为否

noshare.obj & winshare.obj

再次生成解决方案,好了,你成功的将错误减少到了四个

1
2
3
4
5
6
7
8

错误 LNK2005 _platform_ssh_share 已经在 noshare.obj 中定义 putty D:\Desktop\putty-en\windows\VS2017\putty\winshare.obj 1

错误 LNK2005 _platform_ssh_share_cleanup 已经在 noshare.obj 中定义 putty D:\Desktop\putty-en\windows\VS2017\putty\winshare.obj 1

错误 CVT1100 资源重复。类型: MANIFEST,名称: 1,语言: 0x0409 putty D:\Desktop\putty-en\windows\VS2017\putty\CVTRES 1

错误 LNK1123 转换到 COFF 期间失败: 文件无效或损坏 putty D:\Desktop\putty-en\windows\VS2017\putty\LINK 1

对于错误1和错误2,我只能说,可能原本设计项目的人比较神奇,这两个错误花了我相当长的时间才排查掉,原因说得很清楚了,在连接winshare.obj的时候,发现函数_platform_ssh_share_platform_ssh_share_cleanup已经在 noshare.obj内定义过,noshare.c文件内的内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
* Stub implementation of SSH connection-sharing IPC, for any
* platform which can't support it at all.
*/

#include <stdio.h>
#include <assert.h>
#include <errno.h>

#include "tree234.h"
#include "putty.h"
#include "ssh.h"
#include "network.h"

int platform_ssh_share(const char *name, Conf *conf,
Plug downplug, Plug upplug, Socket *sock,
char **logtext, char **ds_err, char **us_err,
int can_upstream, int can_downstream)
{
return SHARE_NONE;
}

void platform_ssh_share_cleanup(const char *name)
{
}

大致上看起来就是重定义了,BUT,为什么原本有的putty项目可以编译?,尝试将noshare.c从项目中移除之后,再次编译,这两错误不见了,但是,为什么原本的项目可以编译呢,好生奇怪,两天之后,偶然发现,原本项目内的noshare.c文件前面的图标和其他源文件长得不一样,仿佛发现了什么,点开属性一看,原来如此:
右击noshare.c点击属性,选中常规,点击“项类型”右边的下拉箭头,改成C/C++标头

MANIFEST

再次生成解决方案,好了,这次你只能看到两个问题了

1
2
3
错误	CVT1100	资源重复。类型: MANIFEST,名称: 1,语言: 0x0409	putty	D:\Desktop\putty-en\windows\VS2017\putty\CVTRES	1	

错误 LNK1123 转换到 COFF 期间失败: 文件无效或损坏 putty D:\Desktop\putty-en\windows\VS2017\putty\LINK 1

但是这两个问题都不是源代码的问题(其实用源码内原本就有的解决方案能编译成功,就说明代码没问题了(PS:严格来说也不是没有可能)),对于错误 CVT1100 资源重复。类型: MANIFEST,名称: 1,语言: 0x0409 putty D:\Desktop\putty-en\windows\VS2017\putty\CVTRES 1 ,右击项目,点击属性,点击清单工具,选中输入和输出,将嵌入清单改成“否”

再次生成解决方案,错误变成了

1
2
3
4
5
6
7
严重性	代码	说明	项目	文件	行	禁止显示状态
错误 LNK2019 无法解析的外部符号 _ImmGetContext@4,该符号在函数 _WndProc@16 中被引用 putty D:\Desktop\putty-en\windows\VS2017\putty\window.obj 1
错误 LNK2019 无法解析的外部符号 _ImmReleaseContext@8,该符号在函数 _WndProc@16 中被引用 putty D:\Desktop\putty-en\windows\VS2017\putty\window.obj 1
错误 LNK2019 无法解析的外部符号 _ImmGetCompositionStringW@16,该符号在函数 _WndProc@16 中被引用 putty D:\Desktop\putty-en\windows\VS2017\putty\window.obj 1
错误 LNK2019 无法解析的外部符号 _ImmSetCompositionFontA@8,该符号在函数 _WndProc@16 中被引用 putty D:\Desktop\putty-en\windows\VS2017\putty\window.obj 1
错误 LNK2019 无法解析的外部符号 _ImmSetCompositionWindow@8,该符号在函数 _sys_cursor_update 中被引用 putty D:\Desktop\putty-en\windows\VS2017\putty\window.obj 1
错误 LNK1120 5 个无法解析的外部命令 putty D:\Desktop\putty-en\windows\VS2017\Debug\putty.exe 1

熟悉的话,很容易就知道这个是因为缺了静态库
右击项目,点击属性,点击链接器,选中输入,点击附加依赖项右边的下拉箭头,点击编辑,

填入imm32.lib,它看起来就是这样子的

再次编译,哈哈哈,终于成功了

其他可能遇到的问题

cannot open include file ‘version.h’

不过你也有可能遇到这个问题

1
2
严重性	代码	说明	项目	文件	行	禁止显示状态
错误 RC1015 cannot open include file 'version.h'. putty D:\Desktop\putty-en\windows\version.rc2 9

如果你在第一步中,填写附加包含目录的时候,填在了VC++目录里面,则不会遇到此问题,若是填到了C/C++则会遇到,一个办法是更改到VC++目录去,另外一个办法是在项目属性的资源选项下面,附加目录里面填上..\..\..\./;

关于依赖库

在putty原本带的解决方案内的附加依赖项是下面这些

1
2
3
4
5
6
7
advapi32.lib
comdlg32.lib
gdi32.lib
imm32.lib
ole32.lib
shell32.lib
user32.lib

在Windows 10 1803上,Visual Studio 2017 的预先包含的静态库里面已经包含了除去imm32.lib之外的所有今天库,所以我只添加了它。有关Visual Studio的各种报错,查看巨硬(微软)的文档是一个好办法,百度得到的办法虽说更为简洁明了一些,但是因为复现环境不一样,有时候并没有效果。

调整项目属性之后不生效

PS:若是调整项目属性之后不生效,请留意调整的项目和生成解决方案的是否是同一个编译选项

让其他项目用同样的属性

按照上一个描述的问题,对于一个工程,在win32和x86的Release和Debug模式都需要调整属性,就整整四个了,整个PuTTY解决方案其实包括了 pageant plink pscp psftp putty puttygen puttytel testbn,其它七个再来一次,简直爽歪歪,这个时候项目属性表就有用了,可以参考https://www.cnblogs.com/haomiao/p/5812860.html,若是找不到属性管理器,可以点击视图下的其他窗口的“属性管理器”。

懒人包

GitHub上有已经汉化完成的版本——https://github.com/larryli/PuTTY
下载搭建好的PuTTY的Visual Studio 2017解决方案,可以前往https://github.com/BDZNH/PuTTY