From 56f4c37ab010bd41739d708107955f403a565bec Mon Sep 17 00:00:00 2001
From: Than Ngo <than@redhat.com>
Date: Fri, 29 Nov 2024 16:32:34 +0100
Subject: [PATCH] - Fix Non-reproducible file names in doxygen output - Fix
 broken markdown links to anchors

Related: RHEL-58045
---
 ...ducible-file-names-in-doxygen-output.patch | 403 ++++++++++++++++++
 doxygen-1.12.0-regression-anchors.patch       |  30 ++
 doxygen.spec                                  | 102 +----
 doxywizard.desktop                            |   6 -
 sources                                       |   1 -
 5 files changed, 448 insertions(+), 94 deletions(-)
 create mode 100644 doxygen-1.12.0-non-reproducible-file-names-in-doxygen-output.patch
 create mode 100644 doxygen-1.12.0-regression-anchors.patch
 delete mode 100644 doxywizard.desktop

diff --git a/doxygen-1.12.0-non-reproducible-file-names-in-doxygen-output.patch b/doxygen-1.12.0-non-reproducible-file-names-in-doxygen-output.patch
new file mode 100644
index 0000000..4882e7e
--- /dev/null
+++ b/doxygen-1.12.0-non-reproducible-file-names-in-doxygen-output.patch
@@ -0,0 +1,403 @@
+commit 040cdc3acd4d417df447199eefb4af08fbbe6907
+Author: Dimitri van Heesch <doxygen@gmail.com>
+Date:   Fri Sep 20 21:10:32 2024 +0200
+
+    issue #11138 Non-reproducible file names in doxygen output
+
+diff --git a/src/doxygen.cpp b/src/doxygen.cpp
+index add2af755..124b5fda4 100644
+--- a/src/doxygen.cpp
++++ b/src/doxygen.cpp
+@@ -1547,6 +1547,7 @@ static void processTagLessClasses(const ClassDef *rootCd,
+     MemberList *ml = cd->getMemberList(MemberListType::PubAttribs());
+     if (ml)
+     {
++      int pos=0;
+       for (const auto &md : *ml)
+       {
+         QCString type = md->typeString();
+@@ -1559,7 +1560,7 @@ static void processTagLessClasses(const ClassDef *rootCd,
+             if (type.find(icd->name())!=-1) // matching tag less struct/union
+             {
+               QCString name = md->name();
+-              if (md->isAnonymous()) name = "__unnamed" + name.right(name.length()-1)+"__";
++              if (md->isAnonymous()) name = "__unnamed" + QCString().setNum(pos++)+"__";
+               if (!prefix.isEmpty()) name.prepend(prefix+".");
+               //printf("    found %s for class %s\n",qPrint(name),qPrint(cd->name()));
+               ClassDefMutable *ncd = createTagLessInstance(rootCd,icd,name);
+@@ -8837,7 +8838,7 @@ static void generateDocsForClassList(const std::vector<ClassDefMutable*> &classL
+         auto ctx = std::make_shared<DocContext>(cd,*g_outputList);
+         auto processFile = [ctx]()
+         {
+-          msg("Generating docs for compound %s...\n",qPrint(ctx->cd->name()));
++          msg("Generating docs for compound %s...\n",qPrint(ctx->cd->displayName()));
+ 
+           // skip external references, anonymous compounds and
+           // template instances
+@@ -8875,7 +8876,7 @@ static void generateDocsForClassList(const std::vector<ClassDefMutable*> &classL
+         if ( !cd->isHidden() && !cd->isEmbeddedInOuterScope() &&
+               cd->isLinkableInProject() && cd->templateMaster()==nullptr)
+         {
+-          msg("Generating docs for compound %s...\n",qPrint(cd->name()));
++          msg("Generating docs for compound %s...\n",qPrint(cd->displayName()));
+ 
+           cd->writeDocumentation(*g_outputList);
+           cd->writeMemberList(*g_outputList);
+@@ -8943,7 +8944,7 @@ static void generateConceptDocs()
+         ) && !cd->isHidden() && cd->isLinkableInProject()
+        )
+     {
+-      msg("Generating docs for concept %s...\n",qPrint(cd->name()));
++      msg("Generating docs for concept %s...\n",qPrint(cd->displayName()));
+       cd->writeDocumentation(*g_outputList);
+     }
+   }
+@@ -9912,7 +9913,7 @@ static void generateNamespaceClassDocs(const ClassLinkedRefMap &classList)
+               && !ctx->cdm->isHidden() && !ctx->cdm->isEmbeddedInOuterScope()
+              )
+           {
+-            msg("Generating docs for compound %s...\n",qPrint(ctx->cdm->name()));
++            msg("Generating docs for compound %s...\n",qPrint(ctx->cdm->displayName()));
+             ctx->cdm->writeDocumentation(ctx->ol);
+             ctx->cdm->writeMemberList(ctx->ol);
+           }
+@@ -9943,7 +9944,7 @@ static void generateNamespaceClassDocs(const ClassLinkedRefMap &classList)
+             && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
+            )
+         {
+-          msg("Generating docs for compound %s...\n",qPrint(cd->name()));
++          msg("Generating docs for compound %s...\n",qPrint(cd->displayName()));
+ 
+           cdm->writeDocumentation(*g_outputList);
+           cdm->writeMemberList(*g_outputList);
+@@ -9982,7 +9983,7 @@ static void generateNamespaceDocs()
+       NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get());
+       if (ndm)
+       {
+-        msg("Generating docs for namespace %s\n",qPrint(nd->name()));
++        msg("Generating docs for namespace %s\n",qPrint(nd->displayName()));
+         ndm->writeDocumentation(*g_outputList);
+       }
+     }
+diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
+index 0582fc983..dd0fb6839 100644
+--- a/src/namespacedef.cpp
++++ b/src/namespacedef.cpp
+@@ -44,6 +44,10 @@ static QCString makeDisplayName(const NamespaceDef *nd,bool includeScope)
+   {
+     result = substitute(result,"::",sep);
+   }
++  if (nd->isAnonymous())
++  {
++    result = removeAnonymousScopes(result);
++  }
+   //printf("makeDisplayName() %s->%s lang=%d\n",qPrint(name()),qPrint(result),lang);
+   return result;
+ }
+diff --git a/src/scanner.l b/src/scanner.l
+index 35850404e..2a2c45b3e 100644
+--- a/src/scanner.l
++++ b/src/scanner.l
+@@ -33,7 +33,6 @@ typedef yyguts_t *yyscan_t;
+ #include <algorithm>
+ #include <vector>
+ #include <utility>
+-#include <atomic>
+ #include <cstdint>
+ #include <cstdio>
+ #include <cstdlib>
+@@ -61,9 +60,6 @@ typedef yyguts_t *yyscan_t;
+ #define YY_NO_INPUT 1
+ #define YY_NO_UNISTD_H 1
+ 
+-static AtomicInt  anonCount;
+-static AtomicInt  anonNSCount;
+-
+ struct scannerYY_state
+ {
+   OutlineParserInterface *thisParser;
+@@ -213,6 +209,9 @@ struct scannerYY_state
+ 
+   int              fakeNS  = 0; //<! number of file scoped namespaces in CSharp file
+   TextStream       dummyTextStream;
++
++  int              anonCount = 0;
++  int              anonNSCount = 0;
+ };
+ 
+ [[maybe_unused]] static const char *stateToString(int state);
+@@ -247,6 +246,7 @@ static void storeClangId(yyscan_t yyscanner,const char *id);
+ static void startVerbatimBlock(yyscan_t yyscanner,const QCString &blockName,size_t fencedSize=0);
+ static bool endVerbatimBlock(yyscan_t yyscanner,const QCString &blockName,size_t fencedSize=0);
+ 
++
+ /* ----------------------------------------------------------------- */
+ #undef  YY_INPUT
+ #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
+@@ -4354,7 +4354,7 @@ NONLopt [^\n]*
+                                           BEGIN(MemberSpecSkip);
+                                         }
+ <TypedefName>";"                        { /* typedef of anonymous type */
+-                                          yyextra->current->name.sprintf("@%d",anonCount++);
++                                          yyextra->current->name = generateAnonymousAnchor(yyextra->fileName,yyextra->anonCount++);
+                                           if (yyextra->current->section.isEnum() || yyextra->current->spec.isEnum())
+                                           {
+                                             yyextra->current->program << ','; // add field terminator
+@@ -4429,7 +4429,7 @@ NONLopt [^\n]*
+                                                 {
+                                                   // anonymous compound yyextra->inside -> insert dummy variable name
+                                                   //printf("Adding anonymous variable for scope %s\n",qPrint(p->name));
+-                                                  yyextra->msName.sprintf("@%d",anonCount++);
++                                                  yyextra->msName = generateAnonymousAnchor(yyextra->fileName,yyextra->anonCount++);
+                                                   break;
+                                                 }
+                                               }
+@@ -6339,12 +6339,12 @@ NONLopt [^\n]*
+                                               }
+                                               else // use invisible name
+                                               {
+-                                                yyextra->current->name.sprintf("@%d",anonNSCount.load());
++                                                yyextra->current->name = generateAnonymousAnchor(yyextra->fileName,yyextra->anonNSCount);
+                                               }
+                                             }
+                                             else
+                                             {
+-                                              yyextra->current->name.sprintf("@%d",anonCount++);
++                                              yyextra->current->name = generateAnonymousAnchor(yyextra->fileName,yyextra->anonCount++);
+                                             }
+                                           }
+                                           yyextra->curlyCount=0;
+@@ -7846,7 +7846,6 @@ static void addKnRArgInfo(yyscan_t yyscanner,const QCString &type,const QCString
+ 
+ //-----------------------------------------------------------------------------
+ 
+-
+ void fixArgumentListForJavaScript(ArgumentList &al)
+ {
+   for (Argument &a : al)
+@@ -7859,6 +7858,7 @@ void fixArgumentListForJavaScript(ArgumentList &al)
+   }
+ }
+ 
++//-----------------------------------------------------------------------------
+ 
+ static void startCommentBlock(yyscan_t yyscanner,bool brief)
+ {
+@@ -8168,6 +8168,8 @@ static void parseMain(yyscan_t yyscanner,
+   yyextra->yyLineNr      = 1 ;
+   yyextra->yyBegLineNr   = 1;
+   yyextra->yyBegColNr    = 0;
++  yyextra->anonCount     = 0;
++  yyextra->anonNSCount   = 0;
+   yyextra->fileName = fileName;
+   yyextra->clangParser = clangParser;
+   setContext(yyscanner);
+@@ -8222,7 +8224,7 @@ static void parseMain(yyscan_t yyscanner,
+ 
+   parseCompounds(yyscanner,rt);
+ 
+-  anonNSCount++;
++  yyextra->anonNSCount++;
+ 
+   // add additional entries that were created during processing
+   for (auto &[parent,child]: yyextra->outerScopeEntries)
+diff --git a/src/sitemap.cpp b/src/sitemap.cpp
+index 67e6c3f35..52e324261 100644
+--- a/src/sitemap.cpp
++++ b/src/sitemap.cpp
+@@ -86,7 +86,7 @@ class Crawlmap::Private
+   public:
+     std::ofstream crawlFile;
+     TextStream crawl;
+-    StringSet crawlLinks;
++    StringVector crawlLinks;
+ };
+ 
+ Crawlmap::Crawlmap() : p(std::make_unique<Private>()) {}
+@@ -117,6 +117,8 @@ void Crawlmap::initialize()
+ 
+ void Crawlmap::finalize()
+ {
++  std::sort(p->crawlLinks.begin(),p->crawlLinks.end());
++  p->crawlLinks.erase(std::unique(p->crawlLinks.begin(),p->crawlLinks.end()),p->crawlLinks.end());
+   for (auto &s : p->crawlLinks)
+   {
+     p->crawl << "<a href=\"" << s << "\"/>\n";
+@@ -132,7 +134,7 @@ void Crawlmap::addIndexFile(const QCString & fileName)
+ {
+   QCString fn = fileName;
+   addHtmlExtensionIfMissing(fn);
+-  p->crawl << "<a href=\"" << fn << "\"/>\n";
++  p->crawlLinks.push_back(fn.str());
+ }
+ 
+ void Crawlmap::addContentsItem(bool, const QCString &, const QCString & ref,
+@@ -163,7 +163,7 @@ void Crawlmap::addContentsItem(bool, con
+         link += currAnc.str();
+       }
+     }
+-    p->crawlLinks.insert(link);
++    p->crawlLinks.push_back(link);
+   }
+ }
+ 
+@@ -213,12 +213,12 @@ void Crawlmap::addIndexItem(const Defini
+     QCString ref;
+ 
+     ref = makeRef(contRef, anchor);
+-    p->crawlLinks.insert(ref.str());
++    p->crawlLinks.push_back(ref.str());
+   }
+   else if (context) // container
+   {
+     QCString contRef = context->getOutputFileBase();
+     QCString ref = makeRef(contRef,sectionAnchor);
+-    p->crawlLinks.insert(ref.str());
++    p->crawlLinks.push_back(ref.str());
+   }
+ }
+diff --git a/src/util.cpp b/src/util.cpp
+index ab30eb461..1aa6916a5 100644
+--- a/src/util.cpp
++++ b/src/util.cpp
+@@ -3877,6 +3877,27 @@ QCString convertNameToFile(const QCString &name,bool allowDots,bool allowUndersc
+   return result;
+ }
+ 
++QCString generateAnonymousAnchor(const QCString &fileName,int count)
++{
++  QCString fn = stripFromPath(fileName)+":"+QCString().setNum(count);
++  const int sig_size=16;
++  uint8_t md5_sig[sig_size];
++  MD5Buffer(fn.data(),static_cast<unsigned int>(fn.length()),md5_sig);
++  char result[sig_size*3+2];
++  char *p = result;
++  *p++='@';
++  for (int i=0;i<sig_size;i++)
++  {
++    static const char oct[]="01234567";
++    uint8_t byte = md5_sig[i];
++    *p++=oct[(byte>>6)&7];
++    *p++=oct[(byte>>3)&7];
++    *p++=oct[(byte>>0)&7];
++  }
++  *p='\0';
++  return result;
++}
++
+ QCString relativePathToRoot(const QCString &name)
+ {
+   QCString result;
+diff --git a/src/util.h b/src/util.h
+index 64ce8e895..31b32aa25 100644
+--- a/src/util.h
++++ b/src/util.h
+@@ -253,6 +253,8 @@ QCString replaceAnonymousScopes(const QCString &s,const QCString &replacement=QC
+ 
+ QCString convertNameToFile(const QCString &name,bool allowDots=FALSE,bool allowUnderscore=FALSE);
+ 
++QCString generateAnonymousAnchor(const QCString &fileName,int count);
++
+ void extractNamespaceName(const QCString &scopeName,
+                           QCString &className,QCString &namespaceName,
+                           bool allowEmptyClass=FALSE);
+diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
+index 4d4913d20..8e3eebe18 100644
+--- a/src/xmlgen.cpp
++++ b/src/xmlgen.cpp
+@@ -2243,12 +2243,12 @@ void generateXML()
+     }
+     for (const auto &cd : *Doxygen::conceptLinkedMap)
+     {
+-      msg("Generating XML output for concept %s\n",qPrint(cd->name()));
++      msg("Generating XML output for concept %s\n",qPrint(cd->displayName()));
+       generateXMLForConcept(cd.get(),t);
+     }
+     for (const auto &nd : *Doxygen::namespaceLinkedMap)
+     {
+-      msg("Generating XML output for namespace %s\n",qPrint(nd->name()));
++      msg("Generating XML output for namespace %s\n",qPrint(nd->displayName()));
+       generateXMLForNamespace(nd.get(),t);
+     }
+     for (const auto &fn : *Doxygen::inputNameLinkedMap)
+diff --git a/testing/071/namespace_a_namespace_1_1_0d0.xml b/testing/071/namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063.xml
+similarity index 62%
+rename from testing/071/namespace_a_namespace_1_1_0d0.xml
+rename to testing/071/namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063.xml
+index c08d49e24..4da395e35 100644
+--- a/testing/071/namespace_a_namespace_1_1_0d0.xml
++++ b/testing/071/namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063.xml
+@@ -1,27 +1,27 @@
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ <doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
+-  <compounddef id="namespace_a_namespace_1_1_0d0" kind="namespace" language="C++">
++  <compounddef id="namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063" kind="namespace" language="C++">
+     <compoundname>ANamespace</compoundname>
+     <sectiondef kind="enum">
+-      <memberdef kind="enum" id="namespace_a_namespace_1_1_0d0_1a96ab6574751fdf6a53ceec8a3896c45d" prot="public" static="no" strong="yes">
++      <memberdef kind="enum" id="namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063_1a80c23b2c34d4baaf4e21819ff9c3dcd6" prot="public" static="no" strong="yes">
+         <type/>
+         <name>Boolean</name>
+         <qualifiedname>ANamespace::Boolean</qualifiedname>
+-        <enumvalue id="namespace_a_namespace_1_1_0d0_1a96ab6574751fdf6a53ceec8a3896c45daf8320b26d30ab433c5a54546d21f414c" prot="public">
++        <enumvalue id="namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063_1a80c23b2c34d4baaf4e21819ff9c3dcd6af8320b26d30ab433c5a54546d21f414c" prot="public">
+           <name>False</name>
+           <briefdescription>
+           </briefdescription>
+           <detaileddescription>
+           </detaileddescription>
+         </enumvalue>
+-        <enumvalue id="namespace_a_namespace_1_1_0d0_1a96ab6574751fdf6a53ceec8a3896c45daf827cf462f62848df37c5e1e94a4da74" prot="public">
++        <enumvalue id="namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063_1a80c23b2c34d4baaf4e21819ff9c3dcd6af827cf462f62848df37c5e1e94a4da74" prot="public">
+           <name>True</name>
+           <briefdescription>
+           </briefdescription>
+           <detaileddescription>
+           </detaileddescription>
+         </enumvalue>
+-        <enumvalue id="namespace_a_namespace_1_1_0d0_1a96ab6574751fdf6a53ceec8a3896c45da2767828026039e8ba7b38973cbb701f2" prot="public">
++        <enumvalue id="namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063_1a80c23b2c34d4baaf4e21819ff9c3dcd6a2767828026039e8ba7b38973cbb701f2" prot="public">
+           <name>FileNotFound</name>
+           <briefdescription>
+           </briefdescription>
+diff --git a/testing/071_enum_in_anon_ns.cpp b/testing/071_enum_in_anon_ns.cpp
+index 8aab15fc8..98843bff2 100644
+--- a/testing/071_enum_in_anon_ns.cpp
++++ b/testing/071_enum_in_anon_ns.cpp
+@@ -1,5 +1,5 @@
+ // objective: test that enum values in anonymous namespaces produce no warning
+-// check: namespace_a_namespace_1_1_0d0.xml
++// check: namespace_a_namespace_1_1_0d130315250316227335362355006121037335073327177063.xml
+ 
+ namespace ANamespace { namespace {
+ 
+diff --git a/testing/073/073__typed__enum_8cpp.xml b/testing/073/073__typed__enum_8cpp.xml
+index 2eaeec9c4..cc7696486 100644
+--- a/testing/073/073__typed__enum_8cpp.xml
++++ b/testing/073/073__typed__enum_8cpp.xml
+@@ -75,10 +75,10 @@
+         </inbodydescription>
+         <location file="073_typed_enum.cpp" line="10" column="1" bodyfile="073_typed_enum.cpp" bodystart="10" bodyend="17"/>
+       </memberdef>
+-      <memberdef kind="enum" id="073__typed__enum_8cpp_1a06fc87d81c62e9abb8790b6e5713c55b" prot="public" static="no" strong="no">
++      <memberdef kind="enum" id="073__typed__enum_8cpp_1a28976fb6fcf15c9e79931f757d4a240a" prot="public" static="no" strong="no">
+         <type/>
+         <name/>
+-        <enumvalue id="073__typed__enum_8cpp_1a06fc87d81c62e9abb8790b6e5713c55ba52c998ad250c15a855ff5559e6d0d1d6" prot="public">
++        <enumvalue id="073__typed__enum_8cpp_1a28976fb6fcf15c9e79931f757d4a240aa52c998ad250c15a855ff5559e6d0d1d6" prot="public">
+           <name>Unnamed1</name>
+           <briefdescription>
+           </briefdescription>
+@@ -93,10 +93,10 @@
+         </inbodydescription>
+         <location file="073_typed_enum.cpp" line="19" column="1" bodyfile="073_typed_enum.cpp" bodystart="19" bodyend="21"/>
+       </memberdef>
+-      <memberdef kind="enum" id="073__typed__enum_8cpp_1adf764cbdea00d65edcd07bb9953ad2b7" prot="public" static="no" strong="no">
++      <memberdef kind="enum" id="073__typed__enum_8cpp_1a3e3cdcfeacb546b98944a745f81d0492" prot="public" static="no" strong="no">
+         <type/>
+         <name/>
+-        <enumvalue id="073__typed__enum_8cpp_1adf764cbdea00d65edcd07bb9953ad2b7a7b130af0c5cb18bfee8c60994fe1d5ee" prot="public">
++        <enumvalue id="073__typed__enum_8cpp_1a3e3cdcfeacb546b98944a745f81d0492a7b130af0c5cb18bfee8c60994fe1d5ee" prot="public">
+           <name>Unnamed2</name>
+           <briefdescription>
+           </briefdescription>
diff --git a/doxygen-1.12.0-regression-anchors.patch b/doxygen-1.12.0-regression-anchors.patch
new file mode 100644
index 0000000..272df09
--- /dev/null
+++ b/doxygen-1.12.0-regression-anchors.patch
@@ -0,0 +1,30 @@
+commit d408967139935bbaeae8d9eac7f0f34877d53d1c
+Author: albert-github <albert.tests@gmail.com>
+Date:   Fri Sep 13 16:02:25 2024 +0200
+
+    issue #11135 The anchors don't work
+    
+    Regression on 300f73d9ecd6b010a160e5f8cef14ecbabab950b:
+    ```
+    commit 300f73d9ecd6b010a160e5f8cef14ecbabab950b
+    
+    Date:   Thu Jul 4 20:41:56 2024 +0200
+    
+        issue #10970 Improvement of end of paragraph detection
+    ```
+    
+    attribute name is not `idname` but there are 2 attributes  possible `id` and `name`
+
+diff --git a/src/commentscan.l b/src/commentscan.l
+index 8520fcb58..767aa440d 100644
+--- a/src/commentscan.l
++++ b/src/commentscan.l
+@@ -591,7 +591,7 @@ DETAILEDHTMLOPTEND {ENDCODE}
+ SUMMARY   ("summary"|"SUMMARY")
+ REMARKS   ("remarks"|"REMARKS")
+ AHTML     [aA]{BN}*
+-ANCHTML   ("idname"|"IDNAME")"="("\""{LABELID}"\""|"'"{LABELID}"'"|{LABELID})
++ANCHTML   ("id"|"name"|"ID"|"NAME")"="("\""{LABELID}"\""|"'"{LABELID}"'"|{LABELID})
+ BN        [ \t\n\r]
+ BL        [ \t\r]*"\n"
+ B         [ \t]
diff --git a/doxygen.spec b/doxygen.spec
index fec6cda..6e5cc59 100644
--- a/doxygen.spec
+++ b/doxygen.spec
@@ -1,28 +1,19 @@
-%if 0%{?fedora}
-%global xapian_core_support ON
-%global clang_support OFF
-%global build_wizard ON
-%else
-%global xapian_core_support OFF
-%global clang_support OFF
-%global build_wizard OFF
-%endif
-
 Summary: A documentation system for C/C++
 Name:    doxygen
 Epoch:   2
 Version: 1.12.0
-Release: 2%{?dist}
+Release: 3%{?dist}
 # No version is specified.
 License: GPL-1.0-or-later
 Url: https://github.com/doxygen
 Source0: https://www.doxygen.nl/files/%{name}-%{version}.src.tar.gz
-# this icon is part of kdesdk
-Source1: doxywizard.desktop
-# these icons are part of doxygen and converted from doxywizard.ico
-Source2: doxywizard-icons.tar.xz
 
 # upstream patches
+# Markdown links to internal anchors broken
+Patch0: doxygen-1.12.0-regression-anchors.patch
+
+# Non-reproducible file names in doxygen output
+Patch1: doxygen-1.12.0-non-reproducible-file-names-in-doxygen-output.patch
 
 BuildRequires: %{_bindir}/python3
 BuildRequires: perl-interpreter, perl-open
@@ -97,15 +88,8 @@ BuildRequires: flex
 BuildRequires: bison
 BuildRequires: cmake
 BuildRequires: git
-%if "x%{?xapian_core_support}" == "xON"
-BuildRequires: xapian-core-devel
-%endif
-%if "x%{?clang_support}" == "xON"
-BuildRequires: llvm-devel
-BuildRequires: clang-devel
-%else
 BuildRequires: gcc-c++ gcc
-%endif
+
 Requires: perl-interpreter
 Requires: graphviz
 
@@ -116,17 +100,6 @@ documentation is extracted directly from the sources. Doxygen can
 also be configured to extract the code structure from undocumented
 source files.
 
-%if  "x%{build_wizard}" == "xON"
-%package doxywizard
-Summary: A GUI for creating and editing configuration files
-Requires: %{name} = %{epoch}:%{version}-%{release}
-BuildRequires: qt5-qtbase-devel
-
-%description doxywizard
-Doxywizard is a GUI for creating and editing configuration files that
-are used by doxygen.
-%endif
-
 %if ! 0%{?_module_build}
 %package latex
 Summary: Support for producing latex/pdf output from doxygen
@@ -204,7 +177,7 @@ Requires: texlive-epstopdf
 
 
 %prep
-%autosetup -p1 -a2
+%autosetup -p1
 
 # convert into utf-8
 iconv --from=ISO-8859-1 --to=UTF-8 LANGUAGE.HOWTO > LANGUAGE.HOWTO.new
@@ -212,21 +185,9 @@ touch -r LANGUAGE.HOWTO LANGUAGE.HOWTO.new
 mv LANGUAGE.HOWTO.new LANGUAGE.HOWTO
 
 %build
-%if  "x%{build_wizard}" == "xON"
 %cmake \
       -DPYTHON_EXECUTABLE=%{_bindir}/python3 \
-      -Duse_libclang=%{clang_support} \
-      -Dbuild_doc=OFF \
-      -Dbuild_wizard=ON \
-      -Dbuild_xmlparser=ON \
-      -Dbuild_search=%{xapian_core_support} \
-      -DMAN_INSTALL_DIR=%{_mandir}/man1 \
-      -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \
-      -DBUILD_SHARED_LIBS=OFF \
-%else
-%cmake \
-      -DPYTHON_EXECUTABLE=%{_bindir}/python3 \
-      -Duse_libclang=%{clang_support} \
+      -Duse_libclang=OFF \
       -Dbuild_doc=OFF \
       -Dbuild_wizard=OFF \
       -Dbuild_xmlparser=ON \
@@ -234,7 +195,6 @@ mv LANGUAGE.HOWTO.new LANGUAGE.HOWTO
       -DMAN_INSTALL_DIR=%{_mandir}/man1 \
       -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \
       -DBUILD_SHARED_LIBS=OFF \
-%endif
 
 %cmake_build %{?_smp_mflags}
 
@@ -243,27 +203,7 @@ mv LANGUAGE.HOWTO.new LANGUAGE.HOWTO
 
 # install man pages
 mkdir -p %{buildroot}/%{_mandir}/man1
-cp doc/*.1 %{buildroot}/%{_mandir}/man1/
-
-%if  "x%{build_wizard}" == "xOFF"
-rm -f %{buildroot}/%{_mandir}/man1/doxywizard.1*
-%else
-# install icons
-icondir=%{buildroot}%{_datadir}/icons/hicolor
-mkdir -m755 -p $icondir/{16x16,32x32,48x48,128x128}/apps
-install -m644 -p -D doxywizard-6.png $icondir/16x16/apps/doxywizard.png
-install -m644 -p -D doxywizard-5.png $icondir/32x32/apps/doxywizard.png
-install -m644 -p -D doxywizard-4.png $icondir/48x48/apps/doxywizard.png
-install -m644 -p -D doxywizard-3.png $icondir/128x128/apps/doxywizard.png
-desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{SOURCE1}
-%endif
-
-%if "x%{?xapian_core_support}" == "xOFF"
-rm -f %{buildroot}/%{_mandir}/man1/doxyindexer.1* %{buildroot}/%{_mandir}/man1/doxysearch.1*
-%endif
-
-# remove duplicate
-rm -rf %{buildroot}/%{_docdir}/packages
+cp doc/doxygen.1 %{buildroot}/%{_mandir}/man1/
 
 %check
 %ctest
@@ -271,25 +211,8 @@ rm -rf %{buildroot}/%{_docdir}/packages
 %files
 %doc LANGUAGE.HOWTO README.md
 %license LICENSE
-%if ! 0%{?_module_build}
-%if "x%{?xapian_core_support}" == "xON"
-%{_bindir}/doxyindexer
-%{_bindir}/doxysearch*
-%endif
-%endif
 %{_bindir}/doxygen
 %{_mandir}/man1/doxygen.1*
-%if "x%{?xapian_core_support}" == "xON"
-%{_mandir}/man1/doxyindexer.1*
-%{_mandir}/man1/doxysearch.1*
-%endif
-%if "x%{build_wizard}" == "xON" 
-%files doxywizard
-%{_bindir}/doxywizard
-%{_mandir}/man1/doxywizard*
-%{_datadir}/applications/doxywizard.desktop
-%{_datadir}/icons/hicolor/*/apps/doxywizard.png
-%endif
 
 %if ! 0%{?_module_build}
 %files latex
@@ -297,6 +220,11 @@ rm -rf %{buildroot}/%{_docdir}/packages
 %endif
 
 %changelog
+* Fri Nov 29 2024 Than Ngo <than@redhat.com> - 2:1.12.0-3
+- Fix Non-reproducible file names in doxygen output
+- Fix broken markdown links to anchors
+Related: RHEL-58045
+
 * Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 2:1.12.0-2
 - Bump release for October 2024 mass rebuild:
   Resolves: RHEL-64018
diff --git a/doxywizard.desktop b/doxywizard.desktop
deleted file mode 100644
index f3d0a4f..0000000
--- a/doxywizard.desktop
+++ /dev/null
@@ -1,6 +0,0 @@
-[Desktop Entry]
-Type=Application
-Exec=doxywizard
-Name=Doxygen Wizard
-Icon=doxywizard
-Categories=Qt;Development;
diff --git a/sources b/sources
index b656c32..df2c443 100644
--- a/sources
+++ b/sources
@@ -1,2 +1 @@
-SHA512 (doxywizard-icons.tar.xz) = 865a86d7535e64ad92e36ba1f901d51cd6b603e762e5c68761a45bc1f965a36e6a6c8d29468ecb2ec799f0add2347537723832aff6660c76af453f80a0a370ad
 SHA512 (doxygen-1.12.0.src.tar.gz) = e407e29c5e232e1f8dca291dd2d00b1dd400be709400225339408fad2cd758563b69f290cbd7c0efeb76b1335c4672fb1d6d580b9e6ed570708cf9b7d78951b1