Static Framework in iOS and linking - c++

I have an xcode workspace which is set up with some project libraries which are dependent on Boost 1_49 (built as an iOS framework), a static framework (a Fake Framework from https://github.com/kstenerud/iOS-Universal-Framework) and then a test app which uses the static framework.
The test app in addition uses boost.
I wanted to do some tests to see if it was possible to have the test app working on a different version of boost than the framework. This way we could deliver the framework as a standalone framework without having any restrictions on the version of boost that needs to be used in an application that is using our framework.
As such, I set up the test app to use boost 1_48 and the framework to use 1_49. I have it set up so that all of the projects which use boost are not set link the boost framework into the binary, and the framework project I have doesn't actually have boost referenced in it at all; it only has references to all the .a libs generated by its dependencies.
ProjectA
- Boost.framework 1_49
ProjectB
MyFramework
- ProjectA.a
- ProjectB.a
TestApp
- MyFramework.framework
- Boost.framework 1_48
I then added some code in both the framework and the test app to print out the boost version. Both places printed out version 1_49, and not 1_48. In addition, I tried to add some code in the test app to step into boost (just getting the current time for example), and the xCode debugger took me into the boost version contained in ProjectA, and not into the boost version contained in the TestApp.
What is going on with the linking and how can I get the application to only use the version of boost included in the TestApp?
Thanks,
Liron

Seems that the problem was that some other libraries in the application were also linking in Boost 1.49, so even though I thought I was using 1.48, 1.49 was there as well. Oh well.

Related

C++ qt application compilation in one file

I have written windows gui application using qt and i want to deploy it.Now when i place .exe to other PC it shows error which says that qt5core.dll and etc required.I can install this dll,but is it possible to run exe app with qt without qt's dll as one file?So i can for example give .exe to my friend and he can instantly run it without installing .dll?
Basically, if you want a single exe file, you probably mean static linking.
The legal commercial version makes it possible or if I am not wrong, you will have to build a static qt version.
In the latter case, you will have to provide the source code of your application.
I do this sometimes, but you'll have to be careful with the license requirements: if you go with GPL, it should be OK, if you choose LGPL, it may be a bit less simple. No idea about the commercial version.
What you must do is building Qt statically, and then use that Qt build to build your application. I had a good experience with mxe. MXE builds an entire crossbuild environment and allows you to build your big Qt exe statically. I used it on Mac OS and Linux to build static executables for Windows, but you can probably run it on WSL. It takes a bit to compile, but it is simple to use. Please note that it cannot be used if your app needs QtWebEngine as it won't build with mingw.
Another simpler option is to create an installer. The Qt installer framework is simple to use. If you include the VS runtime, you end up with a single exe to distribute (the installer).
You always need to include the libraries you use (including your compilers runtime libraries in fact) when you deploy your executable - otherwise how would your application be able to use the code in those libraries? You may be able to statically link some/most things, but rarely everything. Look into how to create an installer / package for your application, so you can bundle up everything as one convenient file.
You can buid you app using QT Static (a large .exe file, no external dependencies)
If you are using LGPL Qt, you must read this:
https://www.qt.io/faq/3.7.-what-are-my-obligations-when-using-qt-under-the-lgpl
Yo can use Qt and static linking, but "The user of your application has to be able to re-link your application against a different or modified version of the Qt library"
You can use an application template like this, very useful for LGPL Qt:
https://marketplace.qt.io/products/qt-lgpl-app-template

How to make Qt Creator add CEF framework to DEST_DIR on Mac OS X?

I'm working on a collaborative project in Qt Creator, and I've managed to get it to compile: I linked CEF Framework and the CEF dll wrapper. However, when I try to run it I get:
dyld: Library not loaded: #executable_path/Chromium Embedded Framework
Reason: image not found
As far as my understanding goes, the framework needs to be copied into my DEST_DIR, into .app/Contents/MacOS or something like that. I have NOT managed to make it work even by copying the framework there manually.
Also, since the development is meant to be cross platform, I was wondering if there's a way to tell qmake how to copy the framework to my DEST_DIR.
Any help in understanding how to deal with frameworks on Mac OS X in Qt Creator would be greatly appreciated.
As far as my understanding goes, the framework needs to be copied into my DEST_DIR, into .app/Contents/MacOS or something like that.
You're nearly there. Frameworks are generally copied into
.app/Contents/Frameworks
However, your bundle's executable contains a reference to where it expects those framework libraries are residing and having copied them into the app bundle, you need to tell the executable where they are.
Using oTool with -L argument, you can see the libraries referenced by the executable. You'd call it with the full path. For example
otool -L /Applications/Calculator.app/Contents/MacOS/Calculator
For each dylib in the framework, you need to fix up the path using the command line tool install_name_tool
When deploying a Qt application for Qt, we must run the macdeployqt. This essentially does the same thing for the Qt Frameworks; copies them into the relevant Frameworks folder and updates the paths.
I've not used it myself, but according to the documentation, macdeployqt supports handling 3rd party frameworks, with the option -executable=< path >

Easy way to build multi platform C++ library with Xcode

I want to build a C++ library for Mac and iOS using the same Xcode project. When I'm creating a new project in Xcode I can choose Mac OS C++ library, but there is no similar option for iOS. The code is exactly the same on both platforms and I don't see any point having 2 different projects.
Can you provide me some guidance to achieve this?
EDIT: Now I'm using same project with different targets, one for Mac and one for iOS
Depending on what you want to use this library for, creating an iOS fake framework may also be an option: https://github.com/kstenerud/iOS-Universal-Framework/tree/master
I usually create both (libraries and (fake) frameworks) for a) binary-delivery only SDK projects or b) very fat libraries which are rarely changed but often used. An example for the latter is SQLite, which takes very long to compile for iOS and is maybe changed once a year. But for debugging purpose, I use the same project and code base using a static library target (for when we update the fake framework once in a while and need to debug it).

Delivering an xcode framework with other dependencies

We are trying to release an iOS version of our library and are planning on delivering it as a compiled static framework. Using Xcode the framework and test app we have are compiling successfully and running fine.
The question is: What is the best way to deliver it?
Our library is dependent on some other opensource frameworks, and we also want to ship a test app with the framework to show how to actually use the library properly.
Should we use an umbrella framework? Apple suggests "Don't Create Umbrella Frameworks" (http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/CreationGuidelines.html)
Should we just deliver a zip that has our framework as well as all the frameworks we're dependent on and just tell the clients that they have to include those frameworks in their projects?
What's the best way to include the test app?
Thanks in advance!
Take a look at CocoaPods as a means to manage the dependencies (especially if those dependencies are open-source).
https://github.com/CocoaPods/CocoaPods
I would include the required frameworks with your compiled framework with the exception of frameworks that come standard with the iOS SDK. Most every framework is going to rely on Foundation and UIKit, those are frameworks that will most likely already be included. Anything else they won't have access to, include with your framework you send over.

SQLite with Android NDK

Is it somehow possible to use SQLite with C++ on an Android phone? I haven't found any documentation around how this could be possible.
Just download the SQLite3 amalgamation source file from:
http://www.sqlite.org/download.html
And then add sqlite3.c to your LOCAL_SRC_FILES variable in Android.mk.
It isn't possible to use the built-in SQLite via NDK (or it wasn't six months ago when I looked into this), that can only be accessed with Java. However it may be possible to link in your own completely separate C++ build of SQLite.
See SQLite Android Bindings http://www.sqlite.org/android/doc/trunk/www/index.wiki which describes how to include sqlite3 for Android targets 15 (4.0.3) and greater. It's copied below.
SQLite Android Bindings
The SQLite library is a core part of the Android environment. Java
applications and content providers access SQLite using the interface
in the android.database.sqlite namespace.
One disadvantage of using Android's built-in SQLite support is that
the application is forced to use the version of SQLite that the
current version of Android happened to ship with. If your application
happens to require a newer version of SQLite, or a build with a custom
extension or VFS installed, you're out of luck.
The code in this project allows an application to use the Android NDK
to build a custom version of SQLite to be shipped with the application
while still continuing to use the standard Java interface.
Normal Usage
Installation
Android API levels 15 (Android 4.0.3) and greater are supported. If
targetting API level 16 or greater, use the default "trunk" branch of
this project. Or, for API level 15, use the "api-level-15" branch. It
is not possible to target an API level lower than 15.
Copy the following files from this project into the equivalent
locations in the application project.
jni/Android.mk
jni/Application.mk
jni/sqlite/* (copy contents of directory recursively)
src/org/sqlite/database/* (copy contents of directory recursively)
Following this, the directory structures should contain
these files.
For API level 15 only, also copy the following:
src/org/sqlite/os/* (copy contents of directory recursively)
Directory "jni/sqlite/" contains copies of the sqlite3.h
and sqlite3.c source files. Between them, they contain the source code
for the SQLite library. If necessary, replace these with the source
for the specific version of SQLite required. If SQLite is to be
compiled with any special pre-processor macros defined, add them to
the "jni/sqlite/Android.mk" file (not jni/Android.mk).
Once the files have been added to the project, run the command
"ndk-build" in the root directory of the project. This compiles the
native code in the jni/ directory (including the custom SQLite
version) to shared libraries that will be deployed to the device along
with the application. Assuming it is successful, unless you modify the
sources or makefiles within the jni/ directory structure, you should
not need to run "ndk-build" again.
Application Programming
The classes that make up the built-in Android SQLite interface reside
in the "android.database.sqlite" namespace. This interface provides
all of the same classes, except within the
"org.sqlite.database.sqlite" namespace. This means that to modify an
application to use the custom version of SQLite, all that is usually
required is to replace all occurrences "android.database.sqlite"
within the source code with "org.sqlite.database.sqlite".
For example,the following:
import android.database.sqlite.SQLiteDatabase;
should be replaced with:
import org.sqlite.database.sqlite.SQLiteDatabase;
As well as replacing all uses of the classes in the android.database.sqlite.*
namespace, the application must also be sure to use the following two:
org.sqlite.database.SQLException
org.sqlite.database.DatabaseErrorHandler
instead of:
android.database.SQLException
android.database.DatabaseErrorHandler
Aside from namespace changes,
there are other differences from the stock Android interface that
applications need to be aware of:
The SQLiteStatement.simpleQueryForBlobFileDescriptor() API is not
available.
The collation sequence "UNICODE" is not available.
The collation sequence "LOCALIZED", which normally changes with the
system's current locale, is always equivalent to SQLite's built in
collation BINARY.
Disclaimer: i have only used this method for standalone executables, not libraries that implement JNI functions. It may work for a .so or not. Also, i'm working with a custom Android device not a phone.
You can use the built in SQLite via NDK but it's more of a hack than something supported. You need to nick sqlite3.h and libsqlite.so from an android source distribution and compile using them. Put sqlite3.h in your application source directory and you need to put the .so somewhere under the out/yourapp directory or build/platform/android-x/arch-arm/usr/lib for the linking step to finish. I have it in both places but i'm not sure which one is really needed.
You will end up linking to the libsqlite.so you provided but the binary will run fine using the system libsqlite.so on a target device.