A Giter8 template for combined Clang/Scala projects
This template generates a skeleton project that contains both Clang and Scala code. The goal is to make all of this work together in a natural way. It's aimed at Scala and Java developers who aren't up-to-date on C++ environment setup, and aims to get them started with a working example.
Specific goals (not all achieved yet) are:
-
The project's directory structure supports multiple languages in a natural way. I should be able to mix Scala Native and Java HotSpot tests into the project in order to build and test linkages to those environments. Adding tests for other language environments, like Python, may also become desirable. (GraalVM may obviate the need for all these variations in the future.) The emphasis, though, is on developing mostly in C++ and testing against a small amount of Scala/Java/etc. code.
-
It's possible to run builds and tests equally well from the command line or the IDE, with sbt controlling the whole.
-
cmake
at the command line builds, tests and packages all the Clang code. -
sbt
at the command line builds, tests and packages everything. -
The IDE shows Doxygen documentation when I hover over terms.
-
I can use either libstdc++ or libc++, as needed.
The definitive instructions for setting up the operating system's environment are found in the continuous integration tests, located in the GitHub Workflow for this project. Instructions are only given for Debian 10 currently.
Prepare Aptitude per the sbt download and backports instructions. I added backports in order to pick up a 3.14+ CMake.
Sbt, CMake, Ninja, Clang and Doxygen are installed in the usual Debian way. It's probably useful to pick up a few extras, too:
sudo aptitude install doxygen-gui doxygen-doc openjdk-11-jdk swig sbt
sudo aptitude -t buster-backports install cmake-qt-gui cmake-doc clang-8 clang-8-doc libc++1-8 ninja-build
An instance of this Giter8 template is created in the usual way:
sbt new performantdata/clang-scala.g8
The below assumes that you've changed into the created directory, the one with the name that you entered.
Though the CMake files theoretically support a range of CMake versions, they've actually only been tested with 3.16.3.
The top-level CMakeLists.txt
file is in the src/
directory, so in the root directory, invoke:
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
cmake -S src -B target/cmake -G Ninja
cmake --build target/cmake
(cd target/cmake; ctest -VV)
setting the environment as described here. You may need to adjust the compiler paths from the above example. (Placing the environment settings in your login script may help keep from forgetting to set them, but then they affect every process. Your choice.)
TBD
The directory layout may be unfamiliar to a typical C/C++ coder, who might have seen something more like this. It instead follows the standard sbt structure, which has been in use in the Java world for decades.
- It extends it by adding directories
src/main/cpp/
andsrc/test/cpp/
for C/C++ source code for the product and the tests, respectively. There is a correspondingsrc/main/include/
for the distributed include files. The top-levelCMakeLists.txt
file is in thesrc/
directory. - Build outputs are placed into
target/cmake/
(instead of the usualbuild/
).
You can think of it as two overlapping trees: one for the sbt build, and one for the CMake build (which the sbt build calls).
This is discussed on a separate page.
The following tools are commonly used in C++ development. This is an opinionated list.
-
Some use GCC rather than Clang, but that's not the direction that I'm going. Future versions of this project will interface with OpenJDK's new GraalVM, which requires LLVM IR.
-
Some use Java tools like
javac -h
to generate a JNI API from Java code. The advantage of SWIG is that it works from a C/C++ header-like syntax, generating the APIs for other languages. So it can not only generate a JNI API, but also APIs for Python, etc. from the same specification.Eventually, as GraalVM matures, I would hope that other languages would adopt it as their runtime. Then there would be no need for SWIG. But that's years away.
-
If you're new to CMake, the tutorial is an obvious place to start, but I found that reading about its build system in parallel helps. The language description is also enlightening on basic syntax. For a more gradual description via examples, you may find CMake Cookbook (2018) online via your local library.
-
If you're new to Ninja, just think of it as an intermediate representation for build scripting. Or as UNIX Makefiles, stripped down for fast execution. You shouldn't need to work with Ninja code directly.
-
Some use Googletest rather than Catch2, but I prefer the BDD style.
Similar instructions to these can be found in the book Advanced C++ (2019), which may be available online through your library. (I started on this project well before discovering this book.)
Mizux Seiha maintains a project demonstrating a polyglot CMake + SWIG project. It addresses CI, portable CMake, and SWIG code generation for Java/Python/.NET with language-specific tests and packaging, but doesn't go so far as to make it a template for new projects. My project doesn't care about CMake portability, since I expect high-performance code to run only on Linux. It's also intended for non-trivial development in the targeted scripting languages in an IDE, for providing a portable fallback implementation should a native code version be unavailable.