OSX Bundle Architecture - objective-c

I need to compare the architecture of a bundle and compare it to the machines architecture from an installer; if they match the installation will proceed else it will abort.
Getting the architecture is easy by using macros; I would like to know if there is a way of checking the architecture of the bundle to be installed.

From the shell, you can do
otool -hv <path to mach-o image>
Images are usually in Contents/MacOS in applications or Versions/Current in frameworks

This will determine if the current application (or whatever bundle determined to be the mainBundle) shares a common architecture with the target bundle. Requires Mac OS X 10.5 for NSBundle's executableArchitectures method.
NSArray *targetArch = p[NSBundle bundleWithPath:#"/path/to/bundle.bundle"] executableArchitectures];
NSArray *thisArch = [[NSBundle mainBundle] executableArchitectures];
if ([targetArch firstObjectInCommonWithArray:thisArch])
{
// target bundle has architecture which matches current application
}

Related

Programatically checking for NSBundle in macOS

I am building my application for macOS using CMake. My application can either be MACOSX_BUNDLE i.e. generated as a .app through CMake or it can even be a Unix-style executable.
Is there a programmatic way in Obj-C to check if the executable is Unix-Style or NSBundle?
Assuming you use Foundation and Objective-C in both binaries it is possible to check using NSBundle properties, because bundle instance itself will created on both cases (it just references to folder around executing binary), but bundle info will be present only on macOS.
So here is possible approach:
if (nil != [[NSBundle mainBundle] bundleIdentifier]) {
// macOS code here
} else {
// linux code here
}

Qt5 can't seem to find Objective-C libraries: unknown type name 'NSAutoreleasePool', etc

I have a Qt4.8.4 desktop application that builds and runs fine on my Macbook Pro, running Mountain Lion with Xcode 5.0.2, using Qt Creator 2.7.0 with Qt 4.8.4 and GCC (x86 64bit). I am trying to port my application to Qt 5.2.1. My code is C++ with some Objective-C.
I built Qt5.2.1 on my same Macbook pro with this configuration:
./configure -prefix $PWD/qtbase -debug-and-release -developer-build -no-c++11 -opensource -plugin-sql-sqlite -nomake tests -confirm-license
and it configured and built fine.
When I try to build my application in Qt Creator 2.7.0 using Qt 5.2.1 and either GCC (x86 64bit) or Clang (x86 64bit), I get lots of errors that seem to me to indicate that the Objective-C parts of my application can't find the libraries they need. For example:
/Users/david/dev/svn/map_creator3/src/widgets/mac_toolbar_button_proxy.mm:15: warning: instance method '-selectedSegment' not found (return type defaults to 'id') [-Wobjc-method-access]
target_->TriggerAction([sender selectedSegment]);
^~~~~~~~~~~~~~~
/Users/david/dev/svn/map_creator3/src/common/locations_mac.mm:34: error: use of undeclared identifier 'NSWorkspace'
[[NSWorkspace sharedWorkspace]
^
/Users/david/dev/svn/map_creator3/src/widgets/mac_toolbar_button_control.mm:30: error: unknown type name 'NSAutoreleasePool'
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
^
and lots more like that. Is there some magic setting somewhere that I need to add, to use Object-C in a C++ Qt5 desktop application?
Merlin069 got me on the right track in the comments on my question (thanks!), and I found an example here. These build errors (and a number of others) disappeared when I added
LIBS += -framework Cocoa
and in my .mm files that were complaining,
#include <Cocoa/Cocoa.h>

"curl_rule_01 declared as an array with negative size" error on built xcode 5 iOs7

I am trying to archive an iOS 7 App that is using BBHTTP-library which includes libCurl. The built-error:
curl_rule_01 declared as an array with negative size
The code-line in curlrules.h with the error:
[CurlchkszEQ(long, CURL_SIZEOF_LONG)];
I've tried it with these changes in curlbuild.h
#define CURL_SIZEOF_LONG 4
to
#define CURL_SIZEOF_LONG 8`
due to 64 bit, but it didn't change anything.
Be careful: you must NOT change these macros inside curlbuild.h! This header is generated at configure time and it records (among other things) which architecture is targeted.
If you look at the pre-built static library provided by BBHTTP you can see that it only targets ARMv7 and ARMv7s architectures:
$ otool -fV External/libcurl.iOS/libcurl.iOS.appstore.a | grep Archive
Archive : External/libcurl.iOS/libcurl.iOS.appstore.a (architecture armv7)
Archive : External/libcurl.iOS/libcurl.iOS.appstore.a (architecture armv7s)
These are 32-bit architectures. Please refer to BBHTTP Dependencies for more details regarding how this static library has been compiled.
If you build an iOS app with iOS 7 as deployment target you certainly have the default archs configured within your build settings. And these defaults include a 32-bit slice, plus a 64-bit slice:
So in such a case you must include a libcurl fat static library that also contains a 64-bit slice (a.k.a arm64).
The curl iOS build scripts from BBHTTP's author might help you. Otherwise please refer to Nick Zitzmann libcurl pre-built.

Cross-compiling - retrieve target CPU and version

I'm cross-compiling for VxWorks using cmake. When I run cmake the first time I have to provide informations about compiler, target OS etc..
In the cross-compile dialogue there are three target system settings I set:
Operating System
Version
Processor
(followed by compiler etc.)
While I can retrieve the first one using CMAKE_SYSTEM_NAME, i can't get the version and the processor.
Both return an empty string.
Here's an example:
MESSAGE("CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
MESSAGE("CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}")
Output:
CMAKE_SYSTEM_PROCESSOR:
CMAKE_SYSTEM_VERSION:
My Cmake Version is 2.8.10.2 and target OS is VxWorks (if this matters - compiler are WindRiver GNU).
How can I get the version and processor I've set in the beginning? Or is this impossible if I cross-compile to an OS that's unknown to cmake?
(Btw. Compiling works fine)
It seems this is not possible so far. I'm getting empty strings all the time.
However, there's a working solution, and i guess it's the better way:
Before:
I specified cross-compile settings (Compiler and target system, see question), then it runs over VxWorks specific parts in the CMake list (checked with if( VxWorks ) to ensure it's not executed when other systems are used).
Now (Solution):
I wrote a toolchain file and platform files for VxWorks and required processors.
Cons:
I have to write some extra files:
Toolchain file
Platform file for VxWorks
Further Platform files for each Processor (and processor type, Gnu and Diab)
Pros:
CMake list is much cleaner now
Separate Project and Target settings
Separate System and processor settings - easy to add new Processors in a very clear way but keep System settings
I write some settings in the toolchain file and CMake loads related system / processor settings
...

Conditionally linking for #autoreleasepool

When I try to run my application in the iOS 4.3 simulator (Xcode 4.2), I crash when I hit #autoreleasepool{}, with:
dyld: lazy symbol binding failed: Symbol not found: _objc_autoreleasePoolPush
I looked around, and I see the workaround is to add libarclite_iphoneos.a. There's a version of this for the simulator, too, as libarclite_iphonesimulator.a.
I need to add both libraries to my project to make it run on both the simulator and hardware. But whichever I build, it complains that the other library is for an unsupported architecture.
For example, building for simulator:
ld: warning: ignoring file /Developer-4.2/Platforms/iPhoneOS.platform/
Developer/usr/lib/arc/libarclite_iphoneos.a, missing required architecture
i386 in file
How do I fix both of these simultaneously? Or should I just stick with the old NSAutoreleasePool syntax for now?
After a trials like clean, clean folder, resetting iPhone Simulator and even a restart, I changed the IPHONE_DEPLYMENT_TARGET on the target build setting down from iOS 5.0 to iOS 4.2.
Worked.
You can use the Other Linker Flags build setting to link in the library, and specialize the value based on whether it's "Any iOS" or "Any iOS Simulator".
You can also merge the two static libraries to one universal library. Go to the Terminal and say
lipo -create -output /where/you/want/it/libarclite_universal.a /Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/arc/libarclite_iphoneos.a /Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/arc/libarclite_iphonesimulator.a
You can verify the resulting file by saying (in Terminal)
file /where/you/put/it/libarclite_universal.a
It should output:
libarclite_universal.a: Mach-O universal binary with 3 architectures
libarclite_universal.a (for architecture i386):current ar archive random library
libarclite_universal.a (for architecture armv6):current ar archive random library
libarclite_universal.a (for architecture armv7):current ar archive random library
Since this lib is linked statically, your final app wont grow because of the included sim library since only whatever is needed by your app will get linked into your final app.