haskell / c2hs

c2hs is a pre-processor for Haskell FFI bindings to C libraries
http://hackage.haskell.org/package/c2hs
Other
198 stars 50 forks source link

cuda package build failure with 1.18 #111

Closed tmcdonell closed 9 years ago

tmcdonell commented 9 years ago

tmcdonell/cuda#18

Upgrading from c2hs-1.17.2 to c2hs-1.18.2, I now get this error on Mac OS X:

$ cabal build --verbose
« snip »
/Users/trevor/.cabal/bin/c2hs --cpp=/usr/local/cuda/bin/nvcc --cppopts=-E --cppopts=-arch=sm_20 --cppopts=-m64 --cppopts=-U__BLOCKS__ --include=dist/build --cppopts=-D__GLASGOW_HASKELL__=708 --cppopts=-I. --cppopts=-I/usr/local/homebrew/include --cppopts=-I/usr/local/homebrew/include --cppopts=-I/usr/local/cuda/include --output-dir=dist/build --output=Foreign/CUDA/Analysis/Device.hs ./Foreign/CUDA/Analysis/Device.chs
In file included from <built-in>:169:
<command line>:5:29: error: expected comma in macro parameter list
#define C2HS_MIN_VERSION(mj 1
                            ^
<command line>:7:11: warning: ISO C99 requires whitespace after the macro name [-Wc99-extensions]
#define rv) (mj<=0&&mn<=18&&rv<=2)
          ^
1 warning and 1 error generated.
c2hs: Error during preprocessing custom header file

From submitted issue, on linux (flavour unknown at this time):

Preprocessing library cuda-0.6.5.0...
<command-line>: error: "1" may not appear in macro parameter list
<command-line>: warning: missing whitespace after the macro name
c2hs: Error during preprocessing custom header file

I'm not sure where the C2HS_MIN_VERSION macro is being introduced, so not sure how to diagnose this.

ian-ross commented 9 years ago

@tmcdonell This appears to be because the CUDA build process uses nvcc as the preprocessor for expanding C2HS files and nvcc doesn't seem to support all of the macro definition syntax that gcc does. In particular, with gcc, you can say -DC2HS_MIN_VERSION(mj,mn,rv)=(mj<=0&&mn<=18&&rv<=2). nvcc doesn't seem to support this syntax for defining macros with parameters from the command line. Let me investigate some more and see if I can come up with a fix.

Here's an example, nvcc first (errors) then gcc (works fine):

[seneca:cuda-0.6.5.0] $ nvcc -x c -E -m64 -D__GLASGOW_HASKELL__=708 -I. -I/opt/cuda/include -U__BLOCKS__ -DC2HS_MIN_VERSION\(mj,mn,rv\)=\(mj\<=0\&\&mn\<=18\&\&rv\<=2\) dist/build/Foreign/CUDA/Analysis/Device.chs.h > tmp.hs
<command-line>:0:21: error: "1" may not appear in macro parameter list
<command-line>:0:3: warning: missing whitespace after the macro name
[seneca:cuda-0.6.5.0] $ gcc -x c -E -m64 -D__GLASGOW_HASKELL__=708 -I. -I/opt/cuda/include -U__BLOCKS__ -DC2HS_MIN_VERSION\(mj,mn,rv\)=\(mj\<=0\&\&mn\<=18\&\&rv\<=2\) dist/build/Foreign/CUDA/Analysis/Device.chs.h > tmp.hs
tmcdonell commented 9 years ago

Okay, thanks @ian-ross. I gather that this use of -DC2HS_MIN_VERSION appeared in 1.18.

Do you know if clang supports this syntax? The style of the error message makes me think that the error is being given by clang (which is invoked by nvcc internally) rather than nvcc itself.

ian-ross commented 9 years ago

Ah, that could very well be -- makes sense. I'll have a look at what syntax clang supports for command-line definition of macros. And yes, the C2HS_MIN_VERSION thing appeared recently, to help fix #107.

ian-ross commented 9 years ago

Hmmm. clang looks OK. With this little test program:

int main(void)
{
  int x = C2HS_MIN_VERSION(0,18,2);
}

gcc 4.9.1 gives this:

[seneca:tmp] $ gcc -E -DC2HS_MIN_VERSION\(mj,mn,rv\)=\(mj\<=0\&\&mn\<=18\&\&rv\<=2\) x.c
# 1 "x.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "x.c"
int main(void)
{
  int x = (0<=0&&18<=18&&2<=2);
}

clang 3.5.0 gives this:

[seneca:tmp] $ clang -E -DC2HS_MIN_VERSION\(mj,mn,rv\)=\(mj\<=0\&\&mn\<=18\&\&rv\<=2\) x.c
# 1 "x.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 312 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "x.c" 2
int main(void)
{
  int x = (0<=0&&18<=18&&2<=2);
}

And nvcc 6.5 gives this (I know that's more recent than the version supported by the Haskell cuda package, but the behaviour seems to be the same):

[seneca:tmp] $ nvcc -E -DC2HS_MIN_VERSION\(mj,mn,rv\)=\(mj\<=0\&\&mn\<=18\&\&rv\<=2\) x.c
# 1 "x.c"
# 1 "<built-in>"
# 1 "<command-line>"
<command-line>:0:21: error: "1" may not appear in macro parameter list
<command-line>:0:3: warning: missing whitespace after the macro name
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "x.c"
int main(void)
{
  int x = C2HS_MIN_VERSION(0,18,2);
}
tmcdonell commented 9 years ago

I am also using CUDA-6.5, this is supported by the Haskell cuda package.

It looks like an escaping problem in what nvcc passes to clang. Looks like the macro is being split at the commas into separate macros.

$ nvcc -E -DC2HS_MIN_VERSION\(mj,mn,rv\)=\(mj\<=0\&\&mn\<=18\&\&rv\<=2\) issue111.c --verbose
« snip »
#$ clang -stdlib=libstdc++ -E -x c -D__NVCC__  "-I/usr/local/cuda/bin/../include"   -D"C2HS_MIN_VERSION(mj" -D"mn" -D"rv)=(mj<=0&&mn<=18&&rv<=2)" -m64 "issue111.c"
# 1 "issue111.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 169 "<built-in>" 3
# 1 "<command line>" 1
In file included from <built-in>:169:
<command line>:2:29: error: expected comma in macro parameter list
#define C2HS_MIN_VERSION(mj 1
                            ^
<command line>:4:11: warning: ISO C99 requires whitespace after the macro name [-Wc99-extensions]
#define rv) (mj<=0&&mn<=18&&rv<=2)
          ^
# 1 "<built-in>" 2
# 1 "issue111.c" 2
int main(void)
{
  int x = C2HS_MIN_VERSION(0,18,2);
}
1 warning and 1 error generated.
# --error 0x1 --

Any ideas for workarounds?

ian-ross commented 9 years ago

No ideas yet. I've not been able to get it to work with any combination of escaping. Something somewhere seems to know that the macro parameter list should be comma-separated:

[seneca:tmp] $ nvcc -E -D'C2HS_MIN_VERSION(j n v)=(j<=0&&n<=18&&v<=2)' x.c
# 1 "x.c"
# 1 "<built-in>"
# 1 "<command-line>"
<command-line>:0:20: error: macro parameters must be comma-separated
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "x.c"
int main(void)
{
  int x = C2HS_MIN_VERSION(0,18,2);
}

but something else is failing to deal with the parameter lists properly:

[seneca:tmp] $ nvcc -E -D'C2HS_MIN_VERSION(j,n,v)=(j<=0&&n<=18&&v<=2)' x.c
# 1 "x.c"
# 1 "<built-in>"
# 1 "<command-line>"
<command-line>:0:20: error: "1" may not appear in macro parameter list
<command-line>:0:2: warning: missing whitespace after the macro name
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "x.c"
int main(void)
{
  int x = C2HS_MIN_VERSION(0,18,2);
}

It looks as though nvcc is splitting on the commas then passing the parts to clang as separate -D flags. Which is, of course, never going to work. Let me think about it some more.

tmcdonell commented 9 years ago

I'll submit this as an issue to NVIDIA as well and see what they say. Currently waiting for the application to be finalised/approved before I can submit bugs.

tmcdonell commented 9 years ago

Submitted as NV Bug ID #1557230

ian-ross commented 9 years ago

@tmcdonell Have you had any feedback from NVIDIA about this? I don't seem to be able to view that bug report link you posted. I'm playing with a possible approach to remove the C2HS_MIN_VERSION macro definition from the preprocessor command line which would fix this problem, but it would be nicer if NVIDIA fixed nvcc! If what I'm trying works, I should have a fixed version of C2HS for you in a day or two.

ian-ross commented 9 years ago

@tmcdonell OK, I've pushed a change to C2HS HEAD that seems to do the job: I just build cuda-0.6.5.0 with it. That was easier than I thought it would be. I'll make a new C2HS release in a day or two once I've cleaned up a couple of other issues. I'll wait to close this issue until I can specify exactly which C2HS release should be used to build the cuda package.

tmcdonell commented 9 years ago

@ian-ross I received an initial confirmation that the bug was reproduced and assigned to an engineer, but since then nothing. I suspect that this means any fix would only come in the next CUDA release at earliest, which I think is a 6/12 month cycle.

I'll try out HEAD and let you know how it goes!

tmcdonell commented 9 years ago

@ian-ross I can confirm that the cuda package compiles with HEAD again, despite the nvcc bug. Thanks for the fixes!

ian-ross commented 9 years ago

Good! I'll do a release in the next couple of days.

On 23 November 2014 at 00:28, Trevor L. McDonell notifications@github.com wrote:

@ian-ross https://github.com/ian-ross I can confirm that the cuda package compiles with HEAD again, despite the nvcc bug. Thanks for the fixes!

— Reply to this email directly or view it on GitHub https://github.com/haskell/c2hs/issues/111#issuecomment-64099627.

Ian Ross Tel: +43(0)6804451378 ian@skybluetrades.net www.skybluetrades.net