First some background – I have three VS2010 C++/OpenCL projects that compile and run fine on Windows 7 64-bit. I’ve been trying to compile and run each of them on Linux 64-bit (Ubuntu/Debian). The first two are compiling and running on linux and don’t really use any external libraries. The third uses only Boost 1.50.0 and isn’t compiling using the same method as the first two. So first let me go through what I did to get the first two to work.
- I extracted only the source from the myriad of folders.
- I ported windows specific code to linux specific code.
- I wrote a bash script to generate the g++ command with all sources to compile them.
- I ran the compile script to generate an output target file.
The bash script is as follows.
#!/bin/bash
SOURCE=""
for i in `ls *.h *.cpp *.hpp`; do
SOURCE+="${i} "
done
COMMAND="g++ -I/home/junkie/downloads/boost_1_51_0 -o out ${SOURCE} -L/opt/AMDAPP/lib/x86_64/ -I/opt/AMDAPP/include -lOpenCL -fpermissive"
echo -e "\n"
echo -e "${COMMAND}"
echo -e "\n"
$COMMAND
exit $?
And it generates and runs a command similar to following.
g++ -I/home/junkie/downloads/boost_1_51_0 -o out blah.cpp blah.h foo.hpp baz.cpp etc.cpp -L/opt/AMDAPP/lib/x86_64/ -I/opt/AMDAPP/include -lOpenCL -fpermissive
I compile using the following command.
./compile.sh &> log; echo $?; grep -ci error log; wc -l log
Now you may be wondering why I’ve adopted such unconventional and redundant means of getting a C++ project to compile and run on linux. Well because I’m new to the linux c and c++ toolchain and this was the quickest and simplest route I could figure out to get the job done and it did get the first two projects up and running. However, the third uses boost and this method isn’t working and I need your help in figuring out what all these strange errors are.
The errors I’m getting are not actually from the project code but instead from Boost and AMD’s opencl libraries code which is strange because the other projects were using opencl too and those worked fine.
Some examples of boost errors are below.
foo.hpp:2331:1: error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
In file included from main.cpp:4:
foo2.hpp:1610:1: error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: variable or field ‘BOOST_PP_CAT_I’ declared void /home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp: At global scope:
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: variable or field ‘BOOST_PP_CAT_I’ declared void
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘;’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘;’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘}’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected unqualified-id at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘}’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘}’ at end of input
foo.hpp:2331:1: error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
Some examples of opencl errors are below.
In file included from /opt/AMDAPP/include/CL/cl_platform.h:35,
from /opt/AMDAPP/include/CL/cl.h:30,
from bar.h:7,
from fooGPU.hpp:6,
from main.cpp:4:
/usr/include/stdint.h:49: error: expected ‘;’ before ‘typedef’
In file included from /opt/AMDAPP/include/CL/cl.h:30,
from bar.h:7,
from fooGPU.hpp:6,
from main.cpp:4:
/opt/AMDAPP/include/CL/cl_platform.h:41: error: expected unqualified-id before string constant
main.cpp:136: error: expected ‘}’ at end of input
main.cpp:136: error: expected unqualified-id at end of input
main.cpp:136: error: expected ‘}’ at end of input
main.cpp:136: error: expected ‘}’ at end of input
The boost includes I’m Using are as follows.
#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/punctuation/comma.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>
So, finally, my questions are as follows.
1) What is the root cause of these errors in light of the building method I’m using and how do I resolve this problem? Does order of files or library inclusion matter? I’m using a local source download of boost as part of my g++ command as instructed by boost documentation rather than prebuilt binaries as I’m not using anything that requires prebuilt binaries.
2) I realise that my way of building things is pretty primitive. I’m learning make and I’ve seen some recommendations to use cmake and kdevelop which I need to look into. The primary problem with using make is that these projects weren’t written with make in mind so I’m not aware of the dependency graph between source files to create the makefile (if I’m thinking correctly; I’m still fairly new to it). If you have any recommendations of how to do things better please do enlighten me.
Thanks.
I finally managed to overcome this problem and here I provide a brief account of how. To be clear I don’t know what the root cause of the original problem was. In other words – I don’t know why the problem occurred. All I’m saying is that my workaround allowed me to resolve the issue and move onto other problems (compile time errors).
Essentially, to reiterate, the problem was that for whatever reason a project using boost wasn’t compiling on Linux because all instances of the use of the BOOST_PP_CAT() function produced the following error.
For whatever reason the compiler wasn’t able to correctly process the use of this function but was able to process the use of other boost functions such as BOOST_PP_LPAREN(), BOOST_PP_RPAREN() and BOOST_PP_COMMA. The problem looked almost certainly related to the preprocessing stage where the combined use of the aforementioned boost functions was resulting in an unterminated argument list.
To elaborate on the nature of the relevant code (which was not written by me thankfully) the prior developers had essentially used boost preprocessor functions to create a DSL that they could then re-use multiple times to generate a list of functions. It would have seemed a lot easier to me to simply write the functions directly but anyway that’s another concern.
My work around was to change the relevant section of code so that it didn’t use any BOOST_PP_CAT() functions but ultimately defined the exact same functions as before. I did this by substituting the use of BOOST_PP_CAT() with the code that was being generated by it. This overcame all instances of the error quoted above but left me with hundreds of other compile time errors in my efforts to migrate this project from windows to linux.
Although this was a very specific and unusual question with an equally specific and unusual answer I wanted to feed this back to dispel the mystery behind this problem. As to why this particular function was failing to preprocess/compile on linux but passing on Windows I don’t know but would very much like to know. I can only assume it is a fundamental difference in the way VC++ performs preprocessing as opposed to g++ and clang or more specifically perhaps a difference in the order of resolution of nested functions in preprocessor directives. Who knows. Anyway, thanks for your help guys.