When using CMake’s add_custom_command and add_custom_target on Windows, if the CMAKE_EXECUTABLE_SUFFIX (which is typically .exe) is not included as part of the command or target, it can lead to the custom target is rebuilt every time the project is rebuilt, even if the command is up to date.
This happens because CMake does not exactly match the output file of the custom command, since the .exe suffix was missing on Windows, and therefore CMake does not properly track the existence of a target’s dependencies.
As a result, CMake assumes that the target is always out of date and needs to be rebuilt.
To avoid this issue, ensure that the output of your custom command includes the CMAKE_EXECUTABLE_SUFFIX.
For example, if generating an executable with add_custom_command, specify the output file with the correct suffix:
By including the CMAKE_EXECUTABLE_SUFFIX in both the OUTPUT and DEPENDS sections, CMake will correctly recognize the target as an executable and will only rebuild it when necessary, thus avoiding unnecessary rebuilds.
Check the desired website’s SSL certificate with a service like Qualys SSL Labs
to see if the certificate is valid and properly configured.
If the certificate is valid but you still encounter SSL errors, it’s possible that the public WiFi network is interfering with the SSL connection.
Also try using command line web programs to see if there are any SSL errors or warnings in the output.
Examples:
An example of the curl output when even HTTP connections are interfered with:
curl -v http://neverssl.com
* Host neverssl.com:80 was resolved.
* IPv6: (none)
* IPv4: x.x.x.x
* Trying x.x.x.x:80...
* connect to x.x.x.x port 80 from 0.0.0.0 port 58197 failed: Timed out
* Failed to connect to neverssl.com port 80 after 21104 ms: Could not connect to server
* closing connection #0
curl: (28) Failed to connect to neverssl.com port 80 after 21104 ms: Could not connect to server
Docker images are useful for reproducibility and ease of setup and for software binary distribution on platforms not natively available on GitHub Actions runner images.
While one can setup a
custom Docker image,
it’s often possible to simply use an existing official image from
Docker Hub.
This example GitHub Actions workflow uses the Ubuntu 20.04 image to build a C++ binary with the GNU C++ compiler.
For APT operations, the “-y” option is necessary.
Environment variable DEBIAN_FRONTEND is set to “noninteractive” to avoid interactive prompts for certain operations despite “-y”.
Don’t use “sudo” as the container user is root and the “sudo” package is not installed.
A special feature of this example is using Kitware’s CMake APT repo to install the latest version of CMake on an EOL Ubuntu distro.
When CMake fails on the configure or generate steps in a CI workflow, having CMakeConfigureLog.yaml uploaded a as a file can help debug the issue.
Add this step to the GitHub Actions workflow YAML file:
The “retention-days” parameter is optional.
Ensure the “name” parameter is unique to avoid conflicts with other jobs in the workflow.
Here we assume that the OS and C compiler are unique between jobs.
Git signed commits help verify the Git author’s identity using PGP.
Optionally, a user or organization can set rules requiring Git PGP signed commits on Git hosting providers such as
GitHub
and
GitLab
PGP public keys can help verify author identity of Git commits, social media, website, etc.
Setup GPG on the laptop:
Export the GPG public and private key and import into GPG:
If one has Keybase, first export Keybase.io PGP key to GPG.
If one does NOT have Keybase, use gpg --full-generate-key to generate a GPG keypair.
Verify PGP key:
gpg --list-secret-keys --keyid-format LONG
The first lines will be like:
sec rsa4096/<public_hex>
The hexadecimal part after the / is a public reference to the GPG keypair.
Add Git provider such as
GitHub
or
GitLab
verified email address to the PGP key.
To make commits “Verified” with the Git provider, at least one of the Git provider verified email addresses must match:
git config --get user.email
Use the GPG public ID below:
gpg --edit-key <public_hex>
In the interactive GPG session that launches, type
adduid
and enter Name and the Email address–which must exactly match the GitHub verified email address.
I also add the @users.noreply.github.com fake email that I always use to avoid spam.
Do adduid twice–once for the real
GitHub verified email address
and again for the github_username@users.noreply.github.com fake email.
Add “trust” from the GPG> prompt:
trust
Since it’s you, perhaps a trust level of 5 is appropriate.
type
save
to save changes, which may not show up until exiting and reentering the GPG> prompt.
On Windows, even though “gpg” works from Windows Terminal, it’s essential to tell Git the full path to GPG.exe, otherwise Git will fail to sign commits.
Add the GPG public key to the Git provider.
Copy and paste the output from this command into GPG Key of
GitHub
or
GitLab.
This is done only once per human, not once per device.
If you get gpg: signing failed: No secret key or gpg: skipped "...": No secret key, the signing subkey may have expired.
GPG subkeys (encryption, signing) expire independently from the main key.
Check which subkeys are expired:
gpg --list-secret-keys
Look for subkeys marked expired. To extend them:
gpg --edit-key <public_hex>
key 1expire
1y
save
The key N selects which subkey to extend (1 for first, 2 for second, etc.).
Then export the updated key to GitHub.
Certain networks may block traffic on port 22, which causes failure for Git operations like:
ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.
The solution for this is to at least temporarily configure SSH to use port 443, which is typically open for HTTPS traffic.
This can be persistently done by editing the user SSH config file usually located at “/.ssh/config”, here for
GitHub,
where “/.ssh/github” comes from
GitHub SSH key setup.
To recursively convert line endings from DOS \r\n and old macOS \r to Unix \n format in all files recursively, use “dos2unix” and “mac2unix” commands.
For example, it’s not uncommonn that Matlab .m files shared among groups end up with DOS line endings, which can cause issues across different operating systems.
When viewed with “git diff” or similar, files might have ^M characters at the end of lines, indicating DOS or old macOS line endings.
Run the following command using GNU Find to convert in place all .m files:
find . -type f -name "*.m" -exec sh -c 'dos2unix -e "$1" && mac2unix -e "$1"' _ {} \;
Set Git to use the
correct line endings
to avoid line ending conflicts in Git repositories.
Git over SSH can use
SSH-agent
to remember SSH keys for Linux and Windows.
For those not using Git over SSH but tiring of typing the Git password, on Windows the
Git Credential Manager
can fix that situation.
The install is small and quick, and to use Git Credential Manager, be sure via
git remote -v
that the connection is https:// and not ssh:// where appropriate.
Upon trying to git push or git pull, the Git Credential Manager will appear.
It works with 2-factor Authentication as well, storing in
Windows Credential Manager.
The keys can be deleted from Windows Credential Manager if needed, and / or the Personal Access Token automatically generated can be deleted from GitHub.
Note: If using automatic
Git push SSH
that would need to be disabled to allow git push to use https so that Git Credential Manager is invoked.
For the simplest execution and best performance, an executable file binary architecture should generally correspond to the CPU architecture of the operating system it runs on.
The late 1990s and early 2000s saw a proliferation of CPU architectures including SPARC, PowerPC, DEC Alpha, MIPS, Itanium, and x86.
From the late 2000s through about 2020, the dominant CPU architecture for personal computers was x86_64.
The 2020s saw the rise of ARM64 across operating systems including Windows on ARM, Apple Silicon, and Linux.
Given the development time and maintenance burdern of supporting multiple CPU architectures, there are in general situations where a user needs to run an executable file on a different CPU architecture than the executable file was built for.
It’s a nice practice for program developers to print their native CPU architecture in their program’s about dialog to help users be aware of the CPU architecture of their executable files such that they can seek a native executable if available.
For example, a 32-bit x86 executable might run on a 64-bit x86_64 operating system (via API thunking and environment emulation like WoW64), but a 64-bit x86_64 executable generally cannot natively run on a 32-bit x86 operating system.
With some performance overhead and compatibility limitations, executable JIT translation like macOS Rosetta 2, Windows Prism emulation, or Linux
FEX
emulation can allow executables of one architecture to run on a different CPU architecture.
The operating system level translation or emulation development is typically a large investment in software development and optimization, and is not universally available for all architecture combinations.
Apple Rosetta 2 translates x86-64 instructions to ARM64 on Apple Silicon, allowing x86-64 executables to run on ARM64 macOS.
On Windows, Prism emulation generally allows x86-64 executables to run on ARM64 Windows.
On Linux, FEX emulation allows x86-64 executables to run on ARM64 Linux with real-time API call forwarding.
The
LIEF
library can be used to detect the CPU architecture of Windows executable files from
Python.
On Windows if also using MSYS2, don’t add Meld.exe to environment variable Path as it has libstdc++.dll that conflicts with MSYS2 G++.
The symptom is the G++-built executable will segfault silently.