With the release of PVS-Studio 7.34, native builds of the analyzer for macOS on the Apple Silicon (ARM) architecture are now available. In this note, we'd like to delve into the work involved in this implementation and share tips for porting cross-platform tools to a new, future-proof architecture.
As mentioned above, starting with the 7.34 version, PVS-Studio supports macOS on the Apple Silicon (arm64) architecture. The packages for Intel architecture (x86_64) will keep releasing as usual.
The minimum supported versions of macOS:
The following components are ready for release:
You can now download them all by clicking the link, install, and use. Your feedback is always welcome :)
Windows ARM support has been available in PVS-Studio since the 7.28 version.
We have received no requests to support this platform and architecture, so we have no plans for this version for now.
Phew, the official section is over, and we can move on to the fun part :)
So, PVS-Studio is a set of components, utilities, and plugins written in C and C++, C#, and Java. Just by looking at the list of languages, you can try to guess which one has caused the most trouble...
If you were thinking about C and C++, I have to disappoint you—it was the Java analyzer that had the most issues during porting. Although... Interestingly, the challenge wasn't due to the Java language but rather the intricate dependencies between shared components of the C++ and Java analyzers. Perhaps our Java team will someday delve into these nuances in a dedicated discussion. I won't spoil the interesting stuff :)
Well, if not Java, then it's definitely C++? Yep, now you're on point. Let me save you a couple hours of research time.
In reality, if your project is already built under macOS, you won't encounter any major porting issues. If you're using the CMake build system, just add a few entries to your CMakeLists.txt
and you're ready to run the test build:
set(CMAKE_OSX_ARCHITECTURES "arm64") # target architecture
set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0) # target SDK version
set(CMAKE_OSX_SYSROOT "/path/to/sdk") # path to the SDK of the specified version
Note: The 11.0 version of the SDK is required because it's the minimum version that supports the Apple Silicon architecture. By the way, if you need SDK packages for deployment on CI/CD servers, and for some reason you can't install the SDK using XCode, you can get them from this GitHub repository.
Another interesting feature is the capability to build Universal Binaries that can run on both Intel (x86_64) and Apple Silicon (arm64) simultaneously. To do this, just modify the previously mentioned variable:
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
You can check the result by using the file
command. If successful, the output will contain information about both architectures:
>> file hello_world
hello_world: Mach-O universal binary with 2 architectures:
[x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
hello_world (for architecture x86_64): Mach-O 64-bit executable x86_64
hello_world (for architecture arm64): Mach-O 64-bit executable arm64
I've mentioned that if your application has already been ported to macOS, there shouldn't be much of an issue. "Hold my beer," said Clang.
Meet D138307 in LLVM or, as it's also called, "Remove default definition of std::char_traits". The idea behind it is that the developers decided to remove from libc++ the std::char_traits' specializations not explicitly mentioned in the C++ standard. Our surprise when the compiler refused to build code with
std::basic_string<unsinged char> was hard to put into words.
We won't say anything negative about the LLVM developers, as getting rid of redundant code support seems to be a reasonable decision on their part. They even introduced a kind of transitional period, during which a message was issued that these specializations had become obsolete:
However, since we're aware of some users of char_traits for unsigned char and signed char, we're keeping those two specializations around for two releases to give people some time to migrate.
Too bad we missed those transitional releases and landed right into the current version. Oh well, it never hurts to do a bit of research on other people's code. Speaking of that...
If you wonder, "Why do you need such an std::basic_string
specialization?", the answer is the legacy of the OpenC++ library on which the C and C++ analyzer is based. The library code has changed a lot over time, but there are still some funny parts. Someday we'll get rid of them too :)
Porting an application to a new architecture means not only adapting your own code but usually working with third-party libraries as well. If they don't support the target platform and architecture, you have three options: wait for updates, adapt the code yourself, or look for alternative solutions.
We've faced the lack of ARM architecture support (specifically Windows ARM) in backward-cpp, a popular C++ library for collecting stack trace when a program crashes. After looking through the documentation and analyzing the code, we submitted a pull request with fixes to enhance the ARM support. We hope this small improvement will be helpful to other developers who are porting their applications to the ARM :)
By the way, supporting new platforms and architectures is a good opportunity to reconsider your technology stack. Exploring the alternatives can lead to better and safer solutions. The key is to thoroughly test the entire application after the changes are made to ensure that it works correctly on the new architecture.
Luckily, there isn't much to tell. All issues were fixed by changing the target architecture in the project files and "chipping off" the hardcoded paths and values :)
We hope you enjoyed reading some stories about porting the analyzer to a new architecture. You might even be tempted to port your own software as well. After fixing compilation errors and running the application, you may encounter some bugs—this is a normal step in the porting process. Static analyzers such as PVS-Studio, which are designed to detect errors in your code, will help you reduce the number of errors and make this process easier. You can see for yourself (also on macOS Apple Silicon) by clicking the link and downloading the analyzer.