Platforms, Custom Compilers, or both?

Like I said in my comment, I don't think Platforms cover cross compilation very well. To cross compile, you often need to invoke custom compiler programs. This could be possible with a custom compiler definition like described in the comment.

Platforms also don't map to other environments than VisualStudio very well. Code::Blocks doesn't have the concept of Platforms at all, at least not in same way as VisualStudio.

Custom Compilers would be more flexible in any case. They would also allow defining new compilers or build commands (someone requested Nasm for example).

If Platforms are needed for VisualStudio, include them, but IMHO it would be best to have Custom Compilers also.

I responded to your original comment.

I just added a comment to that thread too.

As the conversation appears to be going strong, I'd like to move it from the documentation book over here to the forums where more people might see it.

You can see the original start of the thread on the platforms page for now (those comments will go away once the issue is resolved, to avoid confusion by future users).

To reiterate:

  • I agree that it would be worthwhile to have the ability to set the values for CC, CXX, AR, and WINDRES (Windows resource compiler). This will enable folks to set up GCC-based cross-compiling without any additional support from Premake.
  • I agree that support custom build steps are still required. We've never really worked out what that should look like.

That sounds like a step in the right direction. I wasn't necessarily advocating any particular implementation in my previous post, I'm just getting some ideas out in the open as to how people have solved the build process problem for multi-platform development in the past and on other similar projects to Premake.

I believe that the way target OS and platform are specified should be reorganized slightly, and a couple of additions for hardware platforms to better cover the range of CPU architectures for Windows and Mac OS X development. The way the OS and platform are used as discriminators for a configuration (with the configuration function in the Premake API) is perfectly fine as is.

Right now, the OS, as specified with the --os option, is used to essentially allow for generating files for a given operating system. The platform(s), as specified with the --platform option or with the platforms function, allows you to add new build "variants" or configurations for the different hardware/software platforms you wish to target within the generated files, whether they be visual studio solutions, gmake makefiles, and so on.

I'm kind of going of my experience here with doing multi-platform and cross-platform development, but generally the word platform is used to refer to the software platform that you're targeting, and the word architecture is used to refer to the hardware platform (CPU architecture). If you look at other open source projects that target multiple platforms such as the Boost C++ Libraries, various graphics packages and game engines, they follow something similar. This is all just semantics of course, I'm not proposing to strictly follow my naming schemes here.

I propose merging the OS option into the platform option, and removing the hardware platforms from the platform option and pushing them to a new architecture option. In this sense, it would set the stage for doing full cross-platform development for other operating systems if the tool-set supports it. This might deviate slightly from what you see in the Visual Studio configuration settings editor, where the word platform acts as a catch all for both software and hardware platforms. However, separating it into two words/categories for both software and hardware simply acts as a superset of Visual Studio behavior, there's still a one-to-one mapping from from software platform/hardware architecture pair to what gets generated the Visual Studio project.

As for hardware platforms, or architectures, the way it is now isn't quite powerful enough to capture every possible architecture you can target from Windows or Mac OS X. For Linux and BSD, there are obviously a large number of architectures that can be targeted with cross-compilers, making it important that you should be able to override the compiler toolset as previously discussed. Anyway, under Mac OS X, it's not clear if x32 refers to x86 or to PowerPC-32, and if x64 refers to AMD64/EMT64 or PowerPC-64 (AMD64 is also known as x86_64, EMT64 is Intel's name for it.) Under Windows, I'm assuming that x64 refers to AMD64/EMT64 architectures, but there's also IA64 (Itanium) which is entirely different from x64. There are also multiple 32-bit architectures for Windows CE, so if support for that platform is added in the future, x32 isn't a suitable architecture for Windows development. Furthermore, the -m32 and -m64 options for GCC don't exist for every architecture outside of x86/x86_64 and PowerPC, so you can't just map x32 to -m32 and x64 to -m64, even for native compilers. Therefore, some of these architectures should be renamed, and some new ones added.

And for Linux and BSD, only native compiler support is offered out of the box with Premake, you have to override the compiler tools to target different architectures.

If when calling Premake, you don't specify the target architecture as a command line argument, or if it is not specified what target architectures you want as build variants in your Premake build script, then Premake will simply default to using only the native architecture.

So, going by the above description, your platforms and architectures would look something more like the following:

Platforms
======
bsd
linux
macosx
ps3
windows
xbox360 (based on original XBox os, which in turn was based on Windows 2000)

Architectures
========
native (either the native architecture that you're running the build tool on, or the default/sole architecture if a platform only has a single architecture, for example, PS3 only runs on Cell)
cell (PS3's CPU)
ia64 (Intel's Itanium architecture)
ppc32 (PowerPC 32-bit)
ppc64 (PowerPC 64-bit)
universal (mac os x universal binary)
universal32 (mac os x universal 32-bit only binary)
universal64 (mac os x universal 64-bit only binary)
xenon (the 360's CPU, a tri-core PowerPC based architecture)
x86 (IA-32 based architectures)
x64 (only refers to AMD64/EMT64 architectures)

Windows Architectures
==============
native (maps to the native architecture that you're running the generated visual studio project on)
x86
x64
ia64

Mac OS X Architectures
===============
native (maps to the native architecture that you're running the generated makefile/xcode project on)
x86
x64
ppc32
ppc64
universal
universal32
universal64

Linux
====
native

BSD
====
native

XBox360
=====
native (maps to xenon)
xenon

Playstation3
=======
native (maps to cell)
cell

Visual Studio Configurations
=================
[windows, x86] -> Win32
[windows, x64] -> x64
[windows, ia64] -> IA64
[ps3, cell] -> PS3
[xbox360, xenon] -> XBox360

I forgot to mention, the above proposal no longer makes any assumptions about what platform/architecture a specific configuration is targeting, at least for Windows and Mac OS X based development. This allows for finer-grained control over architecture specific compiler options.

I've got a patch up on the patch tracker that adds support for specifying the floating-point model for C/C++ based projects. The problem, however, is I can't really think of a good way to let you specify the floating-point architecture for use of SIMD instruction sets with Premake as it currently is.

With MSVC++, you can tell it to use x87, SSE or SSE2 instructions for floating point arithmetic for x86 targets. For x64, SSE2 is the default used internally by the compiler. You can't currently tell it to target more advanced versions of SSE, AVX, AES, ABM and so on.

With GCC, for x86 you tell it to use SSE and then the the version of SSE you wish to use. For GCC and PowerPC, you can turn on/off use of either Altivec or SPE (for the PS3's Cell CPU) instruction extensions.

So if something closer to the above proposal is implemented with Premake, perhaps somehow it would be easier to enable architecture specific stuff, on a per architecture basis within the premake build script. I'm not really sure what the syntax for doing that would look like yet though.

A lot there again, I'll try to hit it all:

I think splitting out a separate architecture field is a good idea.

I don't think architectures like "cell" are necessary; if a platform only supports one architecture, that's the one used.

Is there a reason you don't list architectures for Linux and BSD?

I don't think you can get rid of the /os argument. Consider: I'm running on Windows. I want to generate a Makefile for Linux users, that includes a cross-compiling configuration to build a Windows binary. How do you set it up?

In the same way, I don't think Linux and BSD make sense as platforms. To the best of my knowledge, you can't cross-compile for those platforms from Windows or Mac.

I think there really are three separate concepts at work:

  1. I am on Windows and I want to create a makefile that will work for my Linux users: /os=linux
  2. I want a configuration that cross-compiles for the PS3 (or Windows, Xbox360, etc.): /platform=PS3
  3. I want to target a specific CPU architecture (new): /arch=ia64

This sounds good. Except: I would also like to be able to generate one makefile (or c::b project file) containing several configurations, some of them cross-compiling to a different OS and/or architecture.

That's the goal. I still have to figure out how to manage all of those variables in a sensible way.

Don't for get that the SPUs on the Playstation3 have a completely seperate compiler.

Not forgetting, but need to see project/makefile examples from people with their hands on the hardware.