Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tutorial] Windows 下手动编译、交叉编译 v2ray 的详细方法 #756

Closed
RPRX opened this issue Jun 14, 2020 · 18 comments
Closed

[Tutorial] Windows 下手动编译、交叉编译 v2ray 的详细方法 #756

RPRX opened this issue Jun 14, 2020 · 18 comments
Labels

Comments

@RPRX
Copy link

RPRX commented Jun 14, 2020

代码果然还是要自己写,这两天抽空实现 VLess(#2526 v2ray/v2ray-core#2547),目前协议核心部分已经完成。看到有 issue 说 v2ray 的某些问题和 Golang 版本有关,现在把 Win 编译的详细方法写出来,很简洁且更完美。

1.下载 Golang 的 Windows 版本并安装,至少 1.15.x

官网:https://golang.org/dl
或者:https://studygolang.com/dl

安装后,打开 PowerShell 并执行:

go env -w GO111MODULE=on GOPROXY=https://goproxy.cn,https://goproxy.io,direct

2.下载 v2fly 的 v2ray-core 代码并解压

https://github.com/v2fly/v2ray-core/archive/master.zip

解压后,在文件夹内按住 Shift 同时单击右键,打开 PoweShell 并依次执行:

$env:CGO_ENABLED=0

go build -o v2ray.exe -trimpath -ldflags "-s -w -buildid=" ./main
go build -o wv2ray.exe -trimpath -ldflags "-s -w -H windowsgui -buildid=" ./main
go build -o v2ctl.exe -trimpath -ldflags "-s -w -buildid=" -tags confonly ./infra/control/main

将编译到当前目录。geoip.dat 和 geosite.dat 在 ./release/config/ 文件夹下。

第一次编译会自动下载依赖代码,也没有之前的编译缓存,所以编译速度会相对慢一些。

3.交叉编译,这里以编译到 Linux 服务器为例

$env:CGO_ENABLED=0
$env:GOOS="linux"
$env:GOARCH="amd64"

go build -o v2ray -trimpath -ldflags "-s -w" ./main
go build -o v2ctl -trimpath -ldflags "-s -w" -tags confonly ./infra/control/main

上传到服务器后,记得在服务器终端内执行 chmod +x v2raychmod +x v2ctl

提示:PowerShell 执行 go tool dist list 查看所有支持的系统与架构。


这里的很方便、清晰,按上面的流程一步步做即可成功编译,感兴趣的不妨试一下。

go build 加上 -trimpath 用于保护隐私,同时略微减小文件体积。

@RPRX
Copy link
Author

RPRX commented Jun 14, 2020

以及,使用 v2ray 遇到了问题可以试着自己改代码,然后编译出来测试运行。
不管是修 BUG 还是加功能,希望更多的人参与到项目中。Golang 很简单,不难学。

@rendaa
Copy link

rendaa commented Jun 14, 2020

首先感谢作者提供这篇简洁、实用的教程!

按教程尝试在windows系统上安装了go 1.14.4,正确设置 CGO_ENABLED、GOOS、GOARCH、GOARM环境变量后可成功地交叉编译出ARMv5的 v2ra 和 v2ctl 可执行文件。然而1.14版go编译出的文件,如 v2ray/v2ray-core#2536 所述,很快就发生了掉出。所以卸载了go 1.14.3,安装了1.13.2,并试图用 1.13.2 编译。

然而1.13版报如下错误:
# runtime/cgo
exec: "gcc": executable file not found in %PATH%

尝试将 cygwin及MinGW的gcc加入$env:path,但这两个gcc都不支持arm平台的编译。cygwin gcc报错“gcc: error: unrecognized command line option '-marm'; did you mean '-mabm'?”,mingw gcc报错“cc1.exe: error: invalid option `arm'”。

可否能指点一下windows下有哪个gcc可以用?go 1.14安装包里估计是有的,但我怀疑用那个gcc编译出来的文件还是会掉出,所以想另外找个。

顺便提一下,我在跑v2ray的CentOS7服务器上倒是可以用go 1.13.2交叉编译出给ARM路由器用的文件,并且不会发生掉出,但是因为那个服务器是个配置很低的虚拟机,所以编译跑得很慢很慢,所以还是希望能在windows机器上编译以后的版本。因此还请费心指点。

非常感谢!

@RPRX
Copy link
Author

RPRX commented Jun 15, 2020

@rendaa

防止你的描述误导他人,我还是写个白话文版本的:

Golang 安装包里都没有 GCC,你在 Windows 下用 1.14 可以交叉编译而 1.13 却报错,是因为你用 1.14 时按我写的设置了 $env:CGO_ENABLED=0 ,而用 1.13 时忘记设置了,设置一下即可成功交叉编译。

目前已知用 1.13 交叉编译到 arm 都不会掉出,这不取决于用 CentOS 还是 Windows 来编译。


首先,你的描述存在一些误导性成分,建议先忘掉。很显然你在使用 1.14 和 1.13 时设置了不同的环境变量,比如你的那个报错其实和 Golang 版本无关,是因为交叉编译时开启了 CGO,那么建议是不要开启,没必要且有些麻烦:如果要用 C 的代码,鉴于 C 对交叉编译的支持极差,必须提供对应系统和架构的 CC,比如这篇文章。顺便提供另一篇文章,是讲 CGO 对静态编译的影响。

现在的情况应该是,1.14 关闭了 CGO 后编译的程序在你的那个路由器上跑会出问题,而 1.13 关闭了 CGO 则没有这个问题,你可以试一下。以及,你说的 1.13.2,指的是 1.13.12,对吧?

如果你还是想用 1.14,那么需要开启 CGO,用 WSL / WSL2 交叉编译即可。在此基础上,如果目标系统没有用 Glibc,比如这种问题,那么需要用目标 libc 对应的 CC,或者参考第二篇文章,强制静态编译。

@Cwek
Copy link

Cwek commented Jun 15, 2020

已经测试过在x64上CGO_ENABLED=1交叉编译arm版成功,而且暂时没发现Segmentation fault(准确来说这就是掉出的错误原因)。

@RPRX
Copy link
Author

RPRX commented Jun 15, 2020

@Cwek

是的,在常见 Linux 系统上用 1.14 交叉编译 arm 时手动开启 CGO 是没问题的,问题就出在 1.14 关闭了 CGO 后使用的那些 Go 代码上。而 1.13 的那些 Go 代码则没有这个问题,不开启 CGO 也不会掉出。

@Cwek
Copy link

Cwek commented Jun 15, 2020

@Cwek

是的,在常见 Linux 系统上用 1.14 交叉编译 arm 时手动开启 CGO 是没问题的,问题就出在 1.14 关闭了 CGO 后使用的那些 Go 代码上。而 1.13 的那些 Go 代码则没有这个问题,不开启 CGO 也不会出错。

这有两个变量?一个是更改编译环境期间本项目改动的代码,另一个是go的变动。

@RPRX
Copy link
Author

RPRX commented Jun 15, 2020

@Cwek

我觉得是后者的问题。你可以用 1.13 不开 CGO 交叉编译 v2ray 最新版本到 arm,应该不会掉出。
但暂不清楚是有计划的变动还是 BUG,如果是有计划的变动,则需要 v2ray 改代码来适配。

@RPRX
Copy link
Author

RPRX commented Jun 15, 2020

@rendaa @Cwek

想了想,v2ray 的一堆依赖长时间未跟进升级,很可能是某个依赖在 1.14 下存在 BUG 但已经被修复了,你们把所有依赖升级到最新版本然后用 1.14 不开 CGO 交叉编译看看。

@Cwek
Copy link

Cwek commented Jun 15, 2020

@Cwek

我觉得是后者的问题。你可以用 1.13 不开 CGO 交叉编译 v2ray 最新版本到 arm,应该不会掉出。
但暂不清楚是有计划的变动还是 BUG,如果是有计划的变动,则需要 v2ray 改代码来适配。

好像1.13编译不出4.24.2,protobuf锁定了最新版本1.24,1.13的环境下载不了?
这个需要自行搭建环境调试了。

@RPRX
Copy link
Author

RPRX commented Jun 15, 2020

@Cwek

不存在这个问题。

@rendaa
Copy link

rendaa commented Jun 15, 2020

@RPRX

谢谢回复!按你所说设置 $env:CGO_ENABLED=0 后 windows 上的 1.13 版 go 已成功编译出需要的文件。问题已解决!

可能是之前我习惯用 go env -w 来设置这几个变量,以方便后续的使用,然而在进行各种尝试时 CGO_ENABLED 被设成了默认为1,而后在用 1.14 和 1.13 编译时一个执行了$env:CGO_ENABLED=0一个没有执行。

1.13下那个gcc的报错的确是因为开了CGO(因为默认设了1并且没有执行$env:CGO_ENABLED=0)导致。我的电脑是intel cpu/windows系统,手头现有的C编译器都不能支持 arm cpu/linux 的目标系统。自己之所以造成各种误解,是对golang的语言和环境完全不了解。我本来只是个希望能用上稳定运行的新版本的用户,并不是程序员,因为官方发布版暂时不稳定才只好弄个自己编译的环境。对CGO这个选项的意义和要求更是一头雾水,所以没留神开了它、再看到cc的报错就以为是别的问题……然后就整个方向都出问题了……希望别误导别的朋友。

在此也谢谢 rprx 推荐的关于Go的可移植性和交叉编译的两篇文章。

眼下我主要是希望能及时获得可在我的路由器上稳定运行的新版本可执行程序,目前1.14编译器暂时还存在问题,按 rprx 指点,用1.13编译的问题已解决。我继续用1.13即可,

另外借此澄清一下之前提问时的一些可能引起误解或误导的描述,以免造成其他人的困惑。

1、提到 CentOS 只是想说明因为在 Windows 里的编译一直无法成功,只好在一个配置很低的 CentOS 机器上编译,所以非常希望能解决在 Windows 中编译时遇到的那个问题,并不是说两个系统下1.13编译出的一个会掉出一个则正常,

2、1.13.2确实是1.13.12之误,打字错误,抱歉。

多谢 rprx,顺祝各位顺利!

@yunfengwangluo
Copy link

感谢您的 教程 能否提供一个 修改编译成dll 供 vs c++ 调用的方法 网络搜索到的教程很多 但都不太完善

@kslr kslr transferred this issue from v2ray/v2ray-core Jun 23, 2020
@wenjinlibug
Copy link

我編譯出來的任何一個都是只有233k,是什麽原因?沒有任何報錯。

@johnwigley
Copy link

johnwigley commented Jul 27, 2020

@RPRX I couldn't see an issue tracker for VLESS specifically: if there is one apologies for posting here.

In v2ray-vless preview version. When using VLESS if a connection occurs to a protocol where the SERVER sends FIRST, NOT the client, such as SMTP where the client waits for the server banner message before logging in. Then current VLESS does NOT send server first message until after the client has sent data.

This means SMTP through VLESS is broken currently.

On same configuration, switching from vless -> vmess then SMTP works perfectly, so definitely an issue with vless implementation.

@RPRX
Copy link
Author

RPRX commented Jul 27, 2020

@johnwigley

感谢反馈,可以分别测试一下 VLESS BETA 版本和 ALPHA 版本吗

@johnwigley
Copy link

@johnwigley

Thanks for the feedback, can you test the VLESS BETA version and ALPHA version separately

@RPRX

Tested:

Preview: NOT working
Beta: Working
Alpha: Working

So the issue is new in the preview.

To test: setup dokodemo-door port forward to SMTP server, then telnet through dokodemo-door and see if you see the SMTP server banner before you press any key to send data. You should see SMTP server banner without client sending any data,.

@RPRX
Copy link
Author

RPRX commented Jul 28, 2020

@johnwigley

十分感谢,我已经确定了问题所在

PREVIEW 版本中,我把原先的“客户端 100 毫秒内没发数据则只发 VLESS 头”改成了“客户端必须发数据才发送”,所以导致了问题

我将很快发布 PREVIEW 1.1 版本,再次感谢!

@johnwigley
Copy link

@RPRX Thank you for fixing it so quickly 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants