X410 – run WSL gui applications as native Windows applications

Software developers who work on Windows have likely heard of WSL, which stands for the Windows Subsystem for Windows. Essentially, it is a way to run Linux distributions within Windows somewhat like running a virtual machine (VM) but more seamless – or akin to running a Docker container. WSL provides support for GUI applications out-of-the-box with WSLg. The important thing to note about WSLg is that it is implemented using the RDP protocol, so GUI applications are essentially run via an RDP process running on the host Windows machine. Due to this implementation, the performance of GUI applications running on WSLg will not perform as well as would a native Windows application or compared to running the application on a regular Linux installation.

There are some really cool uses of WSL even outside of software development that may be useful for users who are somewhat technical. Some of these are from the interoperability provided with WSL:

  • Windows drive C:\ is mounted in WSL at /mnt/c
  • WSL filesystems can be accessed at \\wsl.localhost and can be mounted to network drives (for example I have \\wsl.localhost\Arch mounted as L:\)

Windows provides the ability to mount network drives using FTP or SMB – however, it doesn’t provide support natively for mounting network locations using SSH/SFTP. Linux has a FUSE filesystem called sshfs. With WSL, this means network locations can be mounted and accessed from Windows. Similarly, Windows does not natively support mounting external drives containing ext4 formatted partitions.

X410 is a really cool alternative to WSLg, which allows X-Window GUI apps to run like any other Windows application. Note that X410 does require the purchase of a license. The license I purchased is for perpetual for the version when I purchased, though updating to newer versions of X410 will require an additional purchase. Here is an example of Caja running in X410: Caja File Manager in X410

Notice how the Window appears like a normal Windows application would. For comparison, here is what Caja looks like in WSLg: Caja File Manager in WSLg

While it may not look like much of a difference, the advantage of X410 is not about the appearance but performance. The UI responsiveness running X410 is noticeably better than running in WSLg.

GCC / make – pcdPointXYZRGB2txt.cpp:12:24: error: ‘split’ is not a member of ‘boost’

If make fails due to

[ 13%] Building CXX object CMakeFiles/treeseg.dir/src/treeseg.cpp.o
./treeseg/src/pcdPointXYZRGB2txt.cpp: In function ‘int main(int, char**)’:
./treeseg/src/pcdPointXYZRGB2txt.cpp:12:24: error: ‘split’ is not a member of ‘boost’
   12 |                 boost::split(tmp1,args[i],boost::is_any_of("/"));
      |                        ^~~~~
./treeseg/src/pcdPointXYZRGB2txt.cpp:13:24: error: ‘split’ is not a member of ‘boost’
   13 |                 boost::split(tmp2,tmp1[tmp1.size()-1],boost::is_any_of("."));
      |                        ^~~~~
make[2]: *** [CMakeFiles/pcdPointXYZRGB2txt.dir/build.make:79: CMakeFiles/pcdPointXYZRGB2txt.dir/src/pcdPointXYZRGB2txt.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:578: CMakeFiles/pcdPointXYZRGB2txt.dir/all] Error 2

This can be resolved by including the required header (source: boost::split in C++ library | GreeksForGeeks):

#include <boost/algorithm/string.hpp>

archlinux-pkgbuilds – Arch Linux PKGBUILDs

I maintain a set of PKGBUILDs for the Arch Linux distro in a public GitHub repository: archlinux-pkgbuilds. Many of these are modified versions from the official Arch package repositories or from AUR packages, however some are not found in either. The modifications for existing packages are usually small fixes for issues building with the existing version or to build configured with different CMake variables.

Many of the packages are GIS applications, including

Some of the PKGBUILDs have not been built in several years. I will periodically update this list with recently built packages that are not available in the official repos or AUR.

error launching Qt6 applications: Cannot mix incompatible Qt library (6.5.2) with this library (6.5.3)

> qt6ct
Cannot mix incompatible Qt library (6.5.2) with this library (6.5.3)
[1]    26923 IOT instruction (core dumped)  qt6ct

In order to determine the problematic library, use the strace command:

> sudo strace qt6ct
mmap(NULL, 24912, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 9, 0) = 0x7f90a0382000
mmap(0x7f90a0385000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 9, 0x3000) = 0x7f90a0385000
mmap(0x7f90a0386000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 9, 0x4000) = 0x7f90a0386000
mmap(0x7f90a0387000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 9, 0x4000) = 0x7f90a0387000
close(9)                                = 0
mprotect(0x7f90a0387000, 4096, PROT_READ) = 0
statx(AT_FDCWD, "/root/.config/qt6ct/qt6ct.conf", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=855, ...}) = 0
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=2852, ...}, 0) = 0
openat(AT_FDCWD, "/usr/lib/qt6/plugins/styles/libqt6gtk2-style.so.avx2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
access("/usr/lib/qt6/plugins/styles/libqt6gtk2-style.so.avx2", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/qt6/plugins/styles/libqt6gtk2-style.so", O_RDONLY|O_CLOEXEC) = 9
read(9, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(9, "", {st_mode=S_IFREG|0755, st_size=236056, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 234272, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 9, 0) = 0x7f909bc9a000
mmap(0x7f909bca5000, 155648, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 9, 0xb000) = 0x7f909bca5000
mmap(0x7f909bccb000, 24576, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 9, 0x31000) = 0x7f909bccb000
mmap(0x7f909bcd1000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 9, 0x37000) = 0x7f909bcd1000
close(9)                                = 0
mprotect(0x7f909bcd1000, 8192, PROT_READ) = 0
openat(AT_FDCWD, "/dev/tty", O_RDONLY|O_CLOEXEC) = 9
close(9)                                = 0
write(2, "Cannot mix incompatible Qt libra"..., 69Cannot mix incompatible Qt library (6.5.2) with this library (6.5.3)

After finding the problematic library, use pacman -Qo to find the package providing this file:

> pacman -Qo /usr/lib/qt6/plugins/styles/libqt6gtk2-style.so      
/usr/lib/qt6/plugins/styles/libqt6gtk2-style.so is owned by qt6gtk2-git 0.2.r5.g441f266-1

After rebuilding qt6gtk2, qt6ct launches successfully.

Linux, Plank Dock & Desktop Entries: Add an open ‘New Window’ action

Plank is a popular application launcher dock in Linux. By default, most application desktop entries do not provide any additional actions. Say we want to add an open ‘new window’ action to our desktop entry for pkgbrowser:

/usr/share/applications/pkgbrowser.desktop

Our desktop entry file looks as follows:

[Desktop Entry]
Name=PkgBrowser
GenericName=Package Browser
Comment=A utility for browsing pacman databases and the AUR
Exec=pkgbrowser
Terminal=false
Type=Application
Icon=pkgbrowser
StartupNotify=false
Categories=Qt;System;
Code language: JavaScript (javascript)

Simply add the following to the end of the file. Of course, if your desktop entry already has a defined Actions property, you’ll want to add this new-window to it.

Actions=new-window;

[Desktop Action new-window]
Name=New Window
Exec=pkgbrowser
Code language: JavaScript (javascript)

Now, right-clicking the desktop entry will appear as follows:

By default, any desktop entries that come from packages for your Linux distro will be overwritten during a package update. To prevent this from happening, you can made the file read-only using chattr:

sudo chattr +i /usr/share/applications/pkgbrowser.desktop

cmake: /usr/include/c++/10.1.0/type_traits(1396): “error: type name is not allowed” or “error: identifier “__is_same_as” is undefined”

If the gcc version being used is incompatible with cuda version, there will be errors such as:

[ 68%] Building NVCC (Device) object src/nvtt/CMakeFiles/cuda_compile_1.dir/cuda/cuda_compile_1_generated_CompressKernel.cu.o
/usr/include/c++/10.1.0/type_traits(1396): error: type name is not allowed

/usr/include/c++/10.1.0/type_traits(1396): error: type name is not allowed

/usr/include/c++/10.1.0/type_traits(1396): error: identifier "__is_same_as" is undefined

3 errors detected in the compilation of "/home/nick/Code/Git/github.com/nvidia-texture-tools/src/nvtt/cuda/CompressKernel.cu".
CMake Error at cuda_compile_1_generated_CompressKernel.cu.o.Release.cmake:280 (message):
  Error generating file
  /home/nick/Code/Git/github.com/nvidia-texture-tools/cmake-build-release/src/nvtt/CMakeFiles/cuda_compile_1.dir/cuda/./cuda_compile_1_generated_CompressKernel.cu.o


make[2]: *** [src/nvtt/CMakeFiles/nvtt.dir/build.make:85: src/nvtt/CMakeFiles/cuda_compile_1.dir/cuda/cuda_compile_1_generated_CompressKernel.cu.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:721: src/nvtt/CMakeFiles/nvtt.dir/all] Error 2
make: *** [Makefile:183: all] Error 2
Code language: JavaScript (javascript)

See discussion on GitHub: CUDA Build error on Arch Linux and CUDA Compilers – nvcc compatibility chart.

This can be resolved by using an earlier version of GCC which is compatible with the CUDA version. In my example setting the following CMake variable resolved the issue:

	-DCUDA_HOST_COMPILER=/usr/bin/gcc-9Code language: JavaScript (javascript)

cmake: undefined reference to std::__cxx11::basic_string

The default version of gcc in the Arch Linux repositories is now gcc10:

➜  ~ pacman -Qo /usr/bin/c++
/usr/bin/c++ is owned by gcc 10.1.0-2Code language: JavaScript (javascript)

This can result in errors during linking while building packages, such as:

[ 75%] Linking CXX executable ../../../../../bin/sst_conn_tool
/usr/bin/ld: ../../../../../lib/libadios2_core.so.2.6.0: undefined reference to `int adios2::format::DataManSerializer::GetData<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, unsigned long, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&)'
/usr/bin/ld: ../../../../../lib/libadios2_core.so.2.6.0: undefined reference to `int adios2::format::DataManSerializer::GetData<float>(float*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, unsigned long, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&)'Code language: PHP (php)

This issue can be resolved by compiling with an earlier version of gcc:

➜  ~ pacman -Qo /usr/bin/g++-9
/usr/bin/g++-9 is owned by gcc9 9.3.0-3

Setting these CMake variables will result in using the gcc9 version of gcc, g++, gcc-ar, and gcc-ranlib:

        -DCMAKE_CXX_COMPILER=/usr/bin/g++-9 \
        -DCMAKE_CXX_COMPILER_AR=/usr/bin/gcc-ar-9 \
        -DCMAKE_CXX_COMPILER_RANLIB=/usr/bin/gcc-ranlib-9 \
        -DCMAKE_C_COMPILER=/usr/bin/gcc-9 \
        -DCMAKE_C_COMPILER_AR=/usr/bin/gcc-ar-9 \
        -DCMAKE_C_COMPILER_RANLIB=/usr/bin/gcc-ranlib-9 \Code language: JavaScript (javascript)