⬆️ ⬇️

We build a pre-built dylib into the application.

Before the beginning of the May holidays, I spent 5 hard days writing an application for iOS and Mac for the contest. The development went smoothly, by the last day the work of the application began to satisfy me more or less. I decided to postpone the departure on the morning of the very last day in order to do this with a fresh head (there still had to be attached a text description). In the morning, a few hours before the train was on vacation, I sat down and with a calm soul made the final run-in of the main functionality. And then it seemed to me a good idea to potest how the application will behave on a completely different machine, on which the development was not conducted. I archive my application, transfer it to another Mac and ... it does not start. With the super-informative error "Image not found" and by clearly indicating a dylib problem. So: 3 hours before the train and the application not starting for no apparent reason. Why it happened, how it could have been avoided and how I dealt with this problem - about all this under the cut.



I quickly figured out the essence of the problem, but its solution took some time. Let's still make out what happened. OpenCV was used in my application. I collected it from the original sources with the default configuration straight from the official site using CMake. After that, I pointed out the Search Path couple in Xcode and the development advanced, as they say, seamless. As you probably already understood, the problem was that on the working machine, my application used libraries that were located at /usr/local/lib/ .



This path was specified for search in Xcode, and since I linked them with the application, I mistakenly thought that all the necessary libraries to pull up during archiving, now I know that this is not so. The first thought that came to me then: make the installer. In principle, this is a working solution, and many people do just that. However, this was not the time, because in addition to the time spent on developing the installer itself, it took more testing, etc., and the train drove off in a couple of hours.



I started to google this problem and realized that I need to throw dylib into the application itself. Without thinking twice, I threw them into the XCode project, added linkage, archived ... on the working machine everything is OK, on ​​the third-party - the same mistake. The problem was in dylib installing and searching for dependencies. In my case it was monstrous



 /Users/s1ddok/Downloads/opencv-3.1.0/build/lib/libopencv_core.3.1.dylib 


This is because I added dylib intermediate from the build folder to the project, these are the ones that are later installed with the command make install , but even if I took them from /usr/local/lib/ , this did not solve the problem.



How could this problem be avoided? Specify the required installation paths at once during dylib compilation. If you are compiling your libraries, most likely you have already installed everything correctly, but if not, this is easy to do in XCode. Specifically, in the case of OpenCV, it was necessary only to change the default configuration of CMake and add the installation dir prefix there, but I did not have the opportunity to do this at that time.



So, I needed to somehow change the install path in the ready-made dylib so that they run. I will omit the detailed descriptions of how I came to the result, just tell you what worked in the end.



First of all, we need our dylibs, which we added to the project, to be copied to the bundle with our application. In principle, no matter where, you can even shove them in the main bundle, but copying to the Frameworks folder seems logical. To do this, go to Xcode -> Target Settings -> Build Phases and add a new phase of Copy Files. My application uses only 2 libraries from the OpenCV set, so for me it looks like this:



image



Ok, now inside our application all necessary dylib are stored, however it falls out with the same error, because the paths in them are still old. We come to the aid of utilities such as otool and install_name_tool . The first was needed in order to find out which install path is “protected” in existing libraries, and the second in order to change them. Add a new build phase to Xcode, this time Run Script . The script itself turned out like this:



 #         install_name_tool -change lib/libopencv_core.3.1.dylib @executable_path/../Frameworks/libopencv_core.3.1.0.dylib $BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH install_name_tool -change lib/libopencv_imgproc.3.1.dylib @executable_path/../Frameworks/libopencv_imgproc.3.1.0.dylib $BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH #    Frameworks    cd $BUILT_PRODUCTS_DIR cd MyApp.app cd Contents cd Frameworks #        install_name_tool -id @executable_path/../Frameworks/libopencv_core.3.1.0.dylib libopencv_core.3.1.0.dylib install_name_tool -id @executable_path/../Frameworks/libopencv_imgproc.3.1.0.dylib libopencv_imgproc.3.1.0.dylib #    ,  ,     . # otool -L libopencv_imgproc.3.1.0.dylib #       opencv-core     ,    install_name_tool -change /Users/s1ddok/Downloads/opencv-3.1.0/build/lib/libopencv_core.3.1.dylib @executable_path/../Frameworks/libopencv_core.3.1.0.dylib libopencv_imgproc.3.1.0.dylib 


This, of course, is a terrible decision and the script will have to be redone for each library, it is not universal. At that time, I did not have time to develop a generic solution.



I hope my experience will be useful to someone, I dealt with all of this in a very nervous and tense environment, so I am doubly pleased that the application did start up and I was able to successfully send it, although I had to write an essay in 20 minutes without checking, but this little things.



')

Source: https://habr.com/ru/post/283204/



All Articles