Supporting orphaned business-critical code
Stabilisation, modernisation and support of an orphaned, third-party image processing SDK with high availability and dependency requirements.
Problem
A large organisation running a piece of nationally significant critical infrastructure depended upon an image processing SDK deployed to hundreds of devices requiring 24/7 uptime.
The original supplier of the code no longer existed but for certification reasons replacing the SDK was not practical. Due to hardware obsolescence an alternative ongoing software support supplier was urgently required to assume responsibility for modifications and to maintain system stability.
There were a number of issues with the SDK:
- The build process was fragile and incompatible with modern tooling
- It had a complex and out of date dependency tree
- Dependencies were pre-built binaries with no clear method of update or verification
- The codebase was fragmented with excessive redundancy and substantial quantities of unreachable legacy code
- Both 32-bit and 64-bit Windows libraries were required
Without a formalised and robust automatic build process it would be impossible to have confidence that binaries could be reliably and repeatably produced in an appropriate timescale as code changes were made.
Solution
Emergent Design was provided with access to the original codebase and the primary concern was building the native (C++) core of the SDK. The managed layer (C#) of the SDK was addressed at a later stage and initially the original wrappers were used.
A decision was made to use vcpkg as the dependency manager. This has the advantage that Visual Studio supports it natively but it is also cross-platform which opens up the possibility of building and testing on Linux. This allowed us to utilise debugging and profiling tools from both ecosystems when disentangling and correcting the redundancies, vulnerabilities and performance bottlenecks caused by the convoluted structure and flow of the legacy code.
Dependencies were brought up to date and modifications to the SDK were made where required to accommodate breaking changes.
With the codebase stabilised an automated Linux build was set up with both native and mingw-w64 cross-compilation toolchains for C++ elements of the SDK and dotnetcore to compile the managed wrapper components. The final stage of the build process packages the 32 and 64-bit libraries along with the necessary SDK support files ready for deployment.
Maintenance of the SDK is now robust and not reliant upon the existence of a preconfigured machine: Any modern Linux system presented with the codebase will be able to automatically check out all dependencies and successfully build the SDK.
The new build process means that modifications can be made more safely and new versions generated using a repeatable, auditable process. In the event of critical support events or changing hardware requirements we are able to act far more rapidly to resolve issues and distribute updates.
