<div dir="ltr"><div dir="ltr">Another approach involves building the library twice: once as a "normal" build and once as an "internal" build. To implement this, you can create two CMake targets, "mylibrary" and "mylibrary_internal," while utilizing the same headers and source files for both targets. However, for the internal target, certain CMake target properties need to be set differently from the normal target.<br><br>Instead of using:<div><br></div><div><pre lang="cmake"><span id="m_-3601454869079256072m_5609525288502381631m_-1763255687690334495gmail-LC217" lang="cmake"><span> CXX_VISIBILITY_PRESET </span><span>"hidden"</span><span></span></span>
<span id="m_-3601454869079256072m_5609525288502381631m_-1763255687690334495gmail-LC218" lang="cmake"><span> VISIBILITY_INLINES_HIDDEN </span><span>TRUE</span></span>
</pre></div><div><br></div><div>Opt for:</div><div><br></div><div><pre lang="cmake"><span id="m_-3601454869079256072m_5609525288502381631m_-1763255687690334495gmail-LC321" lang="cmake"><span> CXX_VISIBILITY_PRESET </span><span>"default"</span><span></span></span>
<span id="m_-3601454869079256072m_5609525288502381631m_-1763255687690334495gmail-LC322" lang="cmake"><span> VISIBILITY_INLINES_HIDDEN </span><span>FALSE</span></span></pre></div><div><br></div><div>By doing so, all symbols should be exported on Linux without the need to add extra export macros in your source code (although on Windows, additional CMake settings are necessary).</div><br><div>Advantages of this approach:</div><div>+ No need to add extra export macros for the internal API; you can keep your source code as it is.</div><div>+ All symbols are readily available out-of-the-box.</div><div>+ Faster build times compared to proposal number 1: All unit tests build against the same internal library, eliminating the need to rebuild individual sources repeatedly.</div><div>+ Easier compared to proposal number 1: No need to worry about source file dependencies since the entire library is built as a whole, making every symbol available.</div><div><br></div><div>Drawbacks:<div></div><div>- The library will be built twice, once for the internal build and once for the normal build.</div><div>- The approach is not elegant.</div></div><div><br></div><div>Currently, I am using this approach, which can be found in the CMake code here:</div><div><br></div><div><a href="https://invent.kde.org/libraries/perceptualcolor/-/blob/e82c2a62ccd93d9f0f31153e05d80ef746d37806/src/CMakeLists.txt#L317" target="_blank">https://invent.kde.org/libraries/perceptualcolor/-/blob/e82c2a62ccd93d9f0f31153e05d80ef746d37806/src/CMakeLists.txt#L317</a></div><div><br></div><div>While it works well for me, I'm not entirely certain if this is the "preferred option" in general. Nevertheless, it has proven to be effective for my use case.</div><div><br></div><div>(Previously, I attempted something similar to your proposal number 2 to avoid building twice. Unfortunately, I encountered issues, such as a significantly larger binary size in the resulting "normal" build. However, it is possible that simply I made errors in the CMake code.)</div><div><br></div><div>Best regards,<br></div><div><br></div><div><div><div dir="ltr" class="gmail_signature">Lukas Sommer</div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am So., 23. Juli 2023 um 14:16 Uhr schrieb Stefan Brüns <<a href="mailto:stefan.bruens@rwth-aachen.de" target="_blank">stefan.bruens@rwth-aachen.de</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
I am looking for some feedback regarding unit testing libraries (e.g. <br>
Frameworks libraries, but not limited to). First, some background:<br>
<br>
As long as on limits oneself to testing the public API of a library all is <br>
easy, linking and calling the exposed API just works. Some say that's all that <br>
should be tested, case closed.<br>
<br>
Unfortunately, in my experience that does not work out all the time.<br>
<br>
Unit testing requires some input data, and it is not always possible to <br>
provide the required data to the exposed API. One example would be files, <br>
files can be large, especially if there are many variations which need to be <br>
covered. Another one is extended attributes, e.g. KFileMetaData testing <br>
requires a writable filesystem with XAttr support (tmpfs only has limited <br>
XAttr support). The same probably applies to DBs and external (Web) servers, <br>
or anything that involves system calls.<br>
<br>
Public API may also limit the possibility to inject errors, or good coverage <br>
may be limited by combinatorial explosion.<br>
<br>
So there a definitely good reasons to not only test public API, but also <br>
internal functions.<br>
<br>
Hiding just the API is fairly simple, just make the relevant header private.<br>
<br>
But preferably, also the corresponding symbols in the created shared libraries <br>
are hidden. Hiding unexported/private symbols reduces runtime link time, and <br>
allows the compiler to remove unreachable code, due to inlining and/or LTO.<br>
<br>
On the other hand, these hidden functions can also no longer be linked to and <br>
called by any unit tests.<br>
<br>
<br>
So, now to my actual question - what are the preferred options for testing <br>
internal API?<br>
<br>
1. Just link the test binary to the relevant source files<br>
+ Trivial<br>
- May require long lists of sources, extra `target_include_directories` etc.<br>
<br>
2. Create an intermediate CMake OBJECT library, which is linked to by the test <br>
binaries, and used for the exported shared library. The object library is not <br>
affected by symbol visibility<br>
+ CMake properties like include directories still work<br>
- adds an extra intermediate target, less idiomatic<br>
<br>
3. ?<br>
<br>
Kind regards,<br>
<br>
Stefan<br>
<br>
</blockquote></div>
</div>