Note: we have moved most of our projects to Meson, which is generally easier, faster and robust.
A wide variety of programming languages are used by engineers and scientists.
You can tie them all together (C, C++, C#, Cuda, Fortran, etc.) in a platform-independent and simple way using Cmake.
These programs generate Makefiles for the program.
Some choose to use a manually-created Makefile alone, but I prefer the platform-independent nature of Makefile generators such as Cmake.
Basic CMake example
Let’s take a single-file C++ program, like a science/engineering researcher might use.
You will probably be linking the Math library at least, and Boost for flexible command-line input of numerous parameters.
You might like to turn on additional compiler warnings to help avoid common coding pitfalls.
Finally, you want to allow your colleagues on a wide variety of computers and operating systems to compile easily.
To do all of the above easily, Cmake has a simple syntax.
Let’s consider an example
for a C++ and Fortran project, line by line.
Cmake 3.3 is new enough for many small projects, with features such as IN_LIST.
Naming your project can help auto-install if you decide to someday.
CXX is required to enable the hooks for the language(s) you used.
The most frequently used include
Languages that aren’t built into Cmake such as
can be added via custom Cmake modules.
The HDF5 syntax is quite similar (and simpler) for Fortran.
See the hdf5 directory of
Fortran 2018 examples
#include"hdf5.h"#define FILE "dset.h5"
hid_t file_id, dataset_id,dataspace_id; /* identifiers */
int i, j, dset_data, read_data;
/* Initialize the dataset. */for (i =0; i <4; i++)
for (j =0; j <6; j++)
dset_data[i][j] = i *6+ j +1;
/* Create a new file using default properties. */
file_id = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
/* Create the data space for the dataset. */
dataspace_id = H5Screate_simple(2, dims, NULL);
/* Create the dataset. */
dataset_id = H5Dcreate2(file_id, "/dset", H5T_STD_I32BE, dataspace_id,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
/* Write the dataset. */
status = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
/* End access to the dataset and release resources used by it. */
status = H5Dclose(dataset_id);
/* Open an existing dataset. */
dataset_id = H5Dopen2(file_id, "/dset", H5P_DEFAULT);
status = H5Dread(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
for (i =0; i <4; i++)
for (j =0; j <6; j++)
printf("%d ",read_data[i][j]); // 1-24
/* Close the dataset. */
status = H5Dclose(dataset_id);
/* Close the file. */
status = H5Fclose(file_id);
HDF5 compiler macros
As an alternative (or companion to) CMake, one can use compiler macros for HDF5.
HDF group provides compiler macro
linking the needed HDF5 libraries upon installing libhdf5-dev:
EXFAT is the most convenient format for sharing files between MacOS / Linux / Windows / Android.
ExFAT does not support symbolic / soft links.
Operating systems have supported EXFAT for many years, since:
Linux: CentOS 5, Ubuntu 10.04, etc.
On Linux (including Ubuntu 18.04), install ExFAT support:
apt install exfat-utils
Use FAT32 instead of EXFAT for:
Test equipment (e.g. Agilent)
some older USB drive accepting printers (print direct from USB stick)
Other file systems
These file systems are commonly, but not universally supported across OS’s.
MacOS (including MacOS 10.15 Catalina): NTFS is read-only by default.
Android needs additional third-party software for NTFS
FAT32 is readable by Windows / MacOS / Linux / Android, but is limited to 4 GB file size.
With many USB HDDs over 2 TB, you would have to break up your HDD into multiple partitions for FAT32 – quite inconvenient.
You could use FAT32 for a small USB flash drive.
Note: For old printers “USB Direct Print” it may be that only single partition FAT32 is supported.
Keep a small USB drive formatted to FAT32 for this purpose.
ExFAT is generally the best choice for universal support on USB HDD.
For USB flash thumb drives and SD cards, I format most to ExFAT.
Keep a small flash drive formatted to FAT32 for the USB port on old USB direct print printers.
Those who need to keep MacOS-capable hardware around for development or maintenance purposes,
or simply as a form of conserving resources may be interested to know how Apple is increasing MacOS requirements over time.
In general, if the Apple computer is too old for a currently supported MacOS version, consider installing Linux, which normally works well on Apple computer hardware.
Apple maintains a list of
no longer supported Apple hardware.
The red dotted line depicts the oldest supported version of MacOS.
compile the program. This is the command run each time you make a change to the project code.
cmake --build .
Optionally, install the program with
cmake --build . --target install
On Windows, CMake defaults to Visual Studio and Nmake.
The cmake options above direct the build to MinGW.
If you wish to make this change permanent for
CMake ≥ 3.15,
set the Windows environment variable CMAKE_GENERATOR to “MinGW Makefiles”.
This can still be overridden if needed like
cmake -G "Visual Studio 16 2019"
sh.exe error with cmake
The nuisance error from cmake about sh.exe being on the Path.
This error also happens with CMake Windows builds on Azure Pipelines and GitHub Actions.
sh.exe was found in your PATH, here:
For MinGW make to work correctly sh.exe must NOT be in your path.
Run cmake from a shill that does not have sh.exe in your PATH.
If you want to use a UNIX shell, then use MSYS Makefile
this message by adding -DCMAKE_SH="CMAKE_SH-NOTFOUND" to the cmake command, like:
is more than 5 times faster than
at scalar exponentiation, while
was in-between Python and Julia in performance.
was the same for integer or float base or exponent.
Python testing done with:
The ** operator in Python also has the advantage of returning int if inputs are int and arithmetic result is integer.
8.22 ns ± 0.0182 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
227 ns ± 0.313 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
252 ns ± 1.56 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.5 µs ± 2.91 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
is known in general to be slower at scalar operations than Python-native operators and Python built-in
But of course Numpy is generally a lot faster and easier for N-dimensional array operations.
Julia 1.2.0 was likewise
for reference on the same computer.
are adequate for most personal, group and project pages, when website size and / or traffic have grown beyond what is feasible for these solutions, a more comprehensive hosting provider like Netlify may be considered.
Netlify provides its own CDN, so those that had been using Cloudflare for DNS and CDN can configure Cloudflare to provide only DNS, if they so choose.
Netlify is free
for single users, allowing a private GitLab, GitHub or Bitbucket repo (or other suitable source) to deploy to a public custom domain HTTPS website.
SSL certificates can be user-provided or can be created through Netlify for your custom domain (e.g. https://www.example.com).
Why transfer site to Netlify
Netlify provides a
of GitHub Pages and Netlify.
GitLab Pages allows user choice of static site generator (Hugo, Jekyll, etc.), while GitHub Pages allows only Jekyll.
GitLab Pages private repos have a runtime limit of 2000 minutes/month.
Netlify allow 3 builds / minute and
100 GB / month
on the free tier, with
300 build minutes/month.
For sites that are becoming very popular, GitHub Pages will simply want you to move elsewhere, while Netlify will have a paid plan to offer.
This process may be too burdensome for those with limited IT or bandwidth resources, or simply the lack to time to learn how to do this.
Netlify uses webhooks to detect a git push to the website GitLab repo, and then builds the site.
Netlify has a CDN and DDoS protection built-in.
Even if the other features aren’t needed, a key feature is the ability to have the website code in a private repo with unlimited public website deployments and traffic.
Build minute limits (such as on GitLab and Netlify) can legimately be worked around by building the site locally on your laptop and pushing the publish-ready HTML.
Transfer site to Netlify
Note: This process may take down your site for a day or two if things go wrong.
Even under normal conditions, all site visitors may need to allow an HTTPS exception due to SSL certificate error since Netlify requires all DNS servers to update before generating the domain certificate.
if not already on GitLab, copy your website repo to GitLab (any name repo is fine).
disable Auto DevOps and ensure no file named .gitlab-ci.yml exists.
Login to Netlify using Gitlab, which will ask for your website repo.
pick a custom Netlify subdomain like mycompany.netlify.com. Ensure this site is totally working before proceeding.
Set Cloudflare or whatever your DNS provider is to point CNAME or A to mycompany.netlify.com (THIS IS THE PART THAT CAN TAKE YOUR MAIN WEBSITE DOWN!)
Under Netlify Domain Management → HTTPS → Verify DNS config, ensure the verification completes. Until the DNS change propagates worldwide, your main HTTPS domain visitors are getting SSL verification errors. They can use http://mycompany.com instead of https://mycompany.com temporarily. Do this at a low traffic time range!
If you were using Cloudflare CDN, the old records may point to DigitalOcean while the new records point to *.netlify.com.
Optionally, under Netlify → Build & deploy → Post Processing → Asset Optimization consider using these to improve website speed.