Multiplatform Premake Script - premake

I'm the author of Node9, a hosted, hybrid OS that combines Inferno and LuaJIT to create an interactive, distributed development environment. See the project here: https://github.com/jvburnes/node9
I created a basic 4.x premake script to compile all of the dependencies and main source code for OSX, but now people are asking for build configurations for Linux, BSD and Windows. I have the code to do this and I want to create premake configurations to build and run Node9 on these OSs. I'll need to set library and include search paths, compiler names, as well as per-platform defines.
Can anyone point me to a good multi platform premake script?
Do I use "premake gmake" and sense the native platform somehow or do I need to explicitly place the target platform on the command line and refer to that platform in the premake Configuration and Platform sections?
I heard that premake 4.x was legacy and that premake 5.x is the solution going forward. Is it stable and available enough to build for all these platforms?
I know that's a lot of questions, but I want to do this right.
Thanks.

I'm not an expert in multiplatform compilation, but here are some things that might help you. First, I strongly advise you to switch to Premake5. It's stable, the community works on it and is quite active, and you have support for modules (Android ? :p) and a lot of cool other features.
As for your questions:
I can't, but basically it should be as simple as something like this:
solution "multiplatform_solution"
configurations { "debug", "release", "whatever" }
-- now here, you define your supported platforms
platforms {
"win32",
"win64",
"macos",
"linux86",
"linux64",
-- etc.
}
project "some_project"
-- now you can configure some things per platform:
filter { "platforms:win32" }
-- some defines, some specific paths to libs, etc.
-- specific to win 32
defines { "WIN32" }
filter { "platforms:macos" }
-- macos specific configurations
defines { "you_fool_" } -- yes, it's a troll :p
-- etc.
-- and configure the rest as usual
When you invoke premake gmake you just tell premake to build a makefile for gmake. If you have gmake on Windows, MacOS and Linux, you can use premake gmake for all platforms. It's when you actually build that you just need to specify your configuration and platform. I don't know gmake well enough, but that might look something like this: gmake config=release platform=linux32
As I said, you probably want to update to Premake 5. I think it's stable enough, and in case of problem you can ask questions here :)

Can anyone point me to a good multi platform premake script?
If you look at a Premake source package, you'll see that it contains multiple makefiles, one for each platform it targets, in directories named like build/gmake.windows and build/gmake.macosx. That's one option.
Another approach is to put it all in one Makefile, like #Citron suggested in his script, and select the desired configuration on the command line at the time you do the build. In that case, your build command should look like:
$ make config=debug_win32
If you run the help target on the Premake generated Makefile it will give you a list of all the valid configuration options:
$ make help
Or, if you don't mind requiring your developers to have Premake installed locally, they can generate a makefile customized for their environment before building. In that case your script might look something like:
solution "MySolution"
configuration { "Debug", "Release" }
filter { "system:Windows" }
-- windows specific stuff
filter { "system:MacOSX" }
-- mac specific stuff
filter { "system:Linux" }
-- etc.
In this case, running premake5 gmake will create a makefile targeted to the current environment.

This is pretty close. I think a slightly closer answer would be to use filter on the "system:". I think it's the difference between using premake to generate a multiplatform make and using it to build the current platform makefile.
It's the closest answer so far so I'll upvote it.

Related

Modules of Qt 5.1 and their interdependency?

I am looking for a way to create a minimal static build of Qt 5.1. By minimal, I mean a build with only the basic set of widget classes available (including 2D graphics acceleration through an OpenGL canvas/widget). I am aiming for a static build on Windows 7 32-bit using MinGW-builds GCC 4.8.1 as well as their bundle of MSYS and tools.
I have downloaded the entire source tree, and have met some problems with compiling due to the dependency of packages such as OpenSSL and ICU (the latest OpenSSL did not compile). I wanted to see, if I could avoid dependencies of these packages and, at the same time, achieve a minimal static build of Qt 5.1 so my final executable is not gigantic in size.
I took a look at this list:
http://download.qt-project.org/official_releases/qt/5.1/5.1.0/submodules/.
Q1: Which of these modules, do I need to select to have a basic Qt build without all the fancy stuff?
Q2: Are these modules interdependent on each other in some way (I assume they are all dependent on "qtbase")?
Q3: Do I use the names from that list, (for example: "qtxmlpatterns", "qtx11extras", "qtwebkit", etc.), to deselect them in the configuration of my Qt build?
It would also be nice, with an explanation of the various submodules of Qt 5? If someone could point to any links or docs with illuminating words on this subject, that would also be great.
I shared this same goal. I wanted to "minify" Qt, building only a small subset of the libraries/DLL(s) and omitting the rest.
I did succeed, at least on Mac OS X. I assume that this approach will work on other platforms, too.
I thought that the trick would be to find some kind of exclusion flags for the "configure" script, but that turned out not to be the case.
Here is what I did:
Download the source distribution (in my case, qt-everywhere-opensource-src-5.1.1). of course, extract it all.
Edit the following three "pro" files. these files are in a qt-specific format (but plain text). They are platform-independent project files that Qt (via qmake) uses to generate makefiles.
qtbase/src/src.pro
qtbase/src/plugins/plugins.pro
qtbase/examples/examples.pro
All the changes that I made to the "pro" files were deletions. I deleted references to: dbus, ipc, network, qtconcurrent, sql, xml, sqldrivers, qdbusxml2cpp, qdbuscpp2xml, src_dbus, src_concurrent, src_sql, src_network.
That last part may sound scary. It really wasn't.
The pro files contain a list of module names, plugin names, and directory names. It seemed fairly straightforward how to delete (for example) all SQL-related lines.
Step 3.
The usual configure/make/install. However, note the "module-qtbase" argument passed to make:
./configure -prefix ~/my_test_dir/
make -j2 module-qtbase
make -j2 module-qtbase-install_subtargets
Success. This built and installed only the essentials (QtCore, QtGui, QtOpenGL, QtWidgets) and skipped all the supporting dylibs like QtConcurrent, QtMultimedia, QtSql, and QtWebKit.
ICU can link statically, and you can customize it (see docs) to reduce size. By default the data is also large, I don't know how much data you need. You could include only enough data to run in one language.
Only part of an answer.
There's no need to disable Qt modules. Each application that uses Qt decides what modules it uses and links with. A basic console-only application may use the core module only. That's what you'd use when creating, say, a web service in Qt.

macdeployqt on homebrew installed frameworks

I'm trying to deploy an application using macdeployqt. All Qt frameworks get copied correctly into the application bundle. The problem I encounter is that macdeployqt does not have write permissions on the copied frameworks which originally reside in /usr/local/lib. This is because I have installed qt using homebrew which seems to make install everything read only. My question is whether there is a better way to fix this issue then manually changing all permissions of the qt libraries inside /usr/local/lib so that I can use macdeployqt from within a qt .pro project. (I don't want to use macdeployqt manually with sudo or such)
The reason why I'm asking is because I am using many third party libraries in the project (they get copied ok etc.) which I need to update often through homebrew and thus have to redo the permission changing on them.
Thanks in advance!
Just in case someone finds this old post looking for info about macdeployqt:
Use a script to do macdeployqt in preference to scripting the macdeployqt commands in your .pro file. That will allow you to change the permissions on the files on the fly.
Here is [a snippet of] the script I use for one of my apps:
https://bugreports.qt-project.org/browse/QTBUG-23268
If you're on Windows and don't have bash, you can use perl or python. The script referenced above modifies the files on the fly to work around a bug - you can put anything you want here, including changing the permissions on the files.
Using a script also means that you have the flexibility to add commands later to do code-signing, packaging or whatever else you need.
The Qt .pro "scripting language" actually generates Makefile commands under the hood and can be quite obscure if you want to accomplish deployment tasks that relate to paths and sets of files.
Also you'll need to create an extra target or include it into your build target - either way the build process becomes more complex and more error prone.
Disclaimer: I worked on Qt for 8 years as a Senior Engineer for Nokia/Trolltech, and also have published a commercial cross-platform app using Qt.

What should expericenced Unix programmer to be aware of using Microsoft Tools?

I come from UNIX world, I'm quite familiar with Linux, Solaris, Cygwin
and MinGW development. Recently I ported one of my
big projects (cppcms) to support MSVC,
including building static and dynamic libraries with CMake.
And I get all the time absolutely weird issues:
I had CMake build issues because Windows programming
lacks naming convention
for import and static libraries.
Now I discovered that I should use different versions of ICU (debug/release builds) according to the
actual build I do (Debug/RelWithDebInfo -- should use Debug ICU, Release release ICU) and so I should
change actual conventions for searching libraries according to debug/release mode only under MSVC.
Otherwise application just would not start giving a error on missing DLL.
I don't have any such issues under Mingw or Cygwin with GCC, Open Solaris with Sun Studio or Linux with gcc or intel compilers.
And I still have numerous wired issues and wired bugs and very strange behavior -- even some trivial things do not work
under MSVC builds, when everything works absolutely fine under Solaris/Linux/Cygwin/Mingw using GCC from 3.4 up to 4.4,
Sun Studio and Intel compilers). But not under MSVC.
To be honest, I have no idea how to deal with Last one! Because it looks like for me more like environment issues.
I know that the question is not really well defined. I think I'm quite experienced
developer and I know how to write portable and good C++ code. But using Microsoft native
tools drives me crazy with issues I just don't know how to solve.
Question: What should experienced Unix programmer with quite good base in Win32 API should know when it
starts using Genuine Microsoft Tools?
P.S.: Can someone explain why "Release With Debug Info" requires Debug version of MSVC runtime? And why there two versions of runtime exist at all?
P.P.S.: Please note I don't have issues with Win32 API, in fact Windows GCC build works absolutely fine.
Clarifications:
I'm looking for pitfalls that programmer that come from Unix world would may fall into.
For example, when moving from Linux to Solaris: make sure you compile code with -mt or
-pthreads when using multi threaded programs, linking with -lpthread is not enough.
P.S.: Can someone explain why "Release
With Debug Info" requires Debug
version of MSVC runtime?
It doesn't.
And why there
two versions of runtime exist at all?
Because the debug version does more error checking.
And I still have numerous wired issues
and wired bugs and very strange
behavior -- even some trivial things
do not work under MSVC builds,
* What am I doing wrong?
Not telling us what "wired issues and wired bugs and very strange behavior" you get.
* Where should I start?
By telling us the specific errors and problems you encounter.
* What do I miss?
Reading the documentation and learning the tools.
If your question is "What do I read to become a good Windows programmer?" then my answer is: Everything from Jeff Richter, as a start.
There is no magic bullet which will automatically make you an experienced Windows developer. Windows is a very different land compared to Unix. There are lots of quirks, weird behavior, and stuff which is just plain different. The only way to get out with your sanity intact is to tackle the transition one small problem at a time. Concentrate on a specific problem and try to understand the problem. Don't just "get it to work", but really understand what is happening. A good book about Windows programming will help.
There are huge amounts of Windows knowledge and experience accumulated in the SO community, but the only way to access it is to ask concrete questions about specific problems.
The release and debug versions of DLL's use different ways of allocating memory, that is why it is not advisable to mix release and debug versions. If you allocate something in a debug mode DLL and pass it back to the application which was compiled in release mode you may get into trouble.
In the case of your naming issues you may want to have different directories where you place your static / dll's. You can do do this in visual studio by using the configuration manager, not sure how it is under the express version.
I think you need to try and actually understand the new toolset rather than just try and squish it into your current understanding of your existing tools. For that, the best way, IMHO, is for you to try and start to use Visual Studio as Microsoft intended and then once you can build a simple project in the IDE you can move to building it using your preferred make system but do so with an understanding of how the IDE is using its make system to set things up for that build (which WILL work).
So, for example, for part 1 of your question you want to create a simple static library project and a simple dll project and look at the linker options tabs. Jump to the 'Command line' view and you'll see that a DLL uses the /OUT linker option to set the name and location of the dll file and the /LIB linker option to set the name and location of the import library. With a static library only the /OUT option is used and it indicates the name of the static lib. It's true that if you're building a static lib and a DLL from the same source and you have both the /LIB for the dll set to MyCrossPlatformCode.lib and /OUT set to MyCrossPlatformCode.dll then you may have problems if you also build a static lib with an /OUT switch of MyCrossPlatformCode.lib... Simply don't do that; either build the static libs to a different output directory (which is what OpenSSL does), or, better (IMHO), mangle the names somewhat so that you have MyCrossPlatformCode.lib/.dll and MyCrossPlatformCode_static.lib (which is what STLPort does).
Note that you might also want to mangle in (or account for) building with different versions of the Microsoft tool chain (so you might end up with stlport_vc8_x64d_static.5.1, perhaps).
An alternative approach, if you really can't face the thought of understanding your toolset, is that you could take a look at some of the popular open source systems that build quite fine on Windows and Unix systems; OpenSSL and STLPort for a start, perhaps.

What use does ./configure serve (other than checking dependencies)

Why does every source package that uses a makefile come with a ./configure script, what does it do? As far as I can tell, it actually generates the makefile?
Is there anything that can't be done in the makefile?
configure is usually a result of the 'autoconf' system. It can generate headers, makefiles, really anything. 'Usually,' since some are hand-crafted.
The reason for these things is to allow source code to be compiled in disparate environments. There are many variations on Unix / Linux, with slightly different system headers and libraries. configure scripts allow code to auto-adapt.
The configure step is a sort of meta build. It generates the makefile that will work on the specific hardware / distribution you're running. For instance it determines the name of the C or C++ compiler and embeds that in the makefile.
The configure step will also frequently take a set of parameters, the values of which may determine what libraries need to be linked against. For instance if you compile Apache HTTP with SSL enabled it needs to link against more shared libraries than if you don't. Since linking is handled by the makefile, you need an extra step to create a custom makefile (rather than requiring the make command to require dozens or hundreds of options.
Everything can be done from within the makefile but some build systems were implemented otherwise.
I don't personally use configure files for my projects but I admit I mostly export Erlang & Python based projects.
I don't think of the makefile as a script, I think of it as an input to the make utility.
The configure script (as its name suggests) configures the makefile, including as you say resolving dependencies.
If only from the idea of avoiding self-modifying code, the things in the configure script don't really belong in the makefile.
the point is that autoconf autohdr automake form an integrated system the makes cross platform building on unix relatively str8forward. THe docs are really bad and there are lots of horrible gotchas but on the other hand there are a lot of working samples
When I first came across this stuff I thought - "ha I can do that with a nice clean makefile" and proceeded to rework the source that way. Big mistake. Learn to write and edit configure.ac and makefile.am files, you will be happy in the end
To answer your question. Configure is good for
is function foo available on this platform and if so which include and library do I need
letting the builder choose if they want feature wizzbang included in a nice simple consistent way

Tutorials for setting up a robust small-to-medium project *nix build

I'm mostly a spoiled Windows + Visual Studio (or Borland C++ or whatever, in the past) developer. Although my first contact with Unix was around 20 years ago, and I've used Linux on-and-off for some years, I have only a very limited idea of how to set up a build on a *nix system.
For example, I'm OK with the basics of make - I can get a number of files to compile and link. But I don't really know how to set things up to cope with multiple configurations - how to get all the object files and targets for the release version to go to different folders from the debug version etc etc. Yes, I can RTFM and improvise something, but it's a fair guess that I'd improvise something stupid, overcomplex, fragile and WTF, where it'd make so much more sense to copy a common convention if only I knew what the common conventions are.
Also, I can run a configure script, and I'm vaguely aware that they're associated with autoconf, whatever that is, but I have little idea if/why/how I should set this kind of stuff up in my own projects.
Hopefully, this is enough to give the general idea of what I'm looking for. Of course I could ask/search specific questions here, but that assumes I know all the right questions to ask which I almost certainly don't. So - any pointers?
EDIT
Just thought I'd update this with some longer-term experience.
I tried using premake for a while, but couldn't live with it in the long run. In substantial part there's a dislike of Lua behind that.
Now, I'm using cmake. It generates makefiles/visual studio projects/whatever. It has (so far) handled everything I've needed to do, including support for unit testing and custom build steps. And as I got used to the cmake way of doing things, I found it was a good way, allowing me to easily use multiple sets of tools at once - I can be checking test coverage in MinGW GCC while simultaneously debugging in Visual Studio.
That reveals, of course, that I'm still mostly working in Windows - but switching back and forth is easier than ever.
The downsides of cmake...
Although it generates makefiles/whatever, it can't really be seen as a makefile generator. The resulting makefiles are dependent on cmake being installed. To be honest, I don't really understand why they don't drop makefiles altogether for makefile platforms and just do the building directly, slightly reducing the potential for problems.
It wasn't easy to get started.
The second point has mostly been resolved by asking questions here...
How do I fix this cmake file? - problem linking to imported library
How to apply different compiler options for different compilers in cmake?
For the cmake "include" command, what is the difference between a file and a module?
How to adapt my unit tests to cmake and ctest?
I'd strongly suggest using one of the newer cousins of Make instead of autoconf or makefiles for smaller projects. One of the best ones for you (and the one I mostly love) could be premake4. Why do I suggest it? Because it's extremely simple to use, yet quite powerful, and capable of producing GNU Makefiles, Visual Studio projects, Code::Blocks projects and many more. And the premake files are very clear and readable, using the Visual Studio nomenclature that you're already familliar with.
Here's an example:
-- A solution contains projects, and defines the available configurations
solution "MyApplication"
configurations { "Debug", "Release" }
-- A project defines one build target
project "MyApplication"
kind "ConsoleApp"
language "C++"
files { "inc/**.h", "src/**.cpp", "main.cpp" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols" }
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize" }
I would stay away from autoconf until you actually need it as it is pretty complex to use, and in most small projects, make is all you need...
I don't have a tutorial, but I will give you an extremely amazing(and portable between both BSD and GNU make) makefile to start with for small projects. I dug it out of the original BSD 4.3 assembler(as)
HDRS = project.h
OBJS = main.o
LDFLAGS =
project: ${OBJS}
${CC} ${LDFLAGS} ${OBJS} -o project
.c.o: ${HDRS}
${CC} ${CFLAGS} -c $*.c
clean:
rm -f *.o ${OBJS} project *.core a.out errs core
just replace Project with your projects name and such..
edit:
technically, you need a BSD 3 clause license for Berkeley... as per:
* Copyright (c) 1982 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.

Resources