Open MrKepzie opened 4 years ago
I completely understand, this is 100% valid criticism. Part of it is sphinx: more rst docs -> more work. Some users reported that using PyPy rather than Cython was enough of a speed boost to make it worth it.
The other part is more difficult, when my blackout ends (work is borderline killing me these days) the first thing we need to do is rewrite breathe. I think we pinpointed it to the caching strategy being the problem, I think the majority of the time is spent looking up things from the cache (breathe caches the xml and when it's getting rendered looks it up from the cache).
It seems I forgot to enable parallel builds too, I will try and add that today since it's a small change, please nudge me if I forget.
But right now exhale may only be appropriate for small to medium projects. I know the pytorch docs take ~30 minutes to build as well, they just setup a cron build to do it every so often rather than per commit I think.
You're only other option (which isn't ideal) is to not document as many items...
(the sphinx part: to test, try using alabaster theme which is lightweight, some html themes are much more expensive than others)
Thanks for your prompt answer, i'll give it a shot using another theme. I'm actually encountering crashes in sphinx when it reads back the generated rst sources now. Will post a traceback when I get time (it crashes after more than 20mins of processing)
Here is the error I get:
Please also report this if it was a user error, so that a better error message can be provided next time.
A bug report can be filed in the tracker at <https://github.com/sphinx-doc/sphinx/issues>. Thanks!
comper-laptop-alexandre:cmake_build alexandre$ cat /var/folders/hm/gc71lw996d18dnnxhchjywrw0000gn/T/sphinx-err-0pcc6r8n.log
# Sphinx version: 3.3.0+
# Python version: 3.8.2 (CPython)
# Docutils version: 0.16 release
# Jinja2 version: 2.11.2
# Last messages:
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UISeparator.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UIShapes.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UISlider.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UISpinBox.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UISplitLayout.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UIStackedLayout.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UITabBar.h
# reading sources... [ 51%] reference/file__Users_alexandre_development_comper_Plugins_UICommon_private_UITableView.h
# reading sources... [ 51%] reference/file_view_hierarchy
# reading sources... [ 51%] reference/function_BlendModesImpl_8h_1a4681c86281480e7f5992cb6d6db42667
# Loaded extensions:
# sphinx.ext.mathjax (3.3.0+) from /Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/ext/mathjax.py
# sphinxcontrib.applehelp (1.0.2) from /opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sphinxcontrib/applehelp/__init__.py
# sphinxcontrib.devhelp (1.0.2) from /opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sphinxcontrib/devhelp/__init__.py
# sphinxcontrib.htmlhelp (1.0.3) from /opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sphinxcontrib/htmlhelp/__init__.py
# sphinxcontrib.serializinghtml (1.1.4) from /opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sphinxcontrib/serializinghtml/__init__.py
# sphinxcontrib.qthelp (1.0.3) from /opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sphinxcontrib/qthelp/__init__.py
# alabaster (0.7.12) from /opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/alabaster/__init__.py
# breathe (4.20.0) from /Users/alexandre/Library/Python/3.8/lib/python/site-packages/breathe/__init__.py
# exhale (0.2.3) from /Users/alexandre/Library/Python/3.8/lib/python/site-packages/exhale/__init__.py
# sphinxjp.themes.basicstrap (unknown version) from /Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinxjp/themes/basicstrap/__init__.py
Traceback (most recent call last):
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6008, in _parse_declarator
res = self._parse_declarator_name_suffix(named, paramMode, typed)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 5890, in _parse_declarator_name_suffix
paramQual = self._parse_parameters_and_qualifiers(paramMode)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 5645, in _parse_parameters_and_qualifiers
self.fail('Expecting "(" in parameters-and-qualifiers.')
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/util/cfamily.py", line 293, in fail
raise self._make_multi_error(errors, '')
sphinx.util.cfamily.DefinitionError: Invalid C++ declaration: Expecting "(" in parameters-and-qualifiers. [error at 12]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
------------^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6091, in _parse_type
decl = self._parse_declarator(named=True, paramMode=outer,
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6018, in _parse_declarator
raise self._make_multi_error(prevErrors, header) from e
sphinx.util.cfamily.DefinitionError: Error in declarator or parameters-and-qualifiers
Invalid C++ declaration: Expecting "(" in parameters-and-qualifiers. [error at 12]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
------------^
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6008, in _parse_declarator
res = self._parse_declarator_name_suffix(named, paramMode, typed)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 5890, in _parse_declarator_name_suffix
paramQual = self._parse_parameters_and_qualifiers(paramMode)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 5672, in _parse_parameters_and_qualifiers
self.fail(
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/util/cfamily.py", line 293, in fail
raise self._make_multi_error(errors, '')
sphinx.util.cfamily.DefinitionError: Invalid C++ declaration: Expecting "," or ")" in parameters-and-qualifiers, got "-". [error at 32]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
--------------------------------^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6105, in _parse_type
decl = self._parse_declarator(named=True, paramMode=outer)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6018, in _parse_declarator
raise self._make_multi_error(prevErrors, header) from e
sphinx.util.cfamily.DefinitionError: Error in declarator or parameters-and-qualifiers
If pointer to member declarator:
Invalid C++ declaration: Expected '::' in pointer to member (function). [error at 25]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
-------------------------^
If declarator-id:
Invalid C++ declaration: Expecting "," or ")" in parameters-and-qualifiers, got "-". [error at 32]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
--------------------------------^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/cmd/build.py", line 280, in build_main
app.build(args.force_all, filenames)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/application.py", line 348, in build
self.builder.build_update()
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/builders/__init__.py", line 297, in build_update
self.build(to_build,
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/builders/__init__.py", line 311, in build
updated_docnames = set(self.read())
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/builders/__init__.py", line 418, in read
self._read_serial(docnames)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/builders/__init__.py", line 439, in _read_serial
self.read_doc(docname)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/builders/__init__.py", line 479, in read_doc
doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/io.py", line 223, in read_doc
pub.publish()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/core.py", line 217, in publish
self.document = self.reader.read(self.source, self.parser,
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/io.py", line 128, in read
self.parse()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/readers/__init__.py", line 77, in parse
self.parser.parse(self.input, document)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/parsers.py", line 102, in parse
self.statemachine.run(inputlines, document, inliner=self.inliner)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 170, in run
results = StateMachineWS.run(self, input_lines, input_offset,
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
self.section(title, source, style, lineno - 1, messages)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 327, in section
self.new_subsection(title, lineno, messages)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
newabsoffset = self.nested_parse(
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
state_machine.run(block, input_offset, memo=self.memo,
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 196, in run
results = StateMachineWS.run(self, input_lines, input_offset)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
self.section(title, source, style, lineno - 1, messages)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 327, in section
self.new_subsection(title, lineno, messages)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
newabsoffset = self.nested_parse(
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
state_machine.run(block, input_offset, memo=self.memo,
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 196, in run
results = StateMachineWS.run(self, input_lines, input_offset)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/statemachine.py", line 241, in run
context, next_state, result = self.check_line(
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/statemachine.py", line 459, in check_line
return method(match, context, next_state)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
nodelist, blank_finish = self.explicit_construct(match)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
return method(self, expmatch)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
return self.run_directive(
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
result = directive_instance.run()
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/breathe/directives.py", line 99, in run
node_stack = self.resolve_function(matches, args, project_info)
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/breathe/directives.py", line 238, in resolve_function
signature = self.create_function_signature(entry, project_info, filter_, target_handler,
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/breathe/directives.py", line 212, in create_function_signature
ast = parser.parse_declaration('function', 'function')
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6569, in parse_declaration
declaration = self._parse_type(named=True, outer='function')
File "/Users/alexandre/Library/Python/3.8/lib/python/site-packages/sphinx/domains/cpp.py", line 6126, in _parse_type
raise self._make_multi_error(prevErrors, header) from exTyped
sphinx.util.cfamily.DefinitionError: Error when parsing function declaration.
If the function has no return type:
Error in declarator or parameters-and-qualifiers
Invalid C++ declaration: Expecting "(" in parameters-and-qualifiers. [error at 12]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
------------^
If the function has a return type:
Error in declarator or parameters-and-qualifiers
If pointer to member declarator:
Invalid C++ declaration: Expected '::' in pointer to member (function). [error at 25]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
-------------------------^
If declarator-id:
Invalid C++ declaration: Expecting "," or ")" in parameters-and-qualifiers, got "-". [error at 32]
LA_NS_ENTER GCC_DIAG_OFF (unused-parameter) CLANG_DIAG_OFF(unused-parameter) template< bool premult > inline float Copy_rgb(float Sc
--------------------------------^
Here is the content of the faulty file:
.. _exhale_function_BlendModesImpl_8h_1a4681c86281480e7f5992cb6d6db42667:
Function GCC_DIAG_OFF(unused-)
==============================
- Defined in :ref:`file__Users_alexandre_development_comper_Plugins_ImageProc_private_BlendModesImpl.h`
Function Documentation
----------------------
.. doxygenfunction:: GCC_DIAG_OFF(unused-)
It seems it fails on function macros. Any way to your knowledge to workaround this ?
Lol, it's kind of funny that it's an unused
thing that breaks this, LIAR -- it IS used haha!
Ok I've got some time set aside tonight to put some band-aids on exhale and I'll see if there's anything clever I can do about macros. I'm not very optimistic there's much I can do, will create a minimal repro but I expect that the doxygen XML is misleading exhale.
To at least get past the macro I suggest skipping it from being documented at least in it's current form. I can't find the config right now but I remember there being something special about function macros that you can set on the doxygen side, I need to add some test cases for that.
Another alternative is to predefine as shown with the dllexport example here https://www.doxygen.nl/manual/preprocessing.html which should result in it getting removed (?) Not exactly a fix, but should enable the build to at least succeed.
To clarify the breathe side, I think it all stems from memory leaks in minidom which crushes large projects, but it will be a lot of work to redo. So if (a) PyPy and (b) me (soon) adding parallel do not reduce build times enough then it probably isn't going to be a good choice for your project at this time. It is strange that the doxygen index version is not affected though, and may indicate we have other options.
Exhale should be reporting timing metrics near the beginning of the sphinx build log about how long it took to parse and generate things, can you share those times? I'm using lxml which does much better, that's what we intend to switch breathe to.
Will experiment tomorow with doxygen parameters. Doxygen HTML output works fine, some it may be the XML that is misleading.
Timing outputs: [+] Exhale: finished parsing Doxygen XML in 1 minute, and 2.47 seconds. [+] Exhale: generated reStructuredText documents in 36.59 seconds.
Then reading rst sources back takes more than 15 minutes to get around 50% where it crashes
Then I get a bazillion of warnings such as
Current limitations in .. doxygenfunction:: directive affect your code!
(!)
(!) Right now there are 2 functions that will all be generating the
(!) *SAME* directive on different pages:
(!)
(!) .. doxygenfunction:: details::getPolynomial()
(!)
(!) This will result in all 2 pages documenting the same function, however
(!) which function is not known (possibly dependent upon order of Doxygen's
(!) index.xml?). We hope to resolve this issue soon, and appreciate your
(!) understanding.
(!)
(!) The full function signatures as parsed by Exhale that will point to the
(!) same function:
(!)
(!) - template <typename T> constexpr T details::getPolynomial()
(!) - constexpr std::uint32_t details::getPolynomial()
(!)
(!) Unfortunately, there are no known workarounds at this time. Your only options
(!)
(!) 1. Ignore it, hopefully this will be resolved sooner rather than later.
(!) 2. Only let Doxygen document *ONE* of these functions, e.g., by doing
(!)
(!) #if !defined(DOXYGEN_SHOULD_SKIP_THIS)
(!) // function declaration and/or implementation
(!) #endif // DOXYGEN_SHOULD_SKIP_THIS
(!)
(!) Making sure that your Doxygen configuration has
(!)
(!) PREDEFINED += DOXYGEN_SHOULD_SKIP_THIS
(!)
(!) (added by default when using "exhaleDoxygenStdin").
(!)
(!) Sorry :(
Dear svenevs,
I am quite new to Sphinx + Breathe + Exhale but I like your work very much. I was not sure if this is the right "Issue" otherwise, I can generate a new one. I have a similar problem as MrKepzie reported in his last message. My plan is to start documentation for a large existing scientific code (not written by me) which have a lot of non-member functions in .cpp files. They are declared in .h and *.hpp files and can thus be used after including the header files everywhere in the code. Unfortunately, this produces the same errors as reported by MrKepzie. For illustration I created a minimal example with the following folder structure:
__LUdocs ..... | __conf.py, ... | |
---|---|---|
__deleteaftertestscr | ||
..... | __main.cpp | |
..... | __myclass.cpp | |
__deleteaftertestinclude | ||
..... | __myclass.h |
main.cpp
1 #include "myclass.h" // defines MyClass 2 3 int main() 4 { 5 /* 6 Titanium 7 I am 8 / 9 MyClass a; // no longer produces an error, because MyClass is defined 10 return 0; 11} 12 13 size_t goal;
14 goal = curious(5, 4)
myclass.cpp
1 #include "myclass.h" 2 3 /* 4 \author test 5 test 6 / 7 void MyClass::foo() 8 { 9 return 3 10 } 11 12 void curious(size_t a, size_t b){
13 return a + b 14 }
myclass.h
1 class MyClass 2 { 3 public: 4 void foo(); 5 int bar; 6 }; 7 8 void curious(size_t a, size_t b);
which leads to
(!) (!) Current limitations in .. doxygenfunction:: directive affect your code! (!) (!) Right now there are 2 functions that will all be generating the (!) SAME directive on different pages: (!) (!) .. doxygenfunction:: curious(size_t, size_t) (!) (!) This will result in all 2 pages documenting the same function, however (!) which function is not known (possibly dependent upon order of Doxygen's (!) index.xml?). We hope to resolve this issue soon, and appreciate your (!) understanding. (!) (!) The full function signatures as parsed by Exhale that will point to the (!) same function: (!) (!) - void curious(size_t, size_t) (!) - void curious(size_t, size_t) (!) (!) Unfortunately, there are no known workarounds at this time. Your only options (!) (!) 1. Ignore it, hopefully this will be resolved sooner rather than later. (!) 2. Only let Doxygen document ONE of these functions, e.g., by doing (!) (!) #if !defined(DOXYGEN_SHOULD_SKIP_THIS) (!) // function declaration and/or implementation (!) #endif // DOXYGEN_SHOULD_SKIP_THIS (!) (!) Making sure that your Doxygen configuration has (!) (!) PREDEFINED += DOXYGEN_SHOULD_SKIP_THIS (!) (!) (added by default when using "exhaleDoxygenStdin"). (!) (!) Sorry :( (!)
I understand that with "#if !defined(DOXYGEN_SHOULD_SKIP_THIS) ..." this issue can be solved in a hardcoded way, but was hoping there is an alternative since it is a quite large code and would hope to find another solution. Therefore I would like to ask if there is an option from Exhale to resolve this issue?
I apologize for misleading formulations and in case I used some wrong terms!!!
Kind regards
A lot of the problems here are not resolved, and speed for large projects with exhale will need some more serious investigation. That said, a decent number of problems reported here related to signatures of things (functions, and in this case it looks like some macros) could be resolved differently by updating the interface between exhale and breathe. See https://github.com/svenevs/exhale/issues/106#issuecomment-834218192 for more information.
I generated C++ headers for the Infineon XMC4700 here: https://github.com/vkottler/hal-xmc4700.
It's been running for 83 hours and it's not even 50% done with just the reading/ingesting part.
Source-file count:
vkottler at vkottler-tower in ~/src/vkottler/hal-xmc4700/src (master)
$ tree | tail -n 2
10 directories, 3857 files
I did the same for this project: https://github.com/vkottler/hal-rp2040.
https://vkottler.github.io/cpp/sphinx/hal-rp2040/
Took between 1-2 days. I'm happy to wait because the generated output is amazing! Just seems odd that the complexity scaling here is really bad.
Hi,
We have a large codebase for which we use doxygen. Doxygen generation of XML + HTML is quite fast ~10sec. When using only breathe + .. doxygenindex :: directive we are able to generate an index (which looks really bad compared to what Doxygen output offers, but that's not the point). Exhale generates lots of .rst files which then takes more than 30minutes for sphinx to parse in "reading sources..."; This is a deal breaker for us. I am wondering where the bottleneck is and if something can be done to make it more on par with the performances we find with just doxygenindex directive ?