Cmake - cross compiling C++ project for iOS - c++

There is no quite a good tutorial for Cmake integration for iOS projects. There are very few found on internet, but lags information. I have a C++ project and I want to cross compile it for my iOS project. I am really not an expert in C++ and Cmake topics. Though, I followed a blog which I was what exactly looking for.
As mentioned in the blog, I used toolchain to execute the Cmake command
mkdir build/ && cd build/ && cmake -G "Xcode" -DCMAKE_TOOLCHAIN_FILE=../ios-cmake/ios.toolchain.cmake ../../xxx-cpp -DPLATFORM=OS64COMBINED
And it generated the .xcodeproj in the build directory.
As instructed, I included the generated Xcode solution to my main iOS project and added the C++ project to "Frameworks, Libraries, and Embedded Content" and "Dependencies". Actually I wanted to build the library for iOS devices, so, as mentioned in the comment in the same blog, "The Xcode project generated from Cmake does not require any signing itself. Instead you include that generated Xcode project in another Xcode project that DOES have signing configured", my iOS project was already code signed. When I tried to build the project, I got build error saying "Signing for "xxx" requires a development team. Select a development team in the Signing & Capabilities editor."
Here are my observations
Build main iOS project for devices: BUILD FAILED
Signing for "xxx" requires a development team. Select a development team in the Signing & Capabilities editor.
Build main iOS project for simulator: BUILD FAILED
clang: error: no such file or directory: '/Users/user/Workspace/Cmake/Cmake Sample/build/lib/{C++ project}/core/Debug-iphonesimulator/libxxx.dylib'
Command Ld failed with a nonzero exit code
Build generated Xcode project for devices: BUILD FAILED
Choosing ALL_BUILD target
For .app targets: Bundle identifier is missing. xxx doesn't have a bundle identifier. Add a value for PRODUCT_BUNDLE_IDENTIFIER in the build settings editor.
For .dylib targets: Signing for "xxx" requires a development team. Select a development team in the Signing & Capabilities editor.
Build generated Xcode project for simulator: BUILD SUCCEEDED
Choosing ALL_BUILD target
I have no idea where to find the solution and I have already invested more time in analysing and doing many trial and errors. I really need some advise in cross compiling the Cpp libraries for iOS devices. Thanks in advance!!
Another gentleman is facing a same issue

There are multiple ways to solve this problem.
You sign the library manually everytime after building the library with iOS-cmake using codesign command by providing appropriate signing identity. This involves lot of manual work, so I would prefer you to go with approach
You can automatically sign all the included libraries using run script by adding below command codesign -f -s "$EXPANDED_CODE_SIGN_IDENTITY" "$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/<library_name>"
Here signing identity can be either "$EXPANDED_CODE_SIGN_IDENTITY" or "$CODE_SIGN_IDENTITY", it depends on your workspace structure if you are using cocoapods or not
The idea in the second approach is, xcode (xcodebuild) provides few environment variables while building the project, so we try to leverage the same signing identity which was used for signing the application to sign the library.
Also with respect to the way you are integrating the native library, I personally don't recommend doing that because if you change any setting in the generated xcode project, it would be disappeared if you generate the xcode project again
We have a similar dependency in our project, so we took the route of building the libraries in the command line (you can choose to build it using xcode generator or directly with cmake and make). Then we had to set few settings into our project
Adding the build dependency :- For this we have updated framework search paths build setting which points to the library which was generated before (this you can customize depending on arm64 [devices] or x86_64 [simulator])
Give that build dependency is sorted out, but in-order to have them at run time, we have to include these libraries in frameworks directory of .app folder, so we have added a run script to copy these libraries to frameworks directory. Using something like below
# Retrieve architecture type
ARCHITECTURE=""
if [ $NATIVE_ARCH == "i386" ] || [ $NATIVE_ARCH == "x86_64" ] ; then
ARCHITECTURE="x86_64"
else
ARCHITECTURE="arm64"
fi
# Retrieve build configuration
BUILD_CONFIG=""
if [ $CONFIGURATION == "Debug" ] ; then
BUILD_CONFIG="Debug"
else
BUILD_CONFIG="Release"
fi
# Copying library
cp -r <path_to_your_library> "$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/"
Path_to_your_library might vary depending on x86_64, arm64, debug and release builds.
The steps 1 and 2 are automatically taken care by xcode if you go with your route but it has lot of caveats, but configuring these settings is a one time activity which is smooth in day-to-day development process
If you maintain proper directory structure you can smoothly add them to the run script something like
Debug/arm64 for debug arm64 variant
Release/arm64 for release arm64 variant
Debug/x86_64 for debug x86_64 variant
Release/x86_64 for release x86_64 variant
Also make sure that you build framework instead of dylib, else Apple will throw warning and reject while uploading to appstore

Related

Export Eclipse Compiler to cmd

I try to compile an eclipse-project written in c++ which is building a .so-File. Now i try to build the project without an IDE. I tried it with MinGW but the created .so doesn't work. I think there are used some special packages but how can I get the information's.
Is there a way to Export the build settings and import them into MinGW?
How can i else set the compiler?
This is the ToolChainEditor which i would recreat in MinGW.
You can't import a configuration into mingw, but you can tell mingw where to find a configuration of sorts.
Eclipse can be configured to generate a makefile (At least as recent as Neon). Select your project and use the main menu to navigate Project->Properties->C/C++ Build->Tool Chain Editor. Set the "Current builder" to Gnu Make Builder and build the project.
In the generated folder where you would find the finished executable you will find three more files: makefile, objects.mk and sources.mk and can use the make utility that often comes with mingw. It can also be downloaded separately if you have to.
From the command line, enter the folder and type make. Magic will happen. If you want to know more about the magic, make is a very deep topic well worth learning, even if only as a gateway drug to more modern build systems that descended from it.

Can't add dynamic frameworks to Command Line Tool

Goals
I added Command Line Tool target to an iOS app and linked with swift frameworks. (tested with Realm and SwiftyJSON)
Expected Results
Build Command Line tool with those libraries.
Actual Results
Xcode output:
dyld: Library not loaded: #rpath/libswiftCore.dylib
Referenced from: .../Xcode/DerivedData/.../Build/Products/Debug/RealmSwift.framework/Versions/A/RealmSwift
Reason: Incompatible library version: RealmSwift requires version 1.0.0 or later, but libswiftCore.dylib provides version 0.0.0
Steps to Reproduce
Create empty Swift Command Line Tool and link Realm frameworks
Code Sample
CommandLineTest.zip
Version of Frameworks and Tooling
Realm version: github "realm/realm-cocoa" "master"
SwiftyJSON version: github "acegreen/SwiftyJSON" "swift3"
Xcode version: 8 GM (which is on the App Store)
Dependency manager + version: Carthage 0.18
Command-line tools are best with static archives because everything is distributed as a single binary. Looking at Realm, I don't see that there is a static archive option. They do have an iOS static framework that I got compiling for macOS but that's not quite what you want. You might want to try playing with Realm's source a bit more to see if you can get it to produce a static archive.
In the mean time, as a workaround, you'll need to tell Xcode where to find the dylibs at runtime and also to install them somewhere.
In your Build Settings, go down to "Runpath Search Paths" and add "#rpath".
In Build Phases, under Copy Files, click the + button and add both Realm.framework and RealmSwift.framework from your project.
Because Realm is compiled with an older version of Swift, you also need to specify "Use Legacy Swift Language Version" in Build Settings.
That will get your project building and finding the Realm libraries but now it will fail to find libswiftCore.dylib. That's because normally command-line tools are statically linked with the Swift library but as soon as you add a framework/dylib, the linker no longer includes the static version.
Go back to Build Phases, Copy Files, and add the following:
libswiftObjectiveC.dylib
libswiftIOKit.dylib
libswiftFoundation.dylib
libswiftDispatch.dylib
libswiftDarwin.dylib
libswiftCoreGraphics.dylib
libswiftCore.dylib
You can find them inside your Xcode installation and then ./Contents/Developer/Toolchains/Swift_2.3.xctoolchain/usr/lib/swift/macosx/
WARNING: Keep in mind that you will need to distribute the frameworks and the dylibs with your command-line tool and they will need to be in the same directory as the tool. You can put them somewhere else on the system by specifying a different runpath but you'll still need them distributed with your tool.
The nice thing about a .app bundle is that it gives you a place to put this stuff and users can just drag-and-drop it to install it. If you could get a static archive version of Realm, you could distribute everything in one binary.

CMake Roundtrip Workflow

I understand that CMake enables a project to be easily built in a variety of compiler/IDE environments. I have experienced this for myself and was amazed when CMake produced a working, buildable Xcode project for me from some open source project (cool!)
But what I don't understand is how you properly update the CMake system after you have made significant changes to the project that CMake created for you.
For example I am envisioning a workflow in which the project should be kept portable via CMake. So I create a clone of a github project, use CMake to create my XCode project, and then go to work implementing some new feature or bug fix. Perhaps these changes are non-trivial and affect build.
After these changes are complete I want to push the code base back to github. What happens now? Must all of the CMake files be updated by hand to reflect all of the work that I've done? Or is there some equally magical feature to update the CMake files with the changes that were implemented in XCode (or Visual Studio, or some other supported IDE/compiler combo)?
What is the general "Roundtrip" workflow with CMake and how efficient is it?
The point is that you change your project by changing the CMake configuration files themselves. It could be that you'll find some other tool which manages cmake projects, which will make changes to your cmake files. In the example you mention, you have to check if XCode is modifying your cmake files.
You have to commit all the necessary modifications you do to your cmake files, and your build program (make, ninja, or any other) will run cmake every time the cmake project files are touched.
Advanced note: if you use the command file with globbing instructions to get the list of your sources files, you might be interested to read Getting cmake to run before building after pulling from git

mingw-w64-v2.0.6.tar.gz - define environment variables path

I download the latest version of minGW - mingw-w64-v2.0.6.tar.gz . Then I extract in into C:\MinGW . As I saw in some articles, now I have to define the path under environment variables .
In C:\MinGW now have -
I tried to set the variable value of path as C:\MinGW , but when I do in eclipse juno build path for some project I get -
make all
Cannot run program "make": Launching failed
Error: Program "make" not found in PATH
EDIT:
I downloaded GCC+binutils 64-bit ,exctract to c:\mingw64 , change the path to c:\mingw64\bin and changed the build command to mingw32-make.
Now when I build the project I get error -
mingw32-make all
mingw32-make: *** No rule to make target `all'. Stop.
2nd EDIT :
finally I succeeded to run a project by chose -
Note that it must uncheck the show project type and toolchians only if they are supported on the platform otherwise it not let to chose Executable Project type . In addition the build command should be stay on "Use default build command" .
You downloaded the source package.
You need a toolchain (GCC+binutils and maybe make/gdb). Those are located here:
32-bit
64-bit
I recommend my (rubenvb) Personal builds. They are tidy, full-featured and up to date.
After extracting the toolchain anywhere (say, D:\), add D:\mingw64\bin or D:\mingw32\bin to PATH. Or double-click on the batch scripts I include with my latest builds and it'll be done for you.
Note that you'll need to set up Eclipse for MinGW compilation, which means using mingw32-make, not make.
Lastly, I also suggest using MinGW-w64's support channels (forum and mailing list; please subscribe before posting to mingw-w64-public) in the future. I linger there, among other generally nice and helpful people.

Building c++ project in Ubuntu Linux with Makefile.am/Makefile.in

I am new in Ubuntu/Linux and I've been working with java using the NetBeans IDE, so I don't have much experience with building c++ projects. But now I have to provide a proof of concept and I need to connect a C++ client with my ActiveMQ server. I downloaded The ActiveMQ-CPP API from this link, but I can't build/run it.
The download came with the files: Maklefile.am and Makefile.in. I searched it and I found that I need automake/autoconf to build it. I tried running ./configure but it says that it couldn't find such file or directory. I tried
sudo apt-get update
sudo apt-get install automake
sudo apt-get install autoconf
and a lot of other commands that I found on the Internet. None of then worked. I know that this question is really basic and it seems to be already answered somewhere else, but every attempt I've made failed. I think I'm missing something. I even tried the solution provided in the last message in this topic but it didn't work either.
Can anyone help me install autoconf/automake, or tell me how to use Makefile.am / Makefile.in to build the project I downloaded, or even suggest me some other way of building it?
Since you're open to other methods of building your project, I'm going to suggest CMake. It is a far better build system than autotools (at least from where I stand).
#CMakeLists.txt
project(MyProject CXX)
set_minimum_required(VERSION 2.8)
add_executable(foobar foo.cpp bar.cpp)
That example will build an executable called "foobar" by compiling and linking foo.cpp and bar.cpp. Put the above code in a file called CMakeLists.txt, then run the following commands:
cmake <path to project> #run in the folder you want to build in
make #this does the actual work
The really cool thing about CMake is that it generates a build system (Makefiles by default) but you can use it to generate project files for Eclipse, a Visual Studio solution, and a bunch of other things. If you want more information, I'd check out their documentation.
The "configure" script should be in your ActiveMQ-cpp source directory. From the Linux command line, you should be able to:
1) "cd" into your ActiveMQ* directory
2) "ls -l" to see the "configure" script
3) "./configure" to set things up for building the library\
4) "make" to actually build the library
This is mentioned in comments, but this particular point of confusion has been common for well over a decade and I think needs to be clarified as often as possible. You DO NOT need to have autoconf or automake installed to build a project that used those tools. The entire point of the autotools is to generate a build system that will build on a system using only the standard tools (make, a c compiler, sh, and few others.) Unfortunately, many developers release tarballs that do not build cleanly. If you unpack the tarball and it does not contain a configure script, or if the configure script is broken, that is a bug in the package. The solution is absolutely not to install autoconf/automake/libtool and try to produce a working configure script. The solution is to report the build error as a bug to the package maintainer.
The world would be a better place if Linux distributions stopped installing multiple versions of the autotools by default as less than .002% of the population needs those tools, and anyone who actually needs to have the tools should be capable of installing it themselves. Anyone incapable of acquiring and installing the tools has no business using them.