Search code examples
ioseigenblasaccelerate-framework

Using Eigen with EIGEN_USE_BLAS in iOS project


Out of educational purposes I'm trying to use Eigen in my pet project. In order to speed the math I included macro EIGEN_USE_BLAS which activates use of blas library.

But I encountered an issue when I tried to upload my project to Testflight. The Apple response to that was:

ITMS-90338: Non-public API usage - The app references non-public symbols in My-Project: _saxpy_, _sgemm_, _sgemv_, _strmm_, _strmv_. If method names in your source code match the private Apple APIs listed above, altering your method names will help prevent this app from being flagged in future submissions. In addition, note that one or more of the above APIs may be located in a static library that was included with your app. If so, they must be removed. For further information, visit the Technical Support Information at http://developer.apple.com/support/technical/

I know that Apple has blas library as a part of Accelerate.framework and it should be use strictly through Accelerate API. But the thing is that Eigen also has their own blas included in their source and the library actually has no intention of using Accelerate.framework private guts. So that is why Apple asks me to rename those functions or remove them completely in order to get rid of that inconvenience.

But I'm not even sure that it is possible to do - to tune Eigen and its blas to use alternative names.

Is there maybe a way to solve that issue in some efficient manner? Or maybe I don't know something about Eigen usage in iOS environment?


Solution

  • I was lucky to figure out the problem with few tips from my fellow colleagues and a strong will to get the job done, and now I want to share with you my conclusions.

    The problem: Eigen doesn't have BLAS binary provided, it only has it's headers. And when one uses EIGEN_USE_BLAS macro and it actually works, that means that Apple is linking Eigen BLAS functions to their binary - BLAS binary which is a part of Accelerate.framework. The trickiest part is that your project doesn't necessarily should have Accelerate.framework inside. XCode will add necessary files automatically and of course it won't bother to tell you that.

    What's weird for me the most here is that using "naked" BLAS provided by Apple's Accelerate.framework is a clear violation because it's private API. So... from my perspective it's kind of XCode violates this rule without my intention and tells me nothing about it. Strange...

    So, in order to fix it, you need to build BLAS or OpenBLAS binary (I have built OpenBLAS), add it to the project and link through Other linker flags in Build settings. After that the error is gone and you're able to upload your build to Testflight.

    In order to save you some time in building OpenBLAS for iOS, I will leave you few links. I think those would be enough:

    http://www.programmersought.com/article/2638161057/ - very clear tutorial on how to build OpenBLAS https://github.com/xianyi/OpenBLAS/tree/release-0.2.21 - source code of the library https://github.com/xianyi/OpenBLAS/issues/1531 - discussion where you can find solutions to problems you might encounter

    What I found the most confusing part of this whole story is the message from Apple. Here's another copy of that:

    ITMS-90338: Non-public API usage - The app references non-public symbols in My-Project: saxpy, sgemm, sgemv, strmm, strmv. If method names in your source code match the private Apple APIs listed above, altering your method names will help prevent this app from being flagged in future submissions. In addition, note that one or more of the above APIs may be located in a static library that was included with your app. If so, they must be removed. For further information, visit the Technical Support Information at http://developer.apple.com/support/technical/

    I'm not a native English speaker but I feel pretty confident to say that this text is a non-sense and has absolutely nothing to do with the solving of the actual problem.

    It says absolutely nothing about the fact that private API was linked to my code and that is the problem. And that I need to provide my own backend for those functions in order to make error disappear. It says about names matching and that altering my names will help to solve the problem, when it clearly will not in my case.

    I hope Apple will bring more clarity into this problem and that errors descriptions will have more sense in the future.