I could understand this concern strongly in areas where you are covering every single inch of the hardware, like a multithreaded next-gen AAA game engine which uses every single CPU core, SIMD intrinsics, GPU, GPGPU, etc. while delivering a cross-platform product.
In those cases, your worst nightmare will often be those cases where your tests (unit and integration) will pass for the first 5,000 disparate machines/platforms tested, but fails for the 5,001th due to a driver bug for an obscure GPU model Just thinking about this gives me the shivers -- you cannot possibly test or foresee these in advance.
Especially if you write GPU shaders, you can end up playing a reverse lottery where half the code you write will invoke undefined behavior, since there are few portable standard guarantees enforced by all GPU models/drivers involved. While it's getting less and less like playing minesweeper these days, this should give people some idea: http://theorangeduck.com/page/writing-portable-opengl. Trying this in the late 90s and early 2000s was really horrible, and it was minesweeper all the way.
For these kinds of cases, you often need teams of 10,000+ testers with a really wide range of hardware and operating systems to really solidify the product and feel confident about it prior to a stable release. Not all companies can afford to have such a wide test base, and not all have the discipline to do it right (all widely-noticeable issues should be fixed prior to having so many testers in some internal pre-alpha/alpha stage or else the flood of redundant reports can throw developers into a patch-and-pray panic).
What I recommend in this case is what others suggested, focus on a distributed set of integration tests. You can bundle it up with the installer, requiring users to pass a basic diagnostics check with careful attention to providing details as to why the installation failed that they can pass to you, the developers.
Another thing (if you can convince the boss) is to have a wide range of hardware available to do contiguous integration. The more variety in hardware/OS combos, the merrier. You want even a variety of crap hardware that models the bare minimum hardware requirements for your CI servers: you never know.
But there's one more thing I'd suggest:
If you are dealing with anything like the scenario I described above, then often you cannot possibly test for these things which tend to be the most problematic (those worst possible gotchas which show up at the worst possible time and cannot possibly show up in even the most exhaustive test suite since it's an issue constrained to a very specific hardware/OS combo).
Yet most of those kinds of issues like obscure hardware incompatibilities or outright driver glitches or linking against the wrong dylib (I've never actually faced this concern) won't get you far past starting up the software. It's typically gonna crash and burn pretty soon, crudely speaking.
I recommend, for sanity sake, to kind of embrace the inevitable. You can't possibly do anything about these things you cannot possibly test comprehensively. Don't try to prevent the hurricane (impossible), but board up those windows.
Typically here, the best thing we can do is find out the problem as soon as possible, where it occurs as detailed as possible (to narrow our list of suspects), and have the issue fixed ASAP after it's reported.
In this case, logging can be a lifesaver. For these kinds of fields, you can create these spammy technical logs which no one would ever read through. Often relevant is just the very last line recorded in the log before the user faced a crash due to a driver glitch, e.g. You can write an external process or hook which monitors for crashes and then shows the last line of the log that users can copy and paste to you, e.g. in addition to a crash dump.
Since this often needs granular information and a lot of the most susceptible areas in code to these hardware/platform/driver issues is performance-critical, there's this awkward issue where the logging can be happening at such a frequent rate that it'll actually slow down the software.
A useful trick in this case is to rely on the assumption that something executed once will execute successfully the second time, third time, etc. This is not the most sound assumption, but it's often "good enough" (and infinitely better than nothing). With that, you can use a little bit of external state to keep track of when something has been logged already and skip subsequent attempts to log for those really granular cases where the code will be invoked repeatedly in a loop.
Anyway, I hope this helps. I've run into this kind of temptation in the past and have a bit of a paranoia surrounding GPU coding (GPGPU and shaders) as a result of some past experiences among myself and my team (sometimes just seeing other team members deal with these really late and post-release gave me the creeps, like some ATI glitch on a specific Radeon model which would crash on rendering antialiased lines, later reported and marked as a known problem with only a workaround solution available).
Logging was the thing that saved our butts there, letting us often see the issue on that 10,001th obscure prototype machine with an onboard GPU we never heard of, with the last line of code immediately letting us spot exactly where the failure was down to 2 or 3 lines of code as suspect, e.g. If it's inside an elaborate shader, we're kind of SOL since we can't do logging inside a GPU shader, but we can at least use logging to see which shader had the issue right away to start off the investigation.