64-bit Migration

From X-Plane SDK
Revision as of 16:25, 20 December 2012 by Bsupnik (Talk | contribs) (Linux Linker Settings)

Jump to: navigation, search

This tech note describes the steps to porting a plugin to 64-bits. For more info on 64-bit plugins, see here.

Fat Plugins and 64-bit

The rest of this tech note describes how to build a 64-bit only plugin. To build a 'fat' plugin that runs on 32-bit and 64-bit X-Plane, you simply build two plugins (one the same way as you did before, and one using these new instructions). Put the 32-bit builds (for each OS) in a folder called "32" and the 64-bit builds (fore act OS) in a folder called "64".

On OS X you have two options: you can build a plugin with multiple architectures (the standard way to build a 'universal' plugin on OSX) or you can simply build two binaries and put them in the 32 and 64 folders above. The choice is yours; one option may be easier depending on the project settings of your particular plugin.

Update to the 2.1.1 SDK

If your plugin does not already use the new 2.1.1 SDK, update to this SDK now.

  • Download the new SDK libraries and headers from the SDK website.
  • If your plugin used the 1.x or 2.0.x SDK, you will need to replace "long" with "intptr_t" or "int" in your widget and data ref callbacks - simply make the right substitution to fix compile errors. You can look up the 'right' syntax in the docs.
  • If your plugin used XPCAircraft (as part of libxplanemp), copy it from an old SDK into your project - it should not have been part of the X-Plane SDK distribution.

Get New Libraries

If your code uses third party libraries like libpng, libcurl, etc. you will need to get versions of these libraries that ship in both 32 and 64-bit ABIs.

Fix 64-bit Code Issues

If you have any code that won't run with 64-bit compilation, fix that now.

  • You cannot cast a ptr to an int and back in 64-bits. Use intptr_t if you need an int that is the size of a ptr.
  • Don't use "long" for cross-platform code; the treatment of "long" varies by compiler.

Change compile settings to 64-bit

On Linux, and Windows using GCC-based compilers use -m64 and -m32 to set the compilation mode.

For X-Code/Mac use -arch i386 and -arch x86_64 or put the string "i386 x86_64" into the architecture property of your project.

For MSVC, you will need to first change the platform SDK to Windows 7.1 (the default might be v100). If you don't have this, install the Windows 7.1 platform SDK. Then add a new platform to your project using the configuration manager - add x64. You can now compile both x64 (64-bit) and win32 (32-bit) plugins.

Change linker settings to 64-bit

For Windows, link against XPLM_64.lib and XPWidgets_64.lib for the 64-bit build; link against XPLM.lib and XPWidgets.lib for the 32-bit build. If you have static libs, you will need to link against the 64-bit variant. Note that the OS libs (e.g. opengl) are named the same (opengl32.dll, for example) for 64-bit AND 32-bit.

On Mac and Linux, you may need to change which libraries you pass to your plugin, passing 64-bit libs or 32-bit libs depending on the build type.

IMPORTANT: make sure your namespace is "clean" on OSX and Linux. If you do this:

nm mac.xpl | grep "T "

The only symbols listed should be the five plugin functions (XPluginStart, XPluginEnable, XPluginReceiveMessage, XPluginDisable, and XPluginStop). If any other symbols are visible, change your linking settings to the new recommended techniques:

Linux Linker Settings

LINUX: use the linker script option listed under "gcc 3" in the linking instructions - this technique actually works on ALL versions of GCC and always produces a clean plugin:

Use --version-script=<text file> to ld lets you send a linker script. One of the form


C++ Note: if your plugin normally defines an _init and _fini symbol, add these to the "global" list above - they are necessarys for C++ global object setup.

WARNING: if you use global C++ objects, be sure their constructors do not call any XPLM routines - it is illegal to call the XPLM outside one of the official callbacks!!

OS X Linker Settings

Add this to the "Other linker flags":

-Wl,-exported_symbol -Wl,_XPluginStart -Wl,-exported_symbol -Wl,_XPluginEnable
-Wl,-exported_symbol -Wl,_XPluginReceiveMessage -Wl,-exported_symbol -Wl,_XPluginDisable
-Wl,-exported_symbol -Wl,_XPluginStop

You can put all of the flags on one line or put one on each line in X-code. If you use multiple lines in the X-Code UI make sure they are in consecutive order.

Correct xcode settings.png

Correct "nm" Output

This listing shows correct nm output for testing linkage on Mac/Linux. (Thanks to BSUB for providing is linker output as an example!)

Linux: if your plugin is stripped, use

nm -D lin.xpl

Test 1: What symbols are exported?

Bob-Feavers-Computer-487:64 bfeaver$ nm mac.xpl | grep "T "
0000000000000f66 T _XPluginDisable
0000000000000f6c T _XPluginEnable
0000000000003e86 T _XPluginReceiveMessage
0000000000004117 T _XPluginStart
0000000000003eb9 T _XPluginStop

Note that only the "big 5" callbacks are exported! No static library functions and no internal symbols!

Test 2: what does his plugin depend on?

Bob-Feavers-Computer-487:64 bfeaver$ nm mac.xpl | grep "U "
                U _CFRelease
                U _CFStringCreateWithCString
                U _CFStringGetCString
                U _CFURLCopyFileSystemPath
                U _CFURLCreateWithFileSystemPath
                U _XPAddWidgetCallback
                U _XPCreateWidget
                U _XPDestroyWidget
                U _XPLMAppendMenuItem
                U _XPLMBringWindowToFront
                U _XPLMCommandButtonPress
                U _XPLMCommandButtonRelease
                U _XPLMCommandOnce
                U _XPLMControlCamera
                U _XPLMCreateCommand
                U _XPLMCreateMenu
                U _XPLMCreateProbe
                U _XPLMCreateWindow
                U _XPLMCreateWindowEx
                U _XPLMDebugString
                U _XPLMDestroyProbe
                U _XPLMDestroyWindow
                U _XPLMDrawString
                U _XPLMDrawTranslucentDarkBox
                U _XPLMFindCommand
                U _XPLMFindDataRef
                U _XPLMFindPluginsMenu
                U _XPLMGetDatad
                U _XPLMGetDataf
                U _XPLMGetDatai
                U _XPLMGetMouseLocation
                U _XPLMGetScreenSize
                U _XPLMGetSystemPath
                U _XPLMGetWindowGeometry
                U _XPLMProbeTerrainXYZ
                U _XPLMRegisterCommandHandler
                U _XPLMRegisterFlightLoopCallback
                U _XPLMRegisterKeySniffer
                U _XPLMSetWindowIsVisible
                U _XPLMUnregisterCommandHandler
                U _XPLMUnregisterFlightLoopCallback
                U _XPLMUnregisterKeySniffer
                U _XPSetWidgetDescriptor
                U _XPSetWidgetProperty
                U ___cxa_guard_acquire
                U ___cxa_guard_release
                U ___gxx_personality_v0
                U ___stack_chk_fail
                U ___stack_chk_guard
                U _asin
                U _cos
                U _fclose
                U _fopen
                U _fprintf
                U _fscanf
                U _fwrite
                U _kCFAllocatorDefault
                U _sin
                U _sprintf
                U _strcmp
                U _strcpy
                U _tan
                U dyld_stub_binder
Bob-Feavers-Computer-487:64 bfeaver$ 

Here we have only:

  • standard C stuff.
  • XPLM calls.
  • GCC runtime.
  • There is no sign of a missing static lib like libpng.