Is there any non-Xcode-based command line unit testing tool for Objective-C? - objective-c

The post Compiling Objective-C without GUI says the following:
To compile Objective-C on OSX the easy way you have to get XCode, which is free to obtain from the Application Store. Getting XCode will ensure you obtain the necessary frameworks (headers), like Foundation, Cocoa, etc. This will, however, not provide you with the necessary command line tools to compile Object-C from the command line. Open up XCode, go to Preference > Downloads > Components and Install Command Line Tools. This will install gcc, clang, make, etc.
I am looking for a non-Xcode-based tool to address this my question, I've just opened: Is it possible to make an Objective-C project to be tested on Travis?
This tool should meet the following requirements:
It should be not related to Xcode in any way.
The following level of simplicity is pretty enough: just some int main {} code collecting all test-cases files nearby and running test assertions on the code I want to test (like ST- in SetTestingKit or GH- in GHUnit)
I don't need UI, GUI, Xcode, simulator.
It will be great if it could work both on Mac and Ubuntu (yeah, Travis), possibly using
GNUstep like the quoted post describes.
UPDATE BASED ON ACCEPTED ANSWER:
The following simple setup, based on what Malte Tancred have said in the accepted answer, seems pretty enough for my current needs:
Three files, all in the tests directory of my project:
octest.m
#import <Foundation/Foundation.h>
#import <SenTestingKit/SenTestingKit.h>
int main() {
#autoreleasepool {
SenSelfTestMain();
}
return 0;
}
Makefile
CC=clang # or gcc
# Trick to get current dir: https://stackoverflow.com/questions/322936/common-gnu-makefile-directory-path
TESTS_DIR:= $(dir $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR:= $(TESTS_DIR)/..
FRAMEWORKS_PATH:= -F/Applications/Xcode.app/Contents/Developer/Library/Frameworks
FRAMEWORKS:= -framework Foundation -framework SenTestingKit
LIBRARIES:= -lobjc
INCLUDE_PATHS:= -I$(PROJECT_DIR)/Projectfiles\
-I$(TESTS_DIR)/TestHelpers
SOURCE_FILES = $(wildcard $(PROJECT_DIR)/Projectfiles/*.m)
SOURCE_TEST_SUITE = $(wildcard $(TESTS_DIR)/Tests/*.m)
SOURCE_TESTS = $(TESTS_DIR)/TestHelpers/TestHelpers.m\
octest.m
CFLAGS=-Wall -Werror -fobjc-arc -g -v $(SOURCE_FILES) $(SOURCE_TEST_SUITE) $(SOURCE_TESTS)
LDFLAGS=$(LIBRARIES) $(FRAMEWORKS)
OUT=-o octest
all:
$(CC) $(FRAMEWORKS_PATH) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(OUT)
runtests
#!/bin/bash
export DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Library/Frameworks
make
./octest
UPDATE TO CAPTURE EXIT CODE:
A few days after I had asked this question, Travis announced Objective-C support:
http://about.travis-ci.org/blog/introducing-mac-ios-rubymotion-testing/
Though there are default scripts they suggest to use to make builds, I have decided to take the approach described here and still use octest instead of approach with xcodebuild that Travis uses.
By default travis setup relies on the build scripts written by Justin Spahr-Summers: https://github.com/jspahrsummers/objc-build-scripts:
They use awk to capture exit code from xcodebuild's output, since it always exists with 0 exit code, even if the whole test suite has failing!
OCTest behaves the same way - it always exists with 0 code, and here is how I've used simplified version of Travis awk script for my needs of building it the way I decribed above:
octest.awk
# Exit statuses:
#
# 0 - No errors found.
# 1 - Build or test failure. Errors will be logged automatically.
BEGIN {
status = 0;
}
{
print;
fflush(stdout);
}
/[0-9]+: (error|warning):/ {
errors = errors $0 "\n";
}
/with [1-9]+ failures?/ {
status = 1;
}
END {
if (length(errors) > 0) {
print "\n*** All errors:\n" errors;
}
fflush(stdout);
exit status;
}
runtests
#!/bin/bash
export DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Library/Frameworks
make
runtests ()
{
./octest 2>&1 | awk -f "octest.awk"
local awkstatus=$?
if [ "$awkstatus" -eq "1" ]
then
echo "Test suite failed"
return $awkstatus
else
echo "Test suite passed"
return 0
fi
}
echo "*** Building..."
runtests || exit $?

There are ports of objcunit for non Mac platforms. You can look at the port in MidnightBSD that works with GNUstep. The patches should work for other environments too. The pkg-descr has the packages website and the Makefile will have the download URL.

The answer to your main question is yes:
there are command line testing tools for Objective-C
that does not depend on Xcode.
For example,
you can use OCUnit/SenTestingKit without using Xcode.
All you have to do
is to point your compiler/linker to the framework.
Consider the follwing file, octest.m:
#import <Foundation/Foundation.h>
#import <SenTestingKit/SenTestingKit.h>
int main() {
#autoreleasepool {
SenSelfTestMain();
}
return 0;
}
#interface MyTest : SenTestCase
#end
#implementation MyTest
- (void)testSomething {
STAssertEquals(1, 2, #"fail");
}
#end
Compile it:
clang -o octest octest.m -F/Applications/Xcode.app/Contents/Developer/Library/Frameworks -framework Foundation -framework SenTestingKit
Now run it
DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Library/Frameworks ./octest
and you should see something like
Test Suite '/tmp/octest(Tests)' started at 2013-04-04 12:34:49 +0000
Test Suite 'MyTest' started at 2013-04-04 12:34:49 +0000
Test Case '-[MyTest testSomething]' started.
octest.m:16: error: -[MyTest testSomething] : '1' should be equal to '2': fail
Test Case '-[MyTest testSomething]' failed (0.000 seconds).
Test Suite 'MyTest' finished at 2013-04-04 12:34:49 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) seconds
Test Suite '/tmp/octest(Tests)' finished at 2013-04-04 12:34:49 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.001) seconds
make: *** [default] Error 1
This example does depend on Xcode
in that it uses the bundled SenTestingKit framework
but the general process of building and running the tests
as described above
does not depend on Xcode.
Now,
to get this running on a linux system
you'd have to install SenTestingKit (and most probably GNUstep),
but with those components in place
the build and test process should be essentially the same.

For compiling objective-C, I know a quick and dirty (and somewhat limited) way of doing it - I do it online at http://www.compileonline.com/compile_objective-c_online.php . That said, this compiler throws back a lot of c-99 errors which I think is due to it being a strict superset of C and not including some of the more unique features of the language (e.g.: #synthesize, or even dot notation), but it gets the job done. I type up the code with Notepad++. Like I said, limited, but surgical.
*Also - it supports command line style input, which is solid.

Look at xctool from facebook which is a replacement for Apple's xcodebuild. We build our Objective-C library using maven and use it only for tests instead of xcodebuild and it works great. The output is much more readable as compared to xcodebuild.
From the xctool page,
xctool is a replacement for Apple's xcodebuild that makes it easier to build
and test iOS and Mac products.
One thing to note though is it does not support building targets. You can use a scheme though.

Related

wxwidget build failed - windows - mingw - mingw32-make: *** [..\..\lib\gcc_dll\wxmsw313u_gcc_custom.dll] Error 1

I was trying use build wxWidgets-3.1.3 with MinGW-W64 on a x64 windows machine.
I followed this thread, which lead me to download and building. So I installed it and some youtube videos said I need to build it now. So navigate to the installed folder and gave this command :
mingw32-make -f makefile.gcc BUILD=release SHARED=1 MONOLITHIC=1 UNICODE=1.
It took almost half an hour and now it's giving me error saying :
collect2.exe: error: ld returned 1 exit status
makefile.gcc:5329: recipe for target '..\..\lib\gcc_dll\wxmsw313u_gcc_custom.dll' failed
mingw32-make: *** [..\..\lib\gcc_dll\wxmsw313u_gcc_custom.dll] Error 1
Here is the full log file :
https://pastebin.com/zxeHhF6K
MinGW configuration :
Version : 8.1.0
Architecture : x86_64
Threads : posix
Exceptions : seh
Build version : 0
How can I solve this? I'm using CLion, is there any other short or easy way?
The relevant error is
..\..\lib\gcc_dll/libwxexpat.a(wxexpat_xmlparse.o):xmlparse.c:(.text+0x337d): undefined reference to `_imp__rand_s'
and it's very strange because MinGW-w64 8.1 is definitely supposed to have rand_s(). Are you sure you're using the right compiler? I.e. what does g++ -v give you if you run it from the same command prompt?
My only hypothesis is that it's some different (and much older) compiler and the solution would be to just use the right one instead.
Also, the next time you could use -j4 option with make if you have at least 4 logical CPUs in your machine (and chances are you do nowadays), to significantly speed up the build.
Looking back in my notes I once had an issue with missing rand_s() when building glib2 on a certain MinGW build.
I was able to fix it then by adding this at the top of the C file that called this function:
#include <time.h>
#include <stdlib.h>
int rand_s (unsigned int* r)
{
static int srand_called = 0;
if (!srand_called) {
srand(time(0));
srand_called++;
}
if (r)
*r = rand();
return 0;
}
In your case that would be in xmlparse.c.

How to build AWS C++ SDK on Solaris?

I am trying to build the AWS C++ SDK on Solaris, but I cannot do so successfully.
I found this open issue on the AWS C++ SDK page that says it is possible, but there is no guide on it and I am hoping somebody here can help.
Here is the command I use to build it:
$ cmake ../aws-sdk-cpp/ -DCMAKE_BUILD_TYPE=Debug -DBUILD_ONLY="s3"
Here is the output:
-- TARGET_ARCH not specified; inferring host OS to be platform compilation target
-- Building AWS libraries as shared objects
-- Generating linux build config
-- Building project version: 1.7.134
-- Configuring done
-- Generating done
-- Build files have been written to: /workspace/dmoini/sdk_build/.deps
gmake: Warning: File 'Makefile' has modification time 267 s in the future
gmake[1]: Warning: File 'CMakeFiles/Makefile2' has modification time 267 s in the future
gmake[2]: Warning: File 'CMakeFiles/AwsCCommon.dir/progress.make' has modification time 267 s in the future
gmake[2]: warning: Clock skew detected. Your build may be incomplete.
gmake[2]: Warning: File 'CMakeFiles/AwsCCommon.dir/progress.make' has modification time 267 s in the future
[ 4%] Performing build step for 'AwsCCommon'
[ 1%] Building C object CMakeFiles/aws-c-common.dir/source/array_list.c.o
In file included from /usr/include/stdio.h:37:0,
from /workspace/dmoini/sdk_build/.deps/build/src/AwsCCommon/include/aws/common/common.h:22,
from /workspace/dmoini/sdk_build/.deps/build/src/AwsCCommon/include/aws/common/array_list.h:18,
from /workspace/dmoini/sdk_build/.deps/build/src/AwsCCommon/source/array_list.c:16:
/opt/gcc-5.1.0/lib/gcc/i386-pc-solaris2.11/5.1.0/include-fixed/sys/feature_tests.h:405:2: error: #error "Compiler or options invalid for pre-UNIX 03 X/Open applications and pre-2001 POSIX applications"
#error "Compiler or options invalid for pre-UNIX 03 X/Open applications \
^
gmake[5]: *** [CMakeFiles/aws-c-common.dir/build.make:63: CMakeFiles/aws-c-common.dir/source/array_list.c.o] Error 1
gmake[4]: *** [CMakeFiles/Makefile2:484: CMakeFiles/aws-c-common.dir/all] Error 2
gmake[3]: *** [Makefile:139: all] Error 2
gmake[2]: *** [CMakeFiles/AwsCCommon.dir/build.make:112: build/src/AwsCCommon-stamp/AwsCCommon-build] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/AwsCCommon.dir/all] Error 2
gmake: *** [Makefile:84: all] Error 2
CMake Error at CMakeLists.txt:193 (message):
Failed to build third-party libraries.
Additionally, here is my system information:
$ uname -a
SunOS bld-dmoini-01-sv4b 5.11 omnios-r151020-4151d05 i86pc i386 i86pc
Any and all help/guidance is greatly appreciated.
I've successfully completed compiling the AWS C++ SDK on a stock install of Solaris 11.4, and found several issues that could cause the problems noted.
Start with a clean source tree.
Remove -Werror
The first thing do to is remove the -Werror compiler options. The version of OpenSSL installed by default on Solaris 11.4 has quite a few deprecated functions, and the -Werror option causes the build to fail when it runs into those deprecations. I used this find command run from the topmost directory of the AWS SDK source tree to remove all the -Werror options:
vi `find . | xargs grep -l Werror`
You'll get about three or four files, only two of which are actually setting the -Werror as a compiler option. Just remove the "-Werror" strings from those files.
Fix the POSIX defines
Then run cmake . in the topmost directory. It will fail because the cmake files that it downloads will have improper POSIX command-line options - -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=500. That 500 is wrong. _POSIX_C_SOURCE=200809L corresponds to _XOPEN_SOURCE=700. _XOPEN_SOURCE=500 is SUSv2, circa 1997. It's not proper to compile a SUSv2 application with C99.
Per 2.2.1 Strictly Conforming POSIX Application, paragraph 8:
For the C programming language, shall define _POSIX_C_SOURCE to be 200809L before any header is included
and 2.2.4 Strictly Conforming XSI Application, paragraph 8:
For the C programming language, shall define _XOPEN_SOURCE to be 700 before any header is included
Per the Illumos sys/feature_tests.h file (based on OpenSolaris, which was also the basis for Solaris 11):
* Feature Test Macro Specification
* ------------------------------------------------ -------------
* _XOPEN_SOURCE XPG3
* _XOPEN_SOURCE && _XOPEN_VERSION = 4 XPG4
* _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED = 1 XPG4v2
* _XOPEN_SOURCE = 500 XPG5
* _XOPEN_SOURCE = 600 (or POSIX_C_SOURCE=200112L) XPG6
* _XOPEN_SOURCE = 700 (or POSIX_C_SOURCE=200809L) XPG7
The files cmake downloads via git need to be edited:
vi `find .deps | xargs grep -l XOPEN_SOURCE`
Change any -D_XOPEN_SOURCE=500 to -D_XOPEN_SOURCE=700 and rerun cmake .. It should complete successfully this time.
Then run gmake. (I find gmake works much better on Solaris for just about all open source projects, as many open source projects use GNU-specific make extensions.)
Now you get to fix any broken source code you run into.
Fix broken source code
1
The file aws-sdk-cpp/aws-cpp-sdk-core/source/platform/linux-shared/OSVersionInfo.cpp has the following wrong code:
Aws::String ComputeOSVersionString()
{
utsname name;
int32_t success = uname(&name);
Per POSIX, the correct type is struct utsname, not just utsname:
int uname(struct utsname *name);
The AWS code needs to be:
Aws::String ComputeOSVersionString()
{
struct utsname name;
int success = uname(&name);
And no, I'm most certainly not impressed with the quality of the AWS code, given this, umm, laugher:
while (!feof(outputStream))
Yes, an actual while (!feof()) loop...
2
The file aws-sdk-cpp/aws-cpp-sdk-mediaconvert/include/aws/mediaconvert/model/M2tsSegmentationMarkers.h uses an enumeration with the value EBP, which conflicts with the EBP register #define in /usr/include/sys/regset.h.
I just changed it to EBP_HASH as that seems to match the code somewhat:
vi `find . | xargs grep -l EBP`
3
The file aws-sdk-cpp/aws-cpp-sdk-route53domains/include/aws/route53domains/model/CountryCode.h creates an enumeration value ES that conflicts with the ES register #define in /usr/include/sys/regset.h. I just added
#ifdef ES
#undef ES
#endif
and the compile continued. I don't know if that #undef could have broken anything.
4
The file aws-sdk-cpp/aws-cpp-sdk-waf/include/aws/waf/model/GeoMatchConstraintValue.h has ES, GS, and SS enumeration value that conflict with the ES, GS, and SS register #define's in /usr/include/sys/regset.h.
Again, I just added a few more #undef's:
#ifdef ES
#undef ES
#endif
#ifdef GS
#undef GS
#endif
#ifdef SS
#undef SS
#endif
I'm really wondering why sys/regset.h is being #include'd in just about everything in the AWS SDK.
5
Same problem in aws-sdk-cpp/aws-cpp-sdk-waf-regional/include/aws/waf-regional/model/GeoMatchConstraintValue.h. Same fix, add:
#ifdef ES
#undef ES
#endif
#ifdef GS
#undef GS
#endif
#ifdef SS
#undef SS
#endif
Note that compiling on SPARC hardware means the #define value from sys/regset.h will be completely different, and any errors will be completely different.
6
The file aws-sdk-cpp/aws-cpp-sdk-core-tests/utils/FileSystemUtilsTest.cpp incorrectly assumes the POSIX NAME_MAX value is defined. Per the POSIX Pathname Variable Values standard (bolding mine):
Pathname Variable Values
The values in the following list may be constants within an
implementation or may vary from one pathname to another. For example,
file systems or directories may have different characteristics.
A definition of one of the symbolic constants in the following list
shall be omitted from the <limits.h> header on specific
implementations where the corresponding value is equal to or greater
than the stated minimum, but where the value can vary depending on the
file to which it is applied. The actual value supported for a specific
pathname shall be provided by the pathconf() function.
Again: the "definition ... shall be omitted ... where the value can vary".
The AWS code wrongly assumes NAME_MAX must be #define'd.
I just hardcoded a value of 255 to get past this point, although using something like _POSIX_NAME_MAX or _XOPEN_NAME_MAX is probably better.
7
File aws-sdk-cpp/ws-cpp-sdk-core-tests/http/HttpClientTest.cpp seems to be incorrectly assuming a std::shared_ptr will be 8 bytes. This question and answer provides a good example of how that's wrong.
I just ignored this error as it's just a test and continued with gmake -i, which completed successfully outside of this one error.

GCC and -fsanitize=leak

I'm working and on a large C++ project and making it compile with clang would be painful, so I'm stuck with GCC.
I want to use the nice -fsanitize=leak flag that I already used with clang on a previous job, but it does not seem to work.
I made a very simple example to test it:
#include <stdlib.h>
void FooBar() {
malloc(7);
}
int main() {
FooBar();
return 0;
}
With clang it works as expected:
>> clang -fsanitize=leak main.cpp
>> LSAN_OPTIONS=detect_leaks=1 ./a.out
=================================================================
==18052==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 7 byte(s) in 1 object(s) allocated from:
#0 0x41dcbc (~/dev/addresssanitizertest/a.out+0x41dcbc)
#1 0x431ac3 (~/dev/addresssanitizertest/a.out+0x431ac3)
#2 0x431ae3 (~/dev/addresssanitizertest/a.out+0x431ae3)
#3 0x7f8077e71a3f (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f)
SUMMARY: LeakSanitizer: 7 byte(s) leaked in 1 allocation(s).
>>
But with gcc it does not seem to detect anything:
>> gcc -fsanitize=leak main.cpp
>> LSAN_OPTIONS=detect_leaks=1 ./a.out
>>
Did I miss something like a nice environment variable? Did someone ever made it work with gcc?
EDIT: This works for instance:
g++ -fsanitize=address main.cpp
ASAN_OPTIONS=detect_leaks=1 ./a.out
But I can't do that: the perf drawback is too much. I only want leak detection.
You must read this and use the patch :
https://gcc.gnu.org/ml/gcc-patches/2013-11/msg01874.html
I resolved it with gcc 5.1 (I was using 4.9).
EDIT: it looks like 5.2 does not work either
EDIT2: it does not work with the gcc provided with ubuntu 15.10 (5.2.1), however I recompiled a 5.2.0 from sources and it worked fine. I really have no clue.
I had the same issue (with Ubuntu 15.04 and gcc 4.9.2).
Using ldd I noticed that liblsan.so was not linked, so here how I fixed it :
1) Force linking during compilation
>> gcc -fsanitize=leak main.cpp -llsan
2) Execute with
./a.out

XCode 5 unit testing: starts my app

When I run my tests in XCode 5, the main window of my OS X app appears on the screen for a couple of seconds while running the tests. Why? Even if I uncomment all my tests it still opens my main window.
You are running application test, not logic test. This means an instance of your app will be started and then run the unit tests. This allow you to perform some integration test that require your app is running.
Here is the guide to setup application test and logic test.
If you want to change it to logic test (so it run faster and don't need to start your app first):
go to build settings for your unit test target
search Bundle
remove Bundle Loader and Test Host
Thats right, you have to delete the "Bundle Loader" and "Test Host" from your build settings.
But you have to add the necessary implementation files to your unit test target. The necessary files are what you want to use in your unit test cases. You need to do this because in logic tests XCode wont compile the whole application. So some of your files will be missing.
This is en error message if you have left out a file:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_Module", referenced from:
objc-class-ref in Lobic Network.o
objc-class-ref in Logic_Unit.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You can add the missing files by selecting the implementation file and bringing up the file inspector. There will be a section named "Target Membership" and there you can set the files target membership to your unit test also.
With XCTest, application files DO NOT need to be included within XCTest targets. The XCTest bundle is linked against the application which makes those files available during runtime.
To make this work, ensure the compiler option "Symbols hidden by default" is set to NO Within the Application target.
Here is a blog post with screenshots for clarity:
http://zmcartor.github.io/code/2014/02/24/slim-xctest-targets
The advantage of this approach is test target builds much much faster.
In XCode 7, removing Host Application does not work for me. Indeed I use the following to avoid app runs.
Setup Test Scheme Arguments
in main.m
static bool isRunningTests()
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* testEnabled = environment[#"TEST_ENABLED"];
return [testEnabled isEqualToString:#"YES"];
}
modify main()
int main(int argc, char * argv[]) {
#autoreleasepool {
if (isRunningTests()) {
return UIApplicationMain(argc, argv, nil, nil);
} else {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
}
If the tests are for code that can run on desktop and mobile, you can run them without a simulator or hosting them within your app.
The trouble is that you cannot use the scheme chooser for your normal target (desktop or iOS) to run the test.
The following worked for me in Xcode6.
File > New Target...
Select Cocoa Testing Bundle from the OS X category.
Take care to select None from the target drop-down.
Click Finish. Add the relevant files to the new target as described above.
Now create a scheme to run the test.
Click the schemes chooser top-right and choose New Scheme..., click the drop-down and navigate down the list to the new target. Now you can choose the scheme from the schemes chooser, and use ⌘U to run the tests.
I just wasted a morning on this.
Project was created in XCode 4 and used SenTesting.
Tried migrating tests on XCode 5/XCTTest
Had same issue - app ran in simulator and test never started
after trying everything (change from app to logic tests, change to XCTest, remove SenTesting)
gave up created a clean XCode 5 project.
Added all my files in and tests ran ok.
May still have issues with Storyboard as these were built with XCode 4.
Drastic but it works so keep it as last resort.
On XCode5, the app does start. This answer shows how to change its delegate when running unit tests so that it exits right away: https://stackoverflow.com/a/20588035/239408

Adobe ANE works on iOS and Android devices, but not in AIR simulator

The vibration ane by Adobe works well in a Flex mobile app both on iOS and Android, but when I try to launch an AIR simulator from Flash Builder 4.7 on Windows 7 I get the error:
Here a copy of the error message from the latter screenshot:
Process terminated without establishing connection to debugger.
The content cannot be loaded because there was a problem loading an extension: Error: Requested extension com.adobe.Vibration is not supported for Windows-x86.
Launch command details: "C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0 (AIR 3.5)\bin\adl.exe" -runtime "C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0 (AIR 3.5)\runtimes\air\win" -profile extendedMobileDevice -screensize 640x920:640x960 -XscreenDPI 326 -XversionPlatform IOS -extdir "C:\Users\xxx\Adobe Flash Builder 4.7\.metadata\.plugins\com.adobe.flexbuilder.project.ui\ANEFiles\MyApp-Mobile\win32\" C:\Users\xxx\Documents\MyApp\mobile\bin-debug\MyApp-app.xml C:\Users\xxx\Documents\MyApp\mobile\bin-debug
At the same time:
Another ANE by Adobe - the GameCenter.ane included with Adobe Gaming SDK works flawlessly with the AIR Simulator
The com.adobe.extensions.Vibration.ane mentioned above doesn't fail when I select the BlackBerry AIR simulator (but the iOS and Android AIR Simulators do not work).
Is there a way to make this work more comfortable?
I'd like to use the com.adobe.extensions.Vibration.ane in my Flex mobile app, but I also want to use the AIR simulator - without commenting the source code and removing that ANE from project properties.
UPDATE 2016:
Adobe has updated their Vibration native extension (ANE) sample with 64-bit support.
The problem with the ANE is that it's not a complete implementation. Most importantly the ANE doesn't implement a default fallback implementation which is what the device would fallback to if there wasn't a particular implementation for the current platform.
This makes the ANE very hard to use in cross-platform development as it will fail in some cases. Any platform that isn't specifically included will fail with the message you received.
Basically without changing the ANE yourself you won't be able to use it as you are expecting. Your only way is to do some conditional style compilation and not call the ANE in the simulator.
If you do wish to change the ANE then the best option is to implement the default library. This is quite simple, but you will need: XCode, eclipse with Android dev tools, and adt from the AIR SDK.
Firstly you'll need to compile the existing projects, the Android lib, the iOS lib and the existing actionscript library, to generate VibrationAndroidLibrary.jar, libVibrationiOSLibrary.a and VibrationActionScriptLibrary.swc respectively.
You'll then need to make another actionscript library, and duplicate the com.adobe.nativeExtensions.Vibration class as below:
public class Vibration
{
public function Vibration()
{
}
public static function get isSupported():Boolean
{
return false;
}
public function vibrate(duration:Number):void
{
}
}
This class will replace the other class in cases where the extension isn't implemented instead of you getting the above message.
Then we'll need to add the default definition to the extension.xml file:
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
<id>com.adobe.Vibration</id>
<versionNumber>1</versionNumber>
<platforms>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>VibrationAndroidLibrary.jar</nativeLibrary>
<initializer>air.extensions.VibrationExtension</initializer>
<finalizer>air.extensions.VibrationExtension</finalizer>
</applicationDeployment>
</platform>
<platform name="iPhone-ARM">
<applicationDeployment>
<nativeLibrary>libVibrationiOSLibrary.a</nativeLibrary>
<initializer>ExtInitializer</initializer>
<finalizer>ExtFinalizer</finalizer>
</applicationDeployment>
</platform>
<platform name="default">
<applicationDeployment />
</platform>
</platforms>
</extension>
Then we'll need to recompile the ANE using the new default actionscript SWC. Lets say you're in the VibrationNEDeliverables directory from the mentioned ANE, you can enter this into a bash file and run it or put it all on one line from the command line). The first couple of lines just extract the library.swf file and move it to the locations needed by the package command. Be careful with the paths etc here, I've assumed you've put the default lib in VibrationActionScriptDefaultLibrary but you'll need to change this appropriately.
unzip -o -d VibrationActionScriptLibrary/bin VibrationActionScriptLibrary/bin/VibrationActionScriptLibrary.swc
unzip -o -d VibrationActionScriptDefaultLibrary/bin VibrationActionScriptDefaultLibrary/bin/VibrationActionScriptDefaultLibrary.swc
cp VibrationActionScriptLibrary/bin/library.swf VibrationiOSLibrary/build/Release-iphoneos/.
cp VibrationActionScriptLibrary/bin/library.swf VibrationAndroidLibrary/bin/.
adt -package \
-storetype pkcs12 -keystore YOUR_SIGNING_KEY.p12 -storepass KEY_PASSWORD \
-target ane com.adobe.extensions.Vibration.ane VibrationActionScriptLibrary/src/extension.xml \
-swc VibrationActionScriptLibrary/bin/VibrationActionScriptLibrary.swc \
-platform iPhone-ARM -C VibrationiOSLibrary/build/Release-iphoneos . \
-platform Android-ARM -C VibrationAndroidLibrary/bin . \
-platform default -C VibrationActionScriptDefaultLibrary/bin .
Once that's complete you should now have a new version of the ANE with a default lib which will make it much more useable! Personally I don't think an ANE should be released without it.
If you need a fully functional ANE, you can check out ours: http://distriqt.com/native-extensions
A solution that I've used in the past was something like this:
Create a utility class that returns whether you're running on a device that supports the ANE. In my case, the class contained a static method that checked the value of Capabilities.os. See the list of values it can return here.
Put the code that calls the ANE method(s) into their own function, and call this function if the ANE is supported. If I recall correctly, it was necessary to put the code that used the ANE in a separate function, not just inside an if block, otherwise the same error would occur in the simulator:
Do this:
public function doSomethingThatWillUseANE():void
{
if (DeviceCapabilities.supportsANE) // static utility class
{
methodThatUsesANE();
}
}
private function methodThatUsesANE()
{
// execute actual ANE method here
}
Instead of doing it all in one function like this:
public function doSomethingThatWillUseANE():void
{
if (DeviceCapabilities.supportsANE) // static utility class
{
// execute actual ANE method here
}
}
same problem exists with the newest vibration ane built for ios 64bit compatibility. My workaround was to place the ane import statement inside the function that actually called the vibrate method, and uncheck the include box for the ane in the project build path settings for android and ios.
I have a flag variable (set by a separate function) in my application that flags whether the app is being run within the ide. The view that uses vibration will only call the above vibration function if the flag is set to non-IDE mode. I still get an initial warning when I run the ide simulator, but not the critical error. When I do a release build, FlashBuilder forces me to checkmark the include box for the ane in the applicable project build path settings (I have to uncheck it again next time I want to run the simulator).
It's clunky, but it makes working with the ane liveable. Peeves me to no end that adobe hasn't addressed this.