This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Compute Library:- Manual build incantation doesn't work

Hi

It's me again!! I've moved on from compiling via scons, sorting out the libOpenCL stub libs and running the examples. The inacantation shown in the documentation under Building for linux-> How to manually build the examples has some issues that I've been trying to find a solution for but I'm not so familiar with this type of command line compilation!

I'm building natively on an Odroid XU4 board, 32 bit, but following one of the examples under "To compile an OpenCL example for Linux 32bit"  The following line produces:-

odroid@odroid:~/ComputeLibrary-17.12$ g++ examples/cl_convolution.cpp utils/Utils.cpp -I. -Iinclude -std=c++11 
-larm_compute -larm_compute_core -lOpenCL -o cl_convolution -DARM_COMPUTE_CL

/usr/bin/ld: cannot find -larm_compute
/usr/bin/ld: cannot find -larm_compute_core
collect2: error: ld returned 1 exit status

I think this is because it's looking for the .so files that should be libarm_compute and libarm_compute_core not
arm_.... ? Am I correct?

I changed the two entries to -L libarm_compute and -L libarm_compute_core and it seems to remove the "cannot find"
error and moves on to the next stage. I tried -llibarm_compute and -llibarm_compute_core but still causes a later
"cant find" error after what looks like the compile stage. The "-L " before the libs seems to get the process further
down the line. But we now get a host of what I think are linkage errors, possibly to do with the STUB files that are
needed during a Scons build and the LD_LIBRARY_PATH that is needed when running the executable!

I can get round these issues by editing a file in the ComputeLibrary-17.12/examples folder and running scons to compile
the examples, that ignores any that haven't been changed but takes a fair bit of time while during the process! I'd like
to be able to compile just the file I'm working on!!

Can anyone help before I short circuit my brain??

I'm trying to add a text file with the compile output, I haven't done this before so I'm not sure I'm following the
correct protocol, so apologies if I'm wrong!

Regards

Dave

Command line was:-
g++ examples/cl_convolution.cpp utils/Utils.cpp -v -I. -Iinclude -std=c++11 -L libarm_compute -L arm_compute_core -L OpenCL -o cl_convolution -DARM_COMPUTE_CL &> compile.txt

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/5/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --enable-multilib --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-werror --enable-multilib --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 
COLLECT_GCC_OPTIONS='-v' '-I' '.' '-I' 'include' '-std=c++11' '-Llibarm_compute' '-Larm_compute_core' '-LOpenCL' '-o' 'cl_convolution' '-D' 'ARM_COMPUTE_CL' '-shared-libgcc' '-march=armv7-a' '-mfloat-abi=hard' '-mfpu=vfpv3-d16' '-mthumb' '-mtls-dialect=gnu'
 /usr/lib/gcc/arm-linux-gnueabihf/5/cc1plus -quiet -v -I . -I include -imultiarch arm-linux-gnueabihf -D_GNU_SOURCE -D ARM_COMPUTE_CL examples/cl_convolution.cpp -quiet -dumpbase cl_convolution.cpp -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb -mtls-dialect=gnu -auxbase cl_convolution -std=c++11 -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/cci1PXds.s
GNU C++11 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) version 5.4.0 20160609 (arm-linux-gnueabihf)
	compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "/usr/include/arm-linux-gnueabihf/c++/5"
ignoring nonexistent directory "/usr/local/include/arm-linux-gnueabihf"
ignoring nonexistent directory "/usr/lib/gcc/arm-linux-gnueabihf/5/../../../../arm-linux-gnueabihf/include"
#include "..." search starts here:
#include <...> search starts here:
 .
 include
 /usr/include/c++/5
 /usr/include/arm-linux-gnueabihf/c++/5
 /usr/include/c++/5/backward
 /usr/lib/gcc/arm-linux-gnueabihf/5/include
 /usr/local/include
 /usr/lib/gcc/arm-linux-gnueabihf/5/include-fixed
 /usr/include/arm-linux-gnueabihf
 /usr/include
End of search list.
GNU C++11 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) version 5.4.0 20160609 (arm-linux-gnueabihf)
	compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 12831138f3a67787c6ffebe33a0c39c6
COLLECT_GCC_OPTIONS='-v' '-I' '.' '-I' 'include' '-std=c++11' '-Llibarm_compute' '-Larm_compute_core' '-LOpenCL' '-o' 'cl_convolution' '-D' 'ARM_COMPUTE_CL' '-shared-libgcc' '-march=armv7-a' '-mfloat-abi=hard' '-mfpu=vfpv3-d16' '-mthumb' '-mtls-dialect=gnu'
 as -v -I . -I include -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -meabi=5 -o /tmp/ccld62Yl.o /tmp/cci1PXds.s
GNU assembler version 2.26.1 (arm-linux-gnueabihf) using BFD version (GNU Binutils for Ubuntu) 2.26.1
COLLECT_GCC_OPTIONS='-v' '-I' '.' '-I' 'include' '-std=c++11' '-Llibarm_compute' '-Larm_compute_core' '-LOpenCL' '-o' 'cl_convolution' '-D' 'ARM_COMPUTE_CL' '-shared-libgcc' '-march=armv7-a' '-mfloat-abi=hard' '-mfpu=vfpv3-d16' '-mthumb' '-mtls-dialect=gnu'
 /usr/lib/gcc/arm-linux-gnueabihf/5/cc1plus -quiet -v -I . -I include -imultiarch arm-linux-gnueabihf -D_GNU_SOURCE -D ARM_COMPUTE_CL utils/Utils.cpp -quiet -dumpbase Utils.cpp -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb -mtls-dialect=gnu -auxbase Utils -std=c++11 -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/cci1PXds.s
GNU C++11 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) version 5.4.0 20160609 (arm-linux-gnueabihf)
	compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "/usr/include/arm-linux-gnueabihf/c++/5"
ignoring nonexistent directory "/usr/local/include/arm-linux-gnueabihf"
ignoring nonexistent directory "/usr/lib/gcc/arm-linux-gnueabihf/5/../../../../arm-linux-gnueabihf/include"
#include "..." search starts here:
#include <...> search starts here:
 .
 include
 /usr/include/c++/5
 /usr/include/arm-linux-gnueabihf/c++/5
 /usr/include/c++/5/backward
 /usr/lib/gcc/arm-linux-gnueabihf/5/include
 /usr/local/include
 /usr/lib/gcc/arm-linux-gnueabihf/5/include-fixed
 /usr/include/arm-linux-gnueabihf
 /usr/include
End of search list.
GNU C++11 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) version 5.4.0 20160609 (arm-linux-gnueabihf)
	compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 12831138f3a67787c6ffebe33a0c39c6
COLLECT_GCC_OPTIONS='-v' '-I' '.' '-I' 'include' '-std=c++11' '-Llibarm_compute' '-Larm_compute_core' '-LOpenCL' '-o' 'cl_convolution' '-D' 'ARM_COMPUTE_CL' '-shared-libgcc' '-march=armv7-a' '-mfloat-abi=hard' '-mfpu=vfpv3-d16' '-mthumb' '-mtls-dialect=gnu'
 as -v -I . -I include -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -meabi=5 -o /tmp/ccRJh6NL.o /tmp/cci1PXds.s
GNU assembler version 2.26.1 (arm-linux-gnueabihf) using BFD version (GNU Binutils for Ubuntu) 2.26.1
COMPILER_PATH=/usr/lib/gcc/arm-linux-gnueabihf/5/:/usr/lib/gcc/arm-linux-gnueabihf/5/:/usr/lib/gcc/arm-linux-gnueabihf/:/usr/lib/gcc/arm-linux-gnueabihf/5/:/usr/lib/gcc/arm-linux-gnueabihf/
LIBRARY_PATH=/usr/lib/gcc/arm-linux-gnueabihf/5/:/usr/lib/gcc/arm-linux-gnueabihf/5/../../../arm-linux-gnueabihf/:/usr/lib/gcc/arm-linux-gnueabihf/5/../../../../lib/:/lib/arm-linux-gnueabihf/:/lib/../lib/:/usr/lib/arm-linux-gnueabihf/:/usr/lib/../lib/:/usr/lib/gcc/arm-linux-gnueabihf/5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-I' '.' '-I' 'include' '-std=c++11' '-Llibarm_compute' '-Larm_compute_core' '-LOpenCL' '-o' 'cl_convolution' '-D' 'ARM_COMPUTE_CL' '-shared-libgcc' '-march=armv7-a' '-mfloat-abi=hard' '-mfpu=vfpv3-d16' '-mthumb' '-mtls-dialect=gnu'
 /usr/lib/gcc/arm-linux-gnueabihf/5/collect2 -plugin /usr/lib/gcc/arm-linux-gnueabihf/5/liblto_plugin.so -plugin-opt=/usr/lib/gcc/arm-linux-gnueabihf/5/lto-wrapper -plugin-opt=-fresolution=/tmp/ccYDiY0Q.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/ --build-id --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X --hash-style=gnu --as-needed -m armelf_linux_eabi -z relro -o cl_convolution /usr/lib/gcc/arm-linux-gnueabihf/5/../../../arm-linux-gnueabihf/crt1.o /usr/lib/gcc/arm-linux-gnueabihf/5/../../../arm-linux-gnueabihf/crti.o /usr/lib/gcc/arm-linux-gnueabihf/5/crtbegin.o -Llibarm_compute -Larm_compute_core -LOpenCL -L/usr/lib/gcc/arm-linux-gnueabihf/5 -L/usr/lib/gcc/arm-linux-gnueabihf/5/../../../arm-linux-gnueabihf -L/usr/lib/gcc/arm-linux-gnueabihf/5/../../../../lib -L/lib/arm-linux-gnueabihf -L/lib/../lib -L/usr/lib/arm-linux-gnueabihf -L/usr/lib/../lib -L/usr/lib/gcc/arm-linux-gnueabihf/5/../../.. /tmp/ccld62Yl.o /tmp/ccRJh6NL.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/arm-linux-gnueabihf/5/crtend.o /usr/lib/gcc/arm-linux-gnueabihf/5/../../../arm-linux-gnueabihf/crtn.o
/tmp/ccld62Yl.o: In function `main_cl_convolution(int, char const**)':
cl_convolution.cpp:(.text+0x22e): undefined reference to `arm_compute::CLTensor::CLTensor()'
cl_convolution.cpp:(.text+0x238): undefined reference to `arm_compute::CLTensor::CLTensor()'
cl_convolution.cpp:(.text+0x242): undefined reference to `arm_compute::CLTensor::CLTensor()'
cl_convolution.cpp:(.text+0x246): undefined reference to `arm_compute::CLScheduler::get()'
cl_convolution.cpp:(.text+0x272): undefined reference to `clGetDeviceInfo'
cl_convolution.cpp:(.text+0x2d2): undefined reference to `clGetDeviceInfo'
cl_convolution.cpp:(.text+0x356): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text+0x36a): undefined reference to `arm_compute::TensorInfo::TensorInfo(unsigned int, unsigned int, arm_compute::Format)'
cl_convolution.cpp:(.text+0x376): undefined reference to `arm_compute::ITensorAllocator::init(arm_compute::TensorInfo const&)'
cl_convolution.cpp:(.text+0x3e2): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text+0x3ee): undefined reference to `arm_compute::CLTensor::info()'
cl_convolution.cpp:(.text+0x3f8): undefined reference to `arm_compute::ITensorAllocator::init(arm_compute::TensorInfo const&)'
cl_convolution.cpp:(.text+0x402): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text+0x40e): undefined reference to `arm_compute::CLTensor::info()'
cl_convolution.cpp:(.text+0x418): undefined reference to `arm_compute::ITensorAllocator::init(arm_compute::TensorInfo const&)'
cl_convolution.cpp:(.text+0x43e): undefined reference to `arm_compute::CLConvolutionSquare<5u>::CLConvolutionSquare(std::shared_ptr<arm_compute::IMemoryManager>)'
cl_convolution.cpp:(.text+0x46c): undefined reference to `arm_compute::CLConvolution3x3::configure(arm_compute::ICLTensor*, arm_compute::ICLTensor*, short const*, unsigned int, arm_compute::BorderMode, unsigned char)'
cl_convolution.cpp:(.text+0x490): undefined reference to `arm_compute::CLConvolutionSquare<5u>::configure(arm_compute::ICLTensor*, arm_compute::ICLTensor*, short const*, unsigned int, arm_compute::BorderMode, unsigned char)'
cl_convolution.cpp:(.text+0x49a): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text+0x4b0): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text+0x4c6): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text+0x4fc): undefined reference to `arm_compute::ICLSimpleFunction::run()'
cl_convolution.cpp:(.text+0x506): undefined reference to `arm_compute::CLConvolutionSquare<5u>::run()'
cl_convolution.cpp:(.text+0x50a): undefined reference to `arm_compute::CLScheduler::get()'
/tmp/ccld62Yl.o: In function `cl::detail::ReferenceHandler<_cl_context*>::retain(_cl_context*)':
cl_convolution.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP11_cl_contextE6retainES3_[_ZN2cl6detail16ReferenceHandlerIP11_cl_contextE6retainES3_]+0xa): undefined reference to `clRetainContext'
/tmp/ccld62Yl.o: In function `cl::detail::ReferenceHandler<_cl_context*>::release(_cl_context*)':
cl_convolution.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP11_cl_contextE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP11_cl_contextE7releaseES3_]+0xa): undefined reference to `clReleaseContext'
/tmp/ccld62Yl.o: In function `cl::detail::ReferenceHandler<_cl_command_queue*>::retain(_cl_command_queue*)':
cl_convolution.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP17_cl_command_queueE6retainES3_[_ZN2cl6detail16ReferenceHandlerIP17_cl_command_queueE6retainES3_]+0xa): undefined reference to `clRetainCommandQueue'
/tmp/ccld62Yl.o: In function `cl::detail::ReferenceHandler<_cl_command_queue*>::release(_cl_command_queue*)':
cl_convolution.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP17_cl_command_queueE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP17_cl_command_queueE7releaseES3_]+0xa): undefined reference to `clReleaseCommandQueue'
/tmp/ccld62Yl.o: In function `cl::detail::ReferenceHandler<_cl_kernel*>::release(_cl_kernel*)':
cl_convolution.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP10_cl_kernelE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP10_cl_kernelE7releaseES3_]+0xa): undefined reference to `clReleaseKernel'
/tmp/ccld62Yl.o: In function `cl::Platform::makeDefault()':
cl_convolution.cpp:(.text._ZN2cl8Platform11makeDefaultEv[_ZN2cl8Platform11makeDefaultEv]+0x1e): undefined reference to `clGetPlatformIDs'
cl_convolution.cpp:(.text._ZN2cl8Platform11makeDefaultEv[_ZN2cl8Platform11makeDefaultEv]+0x84): undefined reference to `clGetPlatformIDs'
/tmp/ccld62Yl.o: In function `cl::Platform::getDevices(unsigned long long, std::vector<cl::Device, std::allocator<cl::Device> >*) const':
cl_convolution.cpp:(.text._ZNK2cl8Platform10getDevicesEyPSt6vectorINS_6DeviceESaIS2_EE[_ZNK2cl8Platform10getDevicesEyPSt6vectorINS_6DeviceESaIS2_EE]+0x52): undefined reference to `clGetDeviceIDs'
cl_convolution.cpp:(.text._ZNK2cl8Platform10getDevicesEyPSt6vectorINS_6DeviceESaIS2_EE[_ZNK2cl8Platform10getDevicesEyPSt6vectorINS_6DeviceESaIS2_EE]+0xb8): undefined reference to `clGetDeviceIDs'
/tmp/ccld62Yl.o: In function `cl::Platform::get(std::vector<cl::Platform, std::allocator<cl::Platform> >*)':
cl_convolution.cpp:(.text._ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE[_ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE]+0x3c): undefined reference to `clGetPlatformIDs'
cl_convolution.cpp:(.text._ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE[_ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE]+0x96): undefined reference to `clGetPlatformIDs'
/tmp/ccld62Yl.o: In function `cl::Context::Context(unsigned long long, int*, void (*)(char const*, void const*, unsigned int, void*), void*, int*)':
cl_convolution.cpp:(.text._ZN2cl7ContextC2EyPiPFvPKcPKvjPvES6_S1_[_ZN2cl7ContextC5EyPiPFvPKcPKvjPvES6_S1_]+0x1b0): undefined reference to `clCreateContextFromType'
/tmp/ccld62Yl.o: In function `cl::CommandQueue::CommandQueue(cl::Context const&, cl::Device const&, unsigned long long, int*)':
cl_convolution.cpp:(.text._ZN2cl12CommandQueueC2ERKNS_7ContextERKNS_6DeviceEyPi[_ZN2cl12CommandQueueC5ERKNS_7ContextERKNS_6DeviceEyPi]+0x48): undefined reference to `clCreateCommandQueue'
/tmp/ccld62Yl.o: In function `cl::CommandQueue::finish() const':
cl_convolution.cpp:(.text._ZNK2cl12CommandQueue6finishEv[_ZNK2cl12CommandQueue6finishEv]+0xe): undefined reference to `clFinish'
/tmp/ccld62Yl.o: In function `arm_compute::data_size_from_type(arm_compute::DataType)':
cl_convolution.cpp:(.text._ZN11arm_compute19data_size_from_typeENS_8DataTypeE[_ZN11arm_compute19data_size_from_typeENS_8DataTypeE]+0x86): undefined reference to `arm_compute::error(char const*, char const*, int, char const*, ...)'
/tmp/ccld62Yl.o: In function `arm_compute::CLScheduler::default_init(arm_compute::ICLTuner*)':
cl_convolution.cpp:(.text._ZN11arm_compute11CLScheduler12default_initEPNS_8ICLTunerE[_ZN11arm_compute11CLScheduler12default_initEPNS_8ICLTunerE]+0x16): undefined reference to `arm_compute::CLKernelLibrary::get()'
/tmp/ccld62Yl.o: In function `arm_compute::CLScheduler::init(cl::Context, cl::CommandQueue, cl::Device, arm_compute::ICLTuner*)':
cl_convolution.cpp:(.text._ZN11arm_compute11CLScheduler4initEN2cl7ContextENS1_12CommandQueueENS1_6DeviceEPNS_8ICLTunerE[_ZN11arm_compute11CLScheduler4initEN2cl7ContextENS1_12CommandQueueENS1_6DeviceEPNS_8ICLTunerE]+0x36): undefined reference to `arm_compute::get_target_from_device(cl::Device&)'
/tmp/ccld62Yl.o: In function `arm_compute::utils::map(arm_compute::CLTensor&, bool)':
cl_convolution.cpp:(.text._ZN11arm_compute5utils3mapERNS_8CLTensorEb[_ZN11arm_compute5utils3mapERNS_8CLTensorEb]+0x12): undefined reference to `arm_compute::CLTensor::map(bool)'
/tmp/ccld62Yl.o: In function `arm_compute::utils::unmap(arm_compute::CLTensor&)':
cl_convolution.cpp:(.text._ZN11arm_compute5utils5unmapERNS_8CLTensorE[_ZN11arm_compute5utils5unmapERNS_8CLTensorE]+0xa): undefined reference to `arm_compute::CLTensor::unmap()'
/tmp/ccld62Yl.o: In function `arm_compute::utils::PPMLoader::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
cl_convolution.cpp:(.text._ZN11arm_compute5utils9PPMLoader4openERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN11arm_compute5utils9PPMLoader4openERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0xce): undefined reference to `arm_compute::error(char const*, char const*, int, char const*, ...)'
/tmp/ccld62Yl.o: In function `arm_compute::ICLSimpleFunction::~ICLSimpleFunction()':
cl_convolution.cpp:(.text._ZN11arm_compute17ICLSimpleFunctionD2Ev[_ZN11arm_compute17ICLSimpleFunctionD5Ev]+0x40): undefined reference to `vtable for arm_compute::ICLSimpleFunction'
/tmp/ccld62Yl.o: In function `arm_compute::CLConvolution3x3::CLConvolution3x3()':
cl_convolution.cpp:(.text._ZN11arm_compute16CLConvolution3x3C2Ev[_ZN11arm_compute16CLConvolution3x3C5Ev]+0xc): undefined reference to `arm_compute::ICLSimpleFunction::ICLSimpleFunction()'
/tmp/ccld62Yl.o: In function `int cl::Context::getInfo<std::vector<cl::Device, std::allocator<cl::Device> > >(unsigned int, std::vector<cl::Device, std::allocator<cl::Device> >*) const':
cl_convolution.cpp:(.text._ZNK2cl7Context7getInfoISt6vectorINS_6DeviceESaIS3_EEEEijPT_[_ZNK2cl7Context7getInfoISt6vectorINS_6DeviceESaIS3_EEEEijPT_]+0x12): undefined reference to `clGetContextInfo'
cl_convolution.cpp:(.text._ZNK2cl7Context7getInfoISt6vectorINS_6DeviceESaIS3_EEEEijPT_[_ZNK2cl7Context7getInfoISt6vectorINS_6DeviceESaIS3_EEEEijPT_]+0x16): undefined reference to `clGetContextInfo'
/tmp/ccld62Yl.o: In function `void arm_compute::utils::PPMLoader::init_image<arm_compute::CLTensor>(arm_compute::CLTensor&, arm_compute::Format)':
cl_convolution.cpp:(.text._ZN11arm_compute5utils9PPMLoader10init_imageINS_8CLTensorEEEvRT_NS_6FormatE[_ZN11arm_compute5utils9PPMLoader10init_imageINS_8CLTensorEEEvRT_NS_6FormatE]+0x2c): undefined reference to `arm_compute::TensorInfo::TensorInfo(unsigned int, unsigned int, arm_compute::Format)'
cl_convolution.cpp:(.text._ZN11arm_compute5utils9PPMLoader10init_imageINS_8CLTensorEEEvRT_NS_6FormatE[_ZN11arm_compute5utils9PPMLoader10init_imageINS_8CLTensorEEEvRT_NS_6FormatE]+0x32): undefined reference to `arm_compute::CLTensor::allocator()'
cl_convolution.cpp:(.text._ZN11arm_compute5utils9PPMLoader10init_imageINS_8CLTensorEEEvRT_NS_6FormatE[_ZN11arm_compute5utils9PPMLoader10init_imageINS_8CLTensorEEEvRT_NS_6FormatE]+0x40): undefined reference to `arm_compute::ITensorAllocator::init(arm_compute::TensorInfo const&)'
/tmp/ccld62Yl.o: In function `void arm_compute::utils::PPMLoader::fill_image<arm_compute::CLTensor>(arm_compute::CLTensor&)':
cl_convolution.cpp:(.text._ZN11arm_compute5utils9PPMLoader10fill_imageINS_8CLTensorEEEvRT_[_ZN11arm_compute5utils9PPMLoader10fill_imageINS_8CLTensorEEEvRT_]+0x29e): undefined reference to `arm_compute::error(char const*, char const*, int, char const*, ...)'
cl_convolution.cpp:(.text._ZN11arm_compute5utils9PPMLoader10fill_imageINS_8CLTensorEEEvRT_[_ZN11arm_compute5utils9PPMLoader10fill_imageINS_8CLTensorEEEvRT_]+0x2ee): undefined reference to `arm_compute::error(char const*, char const*, int, char const*, ...)'
/tmp/ccld62Yl.o: In function `void arm_compute::utils::save_to_ppm<arm_compute::CLTensor>(arm_compute::CLTensor&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
cl_convolution.cpp:(.text._ZN11arm_compute5utils11save_to_ppmINS_8CLTensorEEEvRT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN11arm_compute5utils11save_to_ppmINS_8CLTensorEEEvRT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x3c6): undefined reference to `arm_compute::error(char const*, char const*, int, char const*, ...)'
cl_convolution.cpp:(.text._ZN11arm_compute5utils11save_to_ppmINS_8CLTensorEEEvRT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN11arm_compute5utils11save_to_ppmINS_8CLTensorEEEvRT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x44a): undefined reference to `arm_compute::error(char const*, char const*, int, char const*, ...)'
/tmp/ccld62Yl.o: In function `arm_compute::IKernel::~IKernel()':
cl_convolution.cpp:(.text._ZN11arm_compute7IKernelD2Ev[_ZN11arm_compute7IKernelD5Ev]+0x24): undefined reference to `vtable for arm_compute::IKernel'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute19CLConvolutionSquareILj5EEE[_ZTVN11arm_compute19CLConvolutionSquareILj5EEE]+0x8): undefined reference to `arm_compute::CLConvolutionSquare<5u>::run()'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute19CLConvolutionKernelILj5EEE[_ZTVN11arm_compute19CLConvolutionKernelILj5EEE]+0x10): undefined reference to `arm_compute::IKernel::is_parallelisable() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute19CLConvolutionKernelILj5EEE[_ZTVN11arm_compute19CLConvolutionKernelILj5EEE]+0x14): undefined reference to `arm_compute::CLConvolutionKernel<5u>::border_size() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute19CLConvolutionKernelILj5EEE[_ZTVN11arm_compute19CLConvolutionKernelILj5EEE]+0x18): undefined reference to `arm_compute::ICLSimple2DKernel::run(arm_compute::Window const&, cl::CommandQueue&)'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE[_ZTVN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE]+0x10): undefined reference to `arm_compute::IKernel::is_parallelisable() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE[_ZTVN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE]+0x14): undefined reference to `arm_compute::CLSeparableConvolutionVertKernel<5u>::border_size() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE[_ZTVN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE]+0x18): undefined reference to `arm_compute::ICLSimple2DKernel::run(arm_compute::Window const&, cl::CommandQueue&)'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE[_ZTVN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE]+0x10): undefined reference to `arm_compute::IKernel::is_parallelisable() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE[_ZTVN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE]+0x14): undefined reference to `arm_compute::CLSeparableConvolutionHorKernel<5u>::border_size() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE[_ZTVN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE]+0x18): undefined reference to `arm_compute::ICLSimple2DKernel::run(arm_compute::Window const&, cl::CommandQueue&)'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute16CLConvolution3x3E[_ZTVN11arm_compute16CLConvolution3x3E]+0x8): undefined reference to `arm_compute::ICLSimpleFunction::run()'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute15ICLSimpleKernelE[_ZTVN11arm_compute15ICLSimpleKernelE]+0x10): undefined reference to `arm_compute::IKernel::is_parallelisable() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute15ICLSimpleKernelE[_ZTVN11arm_compute15ICLSimpleKernelE]+0x14): undefined reference to `arm_compute::IKernel::border_size() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute9ICLKernelE[_ZTVN11arm_compute9ICLKernelE]+0x10): undefined reference to `arm_compute::IKernel::is_parallelisable() const'
/tmp/ccld62Yl.o:(.rodata._ZTVN11arm_compute9ICLKernelE[_ZTVN11arm_compute9ICLKernelE]+0x14): undefined reference to `arm_compute::IKernel::border_size() const'
/tmp/ccld62Yl.o:(.rodata._ZTIN11arm_compute19CLConvolutionKernelILj5EEE[_ZTIN11arm_compute19CLConvolutionKernelILj5EEE]+0x8): undefined reference to `typeinfo for arm_compute::ICLSimple2DKernel'
/tmp/ccld62Yl.o:(.rodata._ZTIN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE[_ZTIN11arm_compute32CLSeparableConvolutionVertKernelILj5EEE]+0x8): undefined reference to `typeinfo for arm_compute::ICLSimple2DKernel'
/tmp/ccld62Yl.o:(.rodata._ZTIN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE[_ZTIN11arm_compute31CLSeparableConvolutionHorKernelILj5EEE]+0x8): undefined reference to `typeinfo for arm_compute::ICLSimple2DKernel'
/tmp/ccld62Yl.o:(.rodata._ZTIN11arm_compute16CLConvolution3x3E[_ZTIN11arm_compute16CLConvolution3x3E]+0x8): undefined reference to `typeinfo for arm_compute::ICLSimpleFunction'
/tmp/ccld62Yl.o:(.rodata._ZTIN11arm_compute9ICLKernelE[_ZTIN11arm_compute9ICLKernelE]+0x8): undefined reference to `typeinfo for arm_compute::IKernel'
/tmp/ccld62Yl.o: In function `arm_compute::ICLTensor::~ICLTensor()':
cl_convolution.cpp:(.text._ZN11arm_compute9ICLTensorD2Ev[_ZN11arm_compute9ICLTensorD5Ev]+0x2c): undefined reference to `vtable for arm_compute::ICLTensor'
/tmp/ccld62Yl.o: In function `arm_compute::CLTensor::~CLTensor()':
cl_convolution.cpp:(.text._ZN11arm_compute8CLTensorD2Ev[_ZN11arm_compute8CLTensorD5Ev]+0x14): undefined reference to `arm_compute::CLTensorAllocator::~CLTensorAllocator()'
cl_convolution.cpp:(.text._ZN11arm_compute8CLTensorD2Ev[_ZN11arm_compute8CLTensorD5Ev]+0x38): undefined reference to `vtable for arm_compute::CLTensor'
/tmp/ccld62Yl.o: In function `arm_compute::TensorInfo::~TensorInfo()':
cl_convolution.cpp:(.text._ZN11arm_compute10TensorInfoD2Ev[_ZN11arm_compute10TensorInfoD5Ev]+0x2c): undefined reference to `vtable for arm_compute::TensorInfo'
/tmp/ccld62Yl.o: In function `arm_compute::CLFillBorderKernel::~CLFillBorderKernel()':
cl_convolution.cpp:(.text._ZN11arm_compute18CLFillBorderKernelD2Ev[_ZN11arm_compute18CLFillBorderKernelD5Ev]+0x2c): undefined reference to `vtable for arm_compute::CLFillBorderKernel'
/tmp/ccld62Yl.o: In function `arm_compute::ICLSimple2DKernel::~ICLSimple2DKernel()':
cl_convolution.cpp:(.text._ZN11arm_compute17ICLSimple2DKernelD2Ev[_ZN11arm_compute17ICLSimple2DKernelD5Ev]+0x2c): undefined reference to `vtable for arm_compute::ICLSimple2DKernel'
collect2: error: ld returned 1 exit status
  • Well, not having had any suggestions after the original post, it looks as though I'm on my own as an attempted early adopter of the Compute Library!!

    I decided to see if I could adapt the Scons process to generate a compilation path for my own code! So I went to scons.org/doc/2.4.1/HTML/scons-user.htm and downloaded the user guide relevant to my installed version of SCons. I found this quite a good intro into the philosophy of how SCons works and why it was recompiling everything when I changed debug settings etc. I then embarked on modifying the SConstruct file in the ComputeLibrary-17.12 directory. I simply searched for the 'examples' BoolVariable and created a new similar one to source a new directory 'MyProg'. There is also an SConscript file in this folder but that doesn't need to be touched!

    BoolVariable("MyProgs", "Build my programs", True),

    Towards the end of the file the 'examples' BoolVariable is used top set up the source and build paths:

    if env['examples'] and env['os'] != 'bare_metal':
    SConscript('./examples/SConscript', variant_dir='#build/%s/examples' % env['build_dir'], duplicate=0)

    I created a new insertion for 'MyProgs'

    if env['MyProgs'] and env['os'] != 'bare_metal':
    SConscript('./MyProgs/SConscript', variant_dir='#build/%s/MyProgs' % env['build_dir'], duplicate=0)

    As I am doing some initial development/investigative work and building natively, I also changed some of the default values in the Sconstruct to reflect the build I would be using for some time yet!

    A further step is needed! In the examples directory along with the source code there is a further Sconscript file which is called by the upper level files, I copied this into the MyProgs folder. I then edited that new file and changed all instances of 'examples' to 'MyProgs'.

    Bingo! I can now compile files in my own compilation folder without recompiling the examples everytime I change one of the compilation directives.

    Ill try attaching (fingers crossed!) the before "OriginalSConstruct" and after "SConstruct" if anyone wants to compare my changes between the files.

    ORIGINAL

    import SCons
    import os
    import subprocess
    
    def version_at_least(version, required):
        end = min(len(version), len(required))
    
        for i in range(0, end, 2):
            if int(version[i]) < int(required[i]):
                return False
            elif int(version[i]) > int(required[i]):
                return True
    
        return True
    
    vars = Variables("scons")
    vars.AddVariables(
        BoolVariable("debug", "Debug", False),
        BoolVariable("asserts", "Enable asserts (this flag is forced to 1 for debug=1)", False),
        BoolVariable("logging", "Logging (this flag is forced to 1 for debug=1)", False),
        EnumVariable("arch", "Target Architecture", "armv7a", allowed_values=("armv7a", "arm64-v8a", "arm64-v8.2-a", "x86_32", "x86_64")),
        EnumVariable("os", "Target OS", "linux", allowed_values=("linux", "android", "bare_metal")),
        EnumVariable("build", "Build type", "cross_compile", allowed_values=("native", "cross_compile")),
        BoolVariable("examples", "Build example programs", True),
        BoolVariable("Werror", "Enable/disable the -Werror compilation flag", True),
        BoolVariable("standalone", "Builds the tests as standalone executables, links statically with libgcc, libstdc++ and libarm_compute", False),
        BoolVariable("opencl", "Enable OpenCL support", True),
        BoolVariable("neon", "Enable Neon support", False),
        BoolVariable("gles_compute", "Enable OpenGL ES Compute Shader support", False),
        BoolVariable("embed_kernels", "Embed OpenCL kernels and OpenGL ES compute shaders in library binary", False),
        BoolVariable("set_soname", "Set the library's soname and shlibversion (requires SCons 2.4 or above)", False),
        BoolVariable("openmp", "Enable OpenMP backend", False),
        BoolVariable("cppthreads", "Enable C++11 threads backend", True),
        PathVariable("build_dir", "Specify sub-folder for the build", ".", PathVariable.PathAccept),
        ("extra_cxx_flags", "Extra CXX flags to be appended to the build command", "")
    )
    
    env = Environment(platform="posix", variables=vars, ENV = os.environ)
    env.Append(LIBPATH = ["#build/%s" % env['build_dir']])
    
    SConsignFile('build/.%s' % env['build_dir'])
    
    Help(vars.GenerateHelpText(env))
    
    if env['neon'] and 'x86' in env['arch']:
        print "Cannot compile NEON for x86"
        Exit(1)
    
    if env['set_soname'] and not version_at_least(SCons.__version__, "2.4"):
        print "Setting the library's SONAME / SHLIBVERSION requires SCons 2.4 or above"
        print "Update your version of SCons or use set_soname=0"
        Exit(1)
    
    if env['os'] == 'bare_metal':
        if env['cppthreads'] or env['openmp']:
             print("ERROR: OpenMP and C++11 threads not supported in bare_metal. Use cppthreads=0 openmp=0")
             Exit(1)
    
    env.Append(CXXFLAGS = ['-Wno-deprecated-declarations','-Wall','-DARCH_ARM',
             '-Wextra','-Wno-unused-parameter','-pedantic','-Wdisabled-optimization','-Wformat=2',
             '-Winit-self','-Wstrict-overflow=2','-Wswitch-default',
             '-fpermissive','-std=gnu++11','-Wno-vla','-Woverloaded-virtual',
             '-Wctor-dtor-privacy','-Wsign-promo','-Weffc++','-Wno-format-nonliteral','-Wno-overlength-strings','-Wno-strict-overflow'])
    
    env.Append(CPPDEFINES = ['_GLIBCXX_USE_NANOSLEEP'])
    
    if os.environ.get('CXX', 'g++') == 'clang++':
        env.Append(CXXFLAGS = ['-Wno-format-nonliteral','-Wno-deprecated-increment-bool','-Wno-vla-extension','-Wno-mismatched-tags'])
    else:
        env.Append(CXXFLAGS = ['-Wlogical-op','-Wnoexcept','-Wstrict-null-sentinel'])
    
    if env['cppthreads']:
        env.Append(CPPDEFINES = [('ARM_COMPUTE_CPP_SCHEDULER', 1)])
    
    if env['openmp']:
        if os.environ.get('CXX', 'g++') == 'clang++':
            print "Clang does not support OpenMP. Use scheduler=cpp."
            Exit(1)
    
        env.Append(CPPDEFINES = [('ARM_COMPUTE_OPENMP_SCHEDULER', 1)])
        env.Append(CXXFLAGS = ['-fopenmp'])
        env.Append(LINKFLAGS = ['-fopenmp'])
    
    prefix = ""
    if env['arch'] == 'armv7a':
        env.Append(CXXFLAGS = ['-march=armv7-a', '-mthumb', '-mfpu=neon'])
    
        if env['os'] == 'linux':
            prefix = "arm-linux-gnueabihf-"
            env.Append(CXXFLAGS = ['-mfloat-abi=hard'])
        elif env['os'] == 'bare_metal':
            prefix = "arm-eabi-"
            env.Append(CXXFLAGS = ['-mfloat-abi=hard'])
        elif env['os'] == 'android':
            prefix = "arm-linux-androideabi-"
            env.Append(CXXFLAGS = ['-mfloat-abi=softfp'])
    elif env['arch'] == 'arm64-v8a':
        env.Append(CXXFLAGS = ['-march=armv8-a'])
        env.Append(CPPDEFINES = ['ARM_COMPUTE_AARCH64_V8A'])
        if env['os'] == 'linux':
            prefix = "aarch64-linux-gnu-"
        elif env['os'] == 'bare_metal':
            prefix = "aarch64-elf-"
        elif env['os'] == 'android':
            prefix = "aarch64-linux-android-"
    elif env['arch'] == 'arm64-v8.2-a':
        env.Append(CPPDEFINES = ['ARM_COMPUTE_AARCH64_V8_2'])
    
        if os.environ.get('CXX', 'g++') == 'clang++':
            env.Append(CXXFLAGS = ['-fno-integrated-as'])
    
        if env['os'] == 'linux':
            prefix = "aarch64-linux-gnu-"
        elif env['os'] == 'bare_metal':
            prefix = "aarch64-elf-"
        elif env['os'] == 'android':
            prefix = "aarch64-linux-android-"
    elif env['arch'] == 'x86_32':
        env.Append(CCFLAGS = ['-m32'])
        env.Append(LINKFLAGS = ['-m32'])
    elif env['arch'] == 'x86_64':
        env.Append(CCFLAGS = ['-m64'])
        env.Append(LINKFLAGS = ['-m64'])
    
    if env['build'] == 'native':
        prefix = ""
    
    env['CC'] = prefix + os.environ.get('CC', 'gcc')
    env['CXX'] = prefix + os.environ.get('CXX', 'g++')
    env['LD'] = prefix + "ld"
    env['AS'] = prefix + "as"
    env['AR'] = prefix + "ar"
    env['RANLIB'] = prefix + "ranlib"
    
    if not GetOption("help"):
        try:
            compiler_ver = subprocess.check_output(env['CXX'].split() + ["-dumpversion"]).strip()
        except OSError:
            print("ERROR: Compiler '%s' not found" % env['CXX'])
            Exit(1)
    
        if os.environ.get('CXX','g++') == 'g++':
            if env['arch'] == 'arm64-v8.2-a' and not version_at_least(compiler_ver, '6.2.1'):
                print "GCC 6.2.1 or newer is required to compile armv8.2-a code"
                Exit(1)
            elif env['arch'] == 'arm64-v8a' and not version_at_least(compiler_ver, '4.9'):
                print "GCC 4.9 or newer is required to compile NEON code for AArch64"
                Exit(1)
    
            if version_at_least(compiler_ver, '6.1'):
                env.Append(CXXFLAGS = ['-Wno-ignored-attributes'])
    
            if compiler_ver == '4.8.3':
                env.Append(CXXFLAGS = ['-Wno-array-bounds'])
    
    if env['standalone']:
        env.Append(CXXFLAGS = ['-fPIC'])
        env.Append(LINKFLAGS = ['-static-libgcc','-static-libstdc++'])
        if env['cppthreads']:
            env.Append(LINKFLAGS = ['-lpthread'])
    
    if env['Werror']:
        env.Append(CXXFLAGS = ['-Werror'])
    
    if env['os'] == 'android':
        env.Append(CPPDEFINES = ['ANDROID'])
        env.Append(LINKFLAGS = ['-pie', '-static-libstdc++'])
    elif env['os'] == 'bare_metal':
        env.Append(LINKFLAGS = ['-static'])
        env.Append(LINKFLAGS = ['-specs=rdimon.specs'])
        env.Append(CXXFLAGS = ['-fPIC'])
        env.Append(CPPDEFINES = ['NO_MULTI_THREADING'])
        env.Append(CPPDEFINES = ['BARE_METAL'])
    
    if env['opencl']:
        if env['os'] in ['bare_metal'] or env['standalone']:
            print("Cannot link OpenCL statically, which is required on bare metal")
            Exit(1)
    
    if env['opencl'] or env['gles_compute']:
        if env['embed_kernels']:
            env.Append(CPPDEFINES = ['EMBEDDED_KERNELS'])
    
    if env['debug']:
        env['asserts'] = True
        env['logging'] = True
        env.Append(CXXFLAGS = ['-O0','-g','-gdwarf-2'])
        env.Append(CPPDEFINES = ['ARM_COMPUTE_DEBUG_ENABLED'])
    else:
        env.Append(CXXFLAGS = ['-O3','-ftree-vectorize'])
    
    if env['asserts']:
        env.Append(CPPDEFINES = ['ARM_COMPUTE_ASSERTS_ENABLED'])
        env.Append(CXXFLAGS = ['-fstack-protector-strong'])
    
    if env['logging']:
        env.Append(CPPDEFINES = ['ARM_COMPUTE_LOGGING_ENABLED'])
    
    env.Append(CPPPATH = ['#/include', "#"])
    env.Append(CXXFLAGS = env['extra_cxx_flags'])
    
    Export('vars')
    Export('env')
    Export('version_at_least')
    
    if env['opencl']:
        SConscript("./opencl-1.2-stubs/SConscript", variant_dir="build/%s/opencl-1.2-stubs" % env['build_dir'], duplicate=0)
    
    if env['gles_compute'] and env['os'] != 'android':
        env.Append(CPPPATH = ['#/include/linux'])
        env.Append(LIBPATH = ["#build/%s/opengles-3.1-stubs" % env['build_dir']])
        SConscript("./opengles-3.1-stubs/SConscript", variant_dir="build/%s/opengles-3.1-stubs" % env['build_dir'], duplicate=0)
    
    SConscript('./SConscript', variant_dir='#build/%s' % env['build_dir'], duplicate=0)
    
    if env['examples'] and env['os'] != 'bare_metal':
        SConscript('./examples/SConscript', variant_dir='#build/%s/examples' % env['build_dir'], duplicate=0)
    
    if env['os'] != 'bare_metal':
        SConscript('./tests/SConscript', variant_dir='#build/%s/tests' % env['build_dir'], duplicate=0)

    MODIFIED

    import SCons
    import os
    import subprocess
    
    def version_at_least(version, required):
        end = min(len(version), len(required))
    
        for i in range(0, end, 2):
            if int(version[i]) < int(required[i]):
                return False
            elif int(version[i]) > int(required[i]):
                return True
    
        return True
    
    vars = Variables("scons")
    vars.AddVariables(
        BoolVariable("debug", "Debug", True),
        BoolVariable("asserts", "Enable asserts (this flag is forced to 1 for debug=1)", False),
        BoolVariable("logging", "Logging (this flag is forced to 1 for debug=1)", False),
        EnumVariable("arch", "Target Architecture", "armv7a", allowed_values=("armv7a", "arm64-v8a", "arm64-v8.2-a", "x86_32", "x86_64")),
        EnumVariable("os", "Target OS", "linux", allowed_values=("linux", "android", "bare_metal")),
        EnumVariable("build", "Build type", "native", allowed_values=("native", "cross_compile")),
        BoolVariable("examples", "Build example programs", False),
        BoolVariable("MyProgs", "Build my programs", True),
        BoolVariable("Werror", "Enable/disable the -Werror compilation flag", True),
        BoolVariable("standalone", "Builds the tests as standalone executables, links statically with libgcc, libstdc++ and libarm_compute", False),
        BoolVariable("opencl", "Enable OpenCL support", True),
        BoolVariable("neon", "Enable Neon support", True),
        BoolVariable("gles_compute", "Enable OpenGL ES Compute Shader support", False),
        BoolVariable("embed_kernels", "Embed OpenCL kernels and OpenGL ES compute shaders in library binary", True),
        BoolVariable("set_soname", "Set the library's soname and shlibversion (requires SCons 2.4 or above)", False),
        BoolVariable("openmp", "Enable OpenMP backend", False),
        BoolVariable("cppthreads", "Enable C++11 threads backend", True),
        PathVariable("build_dir", "Specify sub-folder for the build", ".", PathVariable.PathAccept),
        ("extra_cxx_flags", "Extra CXX flags to be appended to the build command", "")
    )  # end of vars.AddVariables
    
    env = Environment(platform="posix", variables=vars, ENV = os.environ)
    env.Append(LIBPATH = ["#build/%s" % env['build_dir']])
    
    SConsignFile('build/.%s' % env['build_dir'])
    
    Help(vars.GenerateHelpText(env))
    
    if env['neon'] and 'x86' in env['arch']:
        print "Cannot compile NEON for x86"
        Exit(1)
    
    if env['set_soname'] and not version_at_least(SCons.__version__, "2.4"):
        print "Setting the library's SONAME / SHLIBVERSION requires SCons 2.4 or above"
        print "Update your version of SCons or use set_soname=0"
        Exit(1)
    
    if env['os'] == 'bare_metal':
        if env['cppthreads'] or env['openmp']:
             print("ERROR: OpenMP and C++11 threads not supported in bare_metal. Use cppthreads=0 openmp=0")
             Exit(1)
    
    env.Append(CXXFLAGS = ['-Wno-deprecated-declarations','-Wall','-DARCH_ARM',
             '-Wextra','-Wno-unused-parameter','-pedantic','-Wdisabled-optimization','-Wformat=2',
             '-Winit-self','-Wstrict-overflow=2','-Wswitch-default',
             '-fpermissive','-std=gnu++11','-Wno-vla','-Woverloaded-virtual',
             '-Wctor-dtor-privacy','-Wsign-promo','-Weffc++','-Wno-format-nonliteral','-Wno-overlength-strings','-Wno-strict-overflow'])
    
    env.Append(CPPDEFINES = ['_GLIBCXX_USE_NANOSLEEP'])
    
    if os.environ.get('CXX', 'g++') == 'clang++':
        env.Append(CXXFLAGS = ['-Wno-format-nonliteral','-Wno-deprecated-increment-bool','-Wno-vla-extension','-Wno-mismatched-tags'])
    else:
        env.Append(CXXFLAGS = ['-Wlogical-op','-Wnoexcept','-Wstrict-null-sentinel'])
    
    if env['cppthreads']:
        env.Append(CPPDEFINES = [('ARM_COMPUTE_CPP_SCHEDULER', 1)])
    
    if env['openmp']:
        if os.environ.get('CXX', 'g++') == 'clang++':
            print "Clang does not support OpenMP. Use scheduler=cpp."
            Exit(1)
    
        env.Append(CPPDEFINES = [('ARM_COMPUTE_OPENMP_SCHEDULER', 1)])
        env.Append(CXXFLAGS = ['-fopenmp'])
        env.Append(LINKFLAGS = ['-fopenmp'])
    
    prefix = ""
    if env['arch'] == 'armv7a':
        env.Append(CXXFLAGS = ['-march=armv7-a', '-mthumb', '-mfpu=neon'])
    
        if env['os'] == 'linux':
            prefix = "arm-linux-gnueabihf-"
            env.Append(CXXFLAGS = ['-mfloat-abi=hard'])
        elif env['os'] == 'bare_metal':
            prefix = "arm-eabi-"
            env.Append(CXXFLAGS = ['-mfloat-abi=hard'])
        elif env['os'] == 'android':
            prefix = "arm-linux-androideabi-"
            env.Append(CXXFLAGS = ['-mfloat-abi=softfp'])
    elif env['arch'] == 'arm64-v8a':
        env.Append(CXXFLAGS = ['-march=armv8-a'])
        env.Append(CPPDEFINES = ['ARM_COMPUTE_AARCH64_V8A'])
        if env['os'] == 'linux':
            prefix = "aarch64-linux-gnu-"
        elif env['os'] == 'bare_metal':
            prefix = "aarch64-elf-"
        elif env['os'] == 'android':
            prefix = "aarch64-linux-android-"
    elif env['arch'] == 'arm64-v8.2-a':
        env.Append(CPPDEFINES = ['ARM_COMPUTE_AARCH64_V8_2'])
    
        if os.environ.get('CXX', 'g++') == 'clang++':
            env.Append(CXXFLAGS = ['-fno-integrated-as'])
    
        if env['os'] == 'linux':
            prefix = "aarch64-linux-gnu-"
        elif env['os'] == 'bare_metal':
            prefix = "aarch64-elf-"
        elif env['os'] == 'android':
            prefix = "aarch64-linux-android-"
    elif env['arch'] == 'x86_32':
        env.Append(CCFLAGS = ['-m32'])
        env.Append(LINKFLAGS = ['-m32'])
    elif env['arch'] == 'x86_64':
        env.Append(CCFLAGS = ['-m64'])
        env.Append(LINKFLAGS = ['-m64'])
    
    if env['build'] == 'native':
        prefix = ""
    
    env['CC'] = prefix + os.environ.get('CC', 'gcc')
    env['CXX'] = prefix + os.environ.get('CXX', 'g++')
    env['LD'] = prefix + "ld"
    env['AS'] = prefix + "as"
    env['AR'] = prefix + "ar"
    env['RANLIB'] = prefix + "ranlib"
    
    if not GetOption("help"):
        try:
            compiler_ver = subprocess.check_output(env['CXX'].split() + ["-dumpversion"]).strip()
        except OSError:
            print("ERROR: Compiler '%s' not found" % env['CXX'])
            Exit(1)
    
        if os.environ.get('CXX','g++') == 'g++':
            if env['arch'] == 'arm64-v8.2-a' and not version_at_least(compiler_ver, '6.2.1'):
                print "GCC 6.2.1 or newer is required to compile armv8.2-a code"
                Exit(1)
            elif env['arch'] == 'arm64-v8a' and not version_at_least(compiler_ver, '4.9'):
                print "GCC 4.9 or newer is required to compile NEON code for AArch64"
                Exit(1)
    
            if version_at_least(compiler_ver, '6.1'):
                env.Append(CXXFLAGS = ['-Wno-ignored-attributes'])
    
            if compiler_ver == '4.8.3':
                env.Append(CXXFLAGS = ['-Wno-array-bounds'])
    
    if env['standalone']:
        env.Append(CXXFLAGS = ['-fPIC'])
        env.Append(LINKFLAGS = ['-static-libgcc','-static-libstdc++'])
        if env['cppthreads']:
            env.Append(LINKFLAGS = ['-lpthread'])
    
    if env['Werror']:
        env.Append(CXXFLAGS = ['-Werror'])
    
    if env['os'] == 'android':
        env.Append(CPPDEFINES = ['ANDROID'])
        env.Append(LINKFLAGS = ['-pie', '-static-libstdc++'])
    elif env['os'] == 'bare_metal':
        env.Append(LINKFLAGS = ['-static'])
        env.Append(LINKFLAGS = ['-specs=rdimon.specs'])
        env.Append(CXXFLAGS = ['-fPIC'])
        env.Append(CPPDEFINES = ['NO_MULTI_THREADING'])
        env.Append(CPPDEFINES = ['BARE_METAL'])
    
    if env['opencl']:
        if env['os'] in ['bare_metal'] or env['standalone']:
            print("Cannot link OpenCL statically, which is required on bare metal")
            Exit(1)
    
    if env['opencl'] or env['gles_compute']:
        if env['embed_kernels']:
            env.Append(CPPDEFINES = ['EMBEDDED_KERNELS'])
    
    if env['debug']:
        env['asserts'] = True
        env['logging'] = True
        env.Append(CXXFLAGS = ['-O0','-g','-gdwarf-2'])
        env.Append(CPPDEFINES = ['ARM_COMPUTE_DEBUG_ENABLED'])
    else:
        env.Append(CXXFLAGS = ['-O3','-ftree-vectorize'])
    
    if env['asserts']:
        env.Append(CPPDEFINES = ['ARM_COMPUTE_ASSERTS_ENABLED'])
        env.Append(CXXFLAGS = ['-fstack-protector-strong'])
    
    if env['logging']:
        env.Append(CPPDEFINES = ['ARM_COMPUTE_LOGGING_ENABLED'])
    
    env.Append(CPPPATH = ['#/include', "#"])
    env.Append(CXXFLAGS = env['extra_cxx_flags'])
    
    Export('vars')
    Export('env')
    Export('version_at_least')
    
    if env['opencl']:
        SConscript("./opencl-1.2-stubs/SConscript", variant_dir="build/%s/opencl-1.2-stubs" % env['build_dir'], duplicate=0)
    
    if env['gles_compute'] and env['os'] != 'android':
        env.Append(CPPPATH = ['#/include/linux'])
        env.Append(LIBPATH = ["#build/%s/opengles-3.1-stubs" % env['build_dir']])
        SConscript("./opengles-3.1-stubs/SConscript", variant_dir="build/%s/opengles-3.1-stubs" % env['build_dir'], duplicate=0)
    
    SConscript('./SConscript', variant_dir='#build/%s' % env['build_dir'], duplicate=0)
    
    if env['examples'] and env['os'] != 'bare_metal':
        SConscript('./examples/SConscript', variant_dir='#build/%s/examples' % env['build_dir'], duplicate=0)
    
    if env['MyProgs'] and env['os'] != 'bare_metal':
        SConscript('./MyProgs/SConscript', variant_dir='#build/%s/MyProgs' % env['build_dir'], duplicate=0)
    
    if env['os'] != 'bare_metal':
        SConscript('./tests/SConscript', variant_dir='#build/%s/tests' % env['build_dir'], duplicate=0)