@@ -224,19 +224,34 @@ std::string Report::explain(std::string_view artifact) const {
224224 body += " Also provided by:\n " ;
225225 for (auto const & label : providers) body += std::format (" {}\n " , label);
226226
227- // WHY it matters, in the terms the reader can check, then what to do. The
228- // three ways out are not alternatives to taste: the first changes which
229- // form mcpp builds, the second removes a provider, the third makes the two
230- // providers the same file.
227+ // WHY it matters, then what to do — IN THE ORDER THAT ACTUALLY WORKS.
228+ //
229+ // ⚠️ `dependency_linkage = "shared"` is deliberately NOT first, and that
230+ // ordering was corrected against a measurement rather than reasoned. On a
231+ // real graph (a package staging glib, whose libgio pulls libz.so.1, plus a
232+ // statically built compat.zlib) switching the form does remove the
233+ // executable's 88 exported symbols — and then TWO zlibs load, because the
234+ // library mcpp builds is `libzlib.so` while the reference is to
235+ // `libz.so.1`. That is a worse state than the one being reported: two
236+ // copies instead of one, and no diagnostic at all, since the check
237+ // described above only looks at executables.
238+ //
239+ // So the first suggestion is the one that is always correct, and the form
240+ // switch is offered with the condition that makes it work.
231241 body +=
232242 " The executable is searched first, so the copy inside it wins for\n "
233243 " every symbol both provide — the library's own copy is never called,\n "
234244 " and code inside that library now runs against a build it was not\n "
235245 " linked against.\n "
236- " Ways out: give the duplicated package a single form with\n "
237- " `[build] dependency_linkage` or a per-dependency `linkage`; stop one\n "
238- " side from providing it; or give both the same SONAME so they resolve\n "
239- " to one file." ;
246+ " Ways out, in the order they apply:\n "
247+ " 1. stop one side from providing it — usually the package that\n "
248+ " ships a copy of a library the graph already builds;\n "
249+ " 2. make both resolve to ONE file: declare the library's real\n "
250+ " SONAME on its target, so the shared copy and the built one are\n "
251+ " the same name;\n "
252+ " 3. `[build] dependency_linkage` / a per-dependency `linkage`\n "
253+ " changes which form mcpp builds — it removes THIS finding, but\n "
254+ " it only unifies the two providers when (2) holds as well." ;
240255 return body;
241256}
242257
0 commit comments