Monday, January 31, 2011

Mac App Store rejections due to HXRuntime

Recently, we have had reports of applications being rejected from the Mac App Store with the following message:

The application links against </usr/local/lib/HXRuntime Carbon Mach-O.dylib>, which is missing.

We believe that this is a false-positive in Apple's automated rejection tools. While 2011r1 will not have this 'problem', you can work around it via the following command line invocation:
[joe@Mac-Pro.local ~] install_name_tool -id '@executable_path/rbframework.dylib' '/My'

The rest of the post is a technical explanation of what is going on and can be skipped if you are not interested. Also, it describes the current implementation details and is in no way an API contract or something to rely on.

The bulk of the REALbasic framework is implemented in C++ and lives in the 'rbframework.dylib' file next to your executable. When you build an application, the REALbasic linker hardcodes the relative path to that dylib. This can be seen by running 'otool -L' on your binary:

[joe@Mac-Pro.local ~] otool -L '/My Application'
My Application:
@executable_path/rbframework.dylib (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/Carbon.framework/Carbon (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.dylib (compatibility version 0.0.0, current version 0.0.0)

Dylibs also have an 'install name', which is used solely by 'ld' (the linker that comes with Xcode). When you link a binary using Xcode, ld takes the install name of the library it's going to link in and then embeds it in your resulting binary. Since REALbasic does not use ld, we have simply left the install name for rbframework.dylib at its default. This can be seen by running 'otool -l' and searching for the install name's load command:

[joe@Mac-Pro.local ~] otool -l '/My'
Load command 5
cmdsize 72
name /usr/local/lib/HXRuntime Carbon Mach-O.dylib (offset 24)
time stamp 1 Wed Dec 31 19:00:01 1969
current version 1.0.0
compatibility version 1.0.0

Our guess is that Apple has an automated tool that is looking at the install name of rbframework.dylib and rejecting it because it does not exist. However, since the install name is unused by anything but ld64, it is a false positive and not something Apple should be looking at.

While a future version of REALbasic will contain an install name that does not trigger this false positive, a temporary solution is to manually change the install name via install_name_tool, as mentioned above.

Friday, January 28, 2011

Build Automation and IDE Script

Build Automation and IDE Script are two very useful, powerful features of REAL Studio. Each can be used to automate certain parts of your app build process, saving you time.

*Build Automation is used when you want to make changes and you have a single build of your app. 

*IDE Script is used when building your app generates more than 1 build.

Here is an example of an IDE Script that creates 2 builds of a Mac app. It gives a different name to each build and changes a constant value. This code is entered into the IDE Script window available from the File menu. The code assumes that you have an app class property named DebugMode. The Build Automation item in the project window does not need to change for this code to work.

dim AppPath as string
PropertyValue("App.MacOSXAppName") = "Release Build"
ConstantValue("App.DebugMode") = "False"
BuildWin32 = False
BuildLinux = False
BuildMacMachOUniversal = True
AppPath = BuildApp(8,False)
PropertyValue("App.MacOSXAppName") = "Debug Build"
ConstantValue("App.DebugMode") = "True"
AppPath = BuildApp(8,False)

That's it. Now you have 2 builds, each with a different value for the DebugMode constant.

The IDE Script documentation can be found here.

Please remember that both of these are features of REAL Studio Enterprise and Web Editions.

REAL Studio 2010r5.1

REAL Studio release 2010r5.1 is here. You can download it from our Downloads page anytime. 2010r5.1 Release Notes are here.

Tuesday, January 18, 2011

Changing HTMLViewer rendering mode on Windows

I was recently tasked to look into an issue a customer reported about our HTMLViewer rendering using IE7 instead of IE8 (which the user had installed on his computer). Sorry folks, we haven't implemented a way to switch to using WebKit yet. Anyway, knowing how ActiveX controls worked I automatically assumed that we were using a version dependent ProgramID instead of the version independent ProgramID.

What typically happens when a new version of an ActiveX component is installed is that it will register a new dependent ProgramID but also inherit an independent ProgramID so that existing apps that have the ActiveX control embedded in it can automatically use the new one without the need to modify or recompile anything.

After spending a bit of time looking at our code I found that we are indeed just using the independent ProgramID so I was baffled as to why our HTMLViewer isn't rendering using the latest IE that's installed (in this case IE8). As it turns out, IE8 can render using the IE7 engine, and is the default for apps that have the embedded WebBrowser ActiveX control (like our HTMLViewer). Great, so all I need to do is tell the ActiveX control to render using the IE8 rendering engine right? Er, no, unfortunately there is no API to switch modes (that I'm aware of). There is however a sanctioned way to get your HTMLViewer to render using IE8, through the Registry.

To do this you need to run 'regedit' and add the name of your app to the list in
[(HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE)\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
"MyWebBrowser.exe" = dword 8000 (Hex: 0x1F40)

Note: the key FEATURE_BROWSER_EMULATION probably doesn't exist yet so you will need to add that too. As far as I've tested, the absolute path to your application is not required, just the full name.

The registry "hack" and more details about this problem can be found here on Microsoft's blog.

Tuesday, January 4, 2011

Managing Your Memory

When you build applications with REAL Studio, you don't have to think about managing memory to the extent that you would had you created your application using many other development tools. For the most part, the REAL Studio framework handles memory management for you.

For example, if in the Open event of a window or webpage you have created a picture and stored it in a property called MyPic:

MyPic = new picture(100, 100, 32)

Then in some event you set a local variable ("x" let's say) to MyPic and then set MyPic to nil:

x = MyPic
MyPic = nil

When you set x equal to MyPic, what you really are doing is making x point to the same picture object as MyPic. Neither MyPic nor x store the picture. The picture is stored in memory by the REAL Studio framework. What you are doing is pointing the MyPic property at the picture. This is a subtle but important distinction. So when you set MyPic to nil, you are not removing the picture from memory, you are indicating that MyPic now points to nothing.

So when does the picture get removed from memory? In this case, when x also becomes nil. It might become nil by you setting it to nil or, since it's a local variable, when the event ends x will automatically be made nil. When that happens, since there is nothing else referencing the picture, the REAL Studio framework will remove the picture itself from memory.

Most modern frameworks handle memory via one of two methods. They either use
Reference Counting or Garbage Collection. REAL Studio uses Reference Counting. That means that each time something references an object, REAL Studio increments a counter by one and when something stops referencing that object, it decrements that counter by one. Once the counter gets to zero, the framework automatically removes it from memory.

The other form of memory management, Garbage Collection, works a bit differently. Instead of a count of how many things reference an object, this system checks to see if there are any references to objects. It does this on a schedule and then removes the object from memory if nothing references it.

Each method has its own strengths and weaknesses. The weakness of Garbage Collection is that the garbage collector can kick in at an inconvenient moment and affect the performance of your application. There are usually ways for the developer to tell the garbage collector to run so that they have some control over it but it's not 100%. The benefit of Garbage Collection is that it will clear every object from memory, therefore there is no chance for memory leaks.

What is a memory leak? A memory leak is when objects should be cleared from memory but are not. With Reference Counting, you can, by accident, create a memory leak. However, Reference Counting provides for consistent performance. And as long as you are diligent, you won't have memory leaks. It requires a little more effort on your part but you don't have to worry about having uneven performance.

I wanted to write about this after reading an article about performance issues with Android apps. One of Google's Android engineers said that, among other things, Garbage Collection was an issue that affects performance and battery life. Android applications are written in Java and Java uses Garbage Collection.

Personally, I think Referencing Counting is the best solution as it provides even performance and is generally more efficient than Garbage Collection. By "efficient" I mean that it takes less CPU cycles to get the job done. However, like religion and politics, you will never get everyone to agree.

Since REAL Studio uses Reference Counting, just make sure when you store a reference to an object in a property that you add code that will clear (set to nil) that property when the object is no longer needed. If the property is a property or a window or webpage and you are going to need the object until the window or webpage is closed, there is no need to worry about it because when the window or page closes, the properties are all cleared and the object they reference will be cleared as well. Something to keep in mind, if the property is a property of a class, the property will go away when the instance of the class does; but if it's a property of a module or the app class, it will stay around until you specifically set it to nil.

Fortunately, managing memory is mostly handled for you by REAL Studio. As your application gets more complex you will have to take a little more responsibility. But at least your application won't suddenly panic when the garbage man shows up unexpectedly.

Monday, January 3, 2011

Great bug reports

Often the difference between an average bug report and a great one is whether the engineer has to spend a lot of time figuring how to see the reported behavior or if they can reproduce it immediately and find the cause in short order.

I say "short order" as recently I had such a case. The bug had been reported multiple times but none of the reports had any details that led me to the same result as the reporters were seeing. The case in question is Unhandled NilObjectException in FolderItemExtensions.$CreateAliasHandle%o%oo (#15274)
They key thing that finally, after multiple reports, allowed me to resolve the bug was a simple, clear report by one user that stated how to reproduce it 100% reliably.

This report made finding and fixing the bug a very simple task as we could see in the debugger what was going on and why this caused the exception it did. The fix required only 20 minutes once we had this information.

The key here is that user had taken the time to find the steps required to reproduce the issue very reliably and reported them.

THAT's what make s a great bug report.

Having the report of an issue is one thing but having reliable steps to reproduce the bug is great because it makes fixing the bug a lot easier.