Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Lorenz Huedepohl
ftimings
Commits
e81aabad
Commit
e81aabad
authored
Jan 27, 2014
by
Lorenz Huedepohl
Browse files
Add Doxygen support to configure, update documentation
parent
0896521b
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
e81aabad
...
...
@@ -28,3 +28,5 @@ stamp-h1
ftimings-*-*.pc
ftimings_*_test
ftimings.mod
docs/
Doxyfile
Doxyfile.in
0 → 100644
View file @
e81aabad
This diff is collapsed.
Click to expand it.
Makefile.am
View file @
e81aabad
...
...
@@ -30,3 +30,5 @@ ftimings_@FC@_test_LDADD = libftimings-@FTIMINGS_API_VERSION@-@FC@.la
# other files to distribute
filesdir
=
$(datadir)
/@PACKAGE@-@FC@/examples
files_DATA
=
test
/test_timings.F90
include
doxygen.am
configure.ac
View file @
e81aabad
...
...
@@ -22,13 +22,21 @@ LT_INIT
PKG_PROG_PKG_CONFIG
DX_PDF_FEATURE(OFF)
DX_PS_FEATURE(OFF)
DX_MAN_FEATURE(ON)
DX_HTML_FEATURE(ON)
DX_INIT_DOXYGEN([ftimings], [Doxyfile], [docs])
AC_SUBST([FTIMINGS_SO_VERSION], [0:1:0])
AC_SUBST([FTIMINGS_API_VERSION], [0.1])
AC_SUBST([AM_CFLAGS])
AC_SUBST([AM_FCFLAGS])
AC_SUBST([AM_LDFLAGS])
AC_SUBST([DOXYGEN_OUTPUT_DIR], [docs])
AC_CONFIG_FILES([Makefile
Doxyfile
ftimings-${FTIMINGS_API_VERSION}-${FC}.pc:ftimings.pc.in
])
AC_OUTPUT
doxygen.am
0 → 100644
View file @
e81aabad
## --------------------------------- ##
## Format-independent Doxygen rules. ##
## --------------------------------- ##
if DX_COND_doc
## ------------------------------- ##
## Rules specific for HTML output. ##
## ------------------------------- ##
if DX_COND_html
DX_CLEAN_HTML = @DX_DOCDIR@/html
endif DX_COND_html
## ------------------------------ ##
## Rules specific for CHM output. ##
## ------------------------------ ##
if DX_COND_chm
DX_CLEAN_CHM = @DX_DOCDIR@/chm
if DX_COND_chi
DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
endif DX_COND_chi
endif DX_COND_chm
## ------------------------------ ##
## Rules specific for MAN output. ##
## ------------------------------ ##
if DX_COND_man
DX_CLEAN_MAN = @DX_DOCDIR@/man
endif DX_COND_man
## ------------------------------ ##
## Rules specific for RTF output. ##
## ------------------------------ ##
if DX_COND_rtf
DX_CLEAN_RTF = @DX_DOCDIR@/rtf
endif DX_COND_rtf
## ------------------------------ ##
## Rules specific for XML output. ##
## ------------------------------ ##
if DX_COND_xml
DX_CLEAN_XML = @DX_DOCDIR@/xml
endif DX_COND_xml
## ----------------------------- ##
## Rules specific for PS output. ##
## ----------------------------- ##
if DX_COND_ps
DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
DX_PS_GOAL = doxygen-ps
doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
cd @DX_DOCDIR@/latex; \
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
$(DX_LATEX) refman.tex; \
$(MAKEINDEX_PATH) refman.idx; \
$(DX_LATEX) refman.tex; \
countdown=5; \
while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
refman.log > /dev/null 2>&1 \
&& test $$countdown -gt 0; do \
$(DX_LATEX) refman.tex; \
countdown=`expr $$countdown - 1`; \
done; \
$(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
endif DX_COND_ps
## ------------------------------ ##
## Rules specific for PDF output. ##
## ------------------------------ ##
if DX_COND_pdf
DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
DX_PDF_GOAL = doxygen-pdf
doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
cd @DX_DOCDIR@/latex; \
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
$(DX_PDFLATEX) refman.tex; \
$(DX_MAKEINDEX) refman.idx; \
$(DX_PDFLATEX) refman.tex; \
countdown=5; \
while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
refman.log > /dev/null 2>&1 \
&& test $$countdown -gt 0; do \
$(DX_PDFLATEX) refman.tex; \
countdown=`expr $$countdown - 1`; \
done; \
mv refman.pdf ../@PACKAGE@.pdf
endif DX_COND_pdf
## ------------------------------------------------- ##
## Rules specific for LaTeX (shared for PS and PDF). ##
## ------------------------------------------------- ##
if DX_COND_latex
DX_CLEAN_LATEX = @DX_DOCDIR@/latex
endif DX_COND_latex
.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
rm -rf @DX_DOCDIR@
$(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
DX_CLEANFILES = \
@DX_DOCDIR@/@PACKAGE@.tag \
-r \
$(DX_CLEAN_HTML) \
$(DX_CLEAN_CHM) \
$(DX_CLEAN_CHI) \
$(DX_CLEAN_MAN) \
$(DX_CLEAN_RTF) \
$(DX_CLEAN_XML) \
$(DX_CLEAN_PS) \
$(DX_CLEAN_PDF) \
$(DX_CLEAN_LATEX)
endif DX_COND_doc
ftimings/ftimings.f90
View file @
e81aabad
!> Ftimings
!>
!> An almost pure-fortran attempt to play with graph structures :)
module
ftimings
use
,
intrinsic
::
iso_c_binding
,
only
:
C_INT64_T
,
C_DOUBLE
implicit
none
save
public
timer_t
private
! this is mainly needed for Doxygen...
public
timer_start
,
timer_stop
,
timer_free
,
timer_print
,
&
timer_enable
,
timer_disable
,
timer_is_enabled
,
&
timer_in_entries
,
timer_get
,
timer_since
,
timer_sort
integer
,
parameter
,
private
::
name_length
=
32
integer
,
parameter
,
private
::
rk
=
C_DOUBLE
...
...
@@ -17,10 +24,12 @@ module ftimings
end
function
end
interface
! Private type node_t, representing a graph node
!
type
node_t
character
(
len
=
name_length
)
::
name
integer
(
kind
=
C_INT64_T
)
::
micros
integer
::
count
character
(
len
=
name_length
)
::
name
! Descriptive name, used when printing the timings
integer
(
kind
=
C_INT64_T
)
::
micros
! Cumulative microseconds spent in this node
integer
::
count
! Number of calls
type
(
node_t
),
pointer
::
firstChild
=>
NULL
()
type
(
node_t
),
pointer
::
lastChild
=>
NULL
()
type
(
node_t
),
pointer
::
parent
=>
NULL
()
...
...
@@ -37,11 +46,37 @@ module ftimings
procedure
,
pass
::
sort_children
=>
node_sort_children
end
type
type
timer_t
!> Type for a timer instance.
!>
!> Typical usage:
!> \code{.f90}
!> type(timer_t) :: timer
!>
!> call timer%enable()
!>
!> call timer%start("section")
!> ...
!> call timer%start("subsection")
!> ...
!> call timer%stop("subsection")
!> ...
!> call timer%stop("section")
!>
!> call timer%print()
!> \endcode
!>
!> Every first call to timer%start() at a certain point in the graph
!> allocates a small amount of memory. If the timer is no longer needed,
!> all that memory can be freed again with
!>
!> \code{.f90}
!> call timer%free()
!> \endcode
type
,
public
::
timer_t
private
logical
::
active
=
.false.
type
(
node_t
),
pointer
::
root
=>
NULL
()
type
(
node_t
),
pointer
::
current_node
=>
NULL
()
logical
::
active
=
.false.
!< If set to .false., most operations return immediately without any action
type
(
node_t
),
pointer
::
root
=>
NULL
()
!< Start of graph
type
(
node_t
),
pointer
::
current_node
=>
NULL
()
!< Current position in the graph
contains
procedure
,
pass
::
start
=>
timer_start
procedure
,
pass
::
stop
=>
timer_stop
...
...
@@ -56,8 +91,8 @@ module ftimings
procedure
,
pass
::
sort
=>
timer_sort
end
type
character
(
len
=
name_length
),
parameter
::
own
=
"(own)"
character
(
len
=
name_length
),
parameter
::
below
=
"(below threshold)"
character
(
len
=
name_length
),
private
,
parameter
::
own
=
"(own)"
character
(
len
=
name_length
),
private
,
parameter
::
below
=
"(below threshold)"
contains
...
...
@@ -199,22 +234,25 @@ module ftimings
enddo
end
function
subroutine
node_print_line
(
indent_level
,
label
,
number
,
total
)
subroutine
node_print_line
(
indent_level
,
label
,
number
,
total
,
unit
)
integer
,
intent
(
in
)
::
indent_level
character
(
len
=
name_length
),
intent
(
in
)
::
label
integer
(
kind
=
C_INT64_T
),
intent
(
in
)
::
number
,
total
character
(
len
=
64
)
::
format_spec
integer
::
unit
write
(
format_spec
,
'("(",i0,"x,""|_ "",a",i0,",2x,f10.6,10x,f5.3)")'
)
(
indent_level
+
1
)
*
2
+
2
,
name_length
write
(
*
,
format_spec
)
label
,
real
(
number
,
kind
=
rk
)
*
1e-6_rk
,
real
(
number
,
kind
=
rk
)
/
real
(
total
,
kind
=
rk
)
write
(
unit
,
format_spec
)
label
,
real
(
number
,
kind
=
rk
)
*
1e-6_rk
,
real
(
number
,
kind
=
rk
)
/
real
(
total
,
kind
=
rk
)
end
subroutine
recursive
subroutine
node_print_graph
(
self
,
indent_level
,
threshold
,
is_sorted
,
total
)
recursive
subroutine
node_print_graph
(
self
,
indent_level
,
threshold
,
is_sorted
,
total
,
unit
)
use
,
intrinsic
::
iso_fortran_env
,
only
:
output_unit
class
(
node_t
),
intent
(
in
)
::
self
integer
,
intent
(
in
)
::
indent_level
real
(
kind
=
rk
),
intent
(
in
),
optional
::
threshold
logical
,
intent
(
in
),
optional
::
is_sorted
integer
(
kind
=
C_INT64_T
),
intent
(
in
),
optional
::
total
integer
,
optional
::
unit
type
(
node_t
),
pointer
::
node
character
(
len
=
64
)
::
format_spec
...
...
@@ -223,6 +261,8 @@ module ftimings
integer
(
kind
=
C_INT64_T
)
::
current_us
,
own_us
,
below_threshold_us
,
total_act
real
(
kind
=
rk
)
::
threshold_act
logical
::
is_sorted_act
,
print_own
,
print_threshold
integer
::
unit_act
if
(
present
(
threshold
))
then
threshold_act
=
threshold
...
...
@@ -244,6 +284,12 @@ module ftimings
total_act
=
current_us
endif
if
(
present
(
unit
))
then
unit_act
=
unit
else
unit_act
=
output_unit
endif
own_us
=
current_us
-
self
%
sum_of_children
()
below_threshold_us
=
self
%
sum_of_children_below
(
threshold
)
...
...
@@ -266,18 +312,29 @@ module ftimings
do
i
=
len
(
trim
(
name
))
+
2
,
name_length
name
(
i
:
i
)
=
"."
end
do
write
(
*
,
format_spec
)
name
,
real
(
current_us
,
kind
=
rk
)
*
1e-6_rk
,
real
(
current_us
,
kind
=
rk
)
/
real
(
total_act
,
kind
=
rk
)
write
(
unit_act
,
format_spec
)
&
name
,
real
(
current_us
,
kind
=
rk
)
*
1e-6_rk
,
real
(
current_us
,
kind
=
rk
)
/
real
(
total_act
,
kind
=
rk
)
else
return
endif
! \todo this is very clumsy:
!
! we have to insert the (own) and (below threshold) entries
! i) at the start, if printing unsorted or
! ii) at the place they would appear, if sorted
!
! at the moment a lot of copied lines are necessary for this,
! and there is no correct sorting between (own) and (below threshold)
! in all cases
!
if
((
.not.
is_sorted_act
)
.and.
print_own
)
then
call
node_print_line
(
indent_level
,
own
,
own_us
,
current_us
)
call
node_print_line
(
indent_level
,
own
,
own_us
,
current_us
,
unit_act
)
print_own
=
.false.
endif
if
((
.not.
is_sorted_act
)
.and.
print_threshold
)
then
call
node_print_line
(
indent_level
,
below
,
below_threshold_us
,
current_us
)
call
node_print_line
(
indent_level
,
below
,
below_threshold_us
,
current_us
,
unit_act
)
print_threshold
=
.false.
endif
...
...
@@ -286,49 +343,81 @@ module ftimings
if
(
print_own
)
then
if
(
node
%
get_micros
()
<=
own_us
)
then
call
node_print_line
(
indent_level
,
own
,
own_us
,
current_us
)
call
node_print_line
(
indent_level
,
own
,
own_us
,
current_us
,
unit_act
)
print_own
=
.false.
endif
endif
if
(
print_threshold
)
then
if
(
node
%
get_micros
()
<=
below_threshold_us
)
then
call
node_print_line
(
indent_level
,
below
,
below_threshold_us
,
current_us
)
call
node_print_line
(
indent_level
,
below
,
below_threshold_us
,
current_us
,
unit_act
)
print_threshold
=
.false.
endif
endif
call
node
%
print_graph
(
indent_level
+
1
,
threshold
,
is_sorted
,
current_us
)
call
node
%
print_graph
(
indent_level
+
1
,
threshold
,
is_sorted
,
current_us
,
unit_act
)
node
=>
node
%
nextSibling
end
do
if
(
print_own
)
then
call
node_print_line
(
indent_level
,
own
,
own_us
,
current_us
)
call
node_print_line
(
indent_level
,
own
,
own_us
,
current_us
,
unit_act
)
endif
if
(
print_threshold
)
then
call
node_print_line
(
indent_level
,
below
,
below_threshold_us
,
current_us
)
call
node_print_line
(
indent_level
,
below
,
below_threshold_us
,
current_us
,
unit_act
)
endif
end
subroutine
! Public module interface:
!> Active the timer, without this, most methods are no-ops.
!>
!> \implements timer_t::enable
subroutine
timer_enable
(
self
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
self
%
active
=
.true.
end
subroutine
!> Deactive the timer
!>
!> \implements timer_t::disable
subroutine
timer_disable
(
self
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
self
%
active
=
.false.
end
subroutine
!> \implements timer_t::is_enabled
function
timer_is_enabled
(
self
)
result
(
is
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
logical
::
is
is
=
self
%
active
end
function
!> Start a timing section
!>
!> \param name A descriptive name
!> \param replace If .true. (default .false.), replace any entries at the
!> current position with the same name. If .false., add the
!> time to a possibly existing entry
!>
!> Care must be taken to balance any invocations of %start() and %stop(), e.g.
!> the following is valid
!>
!> \code{.f90}
!> call timer%start("A")
!> call timer%start("B")
!> call timer%stop("B")
!> call timer%stop("A")
!> \endcode
!>
!> while the following is not
!>
!> \code{.f90}
!> call timer%start("A")
!> call timer%start("B")
!> call timer%stop("A")
!> call timer%stop("B")
!> \endcode
!>
!> \implements timer_t::start
subroutine
timer_start
(
self
,
name
,
replace
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
character
(
len
=*
),
intent
(
in
)
::
name
...
...
@@ -400,6 +489,11 @@ module ftimings
end
subroutine
!> End a timing segment, \sa timer_start
!>
!> \param name The exact same name as was used for %start()
!>
!> \implements timer_t::stop
subroutine
timer_stop
(
self
,
name
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
character
(
len
=*
),
intent
(
in
)
::
name
...
...
@@ -454,6 +548,9 @@ module ftimings
end
subroutine
!> Deallocate all objects associated with (but not including) self
!>
!> \implements timer_t::free
subroutine
timer_free
(
self
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
if
(
associated
(
self
%
root
))
then
...
...
@@ -463,6 +560,17 @@ module ftimings
nullify
(
self
%
current_node
)
end
subroutine
!> Print a timing graph
!>
!> \param name1 If given, first descend one level to the node with name name1
!> \param name2 If given, also descend another level to the node with name2 there
!> \param name3 etc.
!> \param name4 etc.
!> \param threshold If given, subsume any entries with a value of threshold
!> seconds in a single node "(below threshold)"
!> \param is_sorted Assume a sorted graph for inserting "(own)" and "(below threshold)"
!>
!> \implements timer_t::print
subroutine
timer_print
(
self
,
name1
,
name2
,
name3
,
name4
,
threshold
,
is_sorted
)
class
(
timer_t
),
intent
(
in
),
target
::
self
character
(
len
=*
),
intent
(
in
),
optional
::
name1
,
name2
,
name3
,
name4
...
...
@@ -512,10 +620,12 @@ module ftimings
!>
!> \param name1, .., namei-1 The path to the starting node
!> \param namei The name of all sub-entries below this
!> node
to
which
ar
e summed together
!> node which
should b
e summed together
!>
!> For example timer%in_entries("foo", "bar", "parallel") returns
!> the sum of all entries named "parallel" below the foo->bar node
!>
!> \implements timer_t::in_entries
function
timer_in_entries
(
self
,
name1
,
name2
,
name3
,
name4
)
result
(
s
)
class
(
timer_t
),
intent
(
in
),
target
::
self
character
(
len
=*
),
intent
(
in
)
::
name1
...
...
@@ -561,10 +671,17 @@ module ftimings
s
=
real
(
node
%
sum_of_children_with_name
(
name
),
kind
=
rk
)
*
1e-6_rk
end
function
function
timer_get
(
self
,
name1
,
name2
,
name3
,
name4
,
name5
)
result
(
s
)
!> Access a specific, already stopped entry of the graph by specifying the
!> names of the nodes along the graph from the root node
!>
!> The result is only meaningfull if the entry was never appended by
!> additional %start() calls.
!>
!> \implements timer_t::get
function
timer_get
(
self
,
name1
,
name2
,
name3
,
name4
,
name5
,
name6
)
result
(
s
)
class
(
timer_t
),
intent
(
in
),
target
::
self
! this is clunky, but what can you do..
character
(
len
=*
),
intent
(
in
),
optional
::
name1
,
name2
,
name3
,
name4
,
name5
character
(
len
=*
),
intent
(
in
),
optional
::
name1
,
name2
,
name3
,
name4
,
name5
,
name6
real
(
kind
=
rk
)
::
s
type
(
node_t
),
pointer
::
node
...
...
@@ -610,6 +727,13 @@ module ftimings
return
endif
end
if
if
(
present
(
name6
))
then
node
=>
node
%
get_child
(
name6
)
if
(
.not.
associated
(
node
))
then
write
(
0
,
'(a)'
)
"Could not descend to
""
"
//
trim
(
name6
)
//
"
""
"
return
endif
end
if
if
(
node
%
is_running
())
then
write
(
0
,
'(a)'
)
"Timer
""
"
//
trim
(
node
%
name
)
//
"
""
not yet stopped"
return
...
...
@@ -617,6 +741,14 @@ module ftimings
s
=
real
(
node
%
micros
,
kind
=
rk
)
*
1e-6_rk
end
function
!> Access a specific, not yet stopped entry of the graph by specifying the
!> names of the nodes along the graph from the root node and return the
!> seconds that have passed since the entry was created.
!>
!> The result is only meaningfull if the entry was never appended by
!> additional %start() calls.
!>
!> \implements timer_t::since
function
timer_since
(
self
,
name1
,
name2
,
name3
,
name4
)
result
(
s
)
class
(
timer_t
),
intent
(
in
),
target
::
self
character
(
len
=*
),
intent
(
in
),
optional
::
name1
,
name2
,
name3
,
name4
...
...
@@ -661,7 +793,7 @@ module ftimings
s
=
real
(
node
%
micros
+
microseconds_since_epoch
(),
kind
=
rk
)
*
1e-6_rk
end
function
! sort a node_t linked list and return the first and last element
!
In-place
sort a node_t linked list and return the first and last element
,
subroutine
sort_nodes
(
head
,
tail
)
type
(
node_t
),
pointer
,
intent
(
inout
)
::
head
,
tail
...
...
@@ -742,6 +874,10 @@ module ftimings
end
do
end
subroutine
!> Sort the graph on each level.
!> Warning: This irrevocable destroys the old ordering.
!>
!> \implements timer_t::sort
subroutine
timer_sort
(
self
)
class
(
timer_t
),
intent
(
inout
),
target
::
self
type
(
node_t
),
pointer
::
node
...
...
m4/ax_prog_doxygen.m4
0 → 100644
View file @
e81aabad
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
# ===========================================================================
#
# SYNOPSIS
#
# DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR])
# DX_DOXYGEN_FEATURE(ON|OFF)
# DX_DOT_FEATURE(ON|OFF)
# DX_HTML_FEATURE(ON|OFF)
# DX_CHM_FEATURE(ON|OFF)
# DX_CHI_FEATURE(ON|OFF)
# DX_MAN_FEATURE(ON|OFF)
# DX_RTF_FEATURE(ON|OFF)
# DX_XML_FEATURE(ON|OFF)
# DX_PDF_FEATURE(ON|OFF)
# DX_PS_FEATURE(ON|OFF)
#
# DESCRIPTION
#
# The DX_*_FEATURE macros control the default setting for the given
# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
# help (for MS users), 'CHI' for generating a seperate .chi file by the
# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
# specified to override the default 'a4wide' paper size.
#
# By default, HTML, PDF and PS documentation is generated as this seems to
# be the most popular and portable combination. MAN pages created by
# Doxygen are usually problematic, though by picking an appropriate subset
# and doing some massaging they might be better than nothing. CHM and RTF
# are specific for MS (note that you can't generate both HTML and CHM at
# the same time). The XML is rather useless unless you apply specialized
# post-processing to it.
#
# The macros mainly control the default state of the feature. The use can
# override the default by specifying --enable or --disable. The macros
# ensure that contradictory flags are not given (e.g.,
# --enable-doxygen-html and --enable-doxygen-chm,
# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
# feature will be automatically disabled (with a warning) if the required
# programs are missing.
#
# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
# with the following parameters: a one-word name for the project for use
# as a filename base etc., an optional configuration file name (the
# default is 'Doxyfile', the same as Doxygen's default), and an optional
# output directory name (the default is 'doxygen-doc').
#
# Automake Support
#
# The following is a template aminclude.am file for use with Automake.
# Make targets and variables values are controlled by the various