You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/modules/ROOT/pages/usage.adoc
+60-5Lines changed: 60 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -207,28 +207,83 @@ f();
207
207
In this pattern, the user wants to document the function `f` as `__implementation_defined__ f();` because the library contract is that the user should not rely on a specific return type here.
208
208
However, this ill-formed pattern is problematic:
209
209
210
-
* `__implementation_defined__` is not a valid symbol so the code is ill-formed
211
-
* `impl::f_return_t` doesn't express the intent of the user for the documentation
210
+
* `__implementation_defined__` is not a valid symbol so the code is ill-formed
211
+
* `impl::f_return_t` doesn't express the intent of the user for the documentation
212
212
* the developer has to effectively maintain two versions of the code
213
213
* the original source code becomes more and more unreadable
214
214
215
-
Instead, when using MrDocs, while the `\\__MRDOCS__` macro is still available for conditional compilation, the same function could be directly documented as:
215
+
Instead, when using MrDocs, while the `\\__MRDOCS__` macro is still available for conditional compilation, the same function could be directly documented as:
216
216
217
217
[source,c++]
218
218
----
219
219
impl::f_return_t f();
220
220
----
221
221
222
-
And the user can specify that `impl` as a namespace for implementation details in the configuration file:
222
+
And the user can specify that symbols in the `impl` namespace are implementation details in the configuration file:
223
223
224
224
[source,yaml]
225
225
----
226
226
# ...
227
-
implementation-detail: impl
227
+
implementation-detail: impl::**
228
228
# ...
229
229
----
230
230
231
231
The xref:commands.adoc[] and xref:config-file.adoc[] pages contain a list of all available commands and options to identify and extract the relevant information as intended by the user.
232
232
233
233
MrDocs provides multiple mechanisms are provided to specify special {cpp} patterns, such as the example above.
234
234
For each common {cpp} construct that would require macros and two versions of the code, MrDocs provides commands to identify the construct and extract the relevant information as intented by the user.
235
+
236
+
[#dependencies]
237
+
=== Dependencies
238
+
239
+
Another consequence of relying on valid {cpp} code is that MrDocs needs to know about dependencies of the project for the code to be valid. In particular, it needs access to the header files of the project and its dependencies.
240
+
241
+
The `includes` option in the configuration file specifies the directories to search for header files. Suppose a library depends on an external library, such as https://www.boost.org[Boost,window=_blank]:
242
+
243
+
[source,yaml]
244
+
----
245
+
# A library that depends on an external library
246
+
includes:
247
+
- /path/to/boost/include
248
+
----
249
+
250
+
Whatever is specified in the `includes` option is passed to Clang as include directories, regardless of the strategy used to generate the compilation database.
251
+
252
+
If a `compile_commands.json` file is used, these include directories are passed directly to Clang as `-I` flags.
253
+
254
+
If a `CMakeLists.txt` file is used, the `cmake` option in the configuration file can be used to provide the necessary parameters for CMake to find the appropriate header files.
255
+
256
+
[source,yaml]
257
+
----
258
+
cmake: '-D BOOST_ROOT=/path/to/boost'
259
+
----
260
+
261
+
Another option supported by CMake is to set the `BOOST_ROOT` environment variable as `/path/to/boost` before running MrDocs.
262
+
263
+
=== System dependencies
264
+
265
+
It's also common for libraries to depend on the C++ standard library, the C standard library, or other system libraries. These dependencies are usually resolved by the compiler and are not explicitly specified in the source code:
266
+
267
+
* The {cpp} standard library: The compiler will look for specific paths according to the `-stdlib` option and include them as implicit `-isystem` paths. For instance, Clang can use different implementations of the {cpp} standard library. By default, that's Microsoft STL on Windows, libstdc++ on Linux and libc++ otherwise. This can be disabled with `-nostdinc++ -nostdlib++` or, in MrDocs, with `use-system-stdlib=false`.
268
+
* The C standard library (and system libraries): Unlike with libc++, LLVM+Clang does not provide an implementation of the C standard library. It always depends on the system for that. The compiler will not look for specific paths but implicitly include all system libraries. This can be disabled with `-nostdinc` or, in MrDocs, with `use-system-libc=false`.
269
+
270
+
That means unless `-nostdinc` is defined, all systems include paths are included. This is what allows the user to also use headers like `<Windows.h>` or `<linux/version.h>` without explicitly including anything else, even though they are not part of the C standard library. This is often seen as a convenience but can lead to portability issues.
271
+
272
+
In this context, MrDocs provides the `use-system-stdlib` and `use-system-libc` options. Both are set as `false` by default, meaning MrDocs will compile the code as if the `-nostdinc++ -nostdlib++` and `-nostdinc` flags were passed to Clang. Additionally:
273
+
274
+
- When `use-system-stdlib` is `false`, MrDocs will use the bundled libc++ headers available in `<mrdocs-root>/share/mrdocs/headers/libcxx` and `<mrdocs-root>/share/mrdocs/headers/clang`. These paths can be adjusted with the `stdlib-includes` option.
275
+
- When `use-system-libc` is `false`, MrDocs will use the bundled libc stubs available in `<mrdocs-root>/share/mrdocs/headers/libc-stubs`. This path can be adjusted with the `libc-includes` option.
276
+
277
+
The rationale for that is reproducibility. You want to be able to build your documentation and don't want it to stop working because the platform or some platform details have changed.
278
+
These default values also help avoid conflicts where the same symbol or header is defined twice if the compilation database includes system paths relevant to one specific compiler. That can breaks things when MrDocs attempts to compile it with clang.
279
+
In other words, MrDocs becomes a sandboxed environment where only the C and C++ standard libraries are available.
280
+
281
+
The default values described above work for most libraries and applications that only depend on the C and C++ standard libraries. When there are no dependencies outside the standard libraries, the user probably won't even notice the difference between these options.
282
+
283
+
However, if you depend on other system libraries, that means you need to handle these dependencies explicitly. For instance, this is very common with networking libraries. There are a few solutions to this, and these solutions are in a continuum regarding the use of `use-system-stdlib`/`use-system-libc` and the design of the code:
284
+
285
+
1. Depending on the design of your library, you can implement a different path for MrDocs where you don't need these system headers. System headers are often guarded by macros to detect the platform: for instance, `__linux__` for `<linux/version.h>` and `_WIN32` for `<Windows.h>`. You can use the `__MRDOCS__` macro to provide an implementation for MrDocs. This implementation would typically include stubs for the symbols you need in the documentation. Because symbols from system libraries are typically not exposed in the public API of your library, that gives you replacements that make sense for the documentation. However, this solution is not enough when other dependencies also depend on these system libraries.
286
+
2. Handle it as an explicit dependency. Explicitly include the paths you need in your compilation database as if it's a dependency described in the <<dependencies>> section. For instance, you can get CMake to explicitly find `<linux/version.h>` or `<Windows.h>` and only include those directories with `-isystem` or `-I` in the compilation database.
287
+
3. Enable `use-system-libc`. MrDocs will still use the bundled libc++ for the C++ standard library, and use the system headers for the C standard library, making all system paths available. That makes system headers such as `<linux/version.h>` or `<Windows.h>` available by default. The trade-off is losing the reproducibility guarantees described above.
288
+
289
+
The first option in this list provides the most control and the most reproducibility. The third option is the most convenient but also the most fragile.
0 commit comments