.. index:: single: FAQ; macros .. highlight:: bash Why macros do not work in a #pragma? ==================================== OpenMP compilers usually expand macros inside ``#pragma omp``, so why macros do not work in Mercurium? The reason is that when Mercurium compiles an OmpSs/OpenMP program we do not enable OpenMP in the native compiler to reduce the chance of unwanted interferences. This implies that the ``#pragma omp`` is not known to the native preprocessor, which leaves the ``#pragma omp`` as is. As a consequence, macros are not expanded and they become unusable inside pragmas. .. _alternative-to-macros: Alternatives ------------ .. highlight:: c Although macros are not expanded in clauses, most of the cases they are used for integer constants:: #define N 100 #pragma omp task out([N]a) void f(int *a); void g() { int a[N]; f(a); #pragma omp taskwait } The example shown above will not work but fortunately in these cases one can avoid macros. A first approach replaces the macro with an enumerator. This is the most portable approach:: enum { N = 100 }; // Rest of the code Another approach uses an ``const`` integer:: const int N = 100; // Rest of the code .. note:: In C a ``const`` qualified variable is not a constant expression whereas in C++ it may be (`more information `_). Mercurium, though, allows this case as a constant expression in both languages. In case you need to change the value at compile time, you can use the following strategy. Here assume that ``N_`` is a macro that you change through the invocation of the compiler (typically with a compiler flag like ``-DN_=100``):: enum { N = N_ }; // Rest of the code Another feasible scenario where macros and pragmas are combined is when we want to generate the pragma itself via macros. To do that, we could use the ``_Pragma`` operator introduced in ``C99`` and ``C++11``:: #define STRINGIFY(X) #X #define MY_PRAGMA(X) _Pragma(STRINGIFY(X)) #define MY_OPENMP_PARALLEL_LOOP omp parallel for int main() { MY_PRAGMA(MY_OPENMP_PARALLEL_LOOP) for(int i = 0; i < 10; ++i) { // ... } } Why rely on the native preprocessor, then? ------------------------------------------ We could provide our own preprocessor, but this adds a lot of complication just to support this case (and as shown in :ref:`alternative-to-macros` the typical use case can be worked around). Complications include, but do not limit to: * it is not trivial to know where are the system headers. While ``gcc`` provides good support to know which paths it is using, not all compiler vendors provide this information. Even worse, some parameters may change the used paths between invocations of the native compiler * subtleties among preprocessor implementations. Not all preprocessors behave the same way and sometimes these differences are relevant for the native compiler headers