Rust Windows环境搭建

该文章主要讲述在windows10+vscode下如何构建一个完整的rust编译调试环境,以及过程中可能出现的问题。

Rust构造

rust 官方提供了一系列版本、包安装管理工具,如rustup和cargo。

基本组件

rustup

初始化

rustup.rs官网下载rustup-init.exe(其他平台同理),这个软件是一个初始配置包,会帮助你下载选择版本的rustup和cargo。

打开软件后会显示如下信息:

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
Welcome to Rust!

This will download and install the official compiler for the Rust programming
language, and its package manager, Cargo.

It will add the cargo, rustc, rustup and other commands to Cargo's bin
directory, located at:

~\.cargo\bin

This path will then be added to your PATH environment variable by modifying the
HKEY_CURRENT_USER/Environment/PATH registry key.

You can uninstall at any time with rustup self uninstall and these changes will
be reverted.

Current installation options:

default host triple: x86_64-pc-windows-msvc
default toolchain: stable
modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
> _

默认安装于用户目录下。

该软件默认检查环境变量CARGO_HOMERUSTUP_HOME,分别为.cargo.rustup设置目录,按需修改(需要注意的是后期包的累积可能会占用巨量的存储空间)。

安装过程中请选择第二项 “Customize installation” !注意到default host triple中设置的是x86_64-pc-windows-msvc,本文所使用的调试器是GDB,故需要修改为x86_64-pc-windows-gnudefault toolchain请选择stable,即稳定版。nightly为前瞻版,’beta’为测试版,实际使用时我们仍需使用到nightly版,后文会提到。

下载完成后可在path中检查添加.cargo/bin以使用各种命令。

输入rustup --version以检查是否安装成功。

setting.toml

TOML(Tom’s Obvious Minimal Language) 是一个想要打败yuml的标注语言,caogo项目也有使用。

该文件位于.rustup/下。

  • default_host_triple: 第一次安装时设置,只能对该文件进行修改以改变默认值。
  • default_toolchain : 默认使用的toolchain,可由rustup default <toolchain name>进行修改。

rustup命令

以下列出rustup的部分命令:

  • > rsutup show : 列出现在使用的和已安装的rust版本。
  • > rustup update : 更新所有已安装版本,由于nightly偶尔会爆肝日更,所以谨慎更新。
  • > rustup default: 设置将要使用的版本。
  • > rustup component <sub> : 检查(list)、安装(add)、移除(remove)组建。

加速

此处使用科大源为例,修改PATH如下:

  • RUSTUP_DIST_SERVER : https://mirrors.ustc.edu.cn/rust-static
  • RUSTUP_UPDATE_ROOT : https://mirrors.ustc.edu.cn/rust-static/rustup

将同时加速cargo和rust,下载慢的可以体验一下w。

Cargo

cargo既是一个类似于npm、pip的包管理软件,又是一个像marven一样的项目框架。一个> cargo help可以让你懂得它有多nb。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
build       Compile the current package
check Analyze the current package and report errors, but don't build object files
clean Remove the target directory
doc Build this package's and its dependencies' documentation
new Create a new cargo package
init Create a new cargo package in an existing directory
run Build and execute src/main.rs
test Run the tests
bench Run the benchmarks
update Update dependencies listed in Cargo.lock
search Search registry for crates
publish Package and upload this package to the registry
install Install a Rust binary. Default location is $HOME/.cargo/bin
uninstall Uninstall a Rust binary

更详细的介绍……点❤我❤看❤文

集成于VS Code

再此之前,先设置一遍可能用到的环境变量。

  • RUST : 某toolchain的目录,如%USER%\.rust\toolchains\stable-x86_64-pc-windows-gnu
  • RUST_SRC_PATH : 改版本rust的源码目录,如%RUST%\lib\rustlib\src\rust\src,若你的rustlib中没有src,请执行> rustup cpmponent add rust-src
  • RUSTBINPATH : %CARGO_PATH%\bin

好,打开VS Code!

插件配置

sp181222_141230

商店搜索前两个就是几十万人下载的工具,两个都装上吧?前者是官方的包括rls在内的综合插件。后者虽然是第三方,但功能不比官方少。

你需要在settings.json文件中选择性键入以下内容(为第三方插件配置而不是官方):

1
2
3
4
5
6
7
8
9
"rust.mode": "legacy",
"rust.cargoHomePath": "%CARGO_HOME%",
"rust.cargoPath":"%RUSTBINPATH%\\cargo.exe",
"rust.racerPath":"%RUSTBINPATH%\\racer.exe",
"rust.rls":"%RUSTBINPATH%\\rls.exe",
"rust.rustfmtPath":"%RUSTBINPATH%\\rustfmt.exe",
"rust.rustup":"%RUSTBINPATH%\\rustup.exe",
"rust.rustLangSrcPath": "%RUST_SRC_PATH%",
"rust.executeCargoCommandInTerminal": true,

很巧妙的是官方插件会为你提示是否提供权限安装nightly,请选择允许,并把你的default toolchain设置为nightly

1
2
3
4
> rustup default nightly
> rustup update
...
> rustup component add rust-analysis

漫长的安装完成后,写一个小程序试一试。

main.rs

1
2
3
fn main(){
println!("fa ♂");
}

至此,基本能实现实时提示错误、高亮、用户片段。

常见错误

  1. 官方插件提示 RLS could not set RUST_SRC_PATH for Racer because it could not read the Rust sysroot.

    尝试使用以下方法:

    • 使用管理员模式启动Vs Code。
    • 确定各path位置正确。
    • 添加setting.json条目"rust-client.channel": "stable",或nightly。
    • 重新使用cargo建立一个项目

    错误原因如下

    stackoverflow:

    该插件 readme文件列出了如下依赖:

    • Rustup,
    • 一个toolchain (插件会在获得权限后自动安装),
    • RLS, rust-src, rust-analysis组件.
  2. 待补充

调试

LLDB很棒,但是有请我们的TDM-GDB出场(打扰了)。

sourceforge上下载后,解压得到bin、gdb64、share至某目录(我的是D:\env)。

配置rust-gdb

之前下载的rust源码(%rust%\lib\rustlib)提供了一套gdb配置。

修改gdb64\bin目录下的gdbinit文件,在末尾添加以下代码:

1
2
3
4
5
6
python
print "-- loading rust pretty-printers --"
sys.path.insert(0,'%rust%/lib/rustlib/etc')
import gdb_rust_pretty_printing
gdb_rust_pretty_printing.register_printer(gdb)
end

执行(> bin\gdb.exe),若能输出”– loading rust pretty-printers –“并没有报错,说明gdb工具配置成功。

配置Vs Code

安装Native Debug插件(ext install debug)。

用Vs Code打开你的Cargo工程,添加调试配置GDB,将target指向生成的exe文件,将gdbpath设置为刚刚配置的gdb.exe。

添加一个task,选择cargo build,设置为preLaunchTask

task

这时你的launch.json大致如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "gdb",
"request": "launch",
"preLaunchTask": "cargo build",
"target": "${workspaceRoot}\\target\\debug\\optimvsc.exe",
"gdbpath": "D:\\env\\gdb-tdm64\\bin\\gdb.exe",
"cwd": "${workspaceRoot}"
}
]
}

快快创建断点测试一下吧!

Permission denied when git push

在很长一段时间没有使用git push 后,你的sshkey可能会过期:

1
2
3
Permission denied(publickey).
fatal: Could not read from remote repository
Please make sure you have the correct access rights and the repository exists.

解决方案:

  1. 1
    2
    3
    4
    5
    6
    ssh-keygen -t rsa -C "youremail@example.com"
    ssh -v git@github.com
    ssh-agent -s
    # eval `ssh-agent -s`
    ssh-add ~/.ssh/id_rsa
    cat ~/.ssh/id_rsa.pub

注意,上述youremail@example.com是指github账户的注册邮箱

上述命令执行后id_rsa.pub文件内容将输出到终端,复制里面的密钥(内容一般是以ssh-rsa 开头,以github账号的注册邮箱结尾的,全部复制下来)至github设置中的ssh-keys。

最后运行以下命令

1
ssh -T git@github.com

Hi —! You’ve successfully authenticated, but GitHub does not provide shell access.

Keras Intro : 基本模型保存

Sequential-Module模型

常用层

Dense全连接

1
2
3
4
5
6
7
8
9
10
keras.layers.core.Dense(units,
activation = None,
use_bias = True,
kernel_initializer = 'glorot_uniform',
bias_initializer = 'zeros',
kernel_regularizer = None,
bias_regularizer = None,
activity_regularizer = None,
kernel_constraint = None,
bias_constraint = None)

Dense就是常用的全连接层,所实现的运算是output = activation(dot(input, kernel)+bias)。其中activation是逐元素计算的激活函数,kernel是本层的权值矩阵,bias为偏置向量,只有当use_bias=True才会添加。
参数说明

  • units:大于0的整数,代表该层的输出维度
  • activation:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)
  • use_bias: 布尔值,是否使用偏置项
  • kernel_initializer:权值初始化方法,为预定义初始化方法名的字符串,或用于初始化权重的初始化器。参考initializers
  • bias_initializer:偏置向量初始化方法,为预定义初始化方法名的字符串,或用于初始化偏置向量的初始化器。参考initializers
  • kernel_regularizer:施加在权重上的正则项,为Regularizer对象
  • bias_regularizer:施加在偏置向量上的正则项,为Regularizer对象
  • activity_regularizer:施加在输出上的正则项,为Regularizer对象
  • kernel_constraints:施加在权重上的约束项,为Constraints对象
  • bias_constraints:施加在偏置上的约束项,为Constraints对象

SKLearn玄学操作

分离数据集

train_test_split是交叉验证中常用的函数,功能是从样本中随机的按比例选取train data和test data,形式为:

1
X_train,X_test, y_train, y_test = cross_validation.train_test_split(train_data, train_target, test_size=0.4, random_state=0)

  • train_data:所要划分的样本特征集
  • train_target:所要划分的样本结果
  • test_size:样本占比,如果是整数的话就是样本的数量
  • random_state:是随机数的种子。

引用

ML神器:sklearn的快速使用

OneHot编码知识点

机器学习零基础?手把手教你用TensorFlow搭建图像分类器

OpenCV Intro : 基本图像操作

Open Computer Vision 万物起源。

1
2
3
4
import cv2
# OpenCV本体
import numpy as np
# 数学库

图像基本操作

读取、显示、保存

1
2
3
IMG_PATH = "/path/to/img"
# 此处图片链接可能不支持中文
img = cv2.imread(IMG_PATH,cv2.IMREAD_COLOR)

opencv支持以下三种读入方式:

  • cv2.IMREAD_COLOR: 默认,仅(R,G,B)通道
  • cv2.IMREAD_GRATSCALE: 灰度
  • cv2.IMREAD_UNCHANGED: 包括(R,G,B,A)通道
1
2
3
4
5
cv2.imshow("WindowName",img)
# 创建一个名字为WindowName的窗口,把之前imread读入的照片以yuanchicun显示在窗口上。
cv2.waitKey()
# Press Any Key To Continue...
cv2.imwrite("/Path/to/CopiedPic",img)

阅读全文

节奏游戏开发时的万般阻难

施工中……

音符同步

senator

你需要[RequireComponent(typeof(AudioSource))]来规定该元件可被作为音游元件。

  1. 使用AudioSettings.dspTime 跟踪歌曲的位置,而不是使用 Time.timeSinceLevelLoad

  2. 使用歌曲的位置来更新移动。

  3. 不要通过每帧的时差来更新音符。

位置跟踪

在所有节奏游戏中,我们必须跟踪歌曲位置,以确定是否应该生成音符。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
float songPosition;
// 节拍当前位置
float songPosInBeats;
// 节拍的持续时间
float secPerBeat;
float dsptimesong;
// We initialize these fields in the Start() function:
void Start() {
secPerBeat = 60f / bpm;
dsptimesong = (float) AudioSettings.dspTime;
// 开始播放音乐
GetComponent<AudioSource>().Play();
}

我们转换bpmsecPerBeat后面方便使用。secPerBeat将用于计算节拍中的歌曲位置,这对音符生成非常重要。

我们用dsptimesong记录歌曲的开始时间。使用AudioSettings.dspTime跟踪歌曲的位置,而不是使用Time.timeSinceLevelLoad。因为Time.timeSinceLevelLoad只在每个帧中更新,而AudioSettings.dspTime更新频率更高,因为它是音频系统的定时器。为了保持歌曲的速度,我们必须使用音频系统的定时器来避免帧更新和音频更新之间的时间差引起的延迟。

Update()函数中,我们通过AudioSettings.dspTime计算歌曲的位置:

1
2
3
4
5
void Update()
{
songPosition = (float) (AudioSettings.dspTime - dsptimesong);
songPosInBeats = songPosition / secPerBeat;
}

歌曲信息

移动到我们记录歌曲信息的字段:

1
2
3
float bpm;
float [] notes;
int nextIndex = 0;

为了简单起见,我演示的歌曲只有一个轨迹的音符。

bpm是一首歌的每分钟的节拍数。正如我们所看到的,secPerBeat为了方便起见被转换了。

notes是一个数组,保持歌曲中音符的位置。例如,notes将初始化为{1f,2f, 2.5f, 3f,3.5f, 4.5f}

产生音符

我们确定是否应该在Update()函数中产生一个音符前。但我们应该首先确定显示节拍的数量。

例如曲谱中,当前的歌曲position-in-beats为1,但是节拍3已经产生,意味着提前显示3个节拍。

1
2
3
4
5
6
songPosInBeats = songPosition / secPerBeat;, add the following lines:
if (nextIndex < notes.Length && notes[nextIndex] < songPosInBeats beatsShownInAdvance)
{
Instantiate( /* Music Note Prefab */ );
nextIndex ;
}

我们首先检查歌曲(nextIndex < notes.Length)中是否已经没有音符,如果还有音符,那么我们再看看歌曲是否到达要播放下一个音符的节奏(notes[nextIndex] < songPosInBeats + beatsShownInAdvance)。如果满足条件,产生音符,nextIndex自增,以便nextIndex保持下一个音符的产生。

移动音符

最后,如何按照这首歌来移动我们产生的音符。不要通过帧的时差来移动它们。

始终按照歌曲的位置更新移动,因为

  1. 音频定时器与帧定时器有时差

  2. 节拍可能在两帧中间

那么,怎么移动音符呢?插入法!为了简单起见,我将把所有的代码放在MusicNote类上,并且只在Update()移动我们的音符:

1
2
3
4
5
6
7
void Update() {
transform.position = Vector2.Lerp(
SpawnPos,
RemovePos,
(BeatsShownInAdvance - (beatOfThisNote - songPosInBeats) ) / BeatsShownInAdvance
);
}

判定提前

姑且定义以下几种判定时间点:

  • CHECK_PERFECT
  • CHECK_GREAT
  • CHECK_MISS

每个音符到达dspTime - CHECK_MISS时触发miss判定
南梦宫所提出的判定方案是

视觉反馈

额外音效

processing

Tic Tac Toe “我也不知道是什么”算法

为了巩固类、数组等知识,下来一个Assignment,定睛一看,居然是个四子棋!没想到人在江湖,也会遇上如此困难之题,随缘写个备注以防自己忘记。

完整代码已上传至 timrockefeller/ExplotionEuler

阅读全文

ゼロから始めるJAVA世界生活 03

关于数组、函数的碎片知识。

阅读全文

ゼロから始めるJAVA世界生活 02


很快我们就进入了结构阶段,这些东西貌似在c++,c#里都差不多,是逻辑的基本组成部分。

判别结构

if-else

1
2
3
4
5
6
7
8
9
10
11
12
13
if(布尔表达式)
{
//如果布尔表达式为true将执行的语句
}
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}

阅读全文

机械卷轴:概念设计中的心理暗示

谈科幻设计

符号化设计

脑洞 + 凭感觉 (头脑风暴)

一款急速的飞行器,你会如何画?

符号对不同设计倾向的引导。

阅读全文