Ceedling is still probably the best Test-Driven Development (TDD) environment for C programmers out there. But, as with many Free Open-Source Software ( FOSS ), tools getting it to work natively on a Windows environment involves the odd hoop-jumping exercise; either involving messing around with the likes of Cygwin or Mingw; or using a full Virtual Machine (VM) environment such as VirtualBox or VMware.
However, with the introduction of Windows-Subsystem-for-Linux (WSL) and the much-improved update to WSL2, running Linux centric FOSS on a Windows machine has become more straightforward.
Installing Ceedling on WSL2 follows the normal Linux process of installing Ruby and then using the Ruby-based gem to install Ceedling.
Unfortunately, the currently WSL2 environment has one major performance issue. When working in WSL2 with a typical Linux shell (e.g., bash), there are, in effect, a local (Linux) filesystem (where the home directory ‘~’ is located) and a ‘mounted’ file system for the Windows files.
When running a Linux shell using WSL2, the Windows filesystem is accessed using a mount location, such as
/mnt/c/Users/<username>/<windows users filesystem>
For example, on my Win10 laptop, my local Document folder (C:\Users\NiallCooling\Document
) is located at:
/mnt/c/Users/NiallCooling/Documents
For many organisations, there are good reasons to locate the working project files in the Windows filesystem. Significantly, many traditional embedded development tools are still (frustratingly) Windows-only. Also, many company’s IT systems do not allow Linux machines on the company network (all they know is Windows, and it is easier to keep their lives simple by just not allowing anything but Windows!).
The update from WSL to WSL2 improves many aspects of working within a Linux environment (mainly due to it moving to a full Linux kernel implementation) but at the expense of Windows file access performance.
For example, building a small Ceedling-based project located on the Windows filesystem from WSL2 gives the following (using time):
real 0m16.505s
user 0m1.399s
sys 0m2.200s
Whereas building the same project mounted in the WSL2 file system gives
real 0m0.576s
user 0m0.511s
sys 0m0.050s
Note: both projects were clobbered (cleaned) before building
Obviously, your mileage may vary, but it will still likely be a significant performance difference.
Running on the WSL2 file system
This assumes the project should exist primarily in the Windows environment
There are three approaches to mirroring a Windows codebase in WSL2.
- Copy the Windows-based project code to the WSL2 Linux file system
- Remote cloning to both Windows and WSL2
- Local cloning from Windows to WSL2
Copying from Windows to Linux
This may be the most obvious but is not recommended. The WSL2 filesystem can be accessed from Windows at the location
\\wsl$\<Linux-distro-name>\home\<user>\
For example, my WSL2 home (~
) is at:
\\wsl$\Ubuntu\home\niall\
When using Windows File Explorer, the WSL2 filesystem is found in the navigation pane under Network
. You can then copy the project files from the Windows drive (e.g. C:\Users\NiallCooling\Document\project
) to the WSL2 location.
However, working with a copy bypasses version control, and, ultimately, you’re probably going to end with inconsistencies in the project codebase unless you are very careful.
Remote cloning to Linux
In many ways, cloning from the project’s remote repository (e.g. hosted on GitHub or BitBucket) is probably the best option. This way, all changes are managed through version control back to the remote repository.
The downside of this approach is that if you need to switch regularly between the Windows and Linux environments, the constant commit/push/pull cycle can feel cumbersome. It is easy to change environments and forget to pull (or even to have pushed) from the remote, thus getting the project code out of sync.
In addition, depending on your internet bandwidth (especially when working from home), the push/pull cycle can negate some of the time savings of working in the Linux environment in the first place.
Local cloning from Windows to Linux
A nice ‘halfway house’ between copying and remote-cloning is to locally clone. It is easy to forget that git has always supported simple file-based cloning using the Local Protocol capability.
A Windows-based git project can be locally cloned to the Linux filesystem rather than cloning from a remote-hosted repository using the Local Protocol. Any changes committed when working on the Linux codebase can simply be pushed back to the Windows clone, thus eliminating the requirement to ‘pull’ when returning to the Windows-based project code.
To clone a window’s-based git project:
git clone file:///mnt/c/Users/<username>/<project folder>
Note the three /
as the Local Protocol uses file://
+ /mnt/…
For example:
git clone file:///mnt/c/Users/NiallCooling/Documents/projects/tddc-wsl
You can create a local WSL branch (if needed) and add/commit/push as usual, but, importantly, the push is back to the windows filesystem, not the remote repo.
Summary
The addition of Linux support in Windows 10 through WSL2 is a helpful addition to an embedded programmer’s toolbox (especially combined with Docker and VS Code). Nevertheless, the current performance issues of using Windows-hosted projects directly in WSL2 may give a negative first impression of the overwhelming benefits it brings.
Hopefully, this little ‘hack’ means you can enjoy all the benefits of Linux on a Windows machine without a performance bottleneck.
Finally, a thank you to Robin for raising this issue
- Disassembling a Cortex-M raw binary file with Ghidra - December 20, 2022
- Using final in C++ to improve performance - November 14, 2022
- Understanding Arm Cortex-M Intel-Hex (ihex) files - October 12, 2022
Co-Founder and Director of Feabhas since 1995.
Niall has been designing and programming embedded systems for over 30 years. He has worked in different sectors, including aerospace, telecomms, government and banking.
His current interest lie in IoT Security and Agile for Embedded Systems.
I’ve been using VSCode with Docker Desktop to do this kind of thing and it’s been really handy to clone a repository into a remote container. I have also noticed the slowdown when Docker tries to access files in a Windows directory, which seems to increase with each file. Thanks for the tip about pushing to a local branch; it’s frustrating to get the executable image out of the container after compilation.
Hi Niall - Have you seen MSYS2?
No I haven’t but looks quite interesting.
Thanks for the reference.