Support for other languages/compilers

Hi,

Firstly I would like to thank you for your work on Premake - its a very nice, simple, approach to build configs (albeit that it hides quite a bit of complexity).

I would like to try and extend Premake to provide support for the D Language (my current language of choice) and have created a fork to (try to) do so (http://bitbucket.org/goughy/premake-dev-d/).

Firstly, are you happy with this? Is there a preference for how Premake is developed? Would you prefer all proposals/changes were communicated here prior to implementation, or rather review some actual changes? Just trying to get an idea how you'd like it to run.

I am having a bit of trouble getting an understanding of the underlying solution/project/config/platform/tool model and how they interact with each other. There are a lot of dimensions to build configurations, and the underlying design of the code is not immediately obvious to me. Any hints? Any docs?

It seems that there is a degree of constraint of Premake to C, C++, and C# (ie. premake.fields.language.allowed), so adding a new language toolchain is probably not for the faint-hearted. Is there a sensible place to attack this from?

Any hints? Any docs?
I take it you have seen [1] and the example it points to in the source? I will leave the detailed information for starkos if that is OK as I do not want to give misinformation.

I had a quick look at the changes you have already made and was a little confused as to why they were required. Whilst I realised the uuid if faked on none Windows OS's I actually think this is the correct action as the functions you have used are not standard such that 'uuid_generate' on BSD can be 'uuid_create'. I also wonder what the reason for manually copying a files data and introducing a 16kb static buffer instead of using the shell? Also which none Windows OS defines O_BINARY and what is it's function as far as I recall there is no difference between binary and text files on these systems. Edit: I misread the diffs in this commit as you are using open for all OS's

[1] http://industriousone.com/create-new-action

Hi Liam,

Thanks for your response.

I wanted to remove the reliance on the shell action as this seems unnecessarily slow. The code is already in the C world so I figured just use the standard c library mechanism to copy files to make it easier and consistent. Same goes for the UUID - better to use the platform supplied function if/when available than some hand rolled implementation. Surely if its best to use the shell, you'd do that on other platforms also? I'll admit I mostly develop on Linux so its untested on other *nix. I can rectify that pretty easily, though. The O_BINARY just ensures no text translation is performed - it might well be obsolete.

Yes - I have looked at the new action, but that is more tailored to adding support for new target build system rather than providing support for a new language AFAICT. What's thrown me a little is that there are functions called 'premake.iscppproject()' and 'premake.isdotnetproject()' which makes the system seem very constrained to those languages. I feel like there would need to be reasonably major structural changes to have the language support more data driven than it currently is. That's not something I'd want to do without input and guidance from this group.

I would take a look at the Gmake action and see how it handles generating makefiles for C/C++ vs. C#. See the newaction() call at the bottom of src/actions/make/_make.lua, the onproject function in particular. Then use either make_csharp.lua or make_cpp.lua as an example and work from there, replacing things as needed.

You'll also need to add "D" as a valid language value in src/base/api.lua

To echo Liam's comments above, please try to follow the patterns we've set wherever possible, and use the functions we've provided. The smaller and more concise your changeset the easier it will be for us to integrate and maintain it (and the more likely for it to get applied). If you don't like how we're generating UUIDs, for instance, that's cool but a separate issue and should be addressed in a separate changeset. In general, it is better to have lots of little changes than one big one.

And feel free to ask questions, I'm always glad to help out!

Hi starkos,

I have just committed the most basic changes I could to get preliminary support for gmake/D into premake. Could you have a look at the changes posted in https://bitbucket.org/goughy/premake-dev-d/changeset/652aeab432fa - there are other changesets which is me struggling with mercurial ;-)

Could you let me know if its on the right track and I'll continue to polish the code and provide more complete D support.

Thanks.

This looks pretty good to me. There's an awful lot of code duplication, but we can work on factoring that out. Two things I ask:

  • Please keep using the is...project() functions instead of replacing them with if (cfg.language == "..."). I would like to have the ability to change the criteria of those conditionals later, and don't want to have to hunt through the code looking for them.

  • Please don't change code that isn't related to the feature you are trying to add. You removed lines 297-300 of project.lua and replaced it with similar but not quite equivalent code, even though it appears that code has nothing to do with D language support.

Thanks, and nice work so far!

ok cool.

Both issues you pointed to were my (aborted) experiments in trying to understand the code - I'll revert them.

I'll add support for a few more variations of the gmake action and send a pull request (or would you rather a patch set?). Then I'll have a look at Code::Blocks as I use that also. I'll be a bit hampered by VS support as I don't have access to many environments, and its only via a 'VisualD' plugin that VS supports D at the moment anyway.

cheers.

I think the best way would be to finish CodeBlocks and anything else you want in there, get it all neat and tidy, and then submit a patch with a link to your fork. Then we can pull all the changes in once go.

Hi starkos,

It's taken a little while to get back to this, sorry, so I hope the opportunity is still open to make a contribution. I have created a patch in the tracker with the D lang changes. Unfortunately, I'm a noob when it comes to mercurial, so I have struggled with what should be easy - ie. rebasing to head and extracting a diff of my changes.

As such, I used the old fashioned method of just diffing the 2 source trees until I can figure out what I've done :-)

The full code set is available at https://bitbucket.org/goughy/premake-dev-d

I'd appreciate your feedback, and am more than happy to revise any issues you find.

goughy: If it happened that you are more familiar with git, than with hg, you can use automatic git mirror:

https://github.com/annulen/premake

Thanks annulen - I may try that. I think the issue I have is I need a better understanding of DVCS rather than just VCS - all of my experience is CVS/SVN.

Hi starkos,

Well, in a fit of productivity, I have also created a second GDC support patch that adds a second compiler for the D language for the gmake action.

The bitbucket commit(s) included in the patch are here and here (would be nicer if I'd only made a single commit - hopefully next time :-))

Hope you have time to review. Now that I have only added local changes, the diff worked properly from mercurial this time. Let me know if you're happy for me to continue to add D features and I'll open more patch requests.

Cheers.

Hello goughy,

I will do my best to look at these ASAP. In the meantime, I would suggest forking from premake-dev, if you haven't already, and putting all of your D related changes in that fork. Instead of pushing individual patches, perhaps we can get it ship-shape in your fork and then pull over the whole thing?

I'll try to get you some feedback on those patches today if at all possible.

Hi starkos,

I have already forked premake-dev into https://bitbucket.org/goughy/premake-dev-d so if you'd prefer, I can simply create a pull request.

I have already forked premake-dev into https://bitbucket.org/goughy/premake-dev-d so if you'd prefer, I can simply create a pull request.

Thank you for your contribution supporting D.

We read about Lua, hoping to be able to help in the future...

Hi Gour,

No problem - I quite enjoy it. Have you tried premake for your D builds yet? I'd appreciate your feedback. I just pushed another commit that now provides LDC2 support as well, but each of the toolchains only supports some outputs. It's only supporting Makefiles at the moment also.

DMD: "ConsoleApp" and "StaticLib"
GDC & LDC2: "ConsoleApp" only

I have yet to figure out how LDC2 supports shared libs (although I believe it does) so that shouldn't be too hard, and both LDC2 & GDC fail for me on static libs. I haven't tried GDC on shared libs yet, but as its GCC based it should work

No problem - I quite enjoy it.

Great, premake really looks nice to be deployed.

Have you tried premake for your D builds yet? I'd appreciate your feedback.

Not yet...busy with some other non-computer stuff, but I hope I'll do it soon.

I just pushed another commit that now provides LDC2 support as well, but each of the toolchains only supports some outputs. It's only supporting Makefiles at the moment also.

Let's hope it will be applied upstream...Support for Makefiles is OK for now.

I have yet to figure out how LDC2 supports shared libs (although I believe it does) so that shouldn't be too hard, and both LDC2 & GDC fail for me on static libs. I haven't tried GDC on shared libs yet, but as its GCC based it should work.

So far, I only have DMD installed, but looking forward for GDC hoping it will be included in GCC.

However, I'm not so sure about pro/cons of LDC2? What would be advantage of using LDC2 over GDC2?

Feedback on stuff like is a huge help. If anyone has an interest and has time to take a look at goughy's fork, please do!

In general, the patches look good. You're going about things the right way. I appreciate that you're trying to write some tests, that's a big help.

A couple of oddities with your first patch which you may have already taken care of:

* You've an unresolved merge conflict in cmdline.lua

* In project.lua (and elsewhere, but particularly here) it looks like you made changes unrelated to the D stuff. They are odd changes, which makes me thing they might have been caused by a merge gone wrong?

gour: LDC2 vs GDC2?

I'm actually not sure. I pretty much just use DMD myself. The support I added simply maps the relevant command line flags and builds executables in my tests. As to the advantage of one over the other, you'd need to discuss that with the tool owners.

starkos: I have been holding off announcing D support in premake on the D mailing list until you had at least done a first review - I would not like to announce that premake supports D if there is not at least a chance of the changes being accepted upstream. If I do announce it, though, there might be more interest from the community in testing it. Its a bit of a chicken and egg problem. Any preference?

>LDC2 vs GDC2?

[holy war]
LLVM rulez, surely!
[/holy war]

starkos: yes, those issues have been resolved. Being new to mercurial meant I was following recipes to manage upstream merges etc and I've not fully recovered :-) Probably the best way to check out the changes is to look at the diff between my tip and where I rebased against premake-dev at this point. The original changeset I posted has been overtaken by more recent changes, but then it makes it more difficult to review. Once I get my process sorted, it will go more smoothly.

annulen: don't even start :-)

[holy war]
LLVM rulez, surely!
[/holy war]

OK, I just wonder why?

>OK, I just wonder why?

I've tagged it as "holy war" because this statement is not shared by everyone :) Personally I think that gcc will die eventually, and LLVM is the future, but this discussion is off-topic for this forum.

OK ;)

I would prefer not to put D support in 4.4, not because there is anything wrong with it, but because I'm never going to get it out the door if I don't stop accepting new features!

How would you feel about announcing it as alpha and pointing people to your repository? Getting all the kinks worked out there will help save me time applying patches later, once it gets merged into premake-dev.

I would prefer not to put D support in 4.4, not because there is anything wrong with it, but because I'm never going to get it out the door if I don't stop accepting new features!

Only if you release 4.4.1 soon! ;)

It would be possible to avoid both release blocking and forking, if someone factored D support into separate addon.

starkos: no problem - the release schedule is yours to manage, I am hopeful that the D stuff can eventually make it in, that's all.

As for the announce, I'll do that and point them to my bitbucket repo. It'd be nice if I could also say that there are currently no impediments to upstream inclusion?

annulen: I'm not sure what you mean by a separate addon? Do you mean it could all be factored into a 'newaction'?

>I'm not sure what you mean by a separate addon? Do you mean it could all be factored into a 'newaction'?

If seamless integration with 'gmake' action is not your goal, this code could be trivially changed to be newaction, e.g. 'gmake-d'.

It somewhat sacrifices user experience. However, you can do it better: insert "D" into valid_languages, dc into valid_tools, and override onsolution with your own function aware of D. This is a bit more complex and can be considered as 'dirty hack' (relying on private implementation details from external code), however you will be able to use 'gmake' action for D too.

Than you could move it into Premake for 4.5 release, as I'm planning to do with my Qt support code.

I see no reason why D support couldn't be included in the next release.

It might be possible to implement something like an add-on. I don't think I would implement it as a new action though. I'd have a file to include that inserted the new values (api, known languages, etc.) into the right places. Then someone could just include a file at the start of their script to enable the D support (and simply remove it once the D support is built-in).

Ah, I get it - an include file that effectively monkey patches D support in. Its possible, but I'm not sure of the advantage over just using the premake-dev-d fork?

I was not aware about "monkey patch" term, thank you!

Advantage is clear: everyone willing to try D support could use official stable release. This means that 1) no need to build anything (at least on Windows, Linux, and Mac); 2) one can update D support just by downloading newer version of your add-on, still using official stable release of Premake.

Advantage is clear: everyone willing to try D support could use official stable release. This means that 1) no need to build anything (at least on Windows, Linux, and Mac); 2) one can update D support just by downloading newer version of your add-on, still using official stable release of Premake.

+1 for including D support in official premake release.

>+1 for including D support in official premake release

Heh, seems you want to get everything and right now :)

AFAIU, there are only 2 options:
1) use goughy's branch, based on premake-dev, before it's included in 4.5 release
2) move D support into addon (as separate action or monkey patch for 'gmake'), which can be used with official premake release (upcoming 4.4, and probably 4.3 too)

Ok, well your wish is my command, obviously. I have extracted D support into single include module 'd.lua' available here which enables you to simply copy the 'd.lua' file into the directory next to your premake4.lua build script, and place a single "require 'd'" statement at the top to include a monkey patched version of premake with D support.

At the moment, though, I have only tested against premake 4.4, and as there have been some namespace changes, I would not expect this to work against premake 4.3 - if someone is adventurous enough, they can give it a go :-)

Here is an example:

require "d"
 
solution "http4d"
	configurations { "debug", "release" }
 
	configuration "debug"
        buildoptions "-v"
		flags { "Symbols", "ExtraWarnings" }
 
	configuration "release"
		flags { "Optimize" }
 
	project "http4d"
		kind "StaticLib"
		language "D"
		files { "**.d" }
        excludes { "main.d" }
 
	project "test"
		kind "ConsoleApp"
		language "D"
		files { "main.d" }
        links { "libhttp4d.a" }

gour: Please give it a go and let me know the results.

This prints out a big warning that it is experimental, but it appears to work ok for me.
NOTE: This approach depends on the internal implementation of premake. Hence if starkos makes any changes to the internal API, this code is likely to break, so YMMV.

goughy: You could do the next trick with onproject:

local old_onproject = premake.action.list.gmake.onproject
premake.action.list.gmake.onproject = function(prj)
  local makefile = _G._MAKE.getmakefilename(prj, true)
  if premake.isdproject(prj) then
    premake.generate(prj, makefile, premake.make_d)
  else
    old_onproject(prj)
  end
end

This should work even if someone else hooks into gmake.onproject

Looks cool goughy, thanks for that. I will get D support into premake-dev ASAP.

annulen - nice! I'll do that where it makes sense.

Lua is awsome.

goughy: AFAIU, you don't need to write d.lua as a full-fledged Lua module with isolated environment. You could simply put your public functions into table (e.g., "premake.d") and use "local" for everything else.

annulen: probably true, but I like encapsulation. Actually I also thought it would need it to be a module to use "require 'd'" - maybe that's not so.

On another topic: what is the best way to extend the available targets generated? The current makefile generator creates 'all', 'clean' , 'help' and a per project target. However, I would like to be able to do things like 'make doc', 'make test', 'make install' etc. I can easily add those targets to my D-specific module, but I'd like to know if there is a designated way to add additional targets (or if its even contemplated) in the core?

My initial thought is to just add these targets as configurations: so 'make config=test' or 'make config=doc' and so on, but that is less intuitive than 'make doc'. I'd also like to avoid 'premake4 doc' by adding a new premake action, as that also seems counter intuitive (to me).

It's possible to require any Lua script.

To add new targets I'm using custom makefile sections (patch is in the tracker). For example, see how lupdate target is implemented in my qt-support.lua

Previous post was written from phone; here are missing links:

1)patch: http://sourceforge.net/tracker/?func=detail&aid=3353719&group_id=71616&a...

2)qt-support.lua: https://gist.github.com/1312957 (search for "lupdate" - new target is added both to solution and to projects)