Tesseract: [OS X v10.11.6 'El Capitan'] Linkage Issues Under Homebrew

Created on 24 Mar 2017  Â·  39Comments  Â·  Source: tesseract-ocr/tesseract

I'm forking this issue from #739 because the resolution of that issue has _not_ helped me fix Homebrew/homebrew-core#10380. As logged here, my latest build attempt fails as follows:

â‹®
/bin/sh ../libtool  --tag=CXX   --mode=link clang++  -g -O2 -std=c++11 -version-info 3:5 -no-undefined  -L/usr/local/opt/icu4c/lib -o libtesseract.la -rpath /usr/local/Cellar/tesseract/3.05.00/lib  libtesseract_api.la ../ccmain/libtesseract_main.la ../textord/libtesseract_textord.la ../wordrec/libtesseract_wordrec.la ../classify/libtesseract_classify.la ../dict/libtesseract_dict.la ../ccstruct/libtesseract_ccstruct.la ../cutil/libtesseract_cutil.la ../viewer/libtesseract_viewer.la ../ccutil/libtesseract_ccutil.la ../opencl/libtesseract_opencl.la ../cube/libtesseract_cube.la ../neural_networks/runtime/libtesseract_neural.la -llept 
libtool: link: clang++ -dynamiclib  -o .libs/libtesseract.3.dylib   -Wl,-force_load,./.libs/libtesseract_api.a -Wl,-force_load,../ccmain/.libs/libtesseract_main.a -Wl,-force_load,../textord/.libs/libtesseract_textord.a -Wl,-force_load,../wordrec/.libs/libtesseract_wordrec.a -Wl,-force_load,../classify/.libs/libtesseract_classify.a -Wl,-force_load,../dict/.libs/libtesseract_dict.a -Wl,-force_load,../ccstruct/.libs/libtesseract_ccstruct.a -Wl,-force_load,../cutil/.libs/libtesseract_cutil.a -Wl,-force_load,../viewer/.libs/libtesseract_viewer.a -Wl,-force_load,../ccutil/.libs/libtesseract_ccutil.a -Wl,-force_load,../opencl/.libs/libtesseract_opencl.a -Wl,-force_load,../cube/.libs/libtesseract_cube.a -Wl,-force_load,../neural_networks/runtime/.libs/libtesseract_neural.a  -L/usr/local/opt/icu4c/lib -llept  -g -O2   -install_name  /usr/local/Cellar/tesseract/3.05.00/lib/libtesseract.3.dylib -compatibility_version 4 -current_version 4.5 -Wl,-single_module
Undefined symbols for architecture x86_64:
  "_TIFFCleanup", referenced from:
      OpenclDevice::pixReadStreamTiffCl(__sFILE*, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadMemTiffCl(unsigned char const*, unsigned long, int) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFClientOpen", referenced from:
      OpenclDevice::pixReadMemTiffCl(unsigned char const*, unsigned long, int) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFFdOpen", referenced from:
      OpenclDevice::fopenTiffCl(__sFILE*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFGetField", referenced from:
      OpenclDevice::getTiffStreamResolutionCl(tiff*, int*, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadFromTiffStreamCl(tiff*) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFGetFieldDefaulted", referenced from:
      OpenclDevice::getTiffStreamResolutionCl(tiff*, int*, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadFromTiffStreamCl(tiff*) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFReadDirectory", referenced from:
      OpenclDevice::pixReadStreamTiffCl(__sFILE*, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadMemTiffCl(unsigned char const*, unsigned long, int) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFReadRGBAImageOriented", referenced from:
      OpenclDevice::pixReadFromTiffStreamCl(tiff*) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFReadScanline", referenced from:
      OpenclDevice::pixReadFromTiffStreamCl(tiff*) in libtesseract_opencl.a(openclwrapper.o)
  "_TIFFScanlineSize", referenced from:
      OpenclDevice::pixReadFromTiffStreamCl(tiff*) in libtesseract_opencl.a(openclwrapper.o)
  "_clBuildProgram", referenced from:
      OpenclDevice::CompileKernelFile(_GPUEnv*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_clCreateBuffer", referenced from:
      allocateZeroCopyBuffer(_KernelEnv, unsigned int*, unsigned long, unsigned long long, int*) in libtesseract_opencl.a(openclwrapper.o)
      allocateIntBuffer(_KernelEnv, unsigned int const*, unsigned long, int*, bool) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::initMorphCLAllocations(int, int, Pix*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::HistogramRectOCL(unsigned char*, int, int, int, int, int, int, int, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::ThresholdRectToPixOCL(unsigned char*, int, int, int*, int*, Pix**, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixConvertRGBToGrayOCL(Pix*, float, float, float) in libtesseract_opencl.a(openclwrapper.o)
      ...
  "_clCreateCommandQueue", referenced from:
      populateGPUEnvFromDevice(_GPUEnv*, _cl_device_id*) in libtesseract_opencl.a(openclwrapper.o)
  "_clCreateContext", referenced from:
      populateGPUEnvFromDevice(_GPUEnv*, _cl_device_id*) in libtesseract_opencl.a(openclwrapper.o)
  "_clCreateKernel", referenced from:
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL(int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL(int, int, unsigned int, unsigned int) in libtesseract_opencl.a(openclwrapper.o)
      pixORCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      pixANDCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      ...
  "_clCreateProgramWithBinary", referenced from:
      OpenclDevice::CompileKernelFile(_GPUEnv*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_clCreateProgramWithSource", referenced from:
      OpenclDevice::CompileKernelFile(_GPUEnv*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_clEnqueueCopyBuffer", referenced from:
      OpenclDevice::initMorphCLAllocations(int, int, Pix*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixHollowCL(Pix*, Pix*, int, int, int, int, bool) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixGetLinesCL(Pix*, Pix*, Pix**, Pix**, Pix**, bool, int, int, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
  "_clEnqueueMapBuffer", referenced from:
      mapOutputCLBuffer(_KernelEnv, _cl_mem*, Pix*, Pix*, int, unsigned long long, bool, bool) in libtesseract_opencl.a(openclwrapper.o)
      allocateIntBuffer(_KernelEnv, unsigned int const*, unsigned long, int*, bool) in libtesseract_opencl.a(openclwrapper.o)
      copyIntBuffer(_KernelEnv, _cl_mem*, unsigned int const*, unsigned long, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::HistogramRectOCL(unsigned char*, int, int, int, int, int, int, int, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::ThresholdRectToPixOCL(unsigned char*, int, int, int*, int*, Pix**, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixConvertRGBToGrayOCL(Pix*, float, float, float) in libtesseract_opencl.a(openclwrapper.o)
      ...
  "_clEnqueueNDRangeKernel", referenced from:
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL(int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL(int, int, unsigned int, unsigned int) in libtesseract_opencl.a(openclwrapper.o)
      pixORCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      pixANDCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      ...
  "_clEnqueueUnmapMemObject", referenced from:
      mapOutputCLBuffer(_KernelEnv, _cl_mem*, Pix*, Pix*, int, unsigned long long, bool, bool) in libtesseract_opencl.a(openclwrapper.o)
      allocateIntBuffer(_KernelEnv, unsigned int const*, unsigned long, int*, bool) in libtesseract_opencl.a(openclwrapper.o)
      copyIntBuffer(_KernelEnv, _cl_mem*, unsigned int const*, unsigned long, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::HistogramRectOCL(unsigned char*, int, int, int, int, int, int, int, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::ThresholdRectToPixOCL(unsigned char*, int, int, int*, int*, Pix**, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixConvertRGBToGrayOCL(Pix*, float, float, float) in libtesseract_opencl.a(openclwrapper.o)
      ...
  "_clFinish", referenced from:
      mapOutputCLBuffer(_KernelEnv, _cl_mem*, Pix*, Pix*, int, unsigned long long, bool, bool) in libtesseract_opencl.a(openclwrapper.o)
      allocateIntBuffer(_KernelEnv, unsigned int const*, unsigned long, int*, bool) in libtesseract_opencl.a(openclwrapper.o)
      copyIntBuffer(_KernelEnv, _cl_mem*, unsigned int const*, unsigned long, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::HistogramRectOCL(unsigned char*, int, int, int, int, int, int, int, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::ThresholdRectToPixOCL(unsigned char*, int, int, int*, int*, Pix**, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixConvertRGBToGrayOCL(Pix*, float, float, float) in libtesseract_opencl.a(openclwrapper.o)
      ...
  "_clGetContextInfo", referenced from:
      OpenclDevice::CompileKernelFile(_GPUEnv*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_clGetDeviceIDs", referenced from:
      OpenclDevice::getDeviceSelection() in libtesseract_opencl.a(openclwrapper.o)
  "_clGetDeviceInfo", referenced from:
      populateGPUEnvFromDevice(_GPUEnv*, _cl_device_id*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::getDeviceSelection() in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::BinaryGenerated(char const*, __sFILE**) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::GeneratBinFromKernelSource(_cl_program*, char const*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::HistogramRectOCL(unsigned char*, int, int, int, int, int, int, int, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::ThresholdRectToPixOCL(unsigned char*, int, int, int*, int*, Pix**, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
  "_clGetPlatformIDs", referenced from:
      OpenclDevice::getDeviceSelection() in libtesseract_opencl.a(openclwrapper.o)
  "_clGetProgramBuildInfo", referenced from:
      OpenclDevice::CompileKernelFile(_GPUEnv*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_clGetProgramInfo", referenced from:
      OpenclDevice::GeneratBinFromKernelSource(_cl_program*, char const*) in libtesseract_opencl.a(openclwrapper.o)
  "_clReleaseCommandQueue", referenced from:
      OpenclDevice::ReleaseOpenclEnv(_GPUEnv*) in libtesseract_opencl.a(openclwrapper.o)
  "_clReleaseContext", referenced from:
      OpenclDevice::ReleaseOpenclEnv(_GPUEnv*) in libtesseract_opencl.a(openclwrapper.o)
  "_clReleaseMemObject", referenced from:
      OpenclDevice::releaseMorphCLBuffers() in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::HistogramRectOCL(unsigned char*, int, int, int, int, int, int, int, int*) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::ThresholdRectToPixOCL(unsigned char*, int, int, int*, int*, Pix**, int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      OpenclDevice::pixConvertRGBToGrayOCL(Pix*, float, float, float) in libtesseract_opencl.a(openclwrapper.o)
  "_clReleaseProgram", referenced from:
      OpenclDevice::ReleaseOpenclEnv(_GPUEnv*) in libtesseract_opencl.a(openclwrapper.o)
  "_clSetKernelArg", referenced from:
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL(int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL(int, int, unsigned int, unsigned int) in libtesseract_opencl.a(openclwrapper.o)
      pixORCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      pixANDCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [libtesseract.la] Error 1
make: *** [install-recursive] Error 1
â‹®

Both I and those other GitHub users who were helping me with this issue downstream thought it was another instance of the aforementioned #739, but I now think that we were mistaken in believing this given how said issue was resolved. Basically, the crux of the problem is this: is there something that previous committers have neglected to add to Homebrew's Tesseract build formula other than Homebrew/homebrew-core#10596, or is Tesseract at fault here and does solving this require Homebrew to mirror an upstream patch until the next release?

Most helpful comment

I'm not annoyed at all, I just have to do the work that pays the bills first. :)

All 39 comments

First of all: provide details (how you build tesseract, configuration output, libraries version etc.)

Whoops; I should have given that to you in the first place, shouldn't I? Ah, well, here those details are now:

  • I initially built and installed Tesseract from within Homebrew by running brew install -vd --build-from-source tesseract --with-all-languages --with-opencl --with-serial-num-pack --with-training-tools, update it by running brew upgrade -vd --build-from-source tesseract --with-all-languages --with-opencl --with-serial-num-pack --with-training-tools, and retry doing either procedure when they fail by running brew reinstall -vd --build-from-source tesseract --with-all-languages --with-opencl --with-serial-num-pack --with-training-tools. Executing either causes Homebrew to process "$(brew --repository homebrew/homebrew-core)/Formula/tesseract.rb" (a GitHub copy of which is available here,) where "$(brew --repository homebrew/homebrew-core)" is /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core (its default, officially supported location,) according to the brew sub-command given, Homebrew's DSL, and the options I provide using the processing defined in the relevant formula. @JCount confirmed in this comment on my downstream issue that the option causing trouble is --with-opencl, which, as shown on line 94 of the Homebrew Core tap's tesseract.rb formula, corresponds to Tesseract's ./configure's --enable-opencl option.
  • The output I get from ./configure is present in my most recent Homebrew installation attempt logs as both 02.configure and lines 134–339 of reinstall.out.
  • The versions of the build and run-time dependencies required by Tesseract under Homebrew I have installed on my machine are as follows:

    • autoconf v2.69

    • autoconf-archive v2017.03.21

    • automake v1.15

    • GNU libtool v2.4.6, but patched by the Homebrew Core tap to resolve Homebrew/homebrew-core#3056 and Homebrew/homebrew-core#3882. (_Not_ the libtool provided by Apple as part of its command-line tools suite, which I _also_ have installed.)

    • pkg-config v0.29.2

    • Leptonica v1.74.1 (Built with the following dependencies:

    • pkg-config v0.29.2

    • libpng v1.6.29

    • jpeg v8d

    • LibTIFF v4.0.7, but patched by the Homebrew Core tap to resolve Homebrew/homebrew-core#8639 and Homebrew/homebrew-core#9409. — Dependencies are as follows:



      • jpeg v8d


      • xz v5.2.3



    • GIFlib v4.2.3 with a dependency as follows:



      • X11 (supplied by XQuartz v2.7.11)



    • OpenJPEG v2.1.2 with dependencies as follows:



      • CMake v3.7.2 with a dependency as follows:


      • Sphinx v1.5.1


      • Little-CMS2 v2.8 with dependencies as follows:


      • jpeg v8d


      • LibTIFF v4.0.7 as described above for Leptonica itself


      • LibTIFF v4.0.7 as described above for Leptonica itself


      • libpng v1.6.29



    • WebP v0.6.0 with dependencies as follows:



      • libpng v1.6.29


      • jpeg v8d


      • LibTIFF v4.0.7 as described above for Leptonica itself


      • GIFlib v4.2.3 with a dependency as described earlier.)



Is that everything you need, or do I need to provide anything else?

I am not familiar with building on Mac, but can you please try to install tesseract "by hand" (without homebrew)?

For linking on macos10 "-framework OpenCL" should be used. Your configure log showed it was detected correctly, but I do not see it in your make log.

@zdenop: Roger, wilco. That _is_ odd, though, so whatever could have caused _that…?_

@zdenop: I keep getting the following error from ./configure despite the fact that I have Cairo installed even when I add -I/usr/local/opt/cairo/include to CPPFLAGS (though should that be CFLAGS instead…?) and -L/usr/local/opt/cairo/lib to LDFLAGS:

checking for cairo... no
configure: WARNING: Training tools WILL NOT be built because of missing cairo library.
configure: WARNING: Try to install libcairo-dev?? package.

â‹®

You can not build training tools because of missing dependency.
Check configure output for details.

Should I be worried about this, or can I just ignore this error since the build problem I'm trying to solve is, IIRC, in Tesseract itself? I was going to try and make my out-of-Homebrew build and install as close to my _in_-Homebrew one, which said it was going to include the training tools if it had succeeded, if you're wondering why I'm asking. I don't want to overwrite my current _non_-development version of Cairo in the process, so what do I do?

configure uses pkg-config to detect cairo. It can be overridden by setting cairo_CFLAGS and cairo_LIBS, but fixing the installation would be better of course.

First of all - it is a warning, not an error ;-)
Next: it is not related to originally reported issue (opencl build), so please ignore it.

@stweil: Ah, thanks.


@zdenop: Heh, whoops; looks like I was mentally applying the conceptual equivalent of -Wwarnings-as-errors, then; my mistake! In any case, that's what I thought (I just wanted to make sure my judgement was correct by checking with you,) so I'll go ahead and continue this build attempt.

See https://github.com/tesseract-ocr/tesseract/wiki/Compiling for a list of required dependencies. For training tools you need the Dev version of libraries.

@Shreeshrii: That's what confused me in the _first_ place, as _Homebrew_ seems to be able to build the training tools just fine with the _production_ versions of their dependencies. Perhaps it implements some sort of hack to make this (mostly) work, but I'd have to check the package manager's Tesseract formula to be sure of that, as I don't remember seeing anything special there before, which is odd…; maybe the difference is further up in the dependency chain and has to do with Homebrew presents some of its nodes to other software packages? Or perhaps there's a Homebrew shim I don't know about, but I _thought_ I remembered that the package manager only instrumented system-level build tools…

Now that I've kept thinking about this discrepancy for a little bit, maybe it has to do with Homebrew's superenv shim…?

@zdenop: OK, here are the logs from my attempt to build Tesseract manually outside of Homebrew. The new failure looks identical to the one produced when building _inside_ Homebrew at first glance modulo the make procedure's exit status, and I don't think I see -framework OpenCL anywhere in my build logs, either, which is weird since you say Tesseract's ./configure should add that in where needed.

P. S.: I have now compared the undefined symbols diagnosed by each of the log files I just referenced and found them to be identical.

@zdenop: Would like me to run another attempt with make's verbosity increased?

@jbarlow83: Can you have a look on this issue? It seems to me problem with linking (OpenCL build on OS X)

When this issue first cropped up in Homebrew, I tried building it outside of Homebrew's framework in a clean VM. I unsuccessfully tried various approaches, which I have of course forgotten, but it always fails with:

      ...
"_clSetKernelArg", referenced from:
      OpenclDevice::pixReadFromTiffKernel(unsigned int*, int, int, int, unsigned int*) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL_55(int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixDilateCL(int, int, int, int) in libtesseract_opencl.a(openclwrapper.o)
      pixErodeCL(int, int, unsigned int, unsigned int) in libtesseract_opencl.a(openclwrapper.o)
      pixORCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      pixANDCL_work(unsigned int, unsigned int, _cl_mem*, _cl_mem*, _cl_mem*) in libtesseract_opencl.a(openclwrapper.o)
      ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [libtesseract.la] Error 1
make: *** [install-recursive] Error 1

Also, I can confirm this is still an issue using Xcode 8.3 on macOS 10.12.4 as well, no magical, mysterious fix with the latest update.

@JCount: Well, _that's_ not encouraging. I'd update my environment to Sierra and the latest Xcode myself, but I'm stuck on an unsupported machine for the time being. Since it doesn't help in this particular instance, however, I guess I shouldn't push myself to worry about that! 😆


@zdenop: Given that this issue is consistently reproducible both inside and outside of Homebrew, should we perhaps change this issue's title to something more like 'OS X/macOS OpenCL Linkage Errors?'

Maybe it's not a macOS issue, but a Clang issue.

Did someone tested 3.05 on Linux with Clang & OpenCL?

@amitdo: Not that I know of. I don't personally have a Linux install available for testing, either.

Did someone tested 3.05 on Linux with Clang & OpenCL?

I just tested the build, and it worked without any problem using ./configure CXX=clang++-3.8 CXXFLAGS="-g -O2 -Wall" --enable-opencl && make training.

@stweil: What about Clang 4? According to Homebrew, that's what I've got installed:

…$ brew info llvm
llvm: stable 4.0.0 (bottled), HEAD [keg-only]
Next-gen compiler infrastructure
http://llvm.org/
/usr/local/Cellar/llvm/4.0.0 (4,450 files, 2GB)
  Built from source on 2017-03-15 at 00:35:00 with: --with-toolchain --with-python --with-graphviz
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/llvm.rb
==> Dependencies
Build: cmake ✔
Recommended: libffi ✔
Optional: graphviz ✔, ocaml ✔
==> Requirements
Optional: python ✔
==> Options
--with-graphviz
    Build with graphviz support
--with-lldb
    Build LLDB debugger
--with-ocaml
    Build with ocaml support
--with-python
    Build bindings against custom Python
--with-shared-libs
    Build shared instead of static libraries
--with-toolchain
    Build with Toolchain to facilitate overriding system compiler
--without-compiler-rt
    Do not build Clang runtime support libraries for code sanitizers, builtins, and profiling
--without-libcxx
    Do not build libc++ standard library
--without-libffi
    Do not use libffi to call external functions
--HEAD
    Install HEAD version
==> Caveats
LLVM executables are installed in /usr/local/opt/llvm/bin.
Extra tools are installed in /usr/local/opt/llvm/share/llvm.
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"

This formula is keg-only, which means it was not symlinked into /usr/local.

macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have this software first in your PATH run:
  echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/llvm/lib
    CPPFLAGS: -I/usr/local/opt/llvm/include


If you need Python to find bindings for this keg-only formula, run:
  echo /usr/local/opt/llvm/lib/python2.7/site-packages >> /usr/local/lib/python2.7/site-packages/llvm.pth

Scratch that: now I feel somewhat silly, as, according to Apple's list of Macs that support OpenCL, my machine (a mid-2007 aluminum iMac) is listed as supporting a 'non-applicable' version of the standard — that is, none at all! This issue may still be relevant if @JCount's still seeing issues with _his_ setup, though, unless he _also_ has an unsupported machine…. The runtime might still be present in my installation, though, as I've seen the Metal binaries just floating somewhere waiting for when I clone this drive's contents into a machine that supports _that_ API, so I'm not entirely sure whether that means I should be seeing link-time errors or not. With 3.04.01, I was seeing _run_-time errors, possibly even with _return values_ (can't remember what they were off the top of my head, unfortunately, but I'm _pretty_ sure I still have my old Tesseract installation around, so I can go check.)

I think you need OpenCL 1.2 or higher.

@amitdo: Well, again, that _might_ explain things…

I have a machine that supports OpenCL 1.2, both with the Intel Iris Pro Graphics 5200 iGPU and the AMD Radeon R9 M370X dGPU.

I am not OS X user, so maybe I am wrong. But from logs it seems that:

  • configure detect OpenCL framework
  • make output show there is not linking to against OpenCL framework

Yes, it seems to detect the presence of the OpenCL headers, and therefore framework. The issue seems to be in the linking as you say, and I honestly have no idea what is going wrong there.

@zdenop, @JCount: Strangely enough, here is the result of a bit of investigation I just did on my end:

…$ ls -@aHhl /System/Library/Frameworks/ | grep OpenCL.framework
drwxr-xr-x    8 root  wheel   272B Dec 13 16:41 OpenCL.framework

So the OpenCL runtime _is_ present on my machine even if it's not _doing_ anything other than just _sitting_ there. Either this just gets installed with the OS whether your machine supports it or not or the framework's presence is a relic of that one time I tried to install OS X so as to make it bootable on both this iMac and a newer MacBook Pro (can't remember the exact model ATM, sorry…) by _first_ running a clean OS install to this external drive from the latter and _then_ doing an _delta_ install to said drive from the _former_ — though I _think_ I may have once done a clean install to the drive in question just from the iMac, so maybe my earlier hypothesis is correct…? :man_shrugging:

I got vanilla (no homebrew) Tesseract 3.05 to compile and run. Machine is late 2013 iMac 27" with Sierra and OpenCL 1.2 support.

clang --version
Apple LLVM version 8.1.0 (clang-802.0.38)
./configure --enable-opencl LDFLAGS='-framework OpenCL' LIBS='-ltiff'
make -j

When the explicit LDFLAGS='-framework OpenCL' is removed the build fails. For some reason --enable-opencl does not enable linking -framework OpenCL everywhere it should. Doing this causes -framework OpenCL to also show up twice sometimes, based on skimming the logs, so it works partially but incompletely.

Likewise, removing the explicit libtiff linkage will fail.

I don't have a lot of time to investigate the build machinery this week, but hopefully this analysis is enough of a clue to figure what is not working. If nobody bites I will look into it next week.

I did not try building training tools.

@zdenop, @stweil, @JCount, and/or @jbarlow83: What testing remains to be done with respect to tracking down exactly what's going wrong here? Might there be anything _I_ could do to help?

@RandomDSdevel In configure.ac there is some logic that says "if we get --enable-opencl and we are only a Mac, set the variable named OPENCL_LDFLAGS="-framework OpenCL", the special argument for Mac frameworks. Other platforms are working fine because they don't have or don't use -framework as far as I know. I actually don't know the details of what it does.

Most likely there is a Makefile.am (probably) that should set its local local_LDFLAGS= $(OPENCL_LDFLAGS) because it uses OpenCL, but does not. Or perhaps it is the main Makefile at the link step.

The lazy way would be to jump back about six months or so to find a version that compiled and git bisect your way to the breaking change, since it did work until recently.

@jbarlow83: Well, I'm not very fluent in Autoconf, Automake, and/or makefile syntax and have never used git bisect before, but I know bash shell scripting syntax well enough that I _think_ I can at _least_ point others in the right direction to _look._ The v3.05 logic in configure.ac that's responsible for handling that script's --enable-opencl option occupies lines 173–248 — specifically, OPENCL_LDFLAGS is set to "-framework OpenCL" on line 223 in the middle of the code (lines 211-225) responsible for setting up the correct OpenCL compilation and linkage flags for use on Darwin-based operating systems like OS X/macOS. I haven't yet looked for or at a Makefile.am, but I _do_ remember seeing one somewhere in the source code earlier; I'll just have to look for it again (hopefully it's in the repository's root directory or not far from it.) If _that_ doesn't give us any clues, I'll check this 'main Makefile,' whatever it happens to be called.

@jbarlow83: I checked in my last local build attempt and neither "$(git rev-parse --show-toplevel)/Makefile.in", "$(git rev-parse --show-toplevel)/Makefile.am", _nor_ "$(git rev-parse --show-toplevel)/Makefile" (the first and third of which are generated by "$(git rev-parse --show-toplevel)/aurogen.sh" and/or "$(git rev-parse --show-toplevel)/configure.ac" —sorry, but I can't exactly remember which script does what at the moment…) mess with any kind of local_LDFLAGS variable. In fact, I ran find . -type f -print0 | xargs -0 grep "*local_LDFLAGS*" inside my local checkout of the Tesseract repository (still on branch 3.05 with artifacts left over from my last failed out-of-Homebrew/vanilla build) and came up _empty_ — but maybe I was doing something wrong with this command pipeline invocation…?

As I mentioned I can look into this next week, just not now.

The issue is likely that some new code was introduced and the build system was not properly modified so there is no code to search for it. It is the absence of some necessary code that is the trouble. As you're not familiar with autotools my rough problem sketch is probably not helpful. What would help is to run git bisect and find the commit that breaks the build on macOS, since it used to work. That is likely a strong indicator of what kind of fix is needed.

@jbarlow83: Sorry to bother you with details you probably could have figured out easily enough yourself, then.

@RandomDSdevel, please try pull request #808. It fixes make training with OpenCL on macOS for me. Don't forget to run ./autogen.sh after applying the change.

@stweil: Thanks, but I'm not sure that will help with _this_ issue, as it has to do with not being able to linking Tesseract _itself_ with OpenCL… As I mentioned before, though, _this_ problem might _alos_ have something to do with the fact that invoking OpenCL functionality on my machine probably only returns responses indicating the fact that the library doesn't work with my graphics card, as Apple never supplied drivers for it. @JCount, however, has a machine that _does_ support OpenCL and said he's getting similar link-time errors. IIRC, @jbarlow83 has also reproduced this issue and has said he'd look into trying to fix it some time this week, but I'm not going to invoke him any further than that, as he advised not to badger him too much about it (I've _probably_ already annoyed him _enough_ as it _is_, what with my overly enthusiastic impatience to get this fixed and all…) That being said, I'll still take a look at the PR you've pointed me towards and see if does anything to help.

I'm not annoyed at all, I just have to do the work that pays the bills first. :)

@jbarlow83: Whoops, look like I was reading a little too much into things, ha-ha…

@jbarlow83: Just saw your work start popping up in #814. I have one comment on it, but I'll leave it in the relevant discussion thread.

Was this page helpful?
0 / 5 - 0 ratings