Oscillon
Oscillon

Reputation: 237

nvcc compilation errors with "M_PI" and "or"

When trying to compile this piece of code:

#define _USE_MATH_DEFINES
#include <cmath>
#include <cstdio>

void minimal_example(){
    int i=2;
    if(i==3 or i==4) printf("I want %d!\n",M_PI);
}

using

nvcc -x cu -Xcompiler=/permissive- -dc cuda_nvcc_cl_test.cu -o cuda_nvcc_cl_test.obj

I get the follwing errors (in line 7):

error: expected a ")"
error: identifier "M_PI" is undefined

I am using Windows 10 with Visual Studio's cl.exe (Version 19.16.27031.1 for x64) and CUDA toolkit 10.1.

When replacing cmath with math.h and or with || (alternatively add #include <ciso646>), the errors disappear. However, are there some compiler options or other possibilities so that I can keep the code as is?

Also why did -Xcompiler=/permissive- not help?

Upvotes: 0

Views: 1188

Answers (1)

Robert Crovella
Robert Crovella

Reputation: 151799

There are 2 issues here:

  1. Apparently nvcc includes cmath prior to parsing your code. As discussed in the accepted answer here, if you include cmath and you don't have the define instantiated at that point, you won't get M_PI defined, and subsequent inclusions of cmath won't fix this, due to include guards. A possible workaround for this is to add -D_USE_MATH_DEFINES to your compile command line. This puts the define in place from the start of the compilation process, and M_PI gets defined that way.

  2. Contrary to what I read as correct or standard behavior, the use of or in place of || seems to be conditioned on inclusion of ciso646 (on nvcc on windows/visual studio only. nvcc on linux doesn't seem to need this). Yes, I understand it is not supposed to work that way, but nevertheless it appears to be necessary. This may be an issue with Visual Studio. You can experiment with the /Za switch if you like. (It didn't seem to help when I tried it.)

With CUDA 10.1, on VS2019, when I compile this:

#include <cstdio>
#include <ciso646>

void minimal_example(){
    int i=2;
    if(i==3 or i==4) printf("I want %f!\n",M_PI);
}

with this command line:

nvcc -x cu -dc test.cu -o test.obj -D_USE_MATH_DEFINES

I get no errors or warnings. Note that I have also changed your printf format specifier from %d to %f to be consistent with the type of M_PI.

If you really don't want to include ciso646, nvcc supports the -include switch to include a file directly from the command line. Therefore I can compile this:

#include <cstdio>

void minimal_example(){
    int i=2;
    if(i==3 or i==4) printf("I want %f!\n",M_PI);
}

like this:

nvcc -x cu -dc test.cu -o test.obj -D_USE_MATH_DEFINES -include ciso646

with no errors or warnings.

Upvotes: 2

Related Questions