Clang C++ Cross Compiler - Generating Windows Executable from MAC Os X

Clang C++ Cross Compiler - Generating Windows Executable from Mac OS X

Clang can in principle be used as a cross compiler: unlike most compilers clang/LLVM includes components (such as the codegen, assembler, and linker) for different platforms in the same binary.

However you'll run into a number of problems trying to use it as such in a production capacity:

  • You need platform libraries and headers. To generate an executable that will work on Windows you need Windows headers and Windows libraries you want to link to, either import libs if you're dynamically linking or static libs for static linking. You should be able to get these from an installation of Visual Studio.

  • Many C++ features such as name mangling and RTTI support are not complete on Windows. You'd have these same problems compiling for Windows on Windows with Clang. Windows C++ support is pretty much complete these days.

  • The LLVM project includes the lld linker, which is apparently far enough along that it can self host on x86 Windows and so might work for you as a cross-platform linker, however lld is not yet a standard part of clang distributions. Clang on OS X still uses the OS X platform linker ld by default as does Clang on Windows (link.exe). You'll need to get lld and figure out how to link with it, or find some other cross-platform linker.

  • The clang driver isn't written as a cross-platform compiler driver. You'll likely have to do a lot more hands-on work to run a cross-platform compilation. Take a look at the output of clang -###: the clang driver constructs that command for you, but you may have to do much of the same work as the clang driver by hand. And since clang gets much less testing at cross-platform compilation you're likely to run into more bugs.

  • Xcode is not going to help you with any of this. It can configure clang to build for OS X or iOS, but you'll have to manually configure cross-platform builds to Windows.

I'm relatively confident that one could cobble together an LLVM based environment to build a C "Hello, World" Windows exe on OS X or Linux, but it's not quite ready for Xcode to add a "Windows" item to the list of possible target platforms.


If you're not a compiler developer you're probably best off just copying your source code to a Windows machine and building with Visual Studio. If you are, or want to be, a compiler developer then by all means, help push Clang's cross-compilation abilities forward. I think the Clang universal driver project is exciting and I would really like to see progress continue.


I've successfully done the opposite cross-compilation: compiling a Mac OS X executable on Windows. This turned out to be quite easy to do manually on a small program, i.e. directly compiling a .cpp file.

First, Mac OS X development tools come with "SDKs" which contain all the system libraries and headers for a particular OS. The largest challenge here was figuring out how to transfer the SDK to Windows while preserving all the symbolic links in the SDK. (For some reason creating symbolic links on Windows requires elevated privileges, so after producing a tar.gz on OS X with the symbolic links I had to run 7zip on Windows as an administrator to correctly expand the archive.)

Once the SDK is available on Windows there's a single flag to tell clang where to get all the system dependencies: -isysroot. This combined with the -target flag were all that I needed to tell clang how to produce complete object files for OS X.

For linking I manually used lld, as the compiler driver didn't seem support using cross linking with lld. lld supports similar flags for determining the target system libraries.

The final step was simply copying the produced executable to an OS X machine, enabling the execute permission (Windows doesn't support the same file permissions so the execute bit doesn't get set when building) and running the result.

Cross-compiling from OS X to Windows using clang and the Visual Studio 2013 runtime

This is somewhat experimental. This example can be compiled and linked successfully, but I wouldn't have high hopes for building a large and complicated project (e.g. Chromium) this way right now.

Requirements:

  • An installation of clang. I used Apple's clang (3.5) from Xcode 6.1.
  • A copy of the Visual Studio 2013 headers. A standard Visual Studio 2013 installation will put this in C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include by default. This should also be included with the express edition. (/path/to/vs2013_include below)
  • A copy of the Visual Studio 2013 libraries. A standard Visual Studio 2013 installation will put this in C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib by default. This should also be included with the express edition. (/path/to/vs2013_lib below)
  • A copy of the Windows SDK. This can be downloaded from Microsoft (for example, version 7.1). You can find existing installations in C:\Program Files (x86)\Microsoft SDKs\Windows.
    (/path/to/windows/sdk/vX.X/Lib below)
  • A build of lld, the llvm linker. It is not yet entirely complete and must be built per the instructions on its site.

Procedure:

Save this file as test.cpp:

#include <iostream>

int main() {
std::cout << "Hello, world!\n";
}

First, run clang (with the path to wherever you've put the VS2013 headers substituted):

clang++ -target i386-pc-win32 -isystem /path/to/vs2013_include -std=c++11 -fms-extensions -fms-compatibility -fdelayed-template-parsing -fno-rtti -fno-exceptions -D_HAS_EXCEPTIONS=0 -D_ITERATOR_DEBUG_LEVEL=0 -fmsc-version=1800 -c test.cpp

This should generate test.o.

Then, run the linker (with the appropriate VS2013 lib and WinSDK directories):

lld -flavor link /libpath:/path/to/vs2013_lib /libpath:/path/to/windows/sdk/vX.X/Lib kernel32.lib user32.lib shell32.lib /subsystem:console libcmt.lib test.o

This should produce test.exe which can be run on Windows.

Notes:

  • As you can see in the invocation of clang, exceptions and RTTI are disabled. Microsoft compatibility for these features of lld is not yet complete.
  • I have been unable to execute the linking step successfully on Ubuntu, it triggers an assertion in lld. This has only been tested on OS X.

How to Compile for OS X in Linux or Windows?

There appears to be some scripts that have been written to help get you set up cross compiling for the Mac; I can't say how good they are, or how applicable to your project. In the documentation, they refer to these instructions for cross-compiling for 10.4, and these ones for cross compiling for 10.5; those instructions may be more helpful than the script, depending on how well the script fits your needs.

If your program is free or open source software, then you may wish instead to create a MacPorts portfile (documentation here), and allow your users to build your program using MacPorts; that is generally the preferred way to install portable free or open source software on Mac OS X. MacPorts has been known to run on Linux in the past, so it may be possible to develop and test your Portfile on Linux (though it will obviously need to be tested on a Mac).

clang BlocksRuntime embeds 'obsolete compiler' warning in executable when using __block

I've just realized that the warning is probably meant to be a runtime error stored as a string in the executable, which means that there is no problem. Disassembling seems to support this idea - radare2 shows the string in the .rodata section:Screenshot of radare2 showing 'obsolete compiler' string in .rodata section

I really should have though of that earlier...

Cross Compiling from XCode on the Mac to Windows

If you stick strictly to the subset of POSIX C supported by both Mac and Windows (which implicitly limits you to console applications), you can possibly get a Windows cross-compiler for OS X and build applications that way.

However, you will likely find your life vastly simplified if you just run Windows in a VM (or via Boot Camp) and develop your application in Visual Studio or any other Windows development environment. This is the only way to make a Windows GUI app, and realistically the only good way to write a Windows console app.

How to create OS X app with Python on Windows

Short answer:

Apparently, no simple way to do this with the standard set of tools you have mentioned. I outline a completely unprobable solution in the end that's probably too complex to consider.

End result: Keep doing it manually, it's probably the best option so far.


Drawing from credible and/or official sources:

There's already a long and curated list of options specified in micheal0x2a's excelent answer in Create a single executable from a Python project which outlines most tools available for creating standalone distributions of a Python program. One line stands out:

Also, unless otherwise noted, all programs listed below will produce an exe specifically for the operating system it's running in.

I might have read things wrong but there's no explicit note of cross platform support.

Similar lists can be found in in Distribution Utilities and Freezing Your Code — The Hitchhiker's Guide to Python. From these we can take a look at the Windows supported projects:


bbfreeze: Not maintained, no documentation on limitations generally superceded by the rest in this list.


PyInstaller: According to their documentation:

PyInstaller is tested against Windows, Mac OS X, and Linux. However, it is not a cross-compiler: to make a Windows app you run PyInstaller in Windows; to make a Linux app you run it in Linux, etc. PyInstaller has been used successfully with AIX, Solaris, and FreeBSD, but is not tested against them.

PyInstaller once tried to support cross-compilation (From Linux -> Windows) but later dropped the idea.


cx_freeze: Looking at their Freezing for other platforms question in their Frequently Asked Questions list:

cx_Freeze works on Windows, Mac and Linux, but on each platform it only makes an executable that runs on that platform. So if you want to freeze your program for Windows, freeze it on Windows; if you want to run it on Macs, freeze it on a Mac.


py2app: This is not an option since py2app is supported only OSX machines based on their note:

NOTE: py2app must be used on OSX to build applications, it cannot create Mac applications on other platforms.

So installing it on windows is a no-go.

This wraps out the tools available on for creating standalone applications on Windows. Even if not on Windows though, solutions don't exist for creating an OS agnostic tool.

The general consensus for achieving these sort of things is via Virtual Machines; you create a VM image of the target OS, run the dedicated tool for that OS inside the vm and then tranfer the bundled executable to compatible machines. Since OSX is generally not easy to virtualize, from what I know, you kinda run out of luck here.


One complex probable way:

Now, the reason why I said there is no simple way to do this is because there might be one but, from what I can see, it is so tedious you shouldn't even consider it. The general issue we're facing here is that executables for windows are simply not compatible with OSX, heck, Linux executables aren't either. So what we need is the ability to cross-compile things.

One compiler that I've heard supports cross-compilation is clang. So, in order remedy the incompatibility of executables, you could theoretically use clang as a cross compiler. Problem is, this is not a simple task; it is probably way harder than what you're willing to do since it is riddled with complex issues (From OSX to Windows example).

If you do actually find a way to that you now need a .cpp/.c file from your python scripts. Thankfully this is something that can be done by using tools like Nuitka or Cython.

The gist of these is the same, enter .py exit .cpp/.c. The second tricky part might be setting up the clang compiler to be used with these. I honestly have no idea if anyone has done this.

I haven't looked into them much, but for Nuitka, I know that it can also be used to create a standalone executable when passed the --standalone flag (See: Moving to other machines). So, theoretically you could use Nuitka with clang configured to cross-compile for OSX. Then you can rest; you've earned it.



Related Topics



Leave a reply



Submit