Find out what Version of MT and Mono an App was built with? - mono

Is there a way to tell from the app bundle what version of monotouch and mono was used for a specific app?

Here's one way to do this:
$ pwd
/Users/sebastienpouliot/src/TestCase/bin/iPhone/Debug/TestCase.app
$ cat version.cs
using System;
class Program {
static void Main ()
{
Console.WriteLine (MonoTouch.Constants.Version);
}
}
$ /Developer/MonoTouch/usr/bin/smcs version.cs -r:monotouch.dll
$ MONO_PATH=. mono version.exe
4.2
You can infer the version of Mono from the version of MonoTouch (4.x uses 2.10, 3.x used 2.6). Note that this could fail if the linker eliminated Console.WriteLine.

Related

Can't get System.Numerics to work with command-line Mono (mcs) on OS X

We're trying to run a simple Mono script on the command line on OS X. Most scripts work fine for us, but as soon as we try to use System.Numerics, we get "error CS0234: The type or namespace name `Numerics' does not exist in the namespace System."
This isn't too surprising, and should be fixable with an appropriate command-line option to mcs, plus properly set up PKG_CONFIG_PATH... but this is where we get stumped. First, here's the script so you can follow along at home:
using System;
using System.Numerics;
public static class MainProgram {
public static void Main(string[] args) {
Console.WriteLine("Hello world!");
}
}
So next we tried "mcs -r:System.Numerics Test.cs". This produces "error CS0006: Metadata file `System.Numerics' could not be found".
"man mcs" suggests that we can get the other system packages by adding "-pkg:dotnet" to the command line. But that produces:
Package dotnet was not found in the pkg-config search path. Perhaps
you should add the directory containing `dotnet.pc' to the
PKG_CONFIG_PATH environment variable No package 'dotnet' found error
CS8027: Error running pkg-config. Check the above output.
OK then, we had no PKG_CONFIG_PATH, so we tried defining one:
export PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig/
This fixes the CS8027; but we still get the CS0234 we started with. And if I combine the -pkg and the -r, e.g. "mcs -pkg:dotnet -r:System.Numerics Test.cs", I get "error CS0006: Metadata file `System.Numerics' could not be found".
I'm stumped at this point... any idea what incantation I'm missing to make System.Numerics work with mcs?
If you're using Mono 2.10.x, you will have to compile with dmcs rather than mcs to enable the 4.0 profile (System.Numerics is a C# 4.0+ feature only).
If you're using Mono 2.11.x or 3.0.x, then mcs by default should select the 4.5 profile. mcs -help should show 2, 4, and 4.5 as possible values for the -sdk option. If it doesn't, then the framework isn't properly installed; I had that once, where I think that /Library/Frameworks/Mono.framework/Versions/Current pointed to the wrong directory; installing a second time fixed that.
Manipulating pkg-config should be unnecessary.

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.

Is there any non-Xcode-based command line unit testing tool for 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.

mono-test-install reveals I have a broken System.Drawing

I've gotten the tarball of Mono 3.0.3 from the mono project and compiled it on an Ubuntu 12.10 distro.
The configure, make and make install commands all ran without errors. I ran the mono-test-install and it reports "Your system has a broken System.Drawing setup". I'm not quite sure how to fix this or why it's broken. I have a valid libgdiplus.so file and pointed the configuration options to it.
It seems that I am unable to use the System.Drawing until I get this solved. Has anyone run into this before?
The way the mono-test-install script is testing the System.Drawing setup is to compile the code
using System;
using System.Drawing;
class X {
static void Main ()
{
Bitmap b = new Bitmap (100, 100);
}
}
using the command
mcs -pkg:dotnet <filename>
and then runs the resulting file with
mono <filename>.exe
You can do this process by hand to see the actual error message that caused mono to conclude that System.Drawing was broken, possibly allowing you to fix the problem.

Does mono 2.8 support 'dynamic' keyword?

I tested IronPython on mono 2.8 with the code in the book Professional IronPython p.315 listing 15-3.
using System;
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting.Hosting;
namespace Method2
{
class Program
{
static void Main(string[] args)
{
// Obtain the runtime.
var IPY = Python.CreateRuntime();
// Create a dynamic object containing the script.
dynamic TestPy = IPY.UseFile("TestClass.py");
// Execute the __test__() method.
TestPy.__test__();
}
}
}
I see it's compiled OK, and run without a problem on Windows 7, whereas the mono 2.8 gives me the following error message.
Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
`Microsoft.Scripting.Hosting.ScriptScope' does not contain a definition for `__test__'
at (wrapper dynamic-method) object.CallSite.Target (System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,object)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1
(System.Runtime.CompilerServices.CallSite,object)
at Method2.Program.Main (string[])
I thought Mono 2.8 supports C# 4.0 which has the dynamic keyword, but I see that the 'dynamic' keyword is not fully supported with mono.
Is this a bug of Mono 2.8?
ADDED
This is the python script.
# The class you want to access externally.
class DoCalculations():
# A method within the class that adds two numbers.
def DoAdd(self, First, Second):
# Provide a result.
return First + Second
# A test suite in IronPython.
def __test__():
# Create the object.
MyCalc = DoCalculations()
# Perform the test.
print MyCalc.DoAdd(5, 10)
# Pause after the test session.
raw_input('\nPress any key to continue...')
This is the command that I used
dmcs Program.cs /r:System.Core /r:IronPython.dll /r:IronPython.Modules.dll /r:Microsoft.Dynamic.dll /r:Microsoft.Scripting.dll /r:Microsoft.CSharp.dll
It compiles well, but it still breaks when I run the execution binary. Do I need to have all the dlls in the same directory where the execution binary locates?
The fact that you are getting a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException means that the dynamic keyword worked. The problem you are having is that IPY.UseFile("TestClass.py"); is returning a ScriptScope that doesn't see your test method. So the problem lies with your python source or how you are including IronPython with mono.
The dynamic keyword is certainly supported by Mono 2.8 when using the C# 4 profile.
I guess my question is how you are building this sample?
Just for kicks, I just pasted your sample into MonoDevelop. I had to tell MonoDevelop to use C# 4 instead of C# 3.5 first of all.
The dynamic keyword was introduced in C# 4 obviously.
Also, I did have to include a few assembly references: System.Core, IronPython.dll, IronPython.Modules.dll, Microsoft.Dynamic.dll, Microsoft.Scripting.dll, and Microsoft.CSharp.dll. I am not sure if I needed them all.
If you are building from the command-line you need to use 'dmcs' as the compiler (to indicate the .NET 4 profile) and you need to include the assembly references.
It builds without problems with this configuration (for me at least).
I am responding to this question with respect to Mono 2.10.
I could successfully build and execute the code from command line on Windows 7 without using MonoDevelop. Here are the steps:
Install Mono 2.10.8 on Windows 7.
Install IronPython 2.7.2.1.
"C:\Program Files\Mono\bin" or equivalent and "C:\Program Files\IronPython 2.7" or equivalent should be part of system path.
Both TestClass.py and Program.cs should be in the same folder.
From the dos prompt, corresponding to the folder where TestClass.py and Program.cs exists, execute setmonopath batch file.
From the same dos prompt execute the following command:
dmcs Program.cs /r:System /r:"C:\Program Files\IronPython 2.7\IronPython.dll" /r:"C:\Program Files\IronPython 2.7\IronPython.Modules.dll" /r:"C:\Program Files\IronPython 2.7\Microsoft.Dynamic.dll" /r:"C:\Program Files\IronPython 2.7\Microsoft.Scripting.dll" /r:"C:\program Files\IronPython 2.7\Microsoft.Scripting.MetaData.dll" /r:Microsoft.Csharp
Program.exe should be successfully generated and the same can be executed without any error message.