Compiler error while linking .cu to cpp file it seems that types aren't recognized

EDIT: Check the UPDATE at the bottom please.

Hi guys,

Please shed some light into a problem that I’m struggling for a couple of days now.

I receive this error when I compile my project: expected primary-expression before ‘,’ token, on the line pointed below (it seems to not know the argument types?!).

#include "operator.h"

#include "qustate.h"

#include "gpu.h"

#define ROUTINE(n) int n(const sRoutDef *def,const SymTable *loc,int inv)

#define EXTERR(s) throw tError(errEXT,s)

#define PAR_QUSTATE(v,s) quState* v; { GETVAL(s); if(!value->isQuExpr()) EXTERR("quantum expression expected"); v=value->qustate(); }

ROUTINE(ext_bit) {

  int i;

  quState *qbit;

  PAR_QUSTATE(q,"q");

  opBit *op;

...

// The next line raises the error

    gpucaller(opBit, q); // expected primary-expression before ',' token

    //gpucaller(1, 3);

qcl_delete(op);

  return 0;

}

where opBit and quState are classes defined in “qc/operator.h” and in “qc/qustate.h”, and gpu.h has the following content:

#ifndef _GPU_H_

#define _GPU_H_

#include "operator.h"

#include "qustates.h"

void gpucaller(opBit* op, quBaseState* q);

//void gpucaller(int a, int b);

#endif // #ifndef _GPU_H_

My .cu file includes gpu.h and is compiled with nvcc as commented below:

/*

compile with:

nvcc -arch sm_11 -c -I"/home/[user_name]/NVIDIA_GPU_Computing_SDK/C/common/inc" -I"qc" -I"/usr/local/cuda/include" -o cuda_kernel.o cuda_kernel.cu

*/

#ifndef _CUDA_KERNEL_H_

#define _CUDA_KERNEL_H_

// includes

#include <cutil_inline.h>

#include "gpu.h"

__constant__ float devOpBit[2][2];

// kernel function

__global__ void qcl1(cuFloatComplex *a, int N, int qbCount, int blockGrpSize, int k)

{

	...

}

void gpucaller(opBit* op, quBaseState* q) {

    float** myOpBit = (float**)op->getDeviceReadyOpBit();

    ...

    // execute the kernel

    qcl1<<< dimGrid, dimBlock >>>(a_d, N, gates, blockGrpSize, k);

    ...

}

/*

void gpucaller(int a, int b) {

	int c = a+b;

	return;

}

*/

#endif // #ifndef _CUDA_KERNEL_H_

So I generate my .o file and add it in my project’s Makefile, also adding the -lcudart flag to the compiler:

# Makefile for QCL

VERSION=0.6.3

# Directory for Standard .qcl files

QCLDIR = /usr/local/lib/qcl

# Directory for CUDA libraries

CUDALIB = /usr/local/cuda/lib

# Path for qcl binaries

QCLBIN = /usr/local/bin

ARCH = `g++ -dumpmachine || echo bin`

# Comment out if you want to compile for a different target architecture

# To build libqc.a, you will also have to edit qc/Makefile!

#ARCH = i686-linux

#ARCHOPT = -m32 -march=i686

# Debugging and optimization options

#DEBUG = -g -pg -DQCL_DEBUG -DQC_DEBUG

#DEBUG = -g -DQCL_DEBUG -DQC_DEBUG

DEBUG = -O2 -g -DQCL_DEBUG -DQC_DEBUG

#DEBUG = -O2

# Plotting support 

#

# Comment out if you don't have GNU libplotter and X

PLOPT = -DQCL_PLOT

PLLIB = -L/usr/X11/lib -lplotter

# Readline support

#

# Comment out if you don't have GNU readline on your system

# explicit linking against libtermcap or libncurses may be required

RLOPT = -DQCL_USE_READLINE

#RLLIB = -lreadline

RLLIB = -lreadline -lncurses

# Interrupt support

#

# Comment out if your system doesn't support ANSI C signal handling

IRQOPT = -DQCL_IRQ

# Replace with lex and yacc on non-GNU systems (untested)

LEX = flex

YACC = bison 

INSTALL = install

##### You shouldn't have to edit the stuff below #####

DATE = `date +"%y.%m.%d-%H%M"`

QCDIR = qc

QCLIB = $(QCDIR)/libqc.a

QCLINC = lib

#CXX = g++

#CPP = $(CC) -E

CXXFLAGS = -c $(ARCHOPT) -Wall $(DEBUG) $(PLOPT) $(RLOPT) $(IRQOPT) -I$(QCDIR) -DDEF_INCLUDE_PATH="\"$(QCLDIR)\""

LDFLAGS = $(ARCHOPT) -L$(QCDIR) $(DEBUG) $(PLLIB) -lm -lfl -lqc $(RLLIB) -L$(CUDALIB) -lcudart

FILESCC = $(wildcard *.cc)

FILESH = $(wildcard *.h)

SOURCE = $(FILESCC) $(FILESH) qcl.lex qcl.y Makefile

OBJECTS = cuda_kernel.o types.o syntax.o typcheck.o symbols.o error.o \

          lex.o yacc.o print.o quheap.o extern.o eval.o exec.o \

          parse.o options.o debug.o cond.o dump.o plot.o format.o

all: do-it-all

ifeq (.depend,$(wildcard .depend))

include .depend

do-it-all: build

else

do-it-all: dep

	$(MAKE)

endif

#### Rules for depend

dep: lex.cc yacc.cc yacc.h $(QCLIB)

	for i in *.cc; do \

	  $(CPP) -I$(QCDIR) -MM $$i; \

	done > .depend

lex.cc: qcl.lex yacc.h

	$(LEX) -olex.cc qcl.lex

yacc.cc: qcl.y

	$(YACC) -t -d -o yacc.cc qcl.y

yacc.h: yacc.cc

	mv yacc.*?h yacc.h

$(QCLIB):

	cd $(QCDIR) && $(MAKE) libqc.a

#### Rules for build

build: qcl $(QCLINC)/default.qcl

qcl: $(OBJECTS) qcl.o $(QCLIB)

	$(CXX) $(OBJECTS) qcl.o $(LDFLAGS) -o qcl

$(QCLINC)/default.qcl: extern.cc

	grep "^//!" extern.cc | cut -c5- > $(QCLINC)/default.qcl

checkinst:

	[ -f ./qcl -a -f $(QCLINC)/default.qcl ] || $(MAKE) build

install: checkinst

	$(INSTALL) -m 0755 -d $(QCLBIN) $(QCLDIR)

	$(INSTALL) -m 0755 ./qcl $(QCLBIN)

	$(INSTALL) -m 0644 ./$(QCLINC)/*.qcl $(QCLDIR)

uninstall:

	-rm -f $(QCLBIN)/qcl

	-rm -f $(QCLDIR)/*.qcl

	-rmdir $(QCLDIR)

#### Other Functions

edit:

	nedit $(SOURCE) &

clean:

	rm -f *.o lex.* yacc.* 

	cd $(QCDIR) && $(MAKE) clean

clear: clean

	rm -f qcl $(QCLINC)/default.qcl .depend

	cd $(QCDIR) && $(MAKE) clear

dist-src: dep

	mkdir qcl-$(VERSION)

	cp README CHANGES COPYING .depend $(SOURCE) qcl-$(VERSION) 

	mkdir qcl-$(VERSION)/qc

	cp qc/Makefile qc/*.h qc/*.cc qcl-$(VERSION)/qc

	cp -r lib qcl-$(VERSION)

	tar czf qcl-$(VERSION).tgz --owner=0 --group=0 qcl-$(VERSION)

	rm -r qcl-$(VERSION)

dist-bin: build

	mkdir qcl-$(VERSION)-$(ARCH)

	cp Makefile README CHANGES COPYING qcl qcl-$(VERSION)-$(ARCH) 

	cp -r lib qcl-$(VERSION)-$(ARCH)

	tar czf qcl-$(VERSION)-$(ARCH).tgz --owner=0 --group=0 qcl-$(VERSION)-$(ARCH)

	rm -r qcl-$(VERSION)-$(ARCH)

upload: dist-src

	scp qcl-$(VERSION)*.tgz oemer@tph.tuwien.ac.at:html/tgz

scp: dist-src

	scp qcl-$(VERSION).tgz oemer@tph.tuwien.ac.at:bak/qcl-$(DATE).tgz

If I change the gpucaller's function definition to

void gpucaller(int a, int b);

it compiles just fine.

Any help will be appreciated.

UPDATE: I found the answer, I was passing a type as a parameter. Now I get the following error while compiling my project with g++:

tmpxft_00001aba_0000000000-1_cuda_kernel.cudafe1.cpp:(.text+0xe): undefined reference to `opBit::getDeviceReadyOpBit()'

while this method (getDeviceReadyOpBit) is defined in “qc/operator.h” and have included the header.

EDIT: Check the UPDATE at the bottom please.

Hi guys,

Please shed some light into a problem that I’m struggling for a couple of days now.

I receive this error when I compile my project: expected primary-expression before ‘,’ token, on the line pointed below (it seems to not know the argument types?!).

#include "operator.h"

#include "qustate.h"

#include "gpu.h"

#define ROUTINE(n) int n(const sRoutDef *def,const SymTable *loc,int inv)

#define EXTERR(s) throw tError(errEXT,s)

#define PAR_QUSTATE(v,s) quState* v; { GETVAL(s); if(!value->isQuExpr()) EXTERR("quantum expression expected"); v=value->qustate(); }

ROUTINE(ext_bit) {

  int i;

  quState *qbit;

  PAR_QUSTATE(q,"q");

  opBit *op;

...

// The next line raises the error

    gpucaller(opBit, q); // expected primary-expression before ',' token

    //gpucaller(1, 3);

qcl_delete(op);

  return 0;

}

where opBit and quState are classes defined in “qc/operator.h” and in “qc/qustate.h”, and gpu.h has the following content:

#ifndef _GPU_H_

#define _GPU_H_

#include "operator.h"

#include "qustates.h"

void gpucaller(opBit* op, quBaseState* q);

//void gpucaller(int a, int b);

#endif // #ifndef _GPU_H_

My .cu file includes gpu.h and is compiled with nvcc as commented below:

/*

compile with:

nvcc -arch sm_11 -c -I"/home/[user_name]/NVIDIA_GPU_Computing_SDK/C/common/inc" -I"qc" -I"/usr/local/cuda/include" -o cuda_kernel.o cuda_kernel.cu

*/

#ifndef _CUDA_KERNEL_H_

#define _CUDA_KERNEL_H_

// includes

#include <cutil_inline.h>

#include "gpu.h"

__constant__ float devOpBit[2][2];

// kernel function

__global__ void qcl1(cuFloatComplex *a, int N, int qbCount, int blockGrpSize, int k)

{

	...

}

void gpucaller(opBit* op, quBaseState* q) {

    float** myOpBit = (float**)op->getDeviceReadyOpBit();

    ...

    // execute the kernel

    qcl1<<< dimGrid, dimBlock >>>(a_d, N, gates, blockGrpSize, k);

    ...

}

/*

void gpucaller(int a, int b) {

	int c = a+b;

	return;

}

*/

#endif // #ifndef _CUDA_KERNEL_H_

So I generate my .o file and add it in my project’s Makefile, also adding the -lcudart flag to the compiler:

# Makefile for QCL

VERSION=0.6.3

# Directory for Standard .qcl files

QCLDIR = /usr/local/lib/qcl

# Directory for CUDA libraries

CUDALIB = /usr/local/cuda/lib

# Path for qcl binaries

QCLBIN = /usr/local/bin

ARCH = `g++ -dumpmachine || echo bin`

# Comment out if you want to compile for a different target architecture

# To build libqc.a, you will also have to edit qc/Makefile!

#ARCH = i686-linux

#ARCHOPT = -m32 -march=i686

# Debugging and optimization options

#DEBUG = -g -pg -DQCL_DEBUG -DQC_DEBUG

#DEBUG = -g -DQCL_DEBUG -DQC_DEBUG

DEBUG = -O2 -g -DQCL_DEBUG -DQC_DEBUG

#DEBUG = -O2

# Plotting support 

#

# Comment out if you don't have GNU libplotter and X

PLOPT = -DQCL_PLOT

PLLIB = -L/usr/X11/lib -lplotter

# Readline support

#

# Comment out if you don't have GNU readline on your system

# explicit linking against libtermcap or libncurses may be required

RLOPT = -DQCL_USE_READLINE

#RLLIB = -lreadline

RLLIB = -lreadline -lncurses

# Interrupt support

#

# Comment out if your system doesn't support ANSI C signal handling

IRQOPT = -DQCL_IRQ

# Replace with lex and yacc on non-GNU systems (untested)

LEX = flex

YACC = bison 

INSTALL = install

##### You shouldn't have to edit the stuff below #####

DATE = `date +"%y.%m.%d-%H%M"`

QCDIR = qc

QCLIB = $(QCDIR)/libqc.a

QCLINC = lib

#CXX = g++

#CPP = $(CC) -E

CXXFLAGS = -c $(ARCHOPT) -Wall $(DEBUG) $(PLOPT) $(RLOPT) $(IRQOPT) -I$(QCDIR) -DDEF_INCLUDE_PATH="\"$(QCLDIR)\""

LDFLAGS = $(ARCHOPT) -L$(QCDIR) $(DEBUG) $(PLLIB) -lm -lfl -lqc $(RLLIB) -L$(CUDALIB) -lcudart

FILESCC = $(wildcard *.cc)

FILESH = $(wildcard *.h)

SOURCE = $(FILESCC) $(FILESH) qcl.lex qcl.y Makefile

OBJECTS = cuda_kernel.o types.o syntax.o typcheck.o symbols.o error.o \

          lex.o yacc.o print.o quheap.o extern.o eval.o exec.o \

          parse.o options.o debug.o cond.o dump.o plot.o format.o

all: do-it-all

ifeq (.depend,$(wildcard .depend))

include .depend

do-it-all: build

else

do-it-all: dep

	$(MAKE)

endif

#### Rules for depend

dep: lex.cc yacc.cc yacc.h $(QCLIB)

	for i in *.cc; do \

	  $(CPP) -I$(QCDIR) -MM $$i; \

	done > .depend

lex.cc: qcl.lex yacc.h

	$(LEX) -olex.cc qcl.lex

yacc.cc: qcl.y

	$(YACC) -t -d -o yacc.cc qcl.y

yacc.h: yacc.cc

	mv yacc.*?h yacc.h

$(QCLIB):

	cd $(QCDIR) && $(MAKE) libqc.a

#### Rules for build

build: qcl $(QCLINC)/default.qcl

qcl: $(OBJECTS) qcl.o $(QCLIB)

	$(CXX) $(OBJECTS) qcl.o $(LDFLAGS) -o qcl

$(QCLINC)/default.qcl: extern.cc

	grep "^//!" extern.cc | cut -c5- > $(QCLINC)/default.qcl

checkinst:

	[ -f ./qcl -a -f $(QCLINC)/default.qcl ] || $(MAKE) build

install: checkinst

	$(INSTALL) -m 0755 -d $(QCLBIN) $(QCLDIR)

	$(INSTALL) -m 0755 ./qcl $(QCLBIN)

	$(INSTALL) -m 0644 ./$(QCLINC)/*.qcl $(QCLDIR)

uninstall:

	-rm -f $(QCLBIN)/qcl

	-rm -f $(QCLDIR)/*.qcl

	-rmdir $(QCLDIR)

#### Other Functions

edit:

	nedit $(SOURCE) &

clean:

	rm -f *.o lex.* yacc.* 

	cd $(QCDIR) && $(MAKE) clean

clear: clean

	rm -f qcl $(QCLINC)/default.qcl .depend

	cd $(QCDIR) && $(MAKE) clear

dist-src: dep

	mkdir qcl-$(VERSION)

	cp README CHANGES COPYING .depend $(SOURCE) qcl-$(VERSION) 

	mkdir qcl-$(VERSION)/qc

	cp qc/Makefile qc/*.h qc/*.cc qcl-$(VERSION)/qc

	cp -r lib qcl-$(VERSION)

	tar czf qcl-$(VERSION).tgz --owner=0 --group=0 qcl-$(VERSION)

	rm -r qcl-$(VERSION)

dist-bin: build

	mkdir qcl-$(VERSION)-$(ARCH)

	cp Makefile README CHANGES COPYING qcl qcl-$(VERSION)-$(ARCH) 

	cp -r lib qcl-$(VERSION)-$(ARCH)

	tar czf qcl-$(VERSION)-$(ARCH).tgz --owner=0 --group=0 qcl-$(VERSION)-$(ARCH)

	rm -r qcl-$(VERSION)-$(ARCH)

upload: dist-src

	scp qcl-$(VERSION)*.tgz oemer@tph.tuwien.ac.at:html/tgz

scp: dist-src

	scp qcl-$(VERSION).tgz oemer@tph.tuwien.ac.at:bak/qcl-$(DATE).tgz

If I change the gpucaller's function definition to

void gpucaller(int a, int b);

it compiles just fine.

Any help will be appreciated.

UPDATE: I found the answer, I was passing a type as a parameter. Now I get the following error while compiling my project with g++:

tmpxft_00001aba_0000000000-1_cuda_kernel.cudafe1.cpp:(.text+0xe): undefined reference to `opBit::getDeviceReadyOpBit()'

while this method (getDeviceReadyOpBit) is defined in “qc/operator.h” and have included the header.