<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I would like to discuss the way how external dependencies should be searched by qbs.<div class=""><br class=""></div><div class="">While implementing support for the protobuf I found that there several place where a generic c++ can come from.</div><div class=""><br class=""></div><div class="">1. It can be detected via pkg-config</div><div class="">2. It can be detected using probes</div><div class="">3. Other pkg-config-like tools? Maybe Vcpkg?</div><div class="">4. It can be the part of the project.</div><div class=""><br class=""></div><div class="">I am not sure if we need to support 4, but if the mechanism of library searching will be based on the Depends item, I don’t see why user can’t add a «zlib» product that will be fetched prior to system modules. But anyway, that’s not the point.</div><div class=""><br class=""></div><div class="">The point is that for now, I have to write stuff like</div><div class=""><br class=""></div><div class="">
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><!--StartFragment--><span style=" color:#c0c0c0;" class="">    </span><span style=" color:#800080;" class="">Depends</span><span style=" color:#c0c0c0;" class=""> </span>{</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">name</span>:<span style=" color:#c0c0c0;" class=""> </span><span style=" color:#008000;" class="">"internal.libprotobuf.pkgconfig"</span></pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">condition</span>:<span style=" color:#c0c0c0;" class=""> </span><span style=" font-style:italic;" class="">_autoDetect</span></pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">required</span>:<span style=" color:#c0c0c0;" class=""> </span>false</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">    </span>}</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">    </span><span style=" color:#800080;" class="">Depends</span><span style=" color:#c0c0c0;" class=""> </span>{</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">name</span>:<span style=" color:#c0c0c0;" class=""> </span><span style=" color:#008000;" class="">"internal.libprotobuf.probes"</span></pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">condition</span>:<span style=" color:#c0c0c0;" class=""> </span><span style=" font-style:italic;" class="">_autoDetect</span><span style=" color:#c0c0c0;" class=""> </span>&&<span style=" color:#c0c0c0;" class=""> </span>!internal.libprotobuf.pkgconfig.found</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">required</span>:<span style=" color:#c0c0c0;" class=""> </span>false</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">    </span>}<!--EndFragment--></pre><div class=""><br class=""></div></div><div class="">Note, that <span style="color: rgb(0, 128, 0);" class="">libprotobuf.pkgconfig </span>and <span style="color: rgb(0, 128, 0);" class="">libprotobuf.probes </span>are <b class="">different</b> modules in different folders under qbs/modules.</div><div class="">In case I want to add third way to fetch a library, I will require third module and third <span style="color: rgb(128, 0, 128);" class="">Depends </span>item. Too much boilerplate for a modern build system.</div><div class=""><br class=""></div><div class="">This comes from the limitation that modules are loaded only based on their condition and priority and it is not possible to use Probes in conditions. I guess, this limitation comes from the fact that probes are heavy to evaluate, but I’m not sure.</div><div class="">Either that limitation should be removed, or we can extend the way Qbs loads modules by adding <span style="color: rgb(128, 128, 0);" class="">property</span><span style="color: rgb(192, 192, 192);" class=""> </span><span style="color: rgb(128, 128, 0);" class="">bool</span><span style="color: rgb(192, 192, 192);" class=""> </span><span style="color: rgb(128, 0, 0);" class="">recover</span> to the Module which tells Qbs to try loading next module in a chain (with lower priority) if loading «best suitable» module failed. If the property is false by default, current behavior will be preserved and we can use it to implement «chain» loading by simply writing <span style="color: rgb(128, 0, 128);" class="">Depends</span> { name: <span style="color: rgb(0, 128, 0);" class="">"internal.libprotobuf" </span>}. </div><div class=""><br class=""></div><div class="">Next thing I want to discuss is the way how Qbs should search for libraries using Probes. For now, we have IncludeProbe, LibraryProbe and FrameworkProbe (for macOS frameworks). It is not very convenient to use them directly, but we can wrap them into a ExternalPackage module that provides some input properties to tell Probes what to search for:</div><div class=""><br class=""></div><div class="">
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><!--StartFragment--><span style=" color:#c0c0c0;" class="">    </span>ExternalPackage<span style=" color:#c0c0c0;" class=""> </span>{</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">name</span>:<span style=" color:#c0c0c0;" class=""> </span><span style=" color:#008000;" class="">"zlib"</span></pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">headers</span>:<span style=" color:#c0c0c0;" class=""> </span>[<span style=" color:#008000;" class="">"zlib.h"</span>]</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">        </span><span style=" color:#800000;" class="">libraryNames</span>:<span style=" color:#c0c0c0;" class=""> </span>[<span style=" color:#008000;" class="">"z"</span>]</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><span style=" color:#c0c0c0;" class="">    </span>}</pre>
<pre style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""><!--EndFragment--></pre><div class="">We can also provide some properties to tell Qbs where to search for libraries or to override some default behavior:</div><div class=""><br class=""></div><div class="">qbs build modules.ExternalPackage.platformSearchPaths:"/opt/usr/lib" modules.ExternalPackage.staticLibs:true</div><div class=""><br class=""></div><div class="">That way, we will have mechanism similar to CMake find package module and we can provide support for lot of libraries in a <b class="">declarative</b> way.</div></div><div class=""><br class=""></div><div class="">Any thoughts?</div></body></html>