Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/compile osx #171

Closed
wants to merge 7 commits into from
Closed

Feature/compile osx #171

wants to merge 7 commits into from

Conversation

haf
Copy link

@haf haf commented May 17, 2015

Continuation of discussion in #170

@haf
Copy link
Author

haf commented May 17, 2015

# mono bin/Release/Net45/Tesseract.Tests.Console.exe
Is 64bit process: True
Unhandled exception occured:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.DllNotFoundException: Failed to find library "liblept168.so" for platform x64.
  at InteropDotNet.LibraryLoader.LoadLibrary (System.String fileName, System.String platformName) [0x00000] in <filename unknown>:0
  at InteropRuntimeImplementer.LeptonicaApiSignaturesInstance.LeptonicaApiSignaturesImplementation..ctor (InteropDotNet.LibraryLoader loader) [0x00000] in <filename unknown>:0
  at (wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&)
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <filename unknown>:0
  at System.Reflection.MonoCMethod.DoInvoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
  at System.Reflection.MonoCMethod.Invoke (BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
  at System.Activator.CreateInstance (System.Type type, BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0
  at System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0
  at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <filename unknown>:0
  at InteropDotNet.InteropRuntimeImplementer.CreateInstance[ILeptonicaApiSignatures] () [0x00000] in <filename unknown>:0
  at Tesseract.Interop.LeptonicaApi.Initialize () [0x00000] in <filename unknown>:0
  at Tesseract.Interop.TessApi.Initialize () [0x00000] in <filename unknown>:0
  at Tesseract.Interop.TessApi.get_Native () [0x00000] in <filename unknown>:0
  at Tesseract.TesseractEngine..ctor (System.String datapath, System.String language, EngineMode engineMode, IEnumerable`1 configFiles) [0x00000] in <filename unknown>:0
  at Tesseract.TesseractEngine..ctor (System.String datapath, System.String language, EngineMode engineMode, System.String configFile) [0x00000] in <filename unknown>:0
  at Tesseract.Tests.EngineTests.Initialise_CanLoadConfigFile () [0x00000] in <filename unknown>:0
  at Tesseract.Tests.Console.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
Press any key to exit.

@haf
Copy link
Author

haf commented May 17, 2015

No it won't break nuget support on Windows if you add a call to tools/paket.exe restore in the bat file.

@haf
Copy link
Author

haf commented May 17, 2015

May I ask what the purpose of keeping around all these build configurations for is? Why not say 'this library works 4.5 and above'? For example:

screen shot 2015-05-17 at 18 35 34

@haf
Copy link
Author

haf commented May 17, 2015

Hey, @AndreyAkinshin do you have an idea why linux loading doesn't work?

@haf
Copy link
Author

haf commented May 17, 2015

Current platform: x64
Custom search path is not defined, skipping.
Checking executing application domain location '/tmp/build/src/Tesseract.Tests/bin/Release/Net45' for 'liblept168.so' on platform x64.
Trying to load native library (unix) "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so"...
Failed to load native library "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so".
Checking current application domain location '/tmp/build/src/Tesseract.Tests/bin/Release/Net45/' for 'liblept168.so' on platform x64.
Trying to load native library (unix) "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so"...
Failed to load native library "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so".
No bin directory exists under the current application domain's location, skipping.
Checking working directory '/tmp/build/src/Tesseract.Tests/bin/Release/Net45' for 'liblept168.so' on platform x64.
Trying to load native library (unix) "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so"...
Failed to load native library "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so".

@AndreyAkinshin
Copy link
Contributor

Hey, @haf. Where is liblept168.so actually located on your computer?

@haf
Copy link
Author

haf commented May 17, 2015

It's not my computer; it's the dockerfile that is contained in this PR. Run docker build . to reproduce.

However, answering your question's jest: it's right where it's failing to load it; /tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so, meaning I can do docker run --rm -it and then ls /tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so and there will be such a file and $? => 0

@haf
Copy link
Author

haf commented May 17, 2015

Ok, I've modded your code a bit and there's a bug in your code that doesn't check for errors loading the lib... Let me push the changes.

@AndreyAkinshin
Copy link
Contributor

Let me push the changes.

@haf, ok.

@haf
Copy link
Author

haf commented May 17, 2015

There.

@haf
Copy link
Author

haf commented May 17, 2015

So the current error is this:

Inner Exception: System.Exception: dlsym: libpng12.so.0: cannot open shared object file: No such file or directory
  at InteropDotNet.UnixLibraryLoaderLogic.EnsureSuccess () [0x00000] in <filename unknown>:0
  at InteropDotNet.UnixLibraryLoaderLogic.LoadLibrary (System.String fileName) [0x00000] in <filename unknown>:0
No bin directory exists under the current application domain's location, skipping.
Checking working directory '/tmp/build/src/Tesseract.Tests/bin/Release/Net45' for 'liblept168.so' on platform x64.
Trying to load native library (unix) "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so"...
Failed to load native library "/tmp/build/src/Tesseract.Tests/bin/Release/Net45/x64/liblept168.so".
Last Error:0

...Fixing.

@haf
Copy link
Author

haf commented May 17, 2015

@AndreyAkinshin I like your loader btw. It makes it easy to distribute cross-platform libraries which are automatically switched depending on architecture. Did you consider just using <dllmap elements and what were the reasons you didn't use that?

@haf
Copy link
Author

haf commented May 17, 2015

Next error:

Inner Exception: System.Exception: dlsym: libjpeg.so.8: cannot open shared object file: No such file or directory
  at InteropDotNet.UnixLibraryLoaderLogic.EnsureSuccess () [0x00000] in <filename unknown>:0
  at InteropDotNet.UnixLibraryLoaderLogic.LoadLibrary (System.String fileName) [0x00000] in <filename unknown>:0
F.Current platform: x64
[root@8b44d4e61c7b build]# repoquery -q -l libjpeg-turbo-devel-1.2.90-5.el7.x86_64
/usr/include/jconfig.h
/usr/include/jerror.h
/usr/include/jmorecfg.h
/usr/include/jpeglib.h
/usr/lib64/libjpeg.so
/usr/share/doc/libjpeg-turbo-devel-1.2.90
/usr/share/doc/libjpeg-turbo-devel-1.2.90/coderules.txt
/usr/share/doc/libjpeg-turbo-devel-1.2.90/example.c
/usr/share/doc/libjpeg-turbo-devel-1.2.90/jconfig.txt
/usr/share/doc/libjpeg-turbo-devel-1.2.90/libjpeg.txt
/usr/share/doc/libjpeg-turbo-devel-1.2.90/structure.txt

@AndreyAkinshin
Copy link
Contributor

@haf, dllmap is a great feature. However:

  1. Microsoft.NET can't work this dllmap. It is the main reason.
  2. There is a big problem that I had with different native library loading approaches (maybe with dllmap also, but I could be wrong): loading order. Tesseract wrapper requests that you should load leptonica first. If you try to load native tesseract at first, it will try to load native leptonica. But there is a question: where native tesseract should look for native leptonica? In fact, it depends on runtime. Usually, the default location may equals to application folder or native tesseract binary folder. And it is a really big challenge. My approach (InteropDotNet) allows you to control this issue.

If you have found any miskakes in InteropDotNet, PR are welcome!

@haf
Copy link
Author

haf commented May 17, 2015

Either it's in the bin folder of the currently executing dll or it will find the native leptonica from whereever ldconfig -p | grep liblept says it is. At least that's my understanding -- on linux that is.

If we also avoided compiling the respective versions of each library into their names, we could load them globally instead; and have only a single version on the operating system -- given that your deployment supports this (e.g. having a cheap VM).

@AndreyAkinshin
Copy link
Contributor

we could load them globally instead

Yes, it would be cool, but I just wanted to do a standalone solution.

@haf
Copy link
Author

haf commented May 17, 2015

Could you possibly provide an OS X implementation, too?

@AndreyAkinshin
Copy link
Contributor

@haf, unfortunately, I don't have an OS X. So I can't build binary and check it in a real environment. If you can help me with it, it would be great!

@haf
Copy link
Author

haf commented May 17, 2015

@AndreyAkinshin This haf@ee35892#diff-f926a5fb754ac9357f66aee8cbca99bdL22 is the change I think you should make to your library

@AndreyAkinshin
Copy link
Contributor

@haf, geat! Can you make the PR in the main repo: https://github.com/AndreyAkinshin/InteropDotNet ?

@haf
Copy link
Author

haf commented May 17, 2015

Not really my focus right now... Sorry. Here's another problem:

 (int)Environment.OSVersion.Platform;;
val it : int = 4
> (int)PlatformID.MacOSX;;
val it : int = 6
> PlatformID.MacOSX;;
val it : PlatformID = MacOSX
> (int)PlatformID.Unix;;
val it : int = 4

When running on OSX.

@haf
Copy link
Author

haf commented May 17, 2015

Here's the proper check for OS X.

@haf
Copy link
Author

haf commented May 17, 2015

@AndreyAkinshin This is a commit that allows OS X to work: haf@1aadbe4 but hell awaits me, for sure. I can't work with C# without ReSharper and that doesn't exist for OS X; so this code is a copy-paste-mess.

The problem with the pre-compiled .so files is that they are dynamically linked to specific versions of .so files when they were compiled -- and this is also a show-stopper for OS X.

To solve it we'd need a way to either provide multiple names for the library, or to let InteropDotNet first check global names. But since I need to change the names to match homebrew in this case; we're back at having to allow multiple library names depending on platform.

@charlesw
Copy link
Owner

Good work guys.

As an alternative solution it might be easiest to just build a copy of leptonica from source that statically links in all dependant libs such as libpng and use that for standalone installs for Mono and OS X.

If using Global libraries, where native tesseract and leptonica is installed using a package manager, is required I think this could be achieved by adding a fallback to LibraryLoader to just load the dll/so with no path specified. I believe that will mean that os will look in its normal search path. I think this was the behaviour in version 1.

Any thoughts?

@charlesw
Copy link
Owner

P.S. haf .Net 2,. Net 4, and .Net 4 Client Profile is required as some users cannot upgrade to .Net 4 due to company policies and wanting to aim for lowest denominators. I've based the project structure on Reactive Extentions' project structure which uses a different project configuration per target which seems to work ok on windows at least however it does make for an unconventional project configuration as the project configurations are declared in a seperate file and imported into the project which could cause issues for other tools I guess.

@charlesw
Copy link
Owner

Added issue #174 to cover setting up a docker container for Mono.

@haf
Copy link
Author

haf commented Sep 26, 2015

@charlesw @AndreyAkinshin see #210

@haf haf closed this Sep 26, 2015
@haf haf deleted the feature/compile-osx branch September 26, 2015 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants