<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="AsciiDoc 9.1.0">
<title>Dependency flag soup needs some fiber</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */

/* Default font. */
body {
  font-family: Georgia,serif;
}

/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
  font-family: Arial,Helvetica,sans-serif;
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}
h5 {
  font-size: 1.0em;
}

div.sectionbody {
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}
ul > li     { color: #aaa; }
ul > li > * { color: black; }

.monospaced, code, pre {
  font-family: "Courier New", Courier, monospace;
  font-size: inherit;
  color: navy;
  padding: 0;
  margin: 0;
}
pre {
  white-space: pre-wrap;
}

#author {
  color: #527bbd;
  font-weight: bold;
  font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}

#footer {
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid #dddddd;
  border-left: 4px solid #f0f0f0;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid #dddddd;
  border-left: 5px solid #f0f0f0;
  background: #f8f8f8;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #f0f0f0;
  color: #888;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > pre.content {
  font-family: inherit;
  font-size: inherit;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}

div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}

div.colist td {
  padding-right: 0.5em;
  padding-bottom: 0.3em;
  vertical-align: top;
}
div.colist td img {
  margin-top: 0.3em;
}

@media print {
  #footer-badges { display: none; }
}

#toc {
  margin-bottom: 2.5em;
}

#toctitle {
  color: #527bbd;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}

span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }

span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }

span.big { font-size: 2em; }
span.small { font-size: 0.6em; }

span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }

div.unbreakable { page-break-inside: avoid; }


/*
 * xhtml11 specific
 *
 * */

div.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-weight: bold;
  color: #527bbd;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overridden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


/*
 * html5 specific
 *
 * */

table.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
thead, p.tableblock.header {
  font-weight: bold;
  color: #527bbd;
}
p.tableblock {
  margin-top: 0;
}
table.tableblock {
  border-width: 3px;
  border-spacing: 0px;
  border-style: solid;
  border-color: #527bbd;
  border-collapse: collapse;
}
th.tableblock, td.tableblock {
  border-width: 1px;
  padding: 4px;
  border-style: solid;
  border-color: #527bbd;
}

table.tableblock.frame-topbot {
  border-left-style: hidden;
  border-right-style: hidden;
}
table.tableblock.frame-sides {
  border-top-style: hidden;
  border-bottom-style: hidden;
}
table.tableblock.frame-none {
  border-style: hidden;
}

th.tableblock.halign-left, td.tableblock.halign-left {
  text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
  text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
  text-align: right;
}

th.tableblock.valign-top, td.tableblock.valign-top {
  vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
  vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
  vertical-align: bottom;
}


/*
 * manpage specific
 *
 * */

body.manpage h1 {
  padding-top: 0.5em;
  padding-bottom: 0.5em;
  border-top: 2px solid silver;
  border-bottom: 2px solid silver;
}
body.manpage h2 {
  border-style: none;
}
body.manpage div.sectionbody {
  margin-left: 3em;
}

@media print {
  body.manpage div#toc { display: none; }
}


</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  if (!toc) {
    return;
  }

  // Delete existing TOC entries in case we're reloading the TOC.
  var tocEntriesToRemove = [];
  var i;
  for (i = 0; i < toc.childNodes.length; i++) {
    var entry = toc.childNodes[i];
    if (entry.nodeName.toLowerCase() == 'div'
     && entry.getAttribute("class")
     && entry.getAttribute("class").match(/^toclevel/))
      tocEntriesToRemove.push(entry);
  }
  for (i = 0; i < tocEntriesToRemove.length; i++) {
    toc.removeChild(tocEntriesToRemove[i]);
  }

  // Rebuild TOC entries.
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  // Delete existing footnote entries in case we're reloading the footnodes.
  var i;
  var noteholder = document.getElementById("footnotes");
  if (!noteholder) {
    return;
  }
  var entriesToRemove = [];
  for (i = 0; i < noteholder.childNodes.length; i++) {
    var entry = noteholder.childNodes[i];
    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
      entriesToRemove.push(entry);
  }
  for (i = 0; i < entriesToRemove.length; i++) {
    noteholder.removeChild(entriesToRemove[i]);
  }

  // Rebuild footnote entries.
  var cont = document.getElementById("content");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      var note = spans[i].getAttribute("data-note");
      if (!note) {
        // Use [\s\S] in place of . so multi-line matches work.
        // Because JavaScript has no s (dotall) regex flag.
        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
        spans[i].innerHTML =
          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
        spans[i].setAttribute("data-note", note);
      }
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
},

install: function(toclevels) {
  var timerId;

  function reinstall() {
    asciidoc.footnotes();
    if (toclevels) {
      asciidoc.toc(toclevels);
    }
  }

  function reinstallAndRemoveTimer() {
    clearInterval(timerId);
    reinstall();
  }

  timerId = setInterval(reinstall, 500);
  if (document.addEventListener)
    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
  else
    window.onload = reinstallAndRemoveTimer;
}

}
asciidoc.install(5);
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>Dependency flag soup needs some fiber</h1>
<span id="author">Ben Boeckel</span><br>
<span id="email" class="monospaced">&lt;<a href="mailto:ben.boeckel@kitware.com">ben.boeckel@kitware.com</a>&gt;</span><br>
<span id="revnumber">version P2800R0,</span>
<span id="revdate">2023-09-20</span>
<div id="toc">
  <div id="toctitle">Table of Contents</div>
  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="hdlist"><table>
<tr>
<td class="hdlist1">
Document number
<br>
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
ISO/IEC/JTC1/SC22/WG21/P2800R0
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
Date
<br>
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
2023-09-20
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
Reply-to
<br>
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
Ben Boeckel, <a href="mailto:ben.boeckel@kitware.com">ben.boeckel@kitware.com</a>
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
Audience
<br>
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
EWG (Evolution), SG15 (Tooling)
</p>
</td>
</tr>
</table></div>
</div>
</div>
<div class="sect1">
<h2 id="_abstract">1. Abstract</h2>
<div class="sectionbody">
<div class="paragraph"><p>Dependency management and "how to use library X" has always been an important
question to answer. Historical answers have included "assume that headers and
libraries are found in the default locations" allowing simply using <span class="monospaced">-llibname</span>
to use the compiled symbols, asking <span class="monospaced">libname-config</span> tools for flag
information, compiler wrappers such as <span class="monospaced">mpicc</span>, or storing information in a
<span class="monospaced">.pc</span> file and queried by <span class="monospaced">pkgconf</span> <a href="#pkgconf">[pkgconf]</a> or <span class="monospaced">pkg-config</span> <a href="#pkg-config">[pkg-config]</a>.
There are many cases where they do not compose, generate conflicts between each
other, or introduce ambiguities. We need more structured information in order
to accurately account for the variety of projects and how they are used in the
wild. This is especially acute with modules where module clients may need to
create separate BMI files from other clients needing the same module to satisfy
implementation requirements.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_changes">2. Changes</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_r0_initial">2.1. R0 (Initial)</h3>
<div class="paragraph"><p>Description of why usage requirements and how flag soup is not good enough in
the context of modules.</p></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_introduction">3. Introduction</h2>
<div class="sectionbody">
<div class="paragraph"><p>Every project has some set of things that must be done in order to meaningfully
consume it. This can include all kinds of things that tend to be communicated
via compiler flags, linker flags, dynamic loader environment variables, plugin
loading environment variables, and more. I refer to these things as "usage
requirements" of a project. These can meaningfully change between libraries or
other components of a project or even by what is consuming them (though in a
limited way). Discovering these usage requirements is a core part of a build
system&#8217;s job. There are a number of mechanisms that have been used to gather
usage requirements.</p></div>
<div class="paragraph"><p>Few projects are islands that depend on no external code. While vendoring is
common enough, it does not resolve the need to know how to meaningfully use a
library. Much of the time, using a project is communicated via a set of flags
to hand to a toolchain so that the in-source and runtime references to the
library in question. How these flags are collected have been done in multiple
ways over time. In any case, I call this method of gathering usage requirements
"flag soup" as interpreting these flags is only truly possible by the toolchain
itself in general. However, there is no isolation and one project specifying
<span class="monospaced">-Lpatha -la</span> and another <span class="monospaced">-Lpathb -lb</span> can change meaning depending on the
order they are provided to the toolchain if either <span class="monospaced">patha</span> or <span class="monospaced">pathb</span> contains
the other library. Other more-specific flags may also be required to set up
specific instances.</p></div>
<div class="paragraph"><p>Instead, a more structured way of specifying "usage requirements" should be
provided. This paper does not propose any specific way of doing so and instead
argues for why such structured information is necessary. While CMake has "usage
requirements", my vision goes much further in what kinds of information can and
should be communicated through such a mechanism.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_gathering_ingredients_flag_soup_strategies">4. Gathering Ingredients: Flag Soup Strategies</h2>
<div class="sectionbody">
<div class="paragraph"><p>Consuming dependencies is an important part of development. There are many ways
to manage them today. Tools such as <a href="#Anaconda">[Anaconda]</a>, <a href="#vcpkg">[vcpkg]</a>, <a href="#conan">[conan]</a>,
<a href="#spack">[spack]</a>, <a href="#Homebrew">[Homebrew]</a>, <a href="#nix">[nix]</a>, <a href="#ports">[ports]</a> (for FreeBSD as well as other
platforms such as OpenBSD and Gentoo), <a href="#dpkg">[dpkg]</a>, <a href="#rpm">[rpm]</a>, and more I&#8217;m sure I&#8217;m
unaware of all exist to manage dependencies for C++ code. They all need to
solve similar problems:</p></div>
<div class="ulist"><ul>
<li>
<p>
knowing that project X requires project Y;
</p>
</li>
<li>
<p>
making sure that Y is built in a way that is acceptable to X;
</p>
</li>
<li>
<p>
telling X where Y is so that an acceptable version is used (especially if
  multiple installations of Y are supported).
</p>
</li>
</ul></div>
<div class="paragraph"><p>X typically knows how to consume Y, but if this changes over time (say, Y needs
a new project Z), X may need to know this to use newer versions of Y. Ideally,
there would be a reliable way for Y to communicate this to X as needed.</p></div>
<div class="paragraph"><p>These tools all solve these problems in different ways with different benefits
and drawbacks. This paper is not focusing on the solutions these projects have
come up with to stitch various projects together and instead is on making sure
that projects can provide the required information in a rich enough way on
their own. This is so that the problems can be solved once per project instead
of once per project per distribution tool.</p></div>
<div class="paragraph"><p>This section describes the various ways which have been used in various
projects which involve what I call "flag soup". This is where consumers are
handed flags (in some way) by their dependencies libraries to blindly pass to
the toolchain so that the dependency can be used. Interpreting these flags is
generally not possible and they also tend to assume a single command line
dialect (typically GNU-like). While basic flags have compatible spellings
across many compilers, there are differences in critical flags which may be
important. Examples include:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">-pthread</span> (GNU) versus <span class="monospaced">-Xcompiler -pthread</span> (CUDA)
</p>
</li>
<li>
<p>
<span class="monospaced">-fPIC</span> (GNU) versus <span class="monospaced">-qpic</span> (IBM XL)
</p>
</li>
<li>
<p>
<span class="monospaced">-fopenmp</span> (GNU) versus <span class="monospaced">-fiopenmp</span> (non-MSVC frontend of Intel oneAPI)
  versus <span class="monospaced">-openmp</span> (MSVC)
</p>
</li>
</ul></div>
<div class="paragraph"><p>Any dependency which wishes to represent these kinds of things needs to be able
to understand the context in which the dependency is being consumed. This means
that it cannot just be a static lookup and there also needs to be some way to
perform a dynamic lookup to understand the usage. In any case, there&#8217;s no
standard for conveying "I am using vendor X compiler" to these tools.</p></div>
<div class="sect2">
<h3 id="_simple_flags">4.1. Simple flags</h3>
<div class="paragraph"><p>On "single installation prefix" (or "few installation prefix") systems such as
Linux, BSD, or other Unix-like platforms where all dependencies tend to live in
a few places, toolchains tend to search these places by default and simple
flags such as <span class="monospaced">-llibname</span> to load the code (and the headers are already found
implicitly).</p></div>
<div class="paragraph"><p>In this case, the name of the libraries to load is all that is necessary and
<span class="monospaced">-l</span> can be prefixed to the required library names and given to the toolchain
to search for.</p></div>
</div>
<div class="sect2">
<h3 id="_autolinking">4.2. Autolinking</h3>
<div class="paragraph"><p>On Windows there is a mechanism to request a library be linked from the source
code. This allows for dependencies to be used through just an include and
library search path addition. The syntax for this is:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #000080">#pragma</span></span> <span style="font-weight: bold"><span style="color: #000000">comment</span></span><span style="color: #990000">(</span>lib<span style="color: #990000">,</span> <span style="color: #FF0000">"libname"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>During linking, this will cause it to act as if <span class="monospaced">libname.lib</span> were specified as
an additional library to link to. However, the search path must be provided by
other mechanisms.</p></div>
</div>
<div class="sect2">
<h3 id="_compiler_wrappers">4.3. Compiler wrappers</h3>
<div class="paragraph"><p>Some projects ended up writing their own "compiler" which wraps the base
toolchain and adds the required flags as necessary while mediating between the
consumer and the base toolchain.</p></div>
<div class="paragraph"><p>The biggest issue with this approach is that it does not compose. These do not,
generally, have a mechanism to stack them arbitrarily and instead expect to
chain to the "lower" compiler by looking for it through the typical compiler
names such as the <span class="monospaced">CC</span> environment variable or searching for "common" names for
known compilers such as <span class="monospaced">cc</span>, <span class="monospaced">gcc</span>, or <span class="monospaced">clang</span>.</p></div>
<div class="paragraph"><p>If the wrapper is a compiled tool, using it in a cross-compilation context can
be difficult as it tends to be provided by the project itself. Even if not
compiled, it may not understand how to incorporate flags such as <span class="monospaced">--sysroot</span> to
re-root any paths it wants to pass to the underlying compiler.</p></div>
</div>
<div class="sect2">
<h3 id="_configuration_tools">4.4. Configuration tools</h3>
<div class="paragraph"><p>Projects such as <span class="monospaced">freetype</span> and <span class="monospaced">libpng</span> provide executables which provide the
flags necessary to use the library. These can work well, but have real
questions on how to support cross-compilation if provided in a compiled form
(most tend to be shell scripts in practice).</p></div>
<div class="paragraph"><p>These tools essentially manually implement <span class="monospaced">.pc</span> file resolution manually (and,
in fact, are sometimes implemented in terms of <span class="monospaced">pkgconf</span> today). However, there
is a lack of consistency at times, sometimes various features are missing, and
there&#8217;s no coordination with other ways of collecting dependency information.</p></div>
</div>
<div class="sect2">
<h3 id="_span_class_monospaced_pc_span_files">4.5. <span class="monospaced">.pc</span> files</h3>
<div class="paragraph"><p>The <span class="monospaced">pkg-config</span> tool and its associated <span class="monospaced">.pc</span> files are widely used to provide
these flags. These files are widely available and used on Unix-like platforms.
Some projects provide them on Windows as well, but they are not widely
available enough to be relied upon.</p></div>
<div class="paragraph"><p>There is some affordance for getting dependencies and making sure that there is
logic for the different linking requirements for static versus shared
libraries, but the query language is a bit coarse and requesting the static
version of library A while getting the shared version of library B is not easy
to guarantee if both libraries have both variants available. There is also no
way to provide different compilation flags between shared and static (e.g., to
control the export macros on platforms such as Windows or AIX).</p></div>
<div class="paragraph"><p><span class="monospaced">.pc</span> files also tend to prefer <span class="monospaced">-L</span> and <span class="monospaced">-l</span> pairs which can confound each
other. This seems to be done typically to support static and shared usage with
a single set of flags.</p></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_eating_your_greens_usage_requirements">5. Eating Your Greens: Usage Requirements</h2>
<div class="sectionbody">
<div class="paragraph"><p>The term "usage requirements" comes from CMake&#8217;s target-based model that was
first released in CMake 2.8.12. Over time, more and more mechanisms have been
added to this idea so that more than just include directories and libraries to
link. Today, there are usage requirements for compile options, linker options,
source files, compile definitions, and more. This does require some more work
on the part of library authors to classify the flags they would like to use
into "for me" and "for consumers". However, this is done at one central place.</p></div>
<div class="paragraph"><p>CMake has a mechanism for the consuming library to influence these requirements
as well. For example, it is possible to have a usage requirement of "if used by
an executable, please also do X". CMake calls them generator expressions and
uses its own syntax, but I&#8217;ll avoid using its syntax here and instead use
something that is (hopefully) clearer.</p></div>
<div class="sect2">
<h3 id="_terminology">5.1. Terminology</h3>
<div class="paragraph"><p>I&#8217;ll adopt some of CMake&#8217;s terminology for the rest of this paper to discuss
more concrete usage and limitations of the model.</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">library</span>: A logical unit of usage intended to be used by further targets.
  Libraries may be used at runtime by the dynamic loader (<span class="monospaced">shared</span> libraries)
  or a program directly (<span class="monospaced">module</span> libraries), by the linker as a group
  (<span class="monospaced">static</span> libraries), by the linker as a collection of object files (<span class="monospaced">object</span>
  libraries), or only by the build system (<span class="monospaced">interface</span> libraries).
</p>
</li>
<li>
<p>
<span class="monospaced">executable</span>: A program that may be directly executed.
</p>
</li>
<li>
<p>
<span class="monospaced">target</span>: A logical unit of usage. May be an executable, library, or just a
  collection of usage requirements.
</p>
</li>
</ul></div>
</div>
<div class="sect2">
<h3 id="_examples_of_usage_requirements">5.2. Examples of Usage Requirements</h3>
<div class="paragraph"><p>CMake has a number of usage requirements today, but this is certainly not an
exhaustive list of what makes sense. In fact, I feel that projects should be
able to define their own. Actually using them requires some level of support in
tools, but the ability to express the information is, I feel, a good starting
place for representing the information in the first place.</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">compile definition</span>: a flag for the preprocessor (e.g., <span class="monospaced">-Dsome_flag=value</span>)
</p>
</li>
<li>
<p>
<span class="monospaced">compile option</span>: a flag to give to the compiler (e.g., <span class="monospaced">-fstack-protector</span>)
</p>
</li>
<li>
<p>
<span class="monospaced">compile feature</span>: a capability of the compiler that has unification logic
  with other features in the same "category" (e.g., <span class="monospaced">-std=c++17</span> and
  <span class="monospaced">-std=c++20</span> belong to the same "category")
</p>
</li>
<li>
<p>
<span class="monospaced">precompile header</span>: headers to include in the precompiled header (of which
  most implementations only support one per TU); may also be used to indicate
  "use this one already-made PCH elsewhere too"
</p>
</li>
<li>
<p>
<span class="monospaced">include directory</span>: paths to search for textual inclusion sources (e.g.,
  collected and passed via <span class="monospaced">-I</span> or <span class="monospaced">-isystem</span> flags)
</p>
</li>
<li>
<p>
<span class="monospaced">source</span>: sources that should be added to the consuming target&#8217;s source list
  (e.g., <span class="monospaced">crt1.o</span>)
</p>
</li>
<li>
<p>
<span class="monospaced">link option</span>: options to pass to the linker (possibly through another
  frontend) (e.g., <span class="monospaced">--as-needed</span>)
</p>
</li>
<li>
<p>
<span class="monospaced">link directory</span>: directories to search for libraries specified by name
  (e.g., collected and passed via <span class="monospaced">-L</span> flags)
</p>
</li>
<li>
<p>
<span class="monospaced">link library</span>: libraries to link to (e.g., <span class="monospaced">/usr/lib/libdl.so</span> or <span class="monospaced">-ldl</span>)
</p>
</li>
</ul></div>
<div class="paragraph"><p>Further usage requirements I have wished for in the past:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">rpath entry</span>: paths to add to rpath properties (to satisfy <span class="monospaced">@rpath/</span> library
  references on macOS)
</p>
</li>
<li>
<p>
<span class="monospaced">runtime path</span>: paths to include in <span class="monospaced">PATH</span> when using a library (mainly for
  Windows)
</p>
</li>
<li>
<p>
<span class="monospaced">runtime loader path</span>: like <span class="monospaced">runtime path</span>, but for the dynamic loader
  (<span class="monospaced">PATH</span> on Windows, <span class="monospaced">DYLD_LIBRARY_PATH</span> on macOS, and <span class="monospaced">LD_LIBRARY_PATH</span> on
  ELF platforms)
</p>
</li>
<li>
<p>
<span class="monospaced">python path</span>: paths to collect and include in <span class="monospaced">PYTHONPATH</span> to use the
  library
</p>
</li>
</ul></div>
<div class="paragraph"><p>Usage requirements can be used to represent all kinds of information. It is my
feeling that projects should be able to declare and define their own usage
requirements. Support for consuming particular usage requirements may differ as
needed, though I would hope that compelling use cases become influential for
supporting more usage requirements in more tools over time.</p></div>
</div>
<div class="sect2">
<h3 id="_consistency_checking">5.3. Consistency Checking</h3>
<div class="paragraph"><p>There may be checks for consistency across targets in a usage subgraph. For
example, all code in a single program image must agree on the usage of the
<span class="monospaced">-fPIC</span> flag when compiling its constituent objects.</p></div>
</div>
<div class="sect2">
<h3 id="_limitations">5.4. Limitations</h3>
<div class="paragraph"><p>Usage requirements allow querying the consuming environment in order to modify
the set of provided information. However, this is not an unlimited capability.
Of note, nothing that can be queried may be modified through a usage
requirement. If this were possible, statements akin to "this statement is
false" are possible. More concretely, imagine a target (<span class="monospaced">eve</span>) that is able to
set some property on the consuming target (e.g., "set property <span class="monospaced">use-alice</span> to
<span class="monospaced">0</span> on the consuming target"). Another target <span class="monospaced">charlie</span> uses <span class="monospaced">alice</span> if it has
and <span class="monospaced">use-alice</span> set to a non-<span class="monospaced">0</span> value. <span class="monospaced">alice</span> then has a usage requirement
that consumers use <span class="monospaced">eve</span>. Now that the usage requirements of <span class="monospaced">eve</span> apply, it
sets the <span class="monospaced">use-alice</span> property on <span class="monospaced">charlie</span> to <span class="monospaced">0</span>. This is now a paradox that
cannot be resolved because <span class="monospaced">alice</span> should now <strong>not</strong> be used based on the
property settings.</p></div>
<div class="paragraph"><p>Therefore, usage requirements may only rely on properties of the context that
they may not affect. This includes support for "intersectional usage
requirements" such as "if X and Y are used, add usage requirement A".</p></div>
</div>
<div class="sect2">
<h3 id="_representing_targets_as_usage_requirements_with_visibility">5.5. Representing Targets as Usage Requirements with Visibility</h3>
<div class="paragraph"><p>When a layer of "visibility" is layered on top of usage requirements, they may
also be used to represent the properties of the target for itself as well as
for consumers. CMake gives these names:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">interface</span>: usage requirements for consumers
</p>
</li>
<li>
<p>
<span class="monospaced">private</span>: usage requirements for the target itself
</p>
</li>
<li>
<p>
<span class="monospaced">public</span>: a combination of both <span class="monospaced">interface</span> and <span class="monospaced">private</span>
</p>
</li>
</ul></div>
<div class="paragraph"><p>This additionally gives a classification of what flags are important for
consuming modules.</p></div>
</div>
<div class="sect2">
<h3 id="_application_to_modules">5.6. Application to Modules</h3>
<div class="paragraph"><p>Modules have a narrower compatibility contract than the ABI of libraries
and (see <a href="#P2581R2">[P2581R2]</a>). This means that there may be more than one BMI per build
graph so that different consumers can import a module. This is because BMIs may
involve internal data structures that are sensitive to flags such as <span class="monospaced">-std=</span>
where the selection of the TU importing affects what BMIs may actually be
loaded safely. There are many such flags that affect this compatibility in
practice.</p></div>
<div class="paragraph"><p>This narrow compatibility means that when consuming module interface units from
an external project cannot rely on any BMI artifacts to be provided by that
project and must be prepared to build BMIs for these interface units as part of
its own build graph.</p></div>
<div class="paragraph"><p>In terms of usage requirements, this manifests itself as variants of the target
provided by the project for each unique usage pattern which gain some usage
requirements from the direct consumer. An optimization may be made to share BMI
builds if it is found that different importers can share BMIs while
constructing the build graph.</p></div>
<div class="paragraph"><p>In order to do this effectively, it is necessary to know what flags that end up
being given to the compiler can be skipped when compiling these BMIs (the
"safe" option is to give all flags and every potential importer gets its own
BMI as necessary).</p></div>
<div class="sect3">
<h4 id="_example">5.6.1. Example</h4>
<div class="paragraph"><p>As an example, say we have a project with two targets <span class="monospaced">use20</span> and <span class="monospaced">use23</span> which
use the C++20 and C++23 standards, respectively. Both wish to import
modules from a target named <span class="monospaced">has_modules</span>. While it is assumed that the ABI of
the <span class="monospaced">has_modules</span> compile artifacts does not change between standards (the
status quo with textual inclusion today), the BMI almost certainly cannot be
reused and must be generated for each. This means that the build of the <span class="monospaced">use*</span>
project must schedule BMI builds for <span class="monospaced">has_modules</span> with each <span class="monospaced">-std=</span> flag (and
others as necessary).</p></div>
<div class="paragraph"><p>If there is another <span class="monospaced">also_use20</span> target which further has flags to use another
C dependency (in particular, <span class="monospaced">-I</span> flags for its headers), it would be nice to
know that these flags are local to the <span class="monospaced">also_use20</span> target and that it can
share BMI builds with <span class="monospaced">use20</span>. The classification of usage requirements into
visibility classifications for targets gives build systems enough information
to know what can be kept local to a given compilation and BMI requirement
graph.</p></div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_dependency_recipes_examples_of_existing_projects">6. Dependency Recipes: Examples of Existing Projects</h2>
<div class="sectionbody">
<div class="paragraph"><p>This section provides instances of projects where usage is not always
straightforward and/or involve deeper knowledge of the toolchain itself. Each
section has an example set of usage requirements in a Lisp-like syntax. They
are not intended to be 100% accurate, but instead to give an idea of what kinds
of things that might need to be constructed. Lisp is used because it is a
syntax which can represent data structures with embedded code-like queries of
things involving the consuming target.</p></div>
<div class="paragraph"><p>In the examples, there is the <span class="monospaced">match</span> construction which queries the consuming
environment. The particular queries here are meant for exposition and not meant
to be a proposal of how usage requirements should be spelled, merely as a way
to express the kinds of contextual queries that may be useful. The way that
<span class="monospaced">match</span> is intended to work here is as:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">(</span>match {query}
  <span style="color: #FF0000">(</span>{value1} {result}<span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>{value2} {result}<span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>{value3} {result}<span style="color: #FF0000">))</span></tt></pre></div></div>
<div class="paragraph"><p>The <span class="monospaced">{query}</span> is an expression that represents a way to query the environment.
This query is then matched against, in order, each <span class="monospaced">{valueN}</span> and the first
value which matches results in the entire <span class="monospaced">(match)</span> expression with its
corresponding <span class="monospaced">{result}</span>. A <span class="monospaced">_</span> value is a wildcard and matches any query
result.</p></div>
<div class="paragraph"><p>Queries used include:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">'language</span>: The language of the consuming compilation (C, C++, CUDA,
  etc.).
</p>
</li>
<li>
<p>
<span class="monospaced">'platform</span>: The platform of the consuming compilation (Windows, macOS,
  Linux, Android, etc.)
</p>
</li>
<li>
<p>
<span class="monospaced">(property 'target-type)</span>: Query the target for its "type" (executable,
  shared library, interface library, etc.)
</p>
</li>
<li>
<p>
<span class="monospaced">(property {some-other-symbol})</span>: Query the target for some other property
  and evaluate to its value.
</p>
</li>
<li>
<p>
<span class="monospaced">(query {predicate})</span>: Pass the target to <span class="monospaced">{predicate}</span> to evaluate some
  higher-level information about it (e.g., "is a library" or "contains Fortran
  code").
</p>
</li>
<li>
<p>
<span class="monospaced">(capture {name})</span>: The value may be captured and replaced in the <span class="monospaced">{result}</span>
  expression.
</p>
</li>
</ul></div>
<div class="paragraph"><p>Additionally, there are some other patterns used which warrant further
description:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">(compile-definitions {name} ({with_value} {value}))</span>: Compile definitions
  can either be the name of a symbol or a pair with a name and value. These
  typically become <span class="monospaced">-Dname</span> and <span class="monospaced">-Dwith_value=value</span> flags.
</p>
</li>
<li>
<p>
<span class="monospaced">(link-option (for-linker {value}))</span>: The flag needs to be passed directly to
  the linker. When constructing the command line, consider wrapping it as
  necessary to pass through any compiler frontends being preferred to using the
  linker directly (i.e., "add <span class="monospaced">-Wl,</span> if needed)
</p>
</li>
</ul></div>
<div class="sect2">
<h3 id="_sanitizers">6.1. Sanitizers</h3>
<div class="paragraph"><p>Sanitizers are accessed via flags such as <span class="monospaced">-fsanitize=…</span>. These flags have both
compiler and linker effects, namely generating the calls to extra checks in the
code itself and adding the library providing the implementation of these extra
checks to the linker.</p></div>
<div class="paragraph"><p>In addition, for some santizers, if the code is loaded by an executable not
using the sanitizer itself (e.g., a sanitized Python module loaded by a
pre-existing interpreter), <span class="monospaced">LD_PRELOAD</span> is necessary to ensure that the
sanitizer can install hooks early enough to provide their functionality.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'sanitizer-address</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; Give flags to the compiler and linker</span></span>
  <span style="color: #FF0000">(</span>compile-option <span style="color: #FF0000">"-fsanitize=address"</span><span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>link-option <span style="color: #FF0000">"-fsanitize=address"</span><span style="color: #FF0000">)</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; Ensure that the library is preloaded as needed</span></span>
  <span style="color: #FF0000">(</span>runtime-preload <span style="color: #FF0000">"/path/to/libasan.so"</span><span style="color: #FF0000">))</span></tt></pre></div></div>
</div>
<div class="sect2">
<h3 id="_boost">6.2. Boost</h3>
<div class="paragraph"><p>While Boost is largely a header-only project, some of its libraries have
additional compilation and linking requirements. For example, Boost.Archive can
optionally use various compression libraries which must be provided if used.
There is no mechanism for such optional dependencies when just providing flags
a priori.</p></div>
<div class="paragraph"><p>Boost also uses the autolinking mechanism to a note to the linker about
libraries that are required based on the included headers. Projects which use
Boost through more explicit means typically want to disable autolinking they
prefer to provide unambiguous.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'boost-noautolink</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; Turn off "autolinking"</span></span>
  <span style="color: #FF0000">(</span>compile-option <span style="color: #FF0000">"BOOST_ALL_NO_LIB"</span><span style="color: #FF0000">))</span>
<span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'boost-thread</span>
  <span style="color: #FF0000">(</span>link-library <span style="color: #FF0000">"/path/to/libboost_thread.so"</span><span style="color: #FF0000">)</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; Boost thread requires Boost's system library as well as its headers.</span></span>
  <span style="color: #FF0000">(</span>target <span style="color: #009900">'boost-system</span> <span style="color: #009900">'boost-includes</span><span style="color: #FF0000">))</span>
<span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'boost-system</span>
  <span style="color: #FF0000">(</span>link-library <span style="color: #FF0000">"/path/to/libboost_system.so"</span><span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>target <span style="color: #009900">'boost-includes</span><span style="color: #FF0000">))</span>
<span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'boost-includes</span>
  <span style="color: #FF0000">(</span>include-directory <span style="color: #FF0000">"/path/to/includes/for/boost"</span><span style="color: #FF0000">))</span></tt></pre></div></div>
</div>
<div class="sect2">
<h3 id="_mpi">6.3. MPI</h3>
<div class="paragraph"><p>MPI implementations have historically provided "compiler wrappers" named
<span class="monospaced">mpicc</span> and <span class="monospaced">mpic++</span>. These are intended to be used instead of using the
platform toolchain directly. These wrappers essentially just pass the required
compiler and linker flags as necessary.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'mpi</span>
  <span style="color: #FF0000">(</span>include-directory <span style="color: #FF0000">"/path/to/includes/for/mpi"</span><span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>link-library <span style="color: #FF0000">"/path/to/libmpi.so"</span><span style="color: #FF0000">)</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; MPI libraries tend to assume that threads are available.</span></span>
  <span style="color: #FF0000">(</span>target <span style="color: #009900">'threads</span><span style="color: #FF0000">)</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; Executables need to be launched using some tool to perform MPI's</span></span>
  <span style="font-style: italic"><span style="color: #9A1900">;; functionalities. Mark as "mpi-" as there are details about using such</span></span>
  <span style="font-style: italic"><span style="color: #9A1900">;; tools that need to be known anyways.</span></span>
  <span style="color: #FF0000">(</span>mpi-execution-launcher <span style="color: #FF0000">"/path/to/mpiexec"</span><span style="color: #FF0000">))</span>
<span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'threads</span>
  <span style="color: #FF0000">(</span>compile-option
    <span style="font-style: italic"><span style="color: #9A1900">;; Using threads is language-specific, so look at the *consuming* language</span></span>
    <span style="font-style: italic"><span style="color: #9A1900">;; and select the correct flags.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #009900">'language</span>
      <span style="font-style: italic"><span style="color: #9A1900">;; These flags go together and should be treated as a single unit.</span></span>
      <span style="color: #FF0000">(</span><span style="color: #009900">'cuda</span> <span style="color: #FF0000">(</span><span style="color: #FF0000">"-Xcompiler"</span> <span style="color: #FF0000">"-pthread"</span><span style="color: #FF0000">))</span>
      <span style="font-style: italic"><span style="color: #9A1900">;; All other languages should use `-pthread`</span></span>
      <span style="color: #FF0000">(</span>_ <span style="color: #FF0000">"-pthread"</span><span style="color: #FF0000">)))</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; The linker also needs to know (e.g., to add any additional libraries).</span></span>
  <span style="color: #FF0000">(</span>link-option
    <span style="color: #FF0000">(</span>match <span style="color: #009900">'language</span>
      <span style="color: #FF0000">(</span><span style="color: #009900">'cuda</span> <span style="color: #FF0000">(</span><span style="color: #FF0000">"-Xcompiler"</span> <span style="color: #FF0000">"-pthread"</span><span style="color: #FF0000">))</span>
      <span style="color: #FF0000">(</span>_ <span style="color: #FF0000">"-pthread"</span><span style="color: #FF0000">))))</span></tt></pre></div></div>
</div>
<div class="sect2">
<h3 id="_python">6.4. Python</h3>
<div class="paragraph"><p>Python is among one of the more complicated libraries to use due to the various
ways in which it can be used and deployment strategies used for its
distributions. Some consumers are creating modules, others are embedding the
interpreter. Some module-using consumers additionally wish to limit their
symbol usage using its "stable ABI" mechanism. These different consumption
patterns are not easily expressible via a simple <span class="monospaced">.pc</span> file as the tools do not
generally support a way to provide this kind of context (particularly for the
"use the stable ABI as of version 3.x" case).</p></div>
<div class="paragraph"><p>The expected usage pattern for Python is that the interpreter always provides
the <span class="monospaced">libpython</span> ABI at runtime. In order to do this, libraries which expect to
be used via an interpreter should <em>not</em> link to the <span class="monospaced">libpython</span> library. Modern
linkers prefer to error if used symbols are not provided by a library given, so
special flags (e.g., <span class="monospaced">-Wl,--unresolved-symbols=ignore-in-shared-libs</span>) are
required to inform the toolchain to not care about missing symbols.</p></div>
<div class="paragraph"><p>Things get more complicated when using these modules via further plugins. For
example, a Python-using library may reasonably expect to be loaded by a Python
interpreter (and so not link to its own <span class="monospaced">libpython</span>) while also wanting to be
used from a plugin of another project that does not use Python itself. Here,
the plugin must be told "you need to guarantee that <span class="monospaced">libpython</span> is provided"
and so <em>it</em> must link to <span class="monospaced">libpython</span> even if it does not directly use any of
its symbols itself. This can also require special flags (e.g.,
<span class="monospaced">-Wl,--no-as-needed</span>) to force the plugin to actually ensure that <span class="monospaced">libpython</span>
is loaded.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'python-executable</span>
  <span style="color: #FF0000">(</span>executable <span style="color: #FF0000">"/path/to/python"</span><span style="color: #FF0000">))</span>
<span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'python-library</span>
  <span style="color: #FF0000">(</span>include-directory <span style="color: #FF0000">"/path/to/includes/for/python"</span><span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>compile-definitions
    <span style="font-style: italic"><span style="color: #9A1900">;; Query the consumer to see if the stable ABI is requested.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'python-use-stable-abi</span><span style="color: #FF0000">)</span>
      <span style="font-style: italic"><span style="color: #9A1900">;; The value of this property is the version of the stable ABI to use.</span></span>
      <span style="color: #FF0000">((</span>capture <span style="color: #009900">'version</span><span style="color: #FF0000">)</span> <span style="color: #FF0000">(</span><span style="color: #FF0000">"Py_LIMITED_API"</span> <span style="color: #009900">'version</span><span style="color: #FF0000">))))</span>
  <span style="font-style: italic"><span style="color: #9A1900">;; Not everything should link directly to `libpython`, so implement that</span></span>
  <span style="font-style: italic"><span style="color: #9A1900">;; here.</span></span>
  <span style="color: #FF0000">(</span>link-library
    <span style="font-style: italic"><span style="color: #9A1900">;; Consuming executable should always link.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'target-type</span><span style="color: #FF0000">)</span>
      <span style="color: #FF0000">(</span><span style="color: #009900">'executable</span> <span style="color: #FF0000">"/path/to/libpython.so"</span><span style="color: #FF0000">))</span>
    <span style="font-style: italic"><span style="color: #9A1900">;; If the consuming target is embedding or force linking, link to the</span></span>
    <span style="font-style: italic"><span style="color: #9A1900">;; library.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'python-embed</span><span style="color: #FF0000">)</span>
      <span style="color: #FF0000">(</span>t <span style="color: #FF0000">"/path/to/libpython.so"</span><span style="color: #FF0000">))</span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'python-force-link</span><span style="color: #FF0000">)</span>
      <span style="color: #FF0000">(</span>t <span style="color: #FF0000">"/path/to/libpython.so"</span><span style="color: #FF0000">)))</span>
  <span style="color: #FF0000">(</span>link-option
    <span style="font-style: italic"><span style="color: #9A1900">;; Consuming executable should always link.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'target-type</span><span style="color: #FF0000">)</span>
      <span style="color: #FF0000">(</span><span style="color: #009900">'executable</span> <span style="color: #FF0000">())</span>
      <span style="font-style: italic"><span style="color: #9A1900">;; More conditionals here to select the correct flag for the given</span></span>
      <span style="font-style: italic"><span style="color: #9A1900">;; platform and detecting other `python-` properties referenced above.</span></span>
      <span style="color: #FF0000">(</span>_ <span style="color: #FF0000">(</span>for-linker <span style="color: #FF0000">"--no-as-needed"</span><span style="color: #FF0000">)))))</span></tt></pre></div></div>
</div>
<div class="sect2">
<h3 id="_qt">6.5. Qt</h3>
<div class="paragraph"><p>On the whole, Qt is largely a normal dependency as far as direct usage is
concerned. There are some extra tools Qt provides for various subsystems such
as <span class="monospaced">moc</span>, <span class="monospaced">rcc</span>, and <span class="monospaced">uic</span>, but these are essentially additional toolchains
which result in code generation that need to be used. Projects tend to handle
these things explicitly and these use cases are not intended to be solved here.</p></div>
<div class="paragraph"><p>Qt does get more complicated in two specific situations: use from executables
on Windows and when using a static Qt. On Windows, Qt requires that its
<span class="monospaced">qtmain</span> library is linked to, but only for executables in order to assist in
creating a cross-platform <span class="monospaced">main</span> function. However, sometimes this is <em>not</em>
wanted, so there should be a way to skip it (e.g., if some other framework is
also assisting with <span class="monospaced">main</span> portability).</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'qt-core</span>
  <span style="color: #FF0000">(</span>include-directory <span style="color: #FF0000">"/path/to/includes/for/qt"</span><span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>compile-definitions
    <span style="font-style: italic"><span style="color: #9A1900">;; Allow targets to indicate that they would like to use `Q_` spellings for</span></span>
    <span style="font-style: italic"><span style="color: #9A1900">;; all keywords.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'qt-portable-keywords</span><span style="color: #FF0000">)</span>
      <span style="color: #FF0000">(</span>t <span style="color: #FF0000">"QT_NO_KEYWORDS"</span><span style="color: #FF0000">))</span>
  <span style="color: #FF0000">(</span>link-library <span style="color: #FF0000">"/path/to/libQtCore.so"</span><span style="color: #FF0000">)</span>
  <span style="color: #FF0000">(</span>target
    <span style="font-style: italic"><span style="color: #9A1900">;; Executables on Windows also need qt-main.</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>property <span style="color: #009900">'target-type</span><span style="color: #FF0000">)</span>
      <span style="color: #FF0000">(</span><span style="color: #009900">'executable</span>
        <span style="color: #FF0000">(</span>match <span style="color: #009900">'platform</span>
          <span style="color: #FF0000">(</span><span style="color: #009900">'windows</span> <span style="color: #009900">'qt-winmain</span><span style="color: #FF0000">))))</span>
    <span style="font-style: italic"><span style="color: #9A1900">;; Static libraries should also pull in plugins</span></span>
    <span style="color: #FF0000">(</span>match <span style="color: #FF0000">(</span>query is-static<span style="color: #FF0000">)</span>
      <span style="font-style: italic"><span style="color: #9A1900">;; More platform and property checks here to select the right plugins as</span></span>
      <span style="font-style: italic"><span style="color: #9A1900">;; necessary.</span></span>
      <span style="color: #FF0000">(</span>t <span style="color: #FF0000">(</span><span style="color: #009900">'qt-plugin-platform-xcb</span><span style="color: #FF0000">))))</span>
<span style="color: #FF0000">(</span>usage-requirements <span style="color: #009900">'qt-winmain</span>
  <span style="color: #FF0000">(</span>link-library <span style="color: #FF0000">"/path/to/libQtWinMain.lib"</span><span style="color: #FF0000">))</span></tt></pre></div></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_references">7. References</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
<a id="Anaconda"></a>[Anaconda] Anaconda. <a href="https://new.anaconda.com/">https://new.anaconda.com/</a>.
</p>
</li>
<li>
<p>
<a id="conan"></a>[conan] <span class="monospaced">conan</span>. <a href="https://conan.io/">https://conan.io/</a>.
</p>
</li>
<li>
<p>
<a id="dpkg"></a>[dpkg] <span class="monospaced">dpkg</span>. <a href="https://www.dpkg.org/">https://www.dpkg.org/</a>.
</p>
</li>
<li>
<p>
<a id="Homebrew"></a>[Homebrew] Homebrew. <a href="https://brew.sh/">https://brew.sh/</a>.
</p>
</li>
<li>
<p>
<a id="nix"></a>[nix] <span class="monospaced">nix</span>. <a href="https://nixos.org/">https://nixos.org/</a>.
</p>
</li>
<li>
<p>
<a id="pkgconf"></a>[pkgconf] <span class="monospaced">pkgconf</span>. <a href="http://pkgconf.org/">http://pkgconf.org/</a>.
</p>
</li>
<li>
<p>
<a id="pkg-config"></a>[pkg-config] <span class="monospaced">pkg-config</span>.
  <a href="https://www.freedesktop.org/wiki/Software/pkg-config/">https://www.freedesktop.org/wiki/Software/pkg-config/</a>.
</p>
</li>
<li>
<p>
<a id="P2581R2"></a>[P2581R2] Ruoso, Daniel. Specifying the Interoperatbility of Built Module
  Interface Files.
  <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2581r2.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2581r2.pdf</a>.
</p>
</li>
<li>
<p>
<a id="ports"></a>[ports] Ports (FreeBSD). <a href="https://www.freebsd.org/ports/">https://www.freebsd.org/ports/</a>.
</p>
</li>
<li>
<p>
<a id="rpm"></a>[rpm] <span class="monospaced">rpm</span>. <a href="http://rpm.org/">http://rpm.org/</a>.
</p>
</li>
<li>
<p>
<a id="spack"></a>[spack] <span class="monospaced">spack</span>. <a href="https://spack.io/">https://spack.io/</a>.
</p>
</li>
<li>
<p>
<a id="vcpkg"></a>[vcpkg] <span class="monospaced">vcpkg</span>. <a href="https://vcpkg.io/">https://vcpkg.io/</a>.
</p>
</li>
</ul></div>
</div>
</div>
</div>
<div id="footnotes"><hr></div>
<div id="footer">
<div id="footer-text">
Version P2800R0<br>
Last updated
 2023-09-20 16:45:48 EDT
</div>
</div>
</body>
</html>
