This year I will hopefully be getting my hands dirty with ADA code. These are some of my notes, which might be useful for someone else trying to get an Ada environment up and running for themselves on their private computer.
I have set this up to work on both WSL (Ubuntu) and my Mac. Adjustments might be necessary, but refer to the dotfiles for more info
P.S. I might update this document several times P.P.S. Some great resources are summarized in this thread on the libadalang forum (which is great and very helpful!) and I found much interesting stuff on Awesome Ada.
Getting the Ada Language Server (ALS) working with VIM and CoC
These are the bits that made me have a pretty-much-functional LSP implementation working for ADA. It's not super smooth, seems a bit buggy (if you tail the log output at ~/.als/ada_ls_*), slow and sometimes gets stuck at 100% CPU for extended periods of time, but it is useful :)
- My CoC settings for Ada
- Download and install Alire, GNAT, GPRBuild, GNAT Studio and ALS
Strictly speaking, GNAT Studio is not necessary, but nice to have for debugging. Also, ALS is bundled with GNAT Studio, but it is a slightly older version.
My dotfiles also refer to specific versions, but by the time you read this, newer releases are bound to appear, so you might want to adjust the versions.
Notes for macOS
No resources are being put into macOS from the AdaCore side, so it is all run by volunteers like Simon J Wright. You get all you need, though, and Simon has FSF builds of the GNAT suite of tools on his personal GitHub: https://github.com/simonjwright/distributing-gcc/releases
That will get you all the GCC stuff, GPRBuild, etc
AUnit - the ADA implementation of xUnit
I like using tests to document learning when encountering new tech (test-driven learning), so the first thing I wanted to do was figuring out how to write unit tests in Ada. This is done using AUnit (or GNATUnit, which builds on AUnit).
The installation docs told me to build and install the library. Unless specified otherwise, it will install itself alongside where gprbuild is installed. By adding --trace to the make command I could see where that was:
❯ make --trace install
Makefile:61: update target 'install-clean' due to: install-clean-legacy
gprinstall -XAUNIT_BUILD_MODE=Install -XAUNIT_RUNTIME=full -XAUNIT_PLATFORM=native --uninstall --prefix=/opt/gprbuild-x86_64-linux-24.0.0-2 aunit
Uninstall project aunit
Makefile:65: update target 'install' due to: install-clean
gprinstall -XAUNIT_BUILD_MODE=Install -XAUNIT_RUNTIME=full -XAUNIT_PLATFORM=native -p -f --prefix=/opt/gprbuild-x86_64-linux-24.0.0-2 \
--no-build-var lib/gnat/aunit.gpr
Install project AUnit
❯ v /opt/gprbuild-x86_64-linux-24.0.0-2/lib/
total 4
drwxr-xr-x 2 oscko oscko 4096 mars 11 09:51 aunit
I expected this to now "just work", but alas ... . If I now build examples/simple_test in the aunit repository, I get an error about it not finding aunit:
❯ gprbuild -P harness.gpr
harness.gpr:1:06: imported project file "aunit" not found
gprbuild: "harness.gpr" processing failed
Turns out that gprbuild did not search these shared diretories when building. To see what it did, I could add -vm (verbose medium), which showed that it was just searching the GNAT directories (in my case /opt/gnat-x86_64-linux-14.2.0-1/...).
To make it compile I could add the absolute (or relative) path to the aunit project file, but that does not scale that well ...
+-- Requires Aunit to be globally available
+-- See https://forum.ada-lang.io/t/making-aunit-available-to-gprbuild/1879/2
-with "aunit";
+--with "aunit";
+-- If AUnit has not been made available, it will need to be included by path
+--with "../../lib/gnat/aunit.gpr";
+with "/opt/gprbuild-x86_64-linux-24.0.0-2/share/gpr/aunit.gpr";
Fix: Adjusting the install path for AUnit
I could probably somehow find out how to make gprbuild also inspect the additional directories, but instead chose to customize the install step of AUnit and move the installation over to the GNAT directories:
make install INSTALL=/opt/gnat-x86_64-linux-14.2.0-1
Now, doing a simple gprbuild on the simple_test case worked fine :)
Ahven is an alternative unit testing framework that looks good
To me, a budding ADA programmer, Ahven's docs are much more to the point and the API looks somewhat nicer to work with.
Examples from Jacob Sparre Andersen's Black HTTP and Websocket library:
Alire is gold, but vastly undocumented
This took me forever to find out, but Alire can actually get you most executables.
Just add ~/.alire/bin to your $PATH.
Alire is the source code based package manager, but it is relatively unknown
to many and seldom mentioned in README's, unlike npm in the Node world or
Gradle/Maven in the Java world. Too bad, as it can do a lot of nice things
that took me ages to find out.
Getting GNAT Test and other libadalang tools
alr install libadalang_tools
You can use Alire to get GNAT and GPRBuild directly
alr install gprbuild gnat
Example for using AUnit in a simple test with Alire handling deps
I created an ADA directory in my test-driven learning repo. This is work-in-progress, so some things might be removed in favor of better examples when I learn more, but is meant to be a usable reference for my own sake and understanding.
There exists a reference project implementation
Checkout ada_spark_workflow. This reference project is made by the Alire crew to show how a modern, best-practices approach to creating Ada projects look. The only real part that is missing is showing how to write/scaffold the minimum of required setup to get working unit tests, as well as implementing GNAT into the testing approaches. For some reason, they have created a tests sub-project with aunit, but there is no use of AUnit in the project ... The GNATCoverage is still demonstrated fine, though, as the "test" is really a demonstration of the API in the main project, which gets good coverage of most functionality.