Lenovo Legion Y7000


In my previous blog, I mentioned I changed a new laptop. My older faulty laptop is Dell Vostro 5459, which was four years old. My current laptop is Lenovo Legion Y7000 2019 PG0 model 81T0, which as higher spec than the old one. Besides that, I added another 1T HDD, just in case I may doing machine learning study, or my work requires large disk space.

Note: All the instructions should follow official Arch Linux Wiki. The followings are only based on my experience of this installation.

Installation preparation

Since I have an extra HDD and plan for dual boot, I preserve the Windows in the SSD. Therefore in Windows, firstly disable Fast Boot, and secondly allow UTC time.

After this, I disable the Secure Boot through BIOS.

Since my primary OS is Arch Linux, I usually prepare two Live USBs, Arch Linux and SystemRescueCD. I just found that the recent SystemRescueCD is built based on Arch Linux.

SystemRescueCD is useful especially doing partitioning, shrinking/growing partition, and moving partitions, using GUI. Command-line like cfdisk and cgdisk can do partitioning, but moving partitions will be less intuitive comparing to GUI.

However, I failed to run SystemRescueCD with Xorg (running startx) due to graphic driver issue. (Though later, I found that it can be solved by going to BIOS, and change the Graphic Mode to “Switchable”, where the default is “Discrete”.)

As a result, I continued with Arch Linux Live USB. Due to the graphic driver issue, the TTY is not rendered properly. This can be solved by adding nomodeset parameter to the Kernel, by editing the GRUB menu during the boot.

Network

After boot into the Arch Linux installation Live USB, the first thing must solve is the networking. In this modern day, a laptop that cannot connect internet with WiFi is useless. However, the WiFi of Lenovo Legion Y7000 was blocked (plane mode) by default when running in Live USB. This can be solved by rfkill unblock all. Then, I started the network service with netctl.

Partitioning and boot loader

I believe most modern laptop and HDD support GPT. Since I am using command-line interface, cgdisk is sufficient for the partitioning. I created three partitions, for / (root), swap, and /home.

After partitioning and mounting, I installed the Arch through network.

Boot loader is a little troublesome. I chose GRUB. I believe most modern laptop supports EFI. So, I booted into Windows and used Disk Management to find the partition that is used for boot. One of the partitions is EFI.

Then in Arch Linux live media, I installed grub, os-probe, and efibootmgr.

Note: I installed the grub after I have run pacstrap. pacstrap will create /boot directory. So, I renamed it to /boot to /boot~, and create another /boot for GRUB installation.

I mounted the partition to /boot (in arch-chroot environment), then follow the instructions here.

os-probe is useful to allow dual boot to Windows, as it will generate the GRUB menu entry for Windows automatically.

After this, reboot to make sure we can boot into the new installation.

Note: Add nomodeset to the Kernel in the /etc/default/grub if rendering fails.

Network again

After boot into newly installed Arch Linux, I was not able to connect internet, because required packages were not installed. So, I needed to boot to the live media again, with the network connection, install wpa_supplicant, netctl, and dhcpcd. Then at least I can connect to internet with the newly installed Arch Linux.

NVIDIA

After the network, the second big problem is NVIDIA. I choose NVIDIA, because it supports CUDA, as it is important for machine learning, especially deep learning.

I used nvidia-dkms, which I have good experience with this package.

But I faced two main problems. One is the brightness not able to be controlled when running Xorg. The documentation mentioned that this can be solved by adding

option "RegistryDwords" "EnableBrightnessControl=1"

in /etc/X11/xorg.conf or relevant file, under “Device” section “nvidia” driver.

The above solution doesn’t work perfectly. When I boot into LightDM (display manager), sometimes the brightness is 100%, which I cannot reduce the brightness. But sometimes it works fine.

When the brightness is 100%, I need to restart the LightDM, or login and logout (I am using Openbox). Then the brightness is controllable.

The second problem is hibernation. I failed to resume from hibernation. It was a nightmare, as one of my testings failed to boot properly.

I have tried several solution, such as this, and this, and this. None of them work.

I also tried to use linux-lts. But it doesn’t solve the brightness problem, and the WiFi failed to work. So, I give up linux-lts.

And I give up the hibernation as well. It is useful, but I still can work without hibernation.

Note: After successful installation of NVIDIA, we can remove nomodeset from the GRUB entry.

Touchpad

I was using Synaptics. But it is no longer actively updated, and the official documentation suggest to use libinput.

So, I am using libinput now, but it sadly doesn’t support circular scrolling.

f.lux

I was using f.lux for health purpose. However, f.lux package doesn’t work on new laptop with NVIDIA. So, I switch to Redshift. The drawback is that, unlike f.lux GUI, Redshift is not able to change the colour temperature on the fly.

Leftover tasks

After these, I have to migrate a lot of data from my previous computer.

Danshari is necessary, so that not all data need to be migrated.

Family and personal photos (and some videos) are important, as they tell me who I was.

Personal data are important, as they tell me who I am.

Working data are important, as they allow me to continue what I am working with.

Configuration files are important, as I need not to waste my time to setup everything again. Especially Openbox, tint2, Mendeley Desktop, Postman, DBeaver, Emacs, VIM, bash, zsh, SSH, fcitx, fonts (and fontconfig), etc.

Other data files like movies, pictures, music are less important, but valuable. As I need not to collect them again.

Chinese New Year and new laptop


This was a disastrous week. Firstly, internet network cable broken. Secondly, my laptop went wild. Internet network cable broken, I still can online through mobile hotspot. But my laptop, it was catastrophic problem. Because I have a lot of valuable data, and I have to work.

Chinese proverb, 旧的不去,新的不来, but it was damn pressure. Because the old laptop had unpredictable behaviour. The problem was that, the keyboard will trigger some keys unintentionally, especially Alt key. I thought it was software problem, but until I reboot, and saw the GRUB menu cursor moving by itself. Damn! This means, (i) I am not able to work, (ii) I have to spend money to buy new laptop, and (iii) I need to get my data out.

First problem means that, I may not able to earn money during the period, as I am a freelance software engineer. Second problem means that, I need to spend money, with the possibility that I am not able to generate income, and the new laptop may not be Linux compatible. Linux compatibility is important to me, due to the familiarity and the working environment. Third problem means that, I may have possibility loss the data. I have done backup, but not frequent and not all data were backup. Though those data which I didn’t backup were less important, they are still valuable as I spent time on them.

Surely most important data are family photos, personal data, and those work related things. Though we use “git” and commit our source code, setup everything again spends time. Your employer doesn’t pay you to setup, but pay you to work. That is why I felt very pressure.

I prayed, I prayed, and prayed. Luckily keyboard problem was partially solved with USB keyboard, and Linux command “xinput float” can disconnect the built-in keyboard. And the new laptop can be used to work now (since yesterday). Though new laptop has higher hardware specifications than the old one, it is not perfect, as I failed to make it able to hibernate. NVIDIA and Linux combination is sh*t. But I still need NVIDIA, just in case I have to do machine learning with CUDA. So, for the moment, I have to sacrifice hibernation. Also, during the testing when resume from hibernation, it showed a freaking behaviour, I cannot type in the LightDM login. Damn, I cannot bear it if new laptop also broken.

Hopefully this is the end of the accident. I pray that this year will be new as this new powerful laptop.

祸不单行昨夜行,福无双至今日至。祝大家新年快乐。

Godot and C#


In my previous post, I wrote about my hobby project with Godot.

Limitations of GDScript

But I personally feel that, Godot script, namely GDScript, is not my favourite. Though GDScript is good enough to do anything, it is not what I like. Firstly, it is Python-like language. In my opinion, using indentation as scope is annoying, because I cannot auto-indent using Emacs. Due to my first programming language is C, and heavy use on JavaScript, braces (curly brackets {}) are easier to read.

Besides that, GDScript doesn’t have array operations similar to JavaScript, such as forEach. C# has List class with ForEach method. There are similar methods like map and reduce using LINQ.

Moreover, C# supports lambda expression. This is which GDScript cannot support. Even Python cannot do multiple lines lambda expression.

Comparing C# and GDScript, C# may be slower for development, but learning C# will be more useful than GDScript, as C# is a general purpose programming language. And C# has richer syntax.

Another reason I choose C# over GDScript is the testing. As a web developer, TDD (test-driven development) is a useful approach to make the product more stable. Development in GDScript doesn’t allow me to test my functions by writing test cases. If I choose C#, I can install Machine.Specifications (or MSpec) and Fluent Assertions through NuGet, then write the tests.

In fact, Godot supports native script using GDNative. This allows you to develop your module using C or C++ language. I like C and C++, but they are less efficient comparing to the modern programming languages. They are inefficient for development, as there is no garbage collection. Smart pointer is not garbage collection. However, C++ is acknowledged as best language for game development, according to Google Search.

Setup Godot Mono in Arch Linux

This section is Arch Linux specific.

Firstly, read this, and install godot-mono-bin. Secondly, install MonoDevelop and msbuild (msbuild-16-bin).

Once using Godot Mono to create a project, a solution file (.sln) and a project file (.csproj) will be created. These files are compatible with MonoDevelop. If you cannot open, probably you are using wrong version of msbuild.

To setup .NET Core in MonoDevelop, go to Edit > Preferences > Projects > SDK Locations > .NET Core, edit the location of the dotnet CLI as /opt/dotnet/dotnet, it will detect the SDK and runtime automatically.

Note: /usr/bin/dotnet cannot work, because it is a script.

Then, you can build your C# module using either MonoDevelop or Godot (Mono support). One great thing is, we can use both C# and GDScript together in the same project.

About NuGet

Unluckily, not every package manager acts like npm (Node) or bundle (Ruby). To install packages through NuGet, best approach is to use MonoDevelop.

Best web application framework I like


So far, in my opinion, Ruby on Rails is the best web application framework that I have used. Compared to others, it is very complete (by installing extra gems) and mature, provides everything that I need.

Version manager

There are two version managers: rvm and rbenv. I prefer rvm. It allows to work on different projects with different Ruby versions. Node has similar manager, nvm. Python has similar feature, but acts differently, using venv or virtualenv. In Python, we need to install the specific version, and create the environment by specifying our Python version. Contrarily, rvm or nvm will download and build the corresponding version.

Lambda expression

Ruby supports lambda or anonymous function, which can also be seen in JavaScript, as callback function. Newer languages such as C# and C++11 also support the syntax. The syntax is so useful when handling array. Python can support lambda expression, but it cannot support multiple lines like JavaScript.

REPL

Ruby on Rails has also very powerful REPL. With rails console, you can access the models easily, and manage the database through models.

Node can do similar, but it requires to write the script to setup the context. Meaning, we need to write the script so that REPL can access the controllers and models.

Debugging

Debugging in Rails can be done like client side JavaScript debug keyword, which require byebug gem. By using pry-byebug, we can debug the script line by line easily.

Migrations

Migrations and ORM in Rails simplify the development, as we need not to take care how the database should be structured, but focus on the models design, especially relationships like one-to-one, one-to-many, and many-to-many.

Migrations is commonly used in various web application frameworks, including .NET, Django, Laravel, etc. Node can implement migrations using sequelize and sequelize-cli.

Pagination

Kaminari gem allows to access the ActiveRecord with pagination related methods.

Serializer

By using ActiveModel::Serializers, we can make our JSON output more consistent.

Mailer

Mailer, which act exactly like Controller. And greatly, we can write preview page for the emails, in HTML or text.

CSRF protection

For the security, we can do protect_from_frogery to protect from CSRF.

BDD/TDD

Since we always need to test our code, BDD or TDD makes our development more stable and interesting.

By using rspec and factory_bot gems, we can do our testing easier, including mocking data and stub the methods.

Time travelling

Related to BDD, by using ActiveSupport::Time, we can test our code by specifying the date. Need not to use a date parameter through out all the function calls.

Job

We can do background job by using ActiveJob and also SideKiq.

Cache (SQL)

By default, the ActiveRecord (model) querying will use cache, example.

Drawback

Though Ruby on Rails is powerful, there is one limitation. There is no official support on Windows, which we cannot find the binary installation of the latest version of Ruby and Rails for Windows.

The only workaround for Windows installation is using WSL (Windows Subsystem for Linux). And this feature only available on Windows 10 and Windows Server 2019.

Meaning in older version Windows, probably needs to use virtualization like Docker or Vagrant. (I never tried before.)

Advantages

I prefer Ruby on Rails over Node, because Node has too many modules doing similar jobs, for example crypto-js and node-crypto-js. Too many options cause me to use extra effort to find out which one is better.

I prefer Ruby over Python, because of the lambda expression.

In my opinion, the advantage of Ruby on Rails is because of Ruby language itself.

To print the output, we can do puts something, instead of console.log(something) (JavaScript). Parentheses are optional to call the function, similar to Perl.

We can pass the hash to the function without braces, such as foobar(a: 1, b: 2). But in JavaScript, we need to do foobar({ a: 1, b: 2 }); in PHP, foobar(['a' => 1, 'b' => 2]); in Python foobar({'a': 1, 'b': 2}).

When developing using Ruby on Rails, we can apply Twelve-Factor and Design Patterns. We focus on code readability (using RuboCop), refactoring, and testing.

You can find a curated list of useful gems as well.

LightDM background image


Recently my old laptop, due to some unknown configuration, it shows a background image in the LightDM login. It is annoying, and it is user specific. Meaning, if I choose another user, the background image will be changed to black background.

Searched for the solution on Internet, most of links are about gsettings, or edit the image in /etc/lightdm/lightdm.conf. But none of the related to my issue.

Finally, I found the solution. The problem is not LightDM itself, but related to AccountsService.

To solve the issue, edit the /var/lib/AccountsService/users/[username], there is a line

[org.freedesktop.DisplayManager.AccountsService]
BackgroundFile='/path/to/custom/image.jpg'

That’s the culprit. Remove or comment out the BackgroundFile, then the problem solved.

Patch Wine and supports both 64-bit and 32-bit


We can build Wine that supports both 64-bit and 32-bit.

The below shows the example that involves patch of a specific Wine version. Sometimes official or latest Wine just doesn’t work. And the patches can be found in the bug report attachment.

Download a patch from Wine bug report, and download the source code. Extract the source

tar xJf wine-4.2.tar.xz
patch -u -p1 < ../swshader_ivb.patch

To build Wine that can work on both 64-bit and 32-bit, we can follow this.

The following is the script to build wine.

#!/bin/bash

srcdir="$(pwd)"
mkdir build-64 build-32

cd "$srcdir/build-64"
../configure --prefix=$HOME/mywines/wine-4.2-sw-blend \
  --libdir=$HOME/mywines/wine-4.2-sw-blend/lib \
  --enable-win64 --with-x
make -j4
cd "$srcdir/build-32"
PKG_CONFIG_PATH=/usr/lib32/pkgconfig ../configure \
  --prefix=$HOME/mywines/wine-4.2-sw-blend \
  --libdir=$HOME/mywines/wine-4.2-sw-blend/lib32 \
  --with-wine64=$HOME/mywines/wines/wine-4.2/build-64 \
  --with-x
make -j4

cd "$srcdir/build-64"
make install
cd "$srcdir/build-32"
make install

Now, you can use the this Wine to run specific game.

A Wine wrapper script can be found here

NVIDIA with Nouveau and Wine


I updated my old laptop HP Pavilion dv3 (2238tx) recently, which was bought in year 2010, installed with Arch Linux.

Because of Linux kernel version, the NVIDIA driver is not officially supported by Arch Linux (detail).

There are two options to resolve this: install (i) Nouveau or (ii) NVIDIA driver from AUR. The former is open source, the latter is closed source from NVIDIA official site. Furthermore, using the latter theoretically allows the usage of CUDA, which is important if I am using it to do some neural networks training.

Now, since this old laptop, 说好不好,说坏不坏, I tried to install games. Unluckily, the Windows 7 (it is dual boot) is 32-bit, which I don’t plan to re-install new version of Windows with 64-bit. So, I am trying to figure out Linux Wine whether it can work or not.

Firstly, I tried PlayOnLinux to install 64-bit Wine. But I found that 64-bit Wine in PlayOnLinux can run only 64-bit programs. Then after some study, I found that Arch Linux official Wine package supports both 64-bit and 32-bit.

So, I wrote a Bash script to do something like PlayOnLinux which can be found here, so that I can isolate the WINEPREFIX for different programs, and allows to use different versions of compiled Wine.

After some trial and errors, I make an almost 9 years old laptop to run a 64-bit game released in 2018, though the performance is not very good.

The followings are the setup/configuration:

  • Nvidia G98M (GeForce G 105M)
  • Nouveau and related packages like “mesa”
  • Wine 4.13
  • VirtualGL (Not sure whether it is required)
  • Winetricks and installed “d3dx9” (Not sure whether this is required)