breathe-doc / breathe

ReStructuredText and Sphinx bridge to Doxygen
https://breathe-doc.org
Other
751 stars 198 forks source link

Duplicate warning with breathe-apidoc #772

Open tdegeus opened 2 years ago

tdegeus commented 2 years ago

I use breathe-apidoc as follows (I don't know if that is what was intended, I have not managed to find any documentation...):

python -m breathe.apidoc -p GooseFEM -o api _doxygen/xml

and that in my index.rst

.. toctree::
   :caption: API
   :maxdepth: 1
   :glob:

   api/*

Which works fine, accept that I'm getting a bunch of warnings such as

api/namespace/namespaceGooseFEM_1_1Tyings.rst:4: WARNING: Duplicate C++ declaration, also defined at api/class/classGooseFEM_1_1Tyings_1_1Control:4.

What can be done to prevent this?

Caelin commented 2 years ago

I am getting the same warnings when generating documents for a tool I built in Java. I am using Doxygen and Breathe to generate Sphinx documentation to go with documentation for a JPype wrapper in Python. I am getting these warnings when using abstract class methods and I am overriding the method in the subclass. Breathe is complaining about a duplicate declaration for each of these abstract methods since they are in the superclass and subclass both. This should not be a warning and Breathe should understand proper inheritance and virtual methods.

I also created another issue related to this one for another error message when parsing abstract class methods and can be found at #778

jakobandersen commented 2 years ago

I'm not sure if he issue is with what apidoc generates or with Breathe it self (or with Sphinx). If I remember correctly there are some duplicate-declaration problems when inheritance is involved. To be able to look more into this, it would be great if (both of) you can provide instructions for reproducing the problem, preferably in minimized example projects.

jrmejiaa commented 2 years ago

I think this is related to the xml output from Doxygen. If you look carefully in the file you are going to see that Doxygen creates a <compound> for every file inside of the INPUT tag. If you are using C++ this means that you are creating a xml file for the header *.h and also for the source *.cpp, which eventually would lead to a Duplication warning from the breathe-apidoc.

There are some workaround to fix this warnings for C++ but I don't know how challenging would be to solve this problem from a Java source code.

@Caelin I am a little curious, Java has already a very robust automated documentation, why do you do not use javadoc?

Attach to this message I send an output of a index.xml Doxygen file with the problem that I am describing

<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<doxygenindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="index.xsd" version="1.8.17">
  <compound refid="classImage" kind="class"><name>Image</name>
    <member refid="classImage_1a5a9b26b4fb221248deb83abb666a1e21" kind="variable"><name>cols</name></member>
    <member refid="classImage_1ad0238c887b63a1d9dedab2edeca64707" kind="variable"><name>rows</name></member>
    <member refid="classImage_1aa06677ad88bf95e3ed87449786c681cb" kind="variable"><name>chan</name></member>
    <member refid="classImage_1a8c885ded00fd35077e4df3be9cc1df95" kind="variable"><name>size</name></member>
    <member refid="classImage_1ac707214a98f76a9bf7a268c10a4f16e1" kind="variable"><name>pixels</name></member>
    <member refid="classImage_1a2999c972d3a441a0af7dfd52441b983d" kind="variable"><name>ppm_type</name></member>
    <member refid="classImage_1a58edd1c45b4faeb5f789b0d036d02313" kind="function"><name>Image</name></member>
    <member refid="classImage_1adc5d9e643b449f21aa5b0d0d7dd4b80f" kind="function"><name>Image</name></member>
    <member refid="classImage_1ad480e22ff4c42487e72727de3417eb3d" kind="function"><name>Image</name></member>
    <member refid="classImage_1a3ba117b81aff6aac412ebfb9496452f2" kind="function"><name>operator[]</name></member>
    <member refid="classImage_1a0294f63700543e11c0f0da85601c7ae5" kind="function"><name>~Image</name></member>
  </compound>
  <compound refid="main_8cpp" kind="file"><name>main.cpp</name>
    <member refid="main_8cpp_1a45ba202b05caf39795aeca91b0ae547e" kind="define"><name>TIMEOUT</name></member>
    <member refid="main_8cpp_1a0ddf1224851353fc92bfbff6f499fa97" kind="function"><name>main</name></member>
  </compound>
  <compound refid="main__noHW_8cpp" kind="file"><name>main_noHW.cpp</name>
    <member refid="main__noHW_8cpp_1a45ba202b05caf39795aeca91b0ae547e" kind="define"><name>TIMEOUT</name></member>
    <member refid="main__noHW_8cpp_1a0ddf1224851353fc92bfbff6f499fa97" kind="function"><name>main</name></member>
  </compound>
  <compound refid="ppm_8cpp" kind="file"><name>ppm.cpp</name>
    <member refid="ppm_8cpp_1ab4fa15fe08bc20636c72949eeeca24ce" kind="function"><name>getHexString</name></member>
    <member refid="ppm_8cpp_1ab65a56f3b98ae30893a9e0c2dd42bf1d" kind="function"><name>readPPM</name></member>
    <member refid="ppm_8cpp_1acc6448566403e47ccb3f02a4a65a6d2b" kind="function"><name>savePPM</name></member>
    <member refid="ppm_8cpp_1acd6c96bf759e72c05352a64b1edc0e0f" kind="function"><name>savePixels</name></member>
  </compound>
  <compound refid="ppm_8h" kind="file"><name>ppm.h</name>
    <member refid="ppm_8h_1aae9749d96e15ccb4f482dd5f55d98f9b" kind="typedef"><name>BYTE</name></member>
    <member refid="ppm_8h_1ab65a56f3b98ae30893a9e0c2dd42bf1d" kind="function"><name>readPPM</name></member>
    <member refid="ppm_8h_1acc6448566403e47ccb3f02a4a65a6d2b" kind="function"><name>savePPM</name></member>
    <member refid="ppm_8h_1acd6c96bf759e72c05352a64b1edc0e0f" kind="function"><name>savePixels</name></member>
  </compound>
  <compound refid="serial_8cpp" kind="file"><name>serial.cpp</name>
    <member refid="serial_8cpp_1ab4b19dfdf208fee18951d91c59d5009c" kind="function"><name>rgbToGrayscale</name></member>
    <member refid="serial_8cpp_1ae55a803cd300fb3f3a7d5ff8be85f3c9" kind="function"><name>rgbToGrayscaleShift</name></member>
  </compound>
  <compound refid="serial_8h" kind="file"><name>serial.h</name>
    <member refid="serial_8h_1ab4b19dfdf208fee18951d91c59d5009c" kind="function"><name>rgbToGrayscale</name></member>
    <member refid="serial_8h_1ae55a803cd300fb3f3a7d5ff8be85f3c9" kind="function"><name>rgbToGrayscaleShift</name></member>
  </compound>
  <compound refid="dir_57e0317f685e46796bf0967b598c2df6" kind="dir"><name>/home/jairom/Documents/TUD_Projects/03_Semester/ESHO2/ESHO2/task_4/host/src/ppm</name>
  </compound>
  <compound refid="dir_ee75d340cb949c8d47b0901592a11d1b" kind="dir"><name>/home/jairom/Documents/TUD_Projects/03_Semester/ESHO2/ESHO2/task_4/host/src/serial</name>
  </compound>
  <compound refid="dir_68267d1309a1af8e8297ef4c3efbcdba" kind="dir"><name>/home/jairom/Documents/TUD_Projects/03_Semester/ESHO2/ESHO2/task_4/host/src</name>
  </compound>
</doxygenindex>
tdegeus commented 2 years ago

Thanks. Just a comment the original question was about C++

jrmejiaa commented 2 years ago

Hi @tdegeus yes, I know. I point out the problem for a C++ implementation with the breathe-apidoc. I tried to workaround the problem changing the Doxygen file, but most of the options does not apply to the output of the XML.

It is necessary to update the code to not use the information from the *.cpp files when there is already a .hpp file with those same functions. If you see the message that I put in the file serial.cpp has the same functions as serial.h. However, as the code of breathe-apidoc is right now, it cannot identify that those are the same implementation and shows the warning of Duplicate C++ declaration.

@jakobandersen are you a collaborator from the breathe-apidoc python file? I could help you but after some weeks because I have some deadlines to deal with in my work. If you are interested, please let me know.

jakobandersen commented 2 years ago

There are so many possible levels where the true problem originates (from Doxygen through Breathe to Sphinx it self), that it is difficult to pinpoint without getting concrete. So I think a great starting point would be if one of you can create a small example project is that reproduces the problem. I.e., something with the minimal amount of source code and rst code.

jrmejiaa commented 2 years ago

Hi @jakobandersen

Attach to this message you will find a test_project that has the problem related to this issue. The only thing that you need to do, if you want to see the directly the warning output messages is use the cmake file that I use to build the documentation. Please be aware that the cmake from the C++ project is independent from the cmake in the folder docs.

# Go to the project
cd docs
mkdir build && cd build
cmake .. && make

The output of the HTML is going to be located in the folder html and the output from the breathe-apidoc command is located in the folder src inside of docs.

test_project.zip

jakobandersen commented 2 years ago

I'm not really familiar with this specific use-case, but based on a bit of playing around with the example, it looks like there are two problems:

sethrj commented 1 year ago

Yes, the file+class conflict seems to be a particularly bad one. Even using .. doxygenfile:: multiple times seems to want to repeat the anchor for a namespace. From https://raw.githubusercontent.com/celeritas-project/celeritas/master/doc/api/corecel.rst I get numerous warnings:

/Users/seth/.local/src/celeritas-temp/doc/api/corecel.rst:22: WARNING: Duplicate C++ declaration, also defined at api/corecel:20.
Declaration is '.. cpp:type:: celeritas'.
/Users/seth/.local/src/celeritas-temp/doc/api/corecel.rst:10: CRITICAL: Duplicate ID: "d2/dd1/namespaceceleritas".
/Users/seth/.local/src/celeritas-temp/doc/api/corecel.rst:10: WARNING: Duplicate explicit target name: "d2/dd1/namespaceceleritas".
/Users/seth/.local/src/celeritas-temp/doc/api/corecel.rst:29: WARNING: Duplicate C++ declaration, also defined at api/corecel:20.

Since all the functions/macros/variables/etc. that I want to document are inside an innernamespace I can't omit that section.

ZedThree commented 8 months ago

I think the duplicate declaration warning for namespaces is inevitable because they're mapped to cpp:type: https://github.com/breathe-doc/breathe/blob/542ae9b9ed6e5bd5e92ba2360b094df8931ba756/breathe/renderer/sphinxrenderer.py#L251

It doesn't look like there is a Spinx entity for namespace, the cpp:namespace directive is actually for changing the current scope.

Maybe it would be better to instead just ensure the namespaces are merged into the entity names themselves?