Starting with Ogre3D on Mac OS X 10.9.2 and Xcode 5.1.1

ogre-logo-wetfloorOgre3D is one of the most popular open-source graphics rendering engines. One of the powerful  advantages it offers is abstraction of rendering engine. It can run same code ("game") on OpenGL, Direct3D9,Direct3D10 or Direct3D11 by just changing application configuration file. Above  all it abstracts very efficiently many of the core game concepts like loading models, composing scenes, working with cameras etc. What attracted me in particular to Ogre is it's portability. Ogre can be compiled and is available as cross-platform SDK, available on Windows, OS X and some Linux distributions. I've got up to speed with Ogre with this excellent book. Even though book says it is platform independent and you can use any c++ compiler you want it is in essence very much tied to Windows and Visual Studio. Ogre has great wiki with a lot of examples and help pages to get you started but I had a ruff first encounter on OS X platform getting SDK and samples even to compile. In essence there are couple of prerequisites before you even compile and information about those is a bit scattered.

My idea here is simple "Hello World" or in this case "Hello Sinbad" example application from ground up. From downloading and installing prerequisites to actually writing and compiling code with Xcode.

At the time of writing current stable SDK version is 1.9. Even though it says stable it would not compile with Xcode because some include paths are not correctly set. It’s probably easy fix but for sake of keeping things simple and because the only good beginner book out there “OGRE 3D 1.7 Beginner's Guide” is using version 1.7 I will use it too. OS X is version 10.9.2 Mavericks with Xcode 5.1.1.

Installing prerequisites

  1. CMake for OS X – Used for compiling SDK  and sample code. You can download it here. At the end of the setup you should allow installation to place aliases in /usr/bin because SDK build will use Cmake from .sh scripts and effectively calling “cmake” without absolute path to your /Applications folder where Cmake will be installed.
  2. Nvidia CG Toolkit -   Installs Cg framework system wide and can be downloaded here.

Downloading and compiling Ogre3D SDK

Go to ogre3d.org and download OS X SDK version 1.7 or just click here. After downloading and mounting SDK .dmg file you should see content similar as shown on this picture. ogreSDK Simply copy entire OgreSDK to your local folder where you have read and write permissions. Important thing to notice when you are copying SDK locally is that you should not have spaces in your path to “OgreSDK”. In my case I had folder structure something like this: /Users/bbizic/Projects/3D Project/Ogre3D/OgreSDK. This one space in “3D Projects” caused SDK build to fails so beware of that when copying SDK files.

Next step is to compile Ogre SDK. As OS X user I was expecting like with other projects simple ./configre make steps but that’s not how it works here. From Terminal/shell navigate to your OgreSDK folder and execute following command.

cmake -GXcode

After this step navigate to your OgreSDK local folder and open OGRE.xcodeproj. You should see similar structure as this.

ogre xcodeI will be using debug version of libraries so make sure from Product –> Edit Scheme debug version was set and as scheme “ALL_BUILD” is checked. After that just click Product –> Build. It will take a while until all the projects are complied.

Notice: Ogre3D uses Boost libraries for threading. If for some reason SDK fails to compile boost libraries as part of the SDK build the reason could be that boost is targeting lover version OS X SDK, namely OS X 10.5. To be able to compile against and for older versions of OS X Xcode/gcc must have copy of OS X SDK either under /Applciations/Xcode.app/Contents/Developer/Platforms/MacOSX.Platform/Developer/SDKs/MacOSX10.5.sdk and/or under /Develper/SDKs/MacOSX10.5.sdk. Let me know if you have problems I will write more details about it. 

Sample Hello Sinbad World Example

 

Finally it’s time to build sample application. Fire up Xcode –> New Project and choose Command Line Tool. xcode commandline 

On next screen give some project name and as type choose C++. We could of gone with Cocoa application to make use of built in bundling system but for sake of simplicity we will build only our executable with correct libraries and then we will make use of SampleBrowser application which we built when we first time build the OgreSDK. In runtime Ogre needs to access it’s libraries from correct location and also few configuration files are needed to be properly set up. To avoid the hustle of configuration we will simple replace SampleBrowser executable with our new one.

Place project in folder next to OgreSDK so it will simplify search paths for include and lib files. Once project was created add new C++ file named main.cpp. and place following content in. You can omit my comments.

//
//  main.cpp
//  HelloSinbad
//
//  Created by Bojan Bizic on 12/05/14.
//  Copyright (c) 2014 BojanBizic. All rights reserved.
//

#include "Ogre/ExampleApplication.h"

class Example1 : public ExampleApplication
{
public:
    void createScene()
    {
        // Set the scene's ambient light
        mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
        
        // Create an Entity
        Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
        
        // Create a SceneNode and attach the Entity to it
        Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");
        headNode->attachObject(ogreHead);
        
        headNode->setPosition(0.0, 0.0, 400.0);
        
        // Create a Light and set its position
        Ogre::Light* light = mSceneMgr->createLight("MainLight");
        light->setPosition(20.0f, 80.0f, 500.0f);
    }
};

int main(void)
{

    // Create application object
    Example1 app;
    
    try
    {
        app.go();
    } catch( Ogre::Exception& e ) {
        std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl;
    }
    
    return 0;
}

Next step is to configure project settings namely include and library paths. First we need to make Boost happy and disable C++11.

cpp settings 

Next, header search paths.

header search paths

You need to add path to OgreSDK/include , OdreSDK/boost_1_46_1 and in case of our Mac OSX OgreSDK/include/OGRE/OSX otherwise compiler want be able to find macUtils.h file.

Next step, library search paths.

library search paths

We need OgreSDK/lib/ and OgreSDK/boost_1_46_1/lib.

Framework paths is also need because on Mac OS X Ogre is bundled as framework and should be referenced as such. Picture below shows setting on my system.framework paths

 

In next step switch over to the Build Phases tab and references as show on image below.

framework referecnces

 

If everything was setup correctly as shown above you should be able to compile at this point. Only thing left to do now is to copy our “HelloSinbad” (in my case this is the name of the project) and copy it to OgreSDK/bin/Debug/SampleBrowser/Content/MacOS and start it from there.

Final result

You can open up SampleBrowser app by right clicking on it and then on “Show Package Content” and place your executable in MacOS folder. Double clicking on executable should bring up Ogre configuration window.

ogre config windowSince we are on Mac OS X on available rendering Subsystem shown should be OpenGL. On Windows we would also see options for Direct3D. By clicking on OK button settings are saved in Resources/ogre.cfg file and our Sinbad is finally shown on screen.

sinbad  

 

 

That was it. Not so straight forward as on Windows but on other hand not less rewarding. Most of the work lies on setup and deployment of Ogre SDK files. Coding part was pretty simple and short. Writing similar application which loads model, sets up lighting and cameras with lower level abstractions such as OpenGL or Direct3D would involve at least thousand lines of C++ code plus GLSL/HLSL counter parts for Shader pipelines, not to mention problems with portability.

Hope this helps and if you have questions regarding this post please post it in comments bellow I will be more then happy to answer them.

Delete old windows folder from separate drive

Very typical and frustrating situation. You had your old system installed on typical old mechanical hard drive and you bought shiny,new, expensive and rather small SSD drive. First idea that comes to mind is to install fresh new system on SSD drive and use old one just for not so frequently used but rather big data. Maybe there is a lot of data you want to keep on that old drive and you do not want to format it, you will leave it in system as it is. SSD will hold system and be C partition and old drive will be D partition.

Installation went smoothly and you see there are folders like “Program Files”, “Users” and in particular “Windows” on that old hard drive which you will never ever use again, but they still take up a lot of space. In my case old Windows folder was almost 100 GB big. Deleting all folders except “Windows” goes pretty much without any problems but deleting old Windows installation doesn’t go as easy.

Deleting it from Windows Explorer says you don’t have permissions to delete it. There is no “chmod 777” on Windows to change them. Trying to change permission trough properties dialog also leads to quite strange errors and some ghost non-killable windows.

Total Commander has a bit different approach. It traverses trough directory structure which can take hours and then at the end gracefully fails with same messages as Windows Explorer.

What to do?

Solution

Best and easiest thing to do is:

  1. In root of your old hard disks partition next to “Windows” folder make new one named “Windows.old”
  2. CUT    (Ctrl+X) entire old “Windows” folder and paste it into “Windows.old”
  3. Start a Disk Cleanup utility. If everything up to here was done correctly you will see following window.DiscCleanUp_CalculateDiskSpace

    Window should show “Scanning: Previous Windows installation(s).

    This can also take up quite some time to finish. On my machine it took more then 3 hours

  4. After scanning process is done select “Previous Windows installation(s) and click OK. PreviousWindowsInstallation
  5. When confirmation dialog pops up click on “Delete Files” AreYouSureYouWantToDeleteWindows 
  6. Done!

Registration-Free COM with .NET

Registration-free COM interop activates a component without using the Windows registry to store assembly information. Instead of registering a component on a computer during deployment, you create Win32-style manifest files at design time that contain information about binding and activation. These manifest files, rather than registry keys, direct the activation of an object.

Using registration-free activation for your assemblies instead of registering them during deployment offers two advantages:

  1. You can control which DLL version is activated when more than one version is installed on a computer.

  2. It simplifies deployment process of the application by allowing replacing DLLs without accessing and editing registry

Simple .NET COM component

For .NET component I will use simple .NET class library project. Let's name it SxsNETCom. To make use of COM we first need to create interface for our component and then actual component/class which will implement this interface and mark it with appropriate attributes. My COM component will simple read XML file and return content in form of string. Here is this interface definition.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace SxsNETCom
{
    [ComVisible(true)]
    [Guid("C38897BF-EA67-46F0-A342-A56C515563C2")]
    public interface IReadXml
    {
        string ReadXmlFile(string filePath);
    }
}

Important to notice here "ComVisible" attribute which tells this interface should be exported and Guid attribute which uniquely defines our interface. This Guid will be later used by clients to actually find our component. Any Guid will do and we can simple generate it from withing Visual Studio under Tools, Create GUID sub menu using Registry format. Next step is to define our COM component an actual class and implement our interface. Here is code for it. Very simple, we take file path as input parameter, read xml file into XmlDocument and return string content of XmlDocument.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

using System.Xml;

namespace SxsNETCom
{
    [ComVisible(true)]
    [Guid("A7DD36C1-15A7-4849-9B35-36F597CE715E")]
    [ClassInterface(ClassInterfaceType.None)]
    public class ReadXml : IReadXml
    {
        public string ReadXmlFile(string filePath)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(filePath);

            return doc.OuterXml;
        }
    }
}

Again, we mark the class with ComVisible, assign unique Guid to it and define class interface type. In this simple case we use ClassInterfaceType.None. Next step to enable our Class library/DLL to be COM component is to sign it. This is simply done under project settings Signing tab.

Any key will do, if you don't have existing one you can simply generate new one by clicking on <New...> option.

At this point our DLL should be able to work as COM component. Next steps would be to generate TLB file for our component or to be precise Type Library Interface file which can be used by unmanaged clients to generate appropriate interface code for our component. We can use Regasm.exe or Tlbexp.exe to generate .tlb files. Since we want to avoid registration Tlbexp.exe will be better tool for the job. From Visual Studio Command Line we simple call following line:

C:\>tlbexp.exe [PathToDll]

This command will generate TLB file with same name as our COM component DLL name. TLB file will come in use later when we build unmanaged client application for our managed COM component.

Since we want to avoid global registration of our COM component, meaning writing into Windows registry, we need application manifest file.

To create an application manifest

Right click on project inside Visual Studio, go to Add New Item and choose "Application Manifest File". Visual studio will create app.manifest file inside your project with empty default settings. Next step is to embed our manifest into our dll. At the moment it is just part of our project but not actually used.

Embed application manifest into Class Library project

In case we had Console application project or Windows Form project we could simply go to Project settings and under Application tab , Icon and Manifest settings simply assign manifest. In case of Class library manifest option is grayed out so we need to add it manually to our .csproj file. Right click on project, click Unload project and then option for editing .csproj file will be available. Find this lines:

<PropertyGroup>
    <AssemblyOriginatorKeyFile>SignKey.snk</AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <PropertyGroup />

And change it to:

<PropertyGroup>
    <AssemblyOriginatorKeyFile>SignKey.snk</AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <PropertyGroup>
    <ApplicationManifest>app.manifest</ApplicationManifest>
  </PropertyGroup>

Visual Studio will complain about new "ApplicationManifest" element but it will work. Save the .csproj file and reload and rebuild project.

Now we need to open up and edit our app.manifest file to expose our COM components. This is how it should look like:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity 
    name="SxsNETCom" 
    version="1.0.0.0" 
    publicKeyToken="765d04d26ffa990b" 
    processorArchitecture="x86">
  </assemblyIdentity>
  <clrClass
    clsid="{A7DD36C1-15A7-4849-9B35-36F597CE715E}"
    progid="SxsNETCom.ReadXml"
    threadingModel="Both"
    name="SxsNETCom.ReadXml"
    runtimeVersion="v4.0.30319"></clrClass>
  <file name="SxsNETCom.dll" hashalg="SHA1"></file>
</assembly>

First important element is "assemblyIdentity", name atribute is name of the assembly we are producing, version is version defined in AssemblyInfo.cs. PublicKeyToken we get from yet another command line tool:

sn.exe -T [Path to DLL]

And here is the output produced by sn.exe

Next is processorArchitecture, if we build our Class library with platform target for x86 then we use it also here in manifest. In case we build for x64 then processorArchitecture should be "amd64" and in case we build with "Any CPU" then it should be defined as "msil". Important to mention here is that it is always better to build managed for specific architecture, namely x86 or x64, because our COM consumers are probably unmanaged and either x86 or x64.In case we build our managed COM component with "Any CPU" settings it means it will be at runtime ,depending on operating system architecture, compiled by Just-In-Time Compiler to either x86 or x64 assembly image which can break your 32 bit client running on 64 bit OS. To sum up, it is better to have 32 and 64 bit manifest for corresponding targets.

Next element in our manifest is clrClass. This is where we define types we want to expose as COM Component. Clsid represents GUID of our class, NOT interface. Name and progid are basically the same thing, fully qualified name of our class, namespace + class name. Threading model "Both" tells that our component can be used by STA and MTA, single and multithreaded clients. RuntimeVersion is version of .NET framework need for component to run. Ok so, now our managed COM component is ready, let's build unmanaged C++ native client.

Native Win32 COM Client

Right click on solution, add new project.

First thing we need to add ATL headers and TLB import statements to our stdafx.h.

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>

#include <atlbase.h>
#include <atlcom.h>
#include <atlstr.h>
#include "atlsafe.h"

#import "..\tlb\SxsNETCom.tlb" no_namespace named_guids auto_rename

Now we are ready to use our COM component. Here is sample code:

// ComClient.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
	CoInitialize(0);

	CComPtr<IReadXml> iReadXmlPtr;
	HRESULT hr = iReadXmlPtr.CoCreateInstance(CLSID_ReadXml);

	if (hr == S_OK)
	{
		_bstr_t filePath(L"C:\\temp\\simpleXml.xml");
		_bstr_t xml = iReadXmlPtr->ReadXmlFile(filePath);
		MessageBox(NULL, xml, L"Done", 0);
		iReadXmlPtr.Release();
	}
	else
	{
		MessageBox(NULL, L"Failed to initialize COM component", L"Failed", 0);
	}

	CoUninitialize();
	return 0;
}

Only thing we are still missing on client side is also a manifest file which will tell our application where to search for those COM types. We simple add following app.manifest to our C++ project.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity name="SxsNETCom"
                         version="1.0.0.0"
                         publicKeyToken="765d04d26ffa990b"
                         processorArchitecture="x86"/>
    </dependentAssembly>
  </dependency>
</assembly>

This time it is quite self explanatory. Dependent assembly simply describes our COM dll. Next and last step is to embed this manifest file into our executable. Once again, right click on project settings, Manifest Tool -> Input and Output. Under Additional Manifest Files we add name of our manifest file.

End result

Common Pitfalls

It is very important to know how Activation context is created and how manifests come into play. Even though we have embedded manifest into our COM client application, if we start debugging it from Visual Studio or better yet if we let Visual Studio initialize debugging by pressing F5 then our application will be loaded from inside VS hosting process and this way our embedded manifest is completely ignored and our application fails to initialize COM components. There is option to disable this behavior. To go around this, we need to first start our application and then attach visual studio to it.

Important to remember is that when creating Activation Context manifest from Caller, top process holding all other, will be used when searching for reg-free COM components. This means if client application A loads in way, by means of dynamic linking, reflection, COM, LoadLibrary() or in any other way, library B and library B tries to access reg-free COM components, ONLY application A has to have defined those COM components in it's manifest, since application A is in this case top process or caller, it creates Activation Context.

Application.EnableVisualStyles() and Reg-free COM Problem

In case we have WinForms application and it uses manifest as described above to create Activation Context and as we know WinForms comes out of the package with call to Application.EnableVisualStyles() in Main method, it will break creation of "our" activation context.  Application.EnableVisualStyles() in itself creates an activation context to redirect process to use Microsoft.Windows.Common-Controls version 6.0.0.0 and this breaks creation of Activation context we defined in our manifest.

One solution to this problem is to create our context at least one time before call to Application.EnableVisualStyles(). From managed code we can instantiate managed COM classes with something simple as this:

Type theType = Type.GetTypeFromCLSID(new Guid("A7DD36C1-15A7-4849-9B35-36F597CE715E"));
object instance = Activator.CreateInstance(theType);

Other and better solution is to comment out Application.EnableVisualStyles() and create activation context for Microsoft.Windows.Common-Controls ourselves by adding it to our manifest.

<dependency>
   <dependentAssembly>
     <assemblyIdentity
       type="win32"
       name="Microsoft.Windows.Common-Controls"
       version="6.0.0.0"
       processorArchitecture="X86"
       publicKeyToken="6595b64144ccf1df"
       language="*"
     />
   </dependentAssembly>
</dependency>

Including external manifest file

It is possible to reference external manifest from within our application manifest file. This way one manifest can be shared from multiple DLLs within same deployment directory. We need to define and reference it just as another dependency:

<dependency>
    <dependentAssembly>
      <assemblyIdentity name="ManifestFileNameWithouthExtension" version="1.0.0.0" type="win32" processorArchitecture="x86"></assemblyIdentity>
    </dependentAssembly>
  </dependency>

Source Code

SxsNETCom.zip (6.18 mb)

Build Qt projects on Windows and OS X from command line

Let us assume you have a project build with Qt version 5.x. You have your Qt installation on your system either Windows, Linux or Mac Os X, doesn't really matter as long as you are compiling your application from Qt creator. What to do if you want to automate this process and you can't install Qt on your, let us assume, build machine. There are several different reasons why you don't want to install Qt on each machine you are building it on. In my particular case application is hosted on TeamFoundation server and code is being pulled and build from there using Python scripts. Whole idea is to make build and deployment process self sufficient and easy to maintain. Python script should get latest code from source control and basically build Qt project from command line with same code on both Windows and Mac Os X. 

Qt projects consist of .pro file which is basically your project file where you define you build settings, which files you want to build, c, c++, h etc. This file is very basic version of make file, but it's NOT. Alongside your standard C++ files you will probably have UI files if you are building application with windows. Those files are basically xml files describing your UI, windows, controls etc. Qt has a special tool inside it's bin directory call "uic" or "uic.exe" depending on which system and this executable is responsible for converting those UI files into "reasonable" C++ code, normally into .h files which all C++ compilers can actually recognise and compile. This tool will come later become my problem on Mac Os X system.

Qt build process

How Qt creator and actual qt build process works is quite simple. Inside Qt installation "bin" folder there is a tool named "qmake". Qmake has a task to take your .pro project file and create universal make file which can be compiled with any extern make program. Make is essentially tool that based on configuration in background calls compiler which eventually compiles your code into library or executable for particular underlaying operating system. If you click on Projects icon inside Qt creator you can see this steps with command line parameters being used. 

Build or copy Qt installation

To be able to compile your application outside qt creator you will need content from Qt installation. One way is to install on local system and copy content of the installation or to build from source. Building from source can be very time consuming and frustrating. Building from source can take hours even if you exclude components you don't need such as example code etc. Basically you have different compilers plus different operating system you need to compile for, it adds up. It is definitely easier to download installer and install it locally and copy content from there.

Qt Qt installation folder

 

In my case I had Qt 5.2.0 and under 5.2.0 folder which is a version there is "clang_64" folder and this means this Qt was build with/for clang 64bit compiler (not to go into many details here). In case of Windows installation this folder will be called for example "msvc2010" if you have version for Visual Studio 2010 C++ compiler. 

To be able to build Qt from command line you will entire content from this folder. Bin subfolder contains various tools such as aforementioned Qmake and uic , lib folder is where Qt prebuild libraries lie, include folder contains header files and "mkspecs" folder contains instructions for Qmake how to build make file for each particular compiler.

Build from command line

Almost there. Let us assume we copied Qt installation on following locations C:\QT5_build for Windows and /Users/yourname/QT5_build for OS X. Build is two step process. First you run Qmake agains your .pro project file and based on your settings it will generate Make, Make.Debug and Make.Release files.

Note:

Since we are not using installed version of Qt we need to instruct Qmake where hour Qt headers and libraries are. This is done with qt.conf file. Make qt.conf text file and save it into "bin" folder where Qmake executable is. Content should be as simple as this

[Paths]
Prefix = C:/QT5_build

Notice forward slash. Forward slash must be used for both Windows and OS X. Also single slash instead of double

In first step execute your Qmake against your project file to generate make files. 

Windows

For a Windows it would be:

C:\QT5_build\bin\qmake.exe [Path to your .pro file] -r spec C:\QT5_build\mkspecs\win32-msvc2010

By specifying "win32-msvc2010" I am telling Qmake to generate Make file for Visual Studio 2010 compiler. This same thing does Qt creator, passes same parameters to QMake and then afterwords calles JOM make tool to compile from those make files. Jom is clone of Microsoft Nmake and it just supports running multiple  commands in parallel.

In second step you call Nmake with your generated Make file like this:

nmake /f [Path to your Make file] [Debug/Release]

Last thing to do Windows would be to check your application, run it and if necessary add needed Qt runtime libraries since build tools will not do that for you.

Mac OS X

This process is quite simple when it's done on Windows, it's quite other story on OS X. Steps are the same, first you run Qmake against your project file and then you call simple Unix make against make files, BUT. Since we took Qt build out of actual installation tools inside bin folder will not work since they have static links and will look for dependent libraries under absolute path where they were installed.

So first running QMake:

./Users/yourname/QT5_build/bin/qmake [Your .pro file] -r -spec /Users/yourname/QT5_build/mkspecs/macx-clang

In my case this returns with following error:

sh: line 1: 25283 Trace/BPT trap: 5       /Users/bbizic/QT5_11_Build/bin/uic -d Forms/advancedviewsettingsdialog.ui
dyld: Library not loaded: /Users/bbizic/Qt5.2.0/5.2.0/clang_64/lib/QtCore.framework/Versions/5/QtCore
  Referenced from: /Users/bbizic/QT5_11_Build/bin/uic
  Reason: image not found

So what happened is QMake called tool named "uic" to convert .UI into C++ header files. Uic returned error saying it can't find dependent library from absolute path where it was originally installed. If we run "otool -L" tool against uic we can see where it is actually looking for this library.

otool -L uic

uic:
	/Users/bbizic/Qt5.2.0/5.2.0/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.2.0, current version 5.2.0)
	/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

Only way I found to work around this was to use install_name_tool. I am not saying it's the only or the best way, it's just the way I solved it. install_name_tool is command line tool which comes, I think with installation of XCode. 

install_name_tool

It allows you to change those absolute paths inside dynamic libraries or executables. 

There are several ways of locating shared libraries:

  1. @executable_path: relative to main executable
  2. @loader_path: relative to the referring binary
  3. @rpath: relative to any of a list of paths
Syntax is as follows:
install_name_tool -change /currentPath @rpath/newpath myexecutable

Note that first parameter after -change must be exactly what is inside executable. 

See man dyld and man install_name_tool for more information.

 

Finally when uic tool is patched with correct paths you can run your Qmake.

After Qmake is finished generating make files you run following command to finally build your project.

make -f [Path to your make file] [debug/release]

Finally on Mac OS X deploying necessary Qt libraries with your application can be done using tool macdeployqt. You can read more about deployment on Mac Os X here. Since this tools is also part of QT installation bin folder it may also need be patched with correct paths with install_name_tool like described above. 

That is it, it should compile and run. If you find better solution or any other thoughts or question on subject please leave comment below.

About me

Bizic Bojan is Freelance Software Development Consultant with focus on C++, Qt and .NET based software solutions development. 

 

Disclaimer:

The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.