Skip to content
Permalink
Browse files

Removes easel's "augmentation" concept; adds safety from gnu autoheader.

Since its inception Easel had an overly cute concept called
"augmentation", whereby modules had a base configuration that could be
stacked with additional modules to add more superpowers. The intent
was to allow easier disentanglement of an Easel .c file from the rest
of the library, if someone wanted to use a small part of our code, not
all of it. I was especially thinking of teaching the WashU Bio5495
course, which was taught in C. However, the #ifdef's required for
augmentation add complexity, and create a combinatorial mess of code
paths that increases testing difficulty; and now that I teach in
Python, the cost outweighs the benefits. After I added
esl_msa_Sample() as an augmentation to msa a few days ago, I made a
note to get rid of augmentation altogether, and here we go.

Also spurred by a bug report from Michael Crusoe of Debian. Debian
runs 'autoreconf' routinely, which runs 'autoheader', and our code was
not built to withstand the evil ravages of gnu autoheader. There are
two issues. 1) autoheader requires all AC_DEFINE() macros to use their
full 3-arg form. On our configure.ac, it errors out. 2) autoheader
creates a .h.in file based on the first AC_CONFIG_HEADERS() that it
sees. On our configure.ac, it overwrites our esl_config.in.

- Removed --enable-modular arg from configure
- Removed all augmentation #ifdef's, and documentation about augs
- Deleted devkit/esl-dependencies, a tool for tracking required
  vs. augmented header file inclusion
- Add decoy_config.h.in and AC_CONFIG_HEADERS([decoy.config.h]) to
  distract autoheader from overwriting our code
- Moved esl_msa_CreateFromString() to esl_msafile, to avoid a
  circular dependency msa <-> msafile
- Made sure esl_config.h is included first in all Easel files
  • Loading branch information...
cryptogenomicon committed Apr 28, 2017
1 parent ff0f894 commit eb6b9f5052439013a862c9b58cdf10b79a589aa1
Showing with 622 additions and 1,738 deletions.
  1. +20 −43 configure.ac
  2. +11 −0 decoy_config.h.in
  3. +0 −155 devkit/esl-dependencies
  4. +4 −14 documentation/codestyle.tex
  5. +0 −83 documentation/intro.tex
  6. +0 −6 documentation/statistics.tex
  7. +0 −4 easel.c
  8. +3 −15 easel.h
  9. +1 −0 esl_alphabet.h
  10. +4 −1 esl_avx.c
  11. +1 −2 esl_avx.h
  12. +4 −2 esl_avx_512.c
  13. +3 −2 esl_avx_512.h
  14. +1 −1 esl_buffer.c
  15. +1 −0 esl_buffer.h
  16. +1 −0 esl_cluster.h
  17. +2 −0 esl_composition.h
  18. +0 −54 esl_config.h.in
  19. +7 −29 esl_dirichlet.c
  20. +11 −21 esl_dirichlet.h
  21. +2 −8 esl_dirichlet.tex
  22. +14 −79 esl_distance.c
  23. +5 −22 esl_distance.h
  24. +5 −10 esl_distance.tex
  25. +1 −0 esl_dmatrix.h
  26. +7 −5 esl_dsqdata.c
  27. +4 −4 esl_dsqdata.h
  28. +7 −20 esl_exponential.c
  29. +5 −13 esl_exponential.h
  30. +1 −0 esl_fileparser.h
  31. +5 −18 esl_gamma.c
  32. +2 −10 esl_gamma.h
  33. +1 −0 esl_gencode.c
  34. +1 −0 esl_gencode.h
  35. +1 −1 esl_getopts.h
  36. +7 −28 esl_gev.c
  37. +4 −7 esl_gev.h
  38. +0 −8 esl_gev.tex
  39. +8 −22 esl_gumbel.c
  40. +6 −7 esl_gumbel.h
  41. +0 −9 esl_gumbel.tex
  42. +0 −1 esl_heap.h
  43. +2 −1 esl_histogram.c
  44. +1 −0 esl_histogram.h
  45. +3 −1 esl_hmm.c
  46. +1 −0 esl_hmm.h
  47. +4 −0 esl_huffman.c
  48. +1 −3 esl_huffman.h
  49. +16 −37 esl_hyperexp.c
  50. +10 −18 esl_hyperexp.h
  51. +1 −0 esl_keyhash.c
  52. +1 −0 esl_keyhash.h
  53. +0 −1 esl_mem.c
  54. +1 −1 esl_mem.h
  55. +1 −0 esl_minimizer.c
  56. +1 −0 esl_minimizer.h
  57. +9 −18 esl_mixgev.c
  58. +2 −8 esl_mixgev.h
  59. +3 −6 esl_mpi.c
  60. +4 −2 esl_mpi.h
  61. +50 −197 esl_msa.c
  62. +4 −17 esl_msa.h
  63. +24 −38 esl_msa.tex
  64. +2 −22 esl_msacluster.c
  65. +1 −1 esl_msacluster.h
  66. +0 −5 esl_msacluster.tex
  67. +61 −30 esl_msafile.c
  68. +3 −6 esl_msafile.h
  69. +12 −29 esl_msafile2.c
  70. +7 −23 esl_msafile2.h
  71. +4 −16 esl_msafile_a2m.c
  72. +1 −0 esl_msafile_a2m.h
  73. +3 −10 esl_msafile_afa.c
  74. +1 −0 esl_msafile_afa.h
  75. +4 −21 esl_msafile_clustal.c
  76. +1 −0 esl_msafile_clustal.h
  77. +2 −14 esl_msafile_phylip.c
  78. +1 −0 esl_msafile_phylip.h
  79. +3 −10 esl_msafile_psiblast.c
  80. +1 −0 esl_msafile_psiblast.h
  81. +3 −10 esl_msafile_selex.c
  82. +1 −0 esl_msafile_selex.h
  83. +4 −32 esl_msafile_stockholm.c
  84. +5 −0 esl_msafile_stockholm.h
  85. +2 −11 esl_msashuffle.c
  86. +2 −5 esl_msashuffle.h
  87. +13 −23 esl_msaweight.c
  88. +1 −0 esl_msaweight.h
  89. +1 −0 esl_neon.h
  90. +4 −3 esl_neon64.h
  91. +1 −0 esl_normal.h
  92. +3 −1 esl_paml.h
  93. +1 −1 esl_quicksort.h
  94. +1 −0 esl_random.h
  95. +1 −0 esl_randomseq.h
  96. +0 −3 esl_ratematrix.c
  97. +1 −0 esl_ratematrix.h
  98. +1 −2 esl_recorder.h
  99. +2 −1 esl_red_black.c
  100. +2 −1 esl_red_black.h
  101. +1 −0 esl_regexp.h
  102. +0 −1 esl_rootfinder.h
  103. +2 −2 esl_scorematrix.c
  104. +1 −0 esl_scorematrix.h
  105. +9 −59 esl_sq.c
  106. +2 −19 esl_sq.h
  107. +4 −4 esl_sq.tex
  108. +27 −74 esl_sqio.c
  109. +5 −29 esl_sqio.h
  110. +2 −8 esl_sqio.tex
  111. +6 −43 esl_sqio_ascii.c
  112. +7 −18 esl_sqio_ascii.h
  113. +2 −5 esl_sqio_ncbi.c
  114. +3 −3 esl_sqio_ncbi.h
  115. +0 −1 esl_sse.c
  116. +4 −2 esl_sse.h
  117. +2 −6 esl_ssi.h
  118. +9 −14 esl_stack.c
  119. +1 −5 esl_stack.h
  120. +1 −0 esl_stats.h
  121. +2 −1 esl_stopwatch.c
  122. +1 −0 esl_stopwatch.h
  123. +13 −29 esl_stretchexp.c
  124. +4 −12 esl_stretchexp.h
  125. +1 −0 esl_threads.h
  126. +3 −2 esl_tree.c
  127. +3 −2 esl_tree.h
  128. +4 −3 esl_vectorops.c
  129. +7 −6 esl_vectorops.h
  130. +4 −2 esl_vmx.h
  131. +15 −31 esl_weibull.c
  132. +4 −13 esl_weibull.h
  133. +1 −0 esl_workqueue.h
  134. +1 −1 esl_wuss.h
  135. +1 −1 interface_gsl.c
  136. +6 −4 interface_gsl.h
  137. +5 −4 interface_lapack.c
  138. +4 −2 interface_lapack.h
@@ -31,6 +31,11 @@
# 13. AC_OUTPUT
#
# Order obeys autoconf manual, "standard configure.ac layout".
#
# Use full 3-arg form of AC_DEFINE() macros. autoheader chokes if you
# don't. We don't use autoheader (we only use autoconf, out of the
# GNU build tools, to limit complexity) but some packagers do, such
# as Debian.



@@ -99,12 +104,10 @@ AC_SUBST(EASEL_VERSION)
AC_SUBST(EASEL_URL)

# Preprocessor symbols.
# adds a -Dvar=value to @DEFS@;
# replace #undef's in easel.h.in
AC_DEFINE_UNQUOTED(EASEL_DATE, "$EASEL_DATE")
AC_DEFINE_UNQUOTED(EASEL_COPYRIGHT, "$EASEL_COPYRIGHT")
AC_DEFINE_UNQUOTED(EASEL_LICENSE, "$EASEL_LICENSE")
AC_DEFINE_UNQUOTED(EASEL_VERSION, "$EASEL_VERSION")
AC_DEFINE_UNQUOTED([EASEL_DATE], ["$EASEL_DATE"], [Release date])
AC_DEFINE_UNQUOTED([EASEL_COPYRIGHT], ["$EASEL_COPYRIGHT"], [Brief copyright statement])
AC_DEFINE_UNQUOTED([EASEL_LICENSE], ["$EASEL_LICENSE"], [Brief license statement])
AC_DEFINE_UNQUOTED([EASEL_VERSION], ["$EASEL_VERSION"], [Version number])

# Figure out what host we're compiling on.
# Three GNU scripts must be included in the distro:
@@ -122,33 +125,6 @@ AC_CANONICAL_HOST
# 4. Process ./configure command line options
################################################################

# --enable-modular - configure for use of standalone modules
#
# Default is to enable all augmentations and compile entire library.
# With --enable-modular, any desired augmentations must be set
# at compile-time by the user.
#
AC_ARG_ENABLE(modular,[AS_HELP_STRING([--enable-modular],[compile and prepare modules for standalone use])],
[
AC_MSG_NOTICE([Compiling for standalone (independent) use of modules.])
],
[
AC_MSG_NOTICE([Compiling the full Easel library, with all augmentations.])
AC_DEFINE(eslAUGMENT_ALPHABET)
AC_DEFINE(eslAUGMENT_NCBI)
AC_DEFINE(eslAUGMENT_DMATRIX)
AC_DEFINE(eslAUGMENT_FILEPARSER)
AC_DEFINE(eslAUGMENT_GEV)
AC_DEFINE(eslAUGMENT_GUMBEL)
AC_DEFINE(eslAUGMENT_HISTOGRAM)
AC_DEFINE(eslAUGMENT_KEYHASH)
AC_DEFINE(eslAUGMENT_MINIMIZER)
AC_DEFINE(eslAUGMENT_MSA)
AC_DEFINE(eslAUGMENT_RANDOM)
AC_DEFINE(eslAUGMENT_SSI)
AC_DEFINE(eslAUGMENT_STATS)
AC_DEFINE(eslLIBRARY)
])

# --enable-debugging - enable basic debugging code (level 1)
# --enable-debugging=x - also set verbosity level to <x> (1-3)
@@ -162,11 +138,11 @@ AS_HELP_STRING([--enable-debugging=x],[also set diagnostics verbosity level to <
enable_debugging=$enableval, enable_debugging=no)

case $enable_debugging in
yes) AC_DEFINE(eslDEBUGLEVEL, 1);;
1) AC_DEFINE(eslDEBUGLEVEL, 1);;
2) AC_DEFINE(eslDEBUGLEVEL, 2);;
3) AC_DEFINE(eslDEBUGLEVEL, 3);;
no) AC_DEFINE(eslDEBUGLEVEL, 0);;
yes) AC_DEFINE([eslDEBUGLEVEL], 1, [debugging on, low verbosity]);;
1) AC_DEFINE([eslDEBUGLEVEL], 1, [debugging on, low verbosity]);;
2) AC_DEFINE([eslDEBUGLEVEL], 2, [debugging on, moderate verbosity]);;
3) AC_DEFINE([eslDEBUGLEVEL], 3, [debugging on, high verbosity]);;
no) AC_DEFINE([eslDEBUGLEVEL], 0, [debugging off]);;
*) AC_MSG_ERROR([Unknown argument to --enable-debugging: $enable_debugging]);;
esac

@@ -198,7 +174,7 @@ case $enable_threads in
esac

AS_IF([test "x$check_threads" != xno],
[ACX_PTHREAD([AC_DEFINE(HAVE_PTHREAD)
[ACX_PTHREAD([AC_DEFINE(HAVE_PTHREAD, [], [POSIX threads supported])
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)],
[if test "x$enable_threads" != xcheck; then
@@ -321,7 +297,7 @@ if test "$enable_sse" = "check" && test "$enable_vmx" != "yes" && test "$enable_
CPPFLAGS="$sre_save_CPPFLAGS"
fi
if test "$enable_sse" = "yes"; then
AC_DEFINE(HAVE_SSE2,1,[Support SSE2 (Streaming SIMD Extensions 2) instructions])
AC_DEFINE([HAVE_SSE2],1,[Support SSE2 (Streaming SIMD Extensions 2) instructions])
fi

if test "$enable_avx2" = "yes" || test "$enable_avx2" = "check"; then
@@ -344,7 +320,7 @@ AC_MSG_CHECKING([whether AVX2 is supported])
test2 = _mm256_set1_epi8(111);
test2 = _mm256_adds_epi8(test1, test2);
]])],
[AC_DEFINE([HAVE_AVX2])
[AC_DEFINE([HAVE_AVX2],1,[Support AVX (Advanced Vector Extensions) instructions])
haveavx=yes])
AC_MSG_RESULT([$haveavx])
CFLAGS="$sre_save_cflags"
@@ -370,7 +346,7 @@ AC_MSG_CHECKING([whether AVX-512 is supported])
test2 = _mm512_set1_epi8(111);
test2 = _mm512_adds_epi8(test1, test2);
]])],
[AC_DEFINE([HAVE_AVX512])
[AC_DEFINE([HAVE_AVX512],1,[Support AVX-512 vector instructions])
haveavx512=yes])
AC_MSG_RESULT([$haveavx512])
CFLAGS="$sre_save_cflags"
@@ -527,7 +503,7 @@ AC_PATH_PROG(HAVE_GZIP, "gzip", "no")
if test "${HAVE_GZIP}" = "no"; then
AC_MSG_WARN([gzip not found])
else
AC_DEFINE(HAVE_GZIP)
AC_DEFINE([HAVE_GZIP],1,[Support external gzip decompression])
fi


@@ -696,6 +672,7 @@ AC_SYS_LARGEFILE
#################################################################
# 13. Write out esl_config.h header and the Makefiles
#################################################################
AC_CONFIG_HEADERS([decoy_config.h]) # This keeps gnu 'autoheader' from overwriting our esl_config.h.in
AC_CONFIG_HEADERS([esl_config.h])
AC_CONFIG_FILES([miniapps/Makefile])
AC_CONFIG_FILES([testsuite/Makefile])
@@ -0,0 +1,11 @@
/* decoy_config.h.in
*
* Easel doesn't use this at all. Some packagers (e.g. Debian)
* inexplicably run GNU 'autoheader' as part of their build/release
* cycle, which will overwrite and destroy esl_config.h.in if we don't
* do something about it. It appears to be sufficient to put
* AC_CONFIG_HEADERS([decoy_config.h])
* first in our configure.ac, to distract autoheader. (autoheader
* only looks at the first AC_CONFIG_HEADERS() to construct its
* output .in filename.)
*/

This file was deleted.

@@ -165,10 +165,8 @@ \subsection{The .c file}
that may affect even the standard library header files. Standard
headers like \ccode{stdio.h} come next, then Easel's main header
\ccode{easel.h}; then headers of any other Easel modules this module
depends on; then any headers for modules this module can be augmented
with, surrounded by appropriate \ccode{\#ifdef}'s; then the module's
own header. For example, the \ccode{\#include}'s in the
\eslmod{buffer} module look like:
depends on, then the module's own header. For example, the
\ccode{\#include}'s in the \eslmod{buffer} module look like:

\input{cexcerpts/include_example}

@@ -197,13 +195,8 @@ \subsection{The .c file}
destroying the object that this module implements.

\item[\textbf{The rest of the API.}]
Everything else that is part of the API for this module in its
baseline (unaugmented) form. This might be split across multiple
sections.

\item[\textbf{Augmented API, if any.}]
Any functions that are only available with one or more augmentations
are split out into one or more separate sections.
Everything else that is part of the API for this module.
This might be split across multiple sections.

\item[\textbf{Debugging/dev code.}]
Most objects can be validated or dumped to an output stream
@@ -1490,9 +1483,6 @@ \section{Writing unit tests}
tests must temporarily register a nonfatal error handler when testing
exceptions.

Unit tests should test all possible combinations of augmentations that
may affect a function.

Every function, procedure, and macro in the exposed API shall be
tested by one or more unit tests. The unit tests aim for complete code
coverage. This is measured by code coverage tests using \ccode{gcov}.

0 comments on commit eb6b9f5

Please sign in to comment.
You can’t perform that action at this time.