Winse Blog

走走停停, 熙熙攘攘, 忙忙碌碌, 不知何畏.

编译JCEF - Win64

参考

简单过程摘录

注意点:

  1. 依赖:git/python2.7/java8/cmake3/visual studio 2017(这是我编译的环境,具体的版本要求请查看官网文档)
  2. 需要用git下载源码
  3. 先把 chromium-clang-format 下载放到 tools 目录下面

步骤:

  1. cmake-3.12.3-win64-x64.zip,配置环境变量PATH
  2. 安装版python-2.7.15.amd64.msi、同时配置把python.exe加入到PATH
  3. 把 PortableGit 加入PATH: set PATH=D:\PortableGit\bin;%PATH%
  4. 使用 VS 的命令行运行
  5. 命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
F:\wv>git clone https://bitbucket.org/chromiumembedded/java-cef.git src

F:\wv\src>mkdir jcef_build && cd jcef_build

F:\wv\src\jcef_build>cmake -G "Visual Studio 14 Win64" ..
用vs编译本地代码:
# Open jcef.sln in Visual Studio
# - Select Build > Configuration Manager and change the "Active solution configuration" to "Release"
# - Select Build > Build Solution.

cd ..\tools
compile.bat win64

run.bat win64 Release detailed

F:\wv\src\tools>make_distrib.bat win64

生成的运行包放在 binary_distrib 目录下。查看下 binary_distrib/win64/run.bat 了解运行配置,同时参考上面文章中提到的项目的创建方法。

1
java -cp "./bin;./bin/*" -Djava.library.path=./bin/lib/win64 tests.detailed.MainFrame

过程截图:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.7.4
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community>F:

F:\>cd wv
F:\wv>set PATH=D:\PortableGit\bin;%PATH%
F:\wv>git clone https://bitbucket.org/chromiumembedded/java-cef.git src

F:\wv\src>mkdir jcef_build && cd jcef_build

F:\wv\src\jcef_build>cmake -G "Visual Studio 14 Win64" ..
-- Selecting Windows SDK version  to target Windows 10.0.16299.
-- The C compiler identification is MSVC 19.0.24234.1
-- The CXX compiler identification is MSVC 19.0.24234.1
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Downloading F:/wv/src/third_party/cef/cef_binary_3.3497.1831.g461fa1f_windows64.tar.bz2.sha1...
-- Downloading F:/wv/src/third_party/cef/cef_binary_3.3497.1831.g461fa1f_windows64.tar.bz2...
-- [download 0% complete]
-- [download 1% complete]
。。。
-- [download 98% complete]
-- [download 99% complete]
-- [download 100% complete]
-- Extracting F:/wv/src/third_party/cef/cef_binary_3.3497.1831.g461fa1f_windows64.tar.bz2...
CMake Warning (dev) at CMakeLists.txt:153 (find_package):
  Policy CMP0074 is not set: find_package uses <PackageName>_ROOT variables.
  Run "cmake --help-policy CMP0074" for policy details.  Use the cmake_policy
  command to set the policy and suppress this warning.

  CMake variable CEF_ROOT is set to:

    F:/wv/src/third_party/cef/cef_binary_3.3497.1831.g461fa1f_windows64

  For compatibility, CMake is ignoring the variable.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Found PythonInterp: C:/Python27/python.exe (found version "2.7.15")
-- Found JNI: C:/Java/jdk/lib/jawt.lib (Required is at least version "1.7")
-- Generating native/jcef_version.h file...
File native/jcef_version.h updated.
-- Downloading clang-format from Google Storage...
0> Failed to fetch file gs://chromium-clang-format/6ddedd571c56b8c184f30a3c1fc36984e8c10ccd for tools/buildtools/win/clang-format.exe, skipping. [Err: F:\wv\src\tools\buildtools\external_bin\gsutil\gsutil_4.15\gsutil\third_party\boto\boto\pyami\config.py:71: UserWarning: Unable to load AWS_CREDENTIAL_FILE ()
  warnings.warn('Unable to load AWS_CREDENTIAL_FILE (%s)' % full_path)
Failure: Unable to find the server at www.googleapis.com.
]
Downloading 1 files took 3153.963000 second(s)
Failed to fetch file gs://chromium-clang-format/6ddedd571c56b8c184f30a3c1fc36984e8c10ccd for tools/buildtools/win/clang-format.exe. [Err: F:\wv\src\tools\buildtools\external_bin\gsutil\gsutil_4.15\gsutil\third_party\boto\boto\pyami\config.py:71: UserWarning: Unable to load AWS_CREDENTIAL_FILE ()
  warnings.warn('Unable to load AWS_CREDENTIAL_FILE (%s)' % full_path)
Failure: Unable to find the server at www.googleapis.com.
]
CMake Error at CMakeLists.txt:265 (message):
  Execution failed with unexpected result: 1


-- Configuring incomplete, errors occurred!
See also "F:/wv/src/jcef_build/CMakeFiles/CMakeOutput.log".

<<== https://my.oschina.net/penngo/blog/1538071
<<<<----https://storage.googleapis.com/chromium-clang-format/6ddedd571c56b8c184f30a3c1fc36984e8c10ccd
~~~~~~

F:\wv\src\jcef_build>cmake -G "Visual Studio 14 Win64" ..
-- Selecting Windows SDK version  to target Windows 10.0.16299.
CMake Warning (dev) at CMakeLists.txt:153 (find_package):
  Policy CMP0074 is not set: find_package uses <PackageName>_ROOT variables.
  Run "cmake --help-policy CMP0074" for policy details.  Use the cmake_policy
  command to set the policy and suppress this warning.

  CMake variable CEF_ROOT is set to:

    F:/wv/src/third_party/cef/cef_binary_3.3497.1831.g461fa1f_windows64

  For compatibility, CMake is ignoring the variable.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Generating native/jcef_version.h file...
File native/jcef_version.h is already up to date.
-- Downloading clang-format from Google Storage...
0> File tools/buildtools/win/clang-format.exe exists and SHA1 matches. Skipping.
Success!
Downloading 1 files took 0.006000 second(s)
-- *** CEF CONFIGURATION SETTINGS ***
-- Generator:                    Visual Studio 14 2015 Win64
-- Platform:                     Windows
-- Project architecture:         x86_64
-- Binary distribution root:     F:/wv/src/third_party/cef/cef_binary_3.3497.1831.g461fa1f_windows64
-- CEF Windows sandbox:          ON
-- Visual Studio ATL support:    ON
-- Standard libraries:           comctl32.lib;rpcrt4.lib;shlwapi.lib;ws2_32.lib;dbghelp.lib;psapi.lib;version.lib;winmm.lib
-- Compile defines:              __STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;WIN32;_WIN32;_WINDOWS;UNICODE;_UNICODE;WINVER=0x0601;_WIN32_WINNT=0x601;NOMINMAX;WIN32_LEAN_AND_MEAN;_HAS_EXCEPTIONS=0;PSAPI_VERSION=1;CEF_USE_SANDBOX;CEF_USE_ATL
-- Compile defines (Debug):
-- Compile defines (Release):    NDEBUG;_NDEBUG
-- C compile flags:              /MP;/Gy;/GR-;/W4;/WX;/wd4100;/wd4127;/wd4244;/wd4481;/wd4512;/wd4701;/wd4702;/wd4996;/Zi
-- C compile flags (Debug):      /MTd;/RTC1;/Od
-- C compile flags (Release):    /MT;/O2;/Ob2;/GF
-- C++ compile flags:            /MP;/Gy;/GR-;/W4;/WX;/wd4100;/wd4127;/wd4244;/wd4481;/wd4512;/wd4701;/wd4702;/wd4996;/Zi
-- C++ compile flags (Debug):    /MTd;/RTC1;/Od
-- C++ compile flags (Release):  /MT;/O2;/Ob2;/GF
-- Exe link flags:                /MANIFEST:NO;/LARGEADDRESSAWARE
-- Exe link flags (Debug):       /DEBUG
-- Exe link flags (Release):
-- Shared link flags:
-- Shared link flags (Debug):    /DEBUG
-- Shared link flags (Release):
-- CEF Binary files:             chrome_elf.dll;d3dcompiler_43.dll;d3dcompiler_47.dll;libcef.dll;libEGL.dll;libGLESv2.dll;natives_blob.bin;snapshot_blob.bin;v8_context_snapshot.bin;swiftshader
-- CEF Resource files:           cef.pak;cef_100_percent.pak;cef_200_percent.pak;cef_extensions.pak;devtools_resources.pak;icudtl.dat;locales
-- *** JCEF CONFIGURATION SETTINGS ***
-- Python executable:            C:/Python27/python.exe
-- Java directory:               C:/Java/jdk
-- JNI libraries:                C:/Java/jdk/lib/jawt.lib;C:/Java/jdk/lib/jvm.lib
-- JNI include directories:      C:/Java/jdk/include;C:/Java/jdk/include/win32;C:/Java/jdk/include
-- Configuring done
-- Generating done
-- Build files have been written to: F:/wv/src/jcef_build

F:\wv\src\jcef_build>

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
F:\wv\src\tools>make_distrib.bat win64
正在加载程序包org.cef.browser的源文件...
正在加载程序包org.cef.browser.mac的源文件...
正在加载程序包org.cef.callback的源文件...
正在加载程序包org.cef的源文件...
正在加载程序包org.cef.handler的源文件...
正在加载程序包org.cef.misc的源文件...
正在加载程序包org.cef.network的源文件...
正在构造 Javadoc 信息...
.\org\cef\browser\CefRenderer.java:11: 错误: 程序包com.jogamp.opengl不存在
import com.jogamp.opengl.GL2;
                        ^
.\org\cef\browser\CefRenderer.java:15: 错误: 找不到符号
    private GL2 initialized_context_ = null;
            ^
  符号:   类 GL2
  位置: 类 CefRenderer
.\org\cef\browser\CefRenderer.java:34: 错误: 找不到符号
    protected void initialize(GL2 gl2) {
                              ^
  符号:   类 GL2
  位置: 类 CefRenderer
.\org\cef\browser\CefRenderer.java:64: 错误: 找不到符号
    protected void cleanup(GL2 gl2) {
                           ^
  符号:   类 GL2
  位置: 类 CefRenderer
.\org\cef\browser\CefRenderer.java:69: 错误: 找不到符号
    protected void render(GL2 gl2) {
                          ^
  符号:   类 GL2
  位置: 类 CefRenderer
.\org\cef\browser\CefRenderer.java:161: 错误: 找不到符号
    protected void onPaint(GL2 gl2, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer,
                           ^
  符号:   类 GL2
  位置: 类 CefRenderer
.\org\cef\browser\CefBrowserOsr.java:23: 错误: 程序包com.jogamp.nativewindow不存在
import com.jogamp.nativewindow.NativeSurface;
                              ^
.\org\cef\browser\CefBrowserOsr.java:24: 错误: 程序包com.jogamp.opengl.awt不存在
import com.jogamp.opengl.awt.GLCanvas;
                            ^
.\org\cef\browser\CefBrowserOsr.java:25: 错误: 程序包com.jogamp.opengl不存在
import com.jogamp.opengl.GLAutoDrawable;
                        ^
.\org\cef\browser\CefBrowserOsr.java:26: 错误: 程序包com.jogamp.opengl不存在
import com.jogamp.opengl.GLEventListener;
                        ^
.\org\cef\browser\CefBrowserOsr.java:27: 错误: 程序包com.jogamp.opengl不存在
import com.jogamp.opengl.GLProfile;
                        ^
.\org\cef\browser\CefBrowserOsr.java:28: 错误: 程序包com.jogamp.opengl不存在
import com.jogamp.opengl.GLCapabilities;
                        ^
.\org\cef\browser\CefBrowserOsr.java:44: 错误: 找不到符号
    private GLCanvas canvas_;
            ^
  符号:   类 GLCanvas
  位置: 类 CefBrowserOsr
.\org\cef\browser\mac\CefBrowserWindowMac.java:9: 错误: 程序包sun.lwawt不存在
import sun.lwawt.LWComponentPeer;
                ^
.\org\cef\browser\mac\CefBrowserWindowMac.java:10: 错误: 程序包sun.lwawt不存在
import sun.lwawt.PlatformWindow;
                ^
.\org\cef\browser\mac\CefBrowserWindowMac.java:11: 错误: 程序包sun.lwawt.macosx不存在
import sun.lwawt.macosx.CFRetainedResource;
                       ^
.\org\cef\browser\mac\CefBrowserWindowMac.java:12: 错误: 程序包sun.lwawt.macosx不存在
import sun.lwawt.macosx.CPlatformWindow;
                       ^
标准 Doclet 版本 1.8.0_181
正在构建所有程序包和类的树...
正在生成..\out\docs\org\cef\browser\CefBrowser.html...
正在生成..\out\docs\org\cef\browser\CefBrowserFactory.html...
正在生成..\out\docs\org\cef\browser\CefBrowserWindow.html...
正在生成..\out\docs\org\cef\browser\CefFrame.html...
正在生成..\out\docs\org\cef\browser\CefMessageRouter.html...
.\org\cef\browser\CefMessageRouter.java:185: 警告 - @return 标记没有参数。
.\org\cef\browser\CefMessageRouter.java:185: 警告 - @param argument "config" 不是参数名称。
正在生成..\out\docs\org\cef\browser\CefMessageRouter.CefMessageRouterConfig.html...
正在生成..\out\docs\org\cef\browser\CefRequestContext.html...
。。。
正在生成..\out\docs\constant-values.html...
正在构建所有程序包和类的索引...
正在生成..\out\docs\overview-tree.html...
正在生成..\out\docs\index-all.html...
正在构建所有类的索引...
正在生成..\out\docs\allclasses-frame.html...
正在生成..\out\docs\allclasses-noframe.html...
正在生成..\out\docs\index.html...
正在生成..\out\docs\overview-summary.html...
正在生成..\out\docs\help-doc.html...
29 个警告
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
F:\wv\src\java\tests\detailed\BrowserFrame.java -> F:\wv\src\binary_distrib\win64\bin\tests\detailed\BrowserFrame.java
F:\wv\src\java\tests\detailed\MainFrame.java -> F:\wv\src\binary_distrib\win64\bin\tests\detailed\MainFrame.java
。。。
F:\wv\src\java\tests\detailed\ui\StatusPanel.java -> F:\wv\src\binary_distrib\win64\bin\tests\detailed\ui\StatusPanel.java
F:\wv\src\java\tests\simple\MainFrame.java -> F:\wv\src\binary_distrib\win64\bin\tests\simple\MainFrame.java
复制了 34 个文件
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
系统找不到指定的文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
已复制         1 个文件。
F:\wv\src\jcef_build\native\Release\cef.pak -> F:\wv\src\binary_distrib\win64\bin\lib\win64\cef.pak
F:\wv\src\jcef_build\native\Release\cef_100_percent.pak -> F:\wv\src\binary_distrib\win64\bin\lib\win64\cef_100_percent.pak
。。。
F:\wv\src\jcef_build\native\Release\locales\zh-CN.pak -> F:\wv\src\binary_distrib\win64\bin\lib\win64\locales\zh-CN.pak
F:\wv\src\jcef_build\native\Release\locales\zh-TW.pak -> F:\wv\src\binary_distrib\win64\bin\lib\win64\locales\zh-TW.pak
复制了 58 个文件
F:\wv\src\jcef_build\native\Release\swiftshader\libEGL.dll -> F:\wv\src\binary_distrib\win64\bin\lib\win64\swiftshader\libEGL.dll
F:\wv\src\jcef_build\native\Release\swiftshader\libGLESv2.dll -> F:\wv\src\binary_distrib\win64\bin\lib\win64\swiftshader\libGLESv2.dll
复制了 2 个文件
F:\wv\src\out\docs\allclasses-frame.html -> F:\wv\src\binary_distrib\win64\docs\allclasses-frame.html
F:\wv\src\out\docs\allclasses-noframe.html -> F:\wv\src\binary_distrib\win64\docs\allclasses-noframe.html
。。。
F:\wv\src\out\docs\org\cef\network\package-summary.html -> F:\wv\src\binary_distrib\win64\docs\org\cef\network\package-summary.html
F:\wv\src\out\docs\org\cef\network\package-tree.html -> F:\wv\src\binary_distrib\win64\docs\org\cef\network\package-tree.html
复制了 151 个文件
Creating README.TXT file.
已复制         1 个文件。
F:\wv\src\third_party\jogamp\gluegen.LICENSE.txt -> F:\wv\src\binary_distrib\win64\gluegen.LICENSE.txt
F:\wv\src\third_party\jogamp\jogl.LICENSE.txt -> F:\wv\src\binary_distrib\win64\jogl.LICENSE.txt
复制了 2 个文件
F:\wv\src\tools\distrib\win64\compile.bat -> F:\wv\src\binary_distrib\win64\compile.bat
F:\wv\src\tools\distrib\win64\run.bat -> F:\wv\src\binary_distrib\win64\run.bat
复制了 2 个文件

F:\wv\src\tools>

–END

视频自动翻译

现在语音翻译应用越来越广泛了。其实视频内的音频应该也可以通过语音的处理方式,来达到添加字幕以及翻译的效果。

google翻译页面已有语音输入的按钮,只是需要我们把电脑视频的声音转换作为 电脑输入 就行了。

语音识别翻译链接

https://speechlogger.appspot.com/zh/

翻译

实现/处理方法

转换工具

第一种(推荐): 使用 VoiceMeeter

第二种:使用 virtual audio cable sofeware

详细步骤:

  1. 安装(以上任意一种)转换工具
  2. 设置系统声音的 播放设备
  3. 在浏览器中点击 录音按钮 后,点击 浏览器地址栏 的右侧麦克风按钮,麦克风 下拉菜单中设置使用的设备(如:VoiceMeeter Output)
  4. (可选)如果想翻译同时自己也听到,打开 Voicemeeter 软件就行了,程序会自动输出选择一个输出。

记住,不能静音,同时要打开 系统的麦克风 !!

–END

斐讯K2刷机记录

很久以前就在JD弄了一个K2,当时没有啥需求,所以也没有折腾 。最近尝试DDNS域名绑定到动态的IP,想在家有一个能提供SSH访问的机器。原来的树莓派被弄坏了,就想着折腾折腾刷刷K2,在上面安装一个SSH。

同时也把官网提供的系统净化净化。

原K2的详细信息

斐讯K2 1200M智能双频无线路由器 WIFI穿墙 PSG1218

了解刷机流程

  • 官方版本可能存在的问题:

http://www.right.com.cn/forum/thread-208302-1-1.html

  • 刷机直接参考

【2017-12-01】斐讯K2 V22.5.9.163官方固件定制版,集成breed,支持官版直刷【V1.8】

详细步骤

  1. 更新版本到 V22.5.9.163

    查看官网提供的软件, 下载对应的版本

    • K2_A2_V21.4.6.12.bin
    • K2_V22.5.9.163.bin
  2. 刷净化版(带Bread)k2_163_v18_breed.rar

    • 下载地址

    • breed刷入第三方固件

      进入Bread方法,这个了解下就行,这里不刷第三方的。

      拔除K2上Wan口的网线,路由器断电,持续按住路由器上的reset按钮,接通路由器电源,3秒后松开reset按钮。 在浏览器地址栏输入 http://192.168.1.1 访问Breed Web。

  3. 启动telnet/手动安装SSH

3.1. 启动telnet

用 高级设置 - 系统设置 - WebShell 执行命令

1
/www/cgi-bin# /usr/sbin/telnetd -l /bin/login.sh

直接连,不用密码!!

1
winse@DESKTOP-ADH7K1Q:~$ telnet 192.168.2.1

同时修改下密码:

1
2
# 更改root密码为 admin
echo -e 'admin\nadmin' | passwd root

3.2. 安装SSH

这个版本没有带opkg,需要首先把opkg安装好。

直接下载 opkg.zip 然后本地起一个 httpserver 提供一个下载的服务。

1
2
winse@DESKTOP-ADH7K1Q:/mnt/e/SOFTWARE/k2$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

在telnet窗口执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@K2:/www/cgi-bin# cd /bin
root@K2:/bin# wget http://192.168.2.160:8000/opkg
--2018-06-20 22:50:18--  http://192.168.2.160:8000/opkg
Connecting to 192.168.2.160:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 130247 (127K) [application/octet-stream]
Saving to: 'opkg'

opkg                                  100%[=========================================================================>] 127.19K   176KB/s   in 0.7s

2018-06-20 22:50:18 (176 KB/s) - 'opkg' saved [130247/130247]

root@K2:/bin# chmod +x opkg
注意:用完后就删掉吧 `rm -rf /bin/opkg` ,空间不够!!查看[安装了那些软件](https://unix.stackexchange.com/questions/157097/how-to-know-disk-space-occupied-by-packages-in-openwrt)

```
rm -rf /bin/opkg

root@K2:/overlay# du -sh */*/*
root@K2:/overlay# rm -rf usr/lib/opkg
```

然后安装ssh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
opkg install http://downloads.openwrt.org/barrier_breaker/14.07/ramips/mt7620a/packages/base/dropbear_2014.63-2_ramips_24kec.ipk
# 开机自启
/etc/init.d/dropbear enable

# https://openwrt.org/docs/guide-user/base-system/ssh_configuration
# https://wiki.openwrt.org/doc/uci/dropbear
vi /etc/config/dropbear
        option GatewayPorts '1'
        
# 启动
/etc/init.d/dropbear start

uci show dropbear

# 如果需要放开防火墙
iptables -I INPUT 1 -p tcp -m tcp --dport 22 -j ACCEPT


vi /etc/firewall.user
# 删除无用文件
rm -rf /etc/dropbear/dropbear_dss_host_key

注意:需要持久化的话,把这句开放22端口的指令写到 /etc/firewall.user 。

客户端登录:

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
26
27
28
29
winse@DESKTOP-ADH7K1Q:~$ ssh root@192.168.2.1
The authenticity of host '192.168.2.1 (192.168.2.1)' can't be established.
RSA key fingerprint is SHA256:vuAY65qk3Us4MyjYT8KPT8lYsTSTqru6W4e7My6CRkk.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.2.1' (RSA) to the list of known hosts.
root@192.168.2.1's password:


BusyBox v1.22.1 (2017-02-15 13:52:46 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

    ___  __ _______________  __  _____  ___  ________  ___
   / _ \/ // /  _/ ___/ __ \/  |/  /  |/  / / __/ __ \/ _ \
  / ___/ _  // // /__/ /_/ / /|_/ / /|_/ / _\ \/ /_/ / ___/
 /_/  /_//_/___/\___/\____/_/  /_/_/  /_/ /___/\____/_/
 ----------------------------------------------------------
 Barrier Breaker, unknown
 ----------------------------------------------------------
 PID=K2
 BUILD_TYPE=release
 BUILD_NUMBER=163
 BUILD_TIME=20170215-134532
 ----------------------------------------------------------
 MTK OpenWrt SDK V3.4
 revision : adab2180
 benchmark : APSoC SDK 5.0.1.0
 kernel : 144992
 ----------------------------------------------------------
root@K2:~#

不推荐用密码,最好使用公钥的方式来处理。但公钥访问有点问题,.ssh的目录权限是个麻烦事 (其实文件的位置不对!!)。

参考: Dropbear public-key authentication HowTo

ssh root@192.168.1.1 “tee -a /etc/dropbear/authorized_keys” < ~/.ssh/id_rsa.pub

把 authorized_keys 文件移到 /etc/dropbear 下面就可以了!

1
2
3
4
5
root@K2:~/.ssh# ls -la
drwx------    2 root     root             0 Jun 21 10:35 .
drwx------    1 root     root             0 Jun 21 08:57 ..
-rw-------    1 root     root           397 Jun 21 10:35 authorized_keys
root@K2:~/.ssh# mv authorized_keys /etc/dropbear/

其他拓展

增加空间,挂载windows共享目录

https://blog.vircloud.net/linux/openwrt-psg1218.html

K2 官方版式不带 USB,因此就限制了很多可玩的东西,但是我们可以通过 SMB 挂载的方式来增加存储空间,需要注意的是老毛子挂载 SMB 的方式与其他 OpenWRT 不同,使用 mount 命令是挂载不成功的,正确的方法是:

位置:高级设置 - 自定义设置 - 脚本 - 在路由器启动后执行 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
### SMB资源挂载(局域网共享映射,无USB也能挂载储存空间)
### 说明:共享路径填写时,【\】要写成【\\】。
sleep 10
modprobe des_generic
modprobe cifs CIFSMaxBufSize=64512
#mkdir -p /media/cifs
#mount -t cifs \\\\{host}\\{share} /media/cifs -o username={user},password={pass}
mount -t cifs \\\\192.168.31.100\\移动磁盘-C /mnt -o username=guest,password=guest

sleep 10
mdev -s
sleep 5
stop_ftpsamba
sleep 2
run_ftpsamba
sleep 5

Breed进入方式

  1. 将要刷的第三方固件准备好。
  2. 断电按着reset键不松手,然后通电5秒后再松开reset键。
  3. 打开浏览器输入http://192.168.1.1%E5%8D%B3%E5%8F%AFBreed Web恢复控制台(记得先在Breed Web恢复控制台中的固件备份里备份下EEPROM和编程器固件,以后可能用得着)。
  4. 恢复固件之前最好在Breed Web恢复控制台恢复一下出厂设置,固件类型:Config区(公版)

参考:

其他参考

–END

使用VMWare安装Mac OS X

参考:

实际操作:

  • 安装 VMware-workstation-full-12.5.7-5813279 。
  • 下载 unlocker208.zip 并使用管理员权限安装 win-install.cmd 。
  • 添加虚拟机,选择 Apple Mac OS X(M) - OS X 10.9;然后修改vmx配置,在 smc.present = "TRUE" 后面添加 smc.version = "0"
  • 然后光盘选择 Mavericks_Install_13A603.cdr 安装系统。磁盘格式化:实用工具 - 磁盘工具
  • 安装VMWare Tools。光盘选择 darwiniso.zip 压缩包里面的 darwin6.0.3.iso 。
  • 配置共享文件夹。进入系统后,Finder - 偏好设置 - 已连接的服务器

–END

使用注解生成代码

Java里面随处可见annotation(注解),RetentionPolicy 指示了注解使用的情况:

  • SOURCE,比如 @Override, @SuppressWarnings
  • RUNTIME,最熟悉的莫过于Spring Bean中使用的 @Controller, @Service 一般和反射同时使用。
  • CLASS

而 CLASS 则是用于 compile 编译阶段的注解。一个注解的处理器,以Java代码(或编译过的字节码)作为输入,生成Java文件。这些生成的Java文件,会同其他普通的手动编写的Java源代码一样被javac编译。

可以自己实现一些类似groovy语法糖的功能(lombok框架修改bytecode为类生成新方法getter/setter、或者使用生成新的辅助类等);减少机械的、冗余代码的管理,使得代码更简洁便于阅读。

代码生成

先来了解下整个过程,javac 从 ServiceLoader 获取一个 Processor 标注处理类,判断是否为符合条件的标注,再收集类的相关信息,然后使用 Filer 创建新的类。Java Annotation Processing and Creating a Builderjava annotation processor 主要涉及到如下三部分:

  • Annotation: @BuilderProperty
  • Processor: BuilderProcessor
  • Service:

    通过google的auto-service来注册服务,最终会在 META-INF/services/ 生成名称为 javax.annotation.processing.Processor 的文件,内容为当前被标注的类名。

项目的目录结构如下:

具体实现:

  • BuilderProperty 注解
1
2
3
4
5
6
7
8
9
10
11
package com.github.winse.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface BuilderProperty {
}
  • BuilderProcessor
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package com.github.winse.processor;

import com.github.winse.annotation.BuilderProperty;
import com.google.auto.service.AutoService;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ExecutableType;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @see BuilderProperty
 */
@SupportedAnnotationTypes("com.github.winse.annotation.BuilderProperty")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class BuilderProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> annotationElements = roundEnv.getElementsAnnotatedWith(annotation);

            Map<Boolean, List<Element>> annotationMethods = annotationElements.stream()
                    .collect(Collectors.partitioningBy(element -> ((ExecutableType) element.asType()).getParameterTypes().size() == 1 && element.getSimpleName().toString().startsWith("set")));

            List<Element> setters = annotationMethods.get(true);
            List<Element> otherMethods = annotationMethods.get(false);

            otherMethods.forEach(element -> processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@BuildProperty must be applied to a setXxx method with a single argument", element));

            if (setters.isEmpty()) {
                continue;
            }

            String className = ((TypeElement) setters.get(0).getEnclosingElement()).getQualifiedName().toString();

            Map<String, String> setterMap = setters.stream().collect(Collectors.toMap(
                    setter -> setter.getSimpleName().toString(),
                    setter -> ((ExecutableType) setter.asType()).getParameterTypes().get(0).toString()
            ));

            try {
                writeBuilderType(className, setterMap);
            } catch (IOException e) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
            }
        }
        return true;
    }

    private void writeBuilderType(String className, Map<String, String> setterMap) throws IOException {
        String packageName = null;
        int lastDot = className.lastIndexOf(".");
        if (lastDot > 0) {
            packageName = className.substring(0, lastDot);
        }

        String simpleClassName = className.substring(lastDot + 1);
        String builderClassName = className + "Builder";
        String builderSimpleClassName = builderClassName.substring(lastDot + 1);

        JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(builderClassName);
        try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
            if (packageName != null) {
                out.printf("package %s;\n", packageName);
                out.println();
            }

            out.printf("public class %s {\n", builderSimpleClassName);
            out.println();
            out.printf("  private %s object = new %s();\n", simpleClassName, simpleClassName);
            out.println();
            out.printf("  public %s build() {\n", simpleClassName);
            out.printf("    return object;\n");
            out.printf("  }\n");
            out.println();

            setterMap.entrySet().forEach(setter -> {
                String methodName = setter.getKey();
                String argumentType = setter.getValue();

                out.printf("  public %s %s(%s value){\n", builderSimpleClassName, methodName, argumentType);
                out.printf("    object.%s(value);\n", methodName);
                out.printf("    return this;\n");
                out.printf("  }\n");
                out.println();
            });

            out.printf("}\n");

        }
    }

}

测试使用:

  • build.gradle

我使用的是4.7的版本,4.7及以上版本可以直接使用 annotationProcessor 来添加标注处理器。(其他版本可以使用 apt 来处理)

1
2
3
4
5
6
7
8
9
10
plugins {
    id "net.ltgt.apt" version "0.10"
}

sourceSets.main.java.srcDirs += ['build/generated/source/apt/main']

dependencies {
    compile rootProject
    annotationProcessor project(':compiler')
}
  • Person

这是一个POJO类,BuilderProcessor处理器会根据BuilderProperty注解来生成PersonBuilder类。

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
26
package com.github.winse.example;

import com.github.winse.annotation.BuilderProperty;

public class Person {
    private int age;
    private String name;

    @BuilderProperty
    public void setAge(int age) {
        this.age = age;
    }

    @BuilderProperty
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

生成代码效果

在 gradle 面板中选择子项目 :example ,然后选择 Tasks 下的 build 任务进行构建。构建完后在 example/build/generated/source/apt 目录下生成了对应的 Builder 代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.github.winse.example;

public class PersonBuilder {

  private Person object = new Person();

  public Person build() {
    return object;
  }

  public PersonBuilder setName(java.lang.String value){
    object.setName(value);
    return this;
  }

  public PersonBuilder setAge(int value){
    object.setAge(value);
    return this;
  }

}

注解处理器调试

不会调试说明还没有真正的入门。并且没有调试的情况下,解决异常、错误也是一件异常痛苦的事情。注解处理器生成代码是在编译阶段来生成代码的,所以调试的选项配置添加到 javac 。而 gradle 提供了一种相对简单的方式来进行。

参考

具体步骤如下:

  1. 在命令行运行构建

    添加调试参数后,gradle 会 暂停等待远程调试 ,相当于添加了 JVM 调试参数。Gradle properties

    hello-annotation-processor\example>gradle clean build --no-daemon -Dorg.gradle.debug=true
    或者
    hello-annotation-processor>gradle example:clean example:compileJava --no-daemon -Dorg.gradle.debug=true
    

    注: –no-daemon 不加也是可以的,但是运行该次构建后不会停止。

  2. 远程调试

其他调试配置方式

  • 通过环境变量

    example>set GRADLE_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
    
    example>gradle clean build
    Listening for transport dt_socket at address: 5005
    
  • 修改 ~/.gradle/gradle.properties

    这种方式不推荐,因为它是全局的。

    org.gradle.daemon=false
    org.gradle.debug=true
    

    或者

    org.gradle.daemon=true
    org.gradle.jvmargs=-XX:MaxPermSize=4g -XX:+HeapDumpOnOutOfMemoryError -Xmx4g -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006
    
    $ gradle --daemon
    

    Then attach your debugger client to port 5006, set your breakpoint, then run your test.

    注:该配置放到项目目录下没用。

其他

–END