Detecting whether Graphicsmagick or ImageMagick headers are included - imagemagick

I'm developing a C/C++ library that uses ImageMagick (using/supporting both libMagickCore and libMagick++), for reading and writing image data (not for processing).
Now, I would also like to support IM's GraphicsMagick fork (e.g. using Debian's graphicsmagick-libmagick-dev-compat package).
Unfortunately, the APIs have diverged enough, so that I cannot use one as a drop-in replacement of the other. Since they are still quite similar, I plan to use a number of #ifdefs for the API specific parts.
Now my problem is, that it seems quite complicated to detect which API is actually used via pre-processor directives, right after including the generic header (which is called the same for both variants).
Basically, I'm looking for something like a #define (provided by the IM/GM headers) that can be used to tell the two APIs apart. Something like:
#include <Magick++.h>
#ifdef GRAPHICSMAGIC_DEFINE
// GM-specific code
#else
// IM-specific code
#endif
or, for the C-API:
#include <magick/MagickCore.h>
#ifdef GRAPHICSMAGIC_DEFINE2
/* GM-specific code */
#else
/* IM-specific code */
#endif
Ideas?

Autoconf, or CMake.
Really - there's no simpler way around it, but you need to package your solution with something that will ask the system what library is present, and will then generate config.h with the correct pre-processor definitions.
The difference between GraphicsMagick & ImageMagick seem simple enough to do something clever, BUT now that we're a year into the release of IM 7, we now need to check which version & adjust definitions as needed. For example
// IM 6
#include <magick/MagickCore.h>
// IM 7
#include <MagickCore/MagickCore.h>
I would suggest reviewing existing m4 scripts used by other projects available online.
So back to the original question, the generic include headers my look something like this... (and I quote from Imagick library, but can be expanded to cover GM)
#if defined (IM_MAGICKWAND_HEADER_STYLE_SEVEN)
# include <MagickWand/MagickWand.h>
#elif defined (IM_MAGICKWAND_HEADER_STYLE_OLD)
# include <wand/magick-wand.h>
#else
# include <wand/MagickWand.h>
#endif

Related

clang-format header include guard

I'd like for the clang-format to check that each of my headers have the proper include guard.
For example, for the file dopelib/dopestuff/whatitisyo.h, I'd like the code to be formatted like this:
#ifndef DOPELIB_DOPESTUFF_WHATITISYO_H
#define DOPELIB_DOPESTUFF_WHATITISYO_H
/** Code here. **/
#endif // DOPELIB_DOPESTUFF_WHATITISYO_H
Can clnag-format check this structure and make sure that the include guard is there and that it is named appropriately with the file name in the #ifndef (sort of what cpplint does)?
As far as I know, clang-format doesn't currently support this.
However, you can do exactly this with clang-tidy (documented here). Invoke it like this:
clang-tidy -checks='-*,llvm-header-guard' -fix-errors myIncludeFile.h
Explanation:
The -* tells clang-tidy to disable all checks
The llvm-header-guard tells clang-tidy to enable the check which deals with include guards (documented here)
The -fix-errors tells clang-tidy to fix any resulting issues, even if it runs into other errors parsing the file
The llvm-header-guard expected format of the include-guards is exactly what you requested above; for example the file mydir/myfile.h would use MYDIR_MYFILE_H. I don't see any documentation which actually specifies that this is the format it uses, but I've verified at least version 6.0.0 does use that format.
Also see: clang include fixer, which does something similar.
The accepted solution may not work if
The project has a different file structure
Uses some extensions that clang does not understand
I have a script here: https://github.com/milasudril/texpainter/blob/master/devtools/include_guard_fix.py

Add #include's to the headers of a program using llvm clang

I need to add headers to an already existing program by transforming it with LLVM and Clang.
I have used clang's rewriter to accomplish a similar thing in the changing function names and arguments, etc.
But the header files aren't present in clang's AST. I already know we need to use PPCallbacks (https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html) but I am in dire need of some examples on how to make it work with the rewriter if at all possible.
Alternatively, adding a #include statement just before the first
using namespace <namespace>;
Also works. I would like to know an example of this as well.
Any help would be appreciated.
There is a bit of confusion in your question. You need to understand in details how the preprocessor works. Be aware that most of C++ compilation happens after the preprocessing phase (so most C++ static analyzers work after that phase).
In other words, the C++ specification (and also the C specification) defines first what is preprocessing, and then what is the syntax and the semantics of the preprocessed form.
In other words, when compiling foo.cc your compiler see the preprocessed form foo.ii that you could obtain with clang++ -C -E foo.cc > foo.ii
In the 1980s the preprocessor /lib/cpp was a separate program forked by the compiler (and some temporary foo.ii was sitting on the disk and removed at end of compilation). Today, it is -for performance reasons- some initial processing done inside the compiler. But you could reason as if it was still separate.
Either you want to alter the Clang compiler, and it deals (like every other C++ compiler or C++ static analyzer) mostly with the preprocessed form. Then you don't want to add new #include-s, but you want to alter the flow of AST given to the compiler (after preprocessing), and that is a different question: you then want to add some AST between existing AST elements (independently of any preprocessor directives).
Or you want to automatically change the C++ source code. The hard part is determining what you want to change and at what place. I suppose that you have used complex stuff to determine that a #include <vector> has to be inserted after line 34 of file foo.cc. Once you've got that information (and getting it is the hard thing), doing the insertion is pretty trivial. For example, you could read every C++ source line, and insert your line when you have read enough lines.

How to check whether system has some header file using bazel build?

What I want to find is the existence of some platform specific header file.
For example, in source code there will be some #ifdef section like this.
#ifdef HAVE_XXX_H
//...do something
#else
//...do other thing
#endif
In Autoconf or Cmake, there exists dedicated macro or command for detecting platform specific header file or definition. So, I can easily set 'HAVE_XXX_H' as 1 or 0 according to the result of that macro.
Using bazel, how can I achieve this kind of thing?
Thanks.
If you are sure that the header is always present on a particular platform, use select() as elaborated by László.
If you actually need to detect the header at the build time, you will have to implement a custom repository_rule that will query the system and will generate a workspace with a header defining the macro.
You can use select().
Example: select() in cc_library.srcs. You can do the same in cc_library.hdrs.

How to portably including mysql headers

I have a library that uses the mysql library (libmysqlclient) on linux that I'm porting to windows, but I seem to run into a "problem" with where the header files are located. Under linux the headers are located under /usr/include/mysql (at least for Debian) so with standard include path they would be included as:
#include <mysql/mysql.h>
However when installed the library under windows the main header seem to be located at c:\Program Files\MySQL\MySQL Connector C 6.1\include\mysql.h which would require it to be included as:
#include <mysql.h>
I need to build it for iOS as well, but at this moment I don't know where the header files will be located there.
What is the normal way to solve this? Should I add /usr/include/mysql to the include path under linux? Wouldn't that open up for higher probability of header name collisions?
You can determine which platform you're running on by checking for a predefined symbol. There are a few lists of such macros floating around; here's one:
http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
Then, you can #include a different path depending on the platform:
#if defined(_WIN32) || defined(_WIN64)
# include <mysql.h>
#elif defined(__linux)
# include <mysql/mysql.h>
#elif defined(__APPLE__)
# include <whatever path works on iOS>
#else
# error Unrecognized platform.
#endif
If you need to do this in more than one place, then put it into one of your own include files, and #include that, which will then #include the correct mysql.h in turn.
The other option, as you've already suggested, is to set your include path on each platform so that #include <mysql.h> works. Which one you use is a matter of taste.

Preprocessor directives supported by the RIM compiler

This isn't really clearly documented, but a shallow search reveals that RIM's RAPC compiler does support preprocessor statements (with some project file modification).
We've been using the simple #ifdef, #else, and #endif directives for quite some time now, as supporting platforms 4.1 through 4.7 with one code base is nearly impossible without them, but I began wondering recently if there are other supported directives which aren't quite as well documented; something akin to C's #elif for example, or even rudimentary equivalency directives?
Here's a complete listing of commands for the RAPC preprocessor. The preprocessor's not very robust, but that's on purpose.
//#preprocess - Used to specify that the file should be preprocessed. It must be the first line of the file.
//#implicit tag - This needs to be on the second line of the file. If tag is part of the command line, then the whole file should be compiled. If not, then it should be excluded.
Then there's the //#ifdef tag ... #else ... #endif and the //#ifndef tag ... #else ... #endif directives that you mentioned.
Also note, there is no nesting of preprocessed blocks and no macros.
RIM Help Center Doc:
http://docs.blackberry.com/en/developers/deliverables/21065/Specifying_preprocessor_directives_657636_11.jsp

Resources