Conditional compiling in OCaml - ocaml

suppose I have a long algorithm which I would like to be optionally verbose to debug it. So far I just added many if verbose then printf "whatever" all around the code but this forces the code to execute many useless tests if I don't want to have it in the verbose mode.
Is there a way to obtain a simple conditional compilation which can just ignore the printf lines if a flag is set?
Something that, for example, I can do in C by using #IFDEF DEBUG printf .. #ENDIF

What you are looking for can be found in camlp4. If you include the predefined macros then you can define flags on the command line using -D (and -U to undef them):
camlp4o pa_macro.cmo -DFOO file.ml
In code it looks like this:
let f x = IFDEF FOO THEN x + 1 ELSE x - 1 END;;

Related

How to print the GCC optimization options?

I'm trying to compile my test program with various GCC optimizations options and I'd like to see all of them in the program output. Something like that (the __cpp_optimizations constant is invented for this question):
std::cout << __cpp_optimizations << std::endl;
Is it any way to do that?
Get the compiler options from a compiled executable? . Compile with -frecord-gcc-switches than read the command line options from the executable, in pseudocode:
buf = popen(std::string() + "readelf -p .GCC.command.line /proc/self/exe").read()
// or read elf yourself instead of popen
// tokenize buf, get all compiler options
// filter out only optimization options
Alternatively, you could instruct your build system to pass that information as a macro. For example, in CMake:
add_compile_options(-O3)
add_compile_definitions("CPP_OPTIMIZATIONS=\"-O3\"")

How to make sure doxygen-style documentation comments aren't missing from C/C++ code?

I want to run some kind of linter or static code analysis on C/C++ code which gives a warning if there is code with missing documentation, for example a function without its doxygen-style documentation coment. In other words, I want to enforce certain code standards. I had a look into clang-tidy and cppcheck, but didn't get very far.
To make it a little bit clearer what I'm expecting - from Python, I'm used to something like this:
$ cat test.py
def answer():
return 42
$ python3 -m pylint test.py
************* Module test
test.py:1:0: C0111: Missing module docstring (missing-docstring)
test.py:1:0: C0111: Missing function docstring (missing-docstring)
------------------------------------------------------------------
Your code has been rated at 0.00/10 (previous run: 0.00/10, +0.00)
Clang has the -Wdocumentation option for statically checking Doxygen-style comments. \see https://clang.llvm.org/docs/UsersManual.html.
Also, as #Null mentioned in the comments, the doxygen tool itself will warn of certain documentation issues.
I faced this issue recently and I actually used doxygen itself + a custom script to make sure that all the documentation is always present.
In the doxygen config file, enable the following:
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
# Do not throw errors on warning
# otherwise, it will stop on first
# error
WARN_AS_ERROR = NO
# It will write all warnings to a
# warning file. Make sure to
# add this to your gitignore
WARN_LOGFILE = doxy.warn
# Optional
QUIET = YES
Now, when you run doxygen command, it will write all errors inside doxy.warn file.
Now, we are going to parse it and throw error if doxygen fails. Here is the shell script that I use (I don't know much about powershell; so, can't provide a snippet for Windows):
doxygen
CURRENT_DIRECTORY=$(pwd)
# If doxy.warn file is not empty
if [ -s "doxy.warn" ]; then
# Remove the current directory from it to
# make error paths relative and shorter
# lines for better readability
cat doxy.warn | sed "s|${CURRENT_DIRECTORY}|.|"
# Print number warnings
echo "Total: $(wc -l < doxy.warn) documentation warnings"
# Exit with error
exit 1;
else
echo "Documentation is valid!"
exit 0;
fi

How to perform multiple actions in [action-if-true]

We are trying to test for -pthread availability and set the flag in both CXXFLAGS and LDFLAGS. We don't want to use ax_pthread because it uses the wrong compiler and sets the wrong flags for a C++ project. And according to Significance of -pthread flag when compiling, -pthread is most portable, so we want to use it for both CXXFLAGS and LDFLAGS.
The scripting we added to configure.ac is:
AC_ARG_ENABLE(tls,
AS_HELP_STRING([--enable-tls], [enable thread storage (default is yes)]),
ac_enable_tls=$enableval,
ac_enable_tls=yes)
AM_CONDITIONAL(HAS_PTHREADS, test $ac_enable_tls = yes)
if test "$ac_enable_tls" = "yes"; then
SAVED_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="-pthread"
AC_MSG_CHECKING([for pthread support])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([-pthread]) && AC_SUBST([AM_CXXFLAGS], ["-pthread"]) && AC_SUBST([AM_LDFLAGS], ["-pthread"])],
[AC_MSG_FAILURE(["--enable-tls=yes but pthreads are not available"])]
)
CXXFLAGS="$SAVED_CXXFLAGS"
fi
It results in:
./configure: line 16173: syntax error near unexpected token `&&'
./configure: line 16173: ` && AM_LDFLAGS="-pthread"'
autoreconf --warnings=all produces no warnings related to the test.
I'm guessing the trouble is trying to do three things in AC_COMPILE_IFELSE and [action-if-true]. The Autoconf AC_COMPILE_IFELSE docs don't tell us how to handle the situation and does not provide examples.
We want to perform three actions in [action-if-true]:
Print the message pthread
AM_CXXFLAGS += -pthread
AM_LDFLAGS += -pthread
How do I perform multiple actions in [action-if-true]?
It is not clear to me why you use the && shell operator; it will not work if the preceding m4 macro emits a newline. You should consider using ; or simply multiple lines.
It's also quite common in configure scripts just to set a shell variable in the AC_COMPILE_IFELSE actions, and check that afterwards. This avoids deeply nested shell code, and issues related to m4 quoting/macro expansion. Here is an example from glibc:
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <sys/sdt.h>
void foo (int i, void *p)
{
asm ("" STAP_PROBE_ASM (foo, bar, STAP_PROBE_ASM_TEMPLATE (2)) ""
:: STAP_PROBE_ASM_OPERANDS (2, i, p));
}]])], [libc_cv_sdt=yes], [libc_cv_sdt=no])

Improving g++ output

g++ sometimes produces pretty convoluted outputs. Specially when dealing with templates. Is there any tool that makes g++ output more readable? ... at least some color?
It may sound silly to ask this question here, but I've been unable to google my way out of this.
GCC as of 4.9 has colourized output ☺
Append the following to your bashrc/zshrc/whatever.
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
If you're free to switch compiler, try clang++. It's error outputs are most of the time very clear and sometimes it will even tell you what to do to fix your error. You can find a comparison of gcc vs clang error output here: http://clang.llvm.org/diagnostics.html.
Otherwise, as noted by Matteo Italia, look to STLFilt.
For the color aspect, Edwin Buck's solution (colorgcc) is very good. You can create symlinks to it named gcc, g++, etc so that it always gets used whenever you run a compiler command (provided you setup the paths in the colorgcc script correctly). I find this especially convenient when compiling some large project from a Makefile. Helps tremendously to detect where exactly something went wrong (especially when you do parallel compilations with make -j).
There's colorgcc, a perl script which wraps the gcc (g++) output with color for easier readability.
As far as the "output" of gcc (g++) I am guessing you're not complaining about the compiled binaries :)
I improve it by using sed to color the output with this script:
#!/bin/bash
while read x ; do echo $x ; done \
| sed -e "s/.*error:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/.*warning:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/^\(.*\)\(required from\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In instantiation of\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In member\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
| sed -e "s/error:/\x1b[1;31m&\x1b[1;36m/" \
-e "s/warning:/\x1b[1;35m&\x1b[1;36m/" \
-e "s/note:/\x1b[1;30m&\x1b[0m/"
If you use gcc 4.9 or higher there are a couple built-in options:
-fmessage-length=n, which optimizes the output for lines of n characters length.
-fdiagnostics-color=always, which applies some nice colors. (Works fine on linux, not so much on msys)
For more options and exact usage heres the documentation:
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html
When dealing with the STL1, STLFilt comes to the rescue.
On a related note, I also heard that the clang compiler produces by itself much better error messages in general.
Nitpickers' corner
Actually, not the SGI STL, but the parts of it that have been adopted in the C++ standard and are part of the standard library.
I can't answer your question directly, but note that in regards to templates if you look at the top message (the error caused by the templated) and the bottom "instantiated from here" message, it usually becomes much more clear. Ignore all the middle messages as they are probably not going to help.
There is colorgcc.
there is my personal function:
colorgcc()
{
perl -wln -M'Term::ANSIColor' -e '
m/not found$/ and print "\e[1;30m$`\e[0m", "$&", "\e[0m"
or
m/found$/ and print "\e[1;30m$`\e[0;32m", "$&", "\e[0m"
or
m/yes$/ and print "\e[1;30m$`\e[0;32m", "$&", "\e[0m"
or
m/no$/ and print "\e[1;30m$`\e[0m", "$&", "\e[0m"
or
m/ Error |error:/i and print "\e[1;91m", "$_", "\e[0m"
or
m/ Warning |warning:/i and print "\e[0;33m", "$_", "\e[0m"
or
m/nsinstall / and print "\e[0;36m", "$_", "\e[0m"
or
m/Linking |link: |\.a\b/ and print "\e[1;36m", "$_", "\e[0m"
or
m/Building|gcc|g++|\bCC\b|\bcc\b/ and print "\e[1;30m", "$_", "\e[0m"
or
print; '
}
you can use GilCC which is a Ruby tool that will convert GCC output to color in real-time. It is free and you can customize it to your preference. It is not intrusive as it does not change your gcc setup and you don't have to edit any system files such as .bash. You have to install Ruby and be able to invoke Ruby programs from the command line. Right now you have two options Perl script or GilCC and if you work with Ruby you will like GilCC.
Then whenever you call "GillCC" it will call "make" behind the scenes with your parameters such as "clean", "debug" or "release". for example if normally you call: "make debug" you should call "GilCC debug".
Almost forgot to mention that GilCC has some statistics such as # of warnings and error as well as build time. These things are handy when you are trying to improve your build.
The link to the download page is here.

Debugging the C++ preprocessor

I'm trying to build Amaya. When the build failed with
error: expected unqualified-id before ‘(’ token
I ran g++ with only the preprocessor (replacing the -c option with -E) on the file that failed to compile to see what was going on. This produced an 80,000 line file, showing me that 'Blue' had been replaced by (2 << 8), which clearly explained the error. If I correct this, the file compiles fine. I guess I could live with that, but I would like to find out why this is happening.
Is there any way I can track how the preprocessor is replacing a specific string, in this case 'Blue'?
================= Update ===================
Well, I found the culprit:
> headers=`g++ [omited for brevity] -M \
../../thotlib/dialogue/AmayaClassicNotebook.cpp`
> for file in $headers ; do grep -s -H Blue $file | grep "(2 << 8)";done
/usr/local/include/gc.h:#define Blue (2 << 8)
So adding #undef Blue fixed the problem. So using this combination of -M and grep seems OK but sometimes C++ preprocessor definitions can be a real forest; I was curious whether there were some better way, some clever GNU tool maybe.
I find running
g++ ... -dD -E $file > $file.ii
to be very useful in untangling preprocessing problems. From man g++:
-dD Dump all macro definitions, at the end of preprocessing,
in addition to normal output.
If nobody comes up with anything better (based on the source line info in the preprocessed file), you could use the -M option to get a list of headers included by the source file, and search those for "Blue". I expect it's possible for some kind of obfuscation to mean that this doesn't find what you're looking for, but normally you'll turn up the definition somewhere.
What's wrong with the perennial
find /src -exec grep Blue {} /dev/null ';'
That usually works for me, at least as a first cut.