Thread: [Premake-users] Custom Build Commands starting
On GitHub now!
Brought to you by:
starkos,
ttk-bandit
From: Jason P. <st...@in...> - 2012-03-11 22:12:04
|
I am going to be starting work on custom build commands in premake-dev this week. I've posted my current working syntax on the wiki at https://bitbucket.org/premake/premake-dev/wiki/Custom_Build_Commands Feedback and design challenges very much appreciated! -st. |
From: Konstantin T. <an...@ya...> - 2012-03-12 09:15:43
|
12.03.2012, 02:10, "Jason Perkins" <st...@in...>: > I am going to be starting work on custom build commands in premake-dev this week. I've posted my current working syntax on the wiki at https://bitbucket.org/premake/premake-dev/wiki/Custom_Build_Commands > > Feedback and design challenges very much appreciated! Great news! My thought on it are in comments for Todd's patch [1]. In particular, I'm not sure that syntax like "configuration '**.lua'" will be reliable enough for all cases. 1) How will it work if I need to transform e.g. *.lua to *.lua (abstract preprocessing)? 2) How more complex filters are meant to be implemented (custom list of input files, or picking up file with use of custom filtering function[2])? 3) Is compilation of generated files supported? [1] http://sourceforge.net/tracker/?func=detail&aid=2793087&group_id=71616&atid=531880 [2] See https://gist.github.com/1312957, e.g. function premake.qt.ismocableheader. It generates moc file from header only if it contains Q_OBJECT macro. -- Regards, Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-12 09:21:35
|
12.03.2012, 02:10, "Jason Perkins" <st...@in...>: > I am going to be starting work on custom build commands in premake-dev this week. I've posted my current working syntax on the wiki at https://bitbucket.org/premake/premake-dev/wiki/Custom_Build_Commands > > Feedback and design challenges very much appreciated! Also, how %(file.abspath) and similar patterns are planned to work? Is "file" a hardcoded "variable"? If so, why not use e.g. "infile" for clarity? -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-12 18:39:15
|
> How will it work if I need to transform e.g. *.lua to *.lua (abstract preprocessing)? You will either have to list out the files you want to transform explicitly, put them in a different folder, or find some other way to identify them. Once identified, the same syntax would be used to describe the build command. > 2) How more complex filters are meant to be implemented (custom list of input files, or picking up > file with use of custom filtering function You can always provide a list of specific files: configuration { "hello.c or goodbye.c" } I'm open to suggestions for improvements there. Support for "custom filtering functions" is a good idea, and worthy of a feature request. Per your example, I think it should be written as: configuration { qt.ismocableheader } The function would get called back at bake time with a list of terms, and would return true or false to apply the configuration block. > 3) Is compilation of generated files supported? I mentioned on the wiki page that source files listed in the outputs should get fed back into the build, and object files back into the link step. Did you mean something else? I am, of course, open to other suggestions. -st. On Mar 12, 2012, at 5:15 AM, Konstantin Tokarev wrote: > > > 12.03.2012, 02:10, "Jason Perkins" <st...@in...>: >> I am going to be starting work on custom build commands in premake-dev this week. I've posted my current working syntax on the wiki at https://bitbucket.org/premake/premake-dev/wiki/Custom_Build_Commands >> >> Feedback and design challenges very much appreciated! > > Great news! > > My thought on it are in comments for Todd's patch [1]. > > In particular, I'm not sure that syntax like "configuration '**.lua'" will be reliable enough for all cases. > > 1) How will it work if I need to transform e.g. *.lua to *.lua (abstract preprocessing)? > 2) How more complex filters are meant to be implemented (custom list of input files, or picking up > file with use of custom filtering function[2])? > 3) Is compilation of generated files supported? > > > [1] http://sourceforge.net/tracker/?func=detail&aid=2793087&group_id=71616&atid=531880 > [2] See https://gist.github.com/1312957, e.g. function premake.qt.ismocableheader. It generates > moc file from header only if it contains Q_OBJECT macro. > > -- > Regards, > Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-12 18:54:14
|
12.03.2012, 22:38, "Jason Perkins" <st...@in...>: > Support for "custom filtering functions" is a good idea, and worthy of a feature request. Per your example, I think it should be written as: > > configuration { qt.ismocableheader } > > The function would get called back at bake time with a list of terms, and would return true or false to apply the configuration block. I'm afraid configuration() is becoming too much overloaded. If meaning of configuration "filename" is more or less clear (note that we can have collisions between names of files, configurations, platforms, compilers, etc.), meaning configuration(function) is dubious. > >> 3) Is compilation of generated files supported? > > I mentioned on the wiki page that source files listed in the outputs should get fed back into the build, and object files back into the link step. Did you mean something else? Sorry, I've overlooked this item. BTW, I think we should ensure that it's possible to create rule chains when outputs of one custom rule are used in another. I also think that each rule should have separate "exclude" list. -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-12 18:50:10
|
> Also, how %(file.abspath) and similar patterns are planned to work? I will add this to the wiki, since it going to have to be as part of 4.5. My intention is to provide a few context objects: sln, prj, cfg, and file. You can then access any field of those objects: %(sln.name) %(prj.location) %(cfg.targetdir) The contents of the $() would be run through loadstring() and executed at token-replacement time, so in theory more complex replacements could be used. %(sln.name:gsub(' ', '_')) I haven't actually done any work against this yet, so it is all open for discussion and subject to change. -st. On Mar 12, 2012, at 5:21 AM, Konstantin Tokarev wrote: > > > 12.03.2012, 02:10, "Jason Perkins" <st...@in...>: >> I am going to be starting work on custom build commands in premake-dev this week. I've posted my current working syntax on the wiki at https://bitbucket.org/premake/premake-dev/wiki/Custom_Build_Commands >> >> Feedback and design challenges very much appreciated! > > Also, how %(file.abspath) and similar patterns are planned to work? Is "file" a hardcoded "variable"? > If so, why not use e.g. "infile" for clarity? > > -- > Regards, > Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-12 19:19:53
|
12.03.2012, 22:49, "Jason Perkins" <st...@in...>: >> Also, how %(file.abspath) and similar patterns are planned to work? > > I will add this to the wiki, since it going to have to be as part of 4.5. > > My intention is to provide a few context objects: sln, prj, cfg, and file. You can then access any field of those objects: > > %(sln.name) > %(prj.location) > %(cfg.targetdir) > > The contents of the $() would be run through loadstring() and executed at token-replacement time, so in theory more complex replacements could be used. > > %(sln.name:gsub(' ', '_')) Seems to be powerful enough. I propose additional variable files with complete list of input files for rule for current configuration. It could be used for "combined" compilations like sometool %(files) -o combined.out -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-12 18:57:45
|
Suggestions? On Mar 12, 2012, at 2:54 PM, Konstantin Tokarev wrote: > > 12.03.2012, 22:38, "Jason Perkins" <st...@in...>: > >> Support for "custom filtering functions" is a good idea, and worthy of a feature request. Per your example, I think it should be written as: >> >> configuration { qt.ismocableheader } >> >> The function would get called back at bake time with a list of terms, and would return true or false to apply the configuration block. > > I'm afraid configuration() is becoming too much overloaded. If meaning of configuration "filename" is more or less clear (note that we can have collisions between names of files, configurations, platforms, compilers, etc.), meaning configuration(function) is dubious. > >> >>> 3) Is compilation of generated files supported? >> >> I mentioned on the wiki page that source files listed in the outputs should get fed back into the build, and object files back into the link step. Did you mean something else? > > Sorry, I've overlooked this item. > > BTW, I think we should ensure that it's possible to create rule chains when outputs of one custom rule are used in another. I also think that each rule should have separate "exclude" list. > > -- > Regards, > Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-12 19:03:41
|
12.03.2012, 22:57, "Jason Perkins" <st...@in...>: > Suggestions? solution "A" -- or on project level buildrule { input = "**.lua", -- or -- inputfiter = myfilterfunction, description = 'Compiling "%(file.abspath)"', dependencies = {}, -- None for this case, but they would go here commands = { 'luac -o "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' }, outputs = { '%(cfg.objdir)/%(file.basename).out' } } -- Regards, Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-12 19:17:01
|
Also there should be a way to configure some aspects of rule interpretation, e.g. whether to skip missing input files or raise an error, or put a list of build product into special field instead of automatic processing as sources or objects. buildrule { -- ... flags = { "Combine", "IgnoreMissing" }, outputvar = "cfg.luac" -- ??? } You can find other possible settings of build rule (sometimes perverted:) here: http://www.qtcentre.org/wiki/index.php?title=Undocumented_qmake#Custom_tools -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-13 00:00:26
|
All good points. It looks like the basic syntax is resilient enough to handle these cases, even if they don't all get supported right away. I'm going to stick with configuration() as the way to specify the file pattern though. Since that is the approach used to set file-level build actions, and eventually all other file-level configurations, it doesn't make sense to offer a second approach. People are going to try to use configuration() and then not understand why it doesn't work. Your concerns are valid, but I think configuration() is versatile enough to handle it, and the consistency will make the API easier to learn in general. -st. On Mar 12, 2012, at 3:16 PM, Konstantin Tokarev wrote: > Also there should be a way to configure some aspects of rule interpretation, e.g. whether to skip missing input files or raise an error, or put a list of build product into special field instead of automatic processing as sources or objects. > > buildrule { > -- ... > flags = { "Combine", "IgnoreMissing" }, > outputvar = "cfg.luac" -- ??? > } > > You can find other possible settings of build rule (sometimes perverted:) here: > > http://www.qtcentre.org/wiki/index.php?title=Undocumented_qmake#Custom_tools |
From: Konstantin T. <an...@ya...> - 2012-03-13 08:55:23
|
13.03.2012, 04:00, "Jason Perkins" <st...@in...>: > All good points. It looks like the basic syntax is resilient enough to handle these cases, even if they don't all get supported right away. > > I'm going to stick with configuration() as the way to specify the file pattern though. Since that is the approach used to set file-level build actions, and eventually all other file-level configurations, it doesn't make sense to offer a second approach. People are going to try to use configuration() and then not understand why it doesn't work. > > Your concerns are valid, but I think configuration() is versatile enough to handle it, and the consistency will make the API easier to learn in general. OK, but I still think that "filter" function should be a property of buildrule because configure(function) is too vague. Some thoughts about further enhancements of build rules: 1. I think that common use case of build rules will be using pre-defined rules from downloadable add-ons for popular programming languages, assemblers, code generators and preprocessors, pluging them to projects and customizing properties. How should syntax look like? Something like this? -- Add-on usage "luac" buildrule { description = 'Compiling "%(file.abspath)"', commands = { 'luac -o "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' }, outputs = { '%(cfg.objdir)/%(file.basename).out' } } -- premake4.lua solution "A" project "B" configuration "**.lua" use "luac" 2. There is a duplication between commands and outputs. We need context object outfiles: buildrule { description = 'Compiling "%(file.abspath)"', commands = { 'luac -o "%(outfiles[1].fullpath)" "%(file.fullpath)"' }, outputs = { '%(cfg.objdir)/%(file.basename).out' } } 3. Customization of add-on buildrule properties for project buildrule("rulename").flags = { ... } => we need rule names to refer to them. 4. There should be one more context object - buildrule itself (e.g., %(rule)). This will allow to use rule properties such as flags in build command, e.g. buildrule { name = "luac", compiler = "luac", description = 'Compiling "%(file.abspath)"', commands = { '%(rule.compiler) -o %(if not rule.flags.DebugInfo then return "-s" end) "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' }, outputs = { '%(cfg.objdir)/%(file.basename).out' } } ----------------- buildrule("luac").compiler = "/usr/local/bin/luac" -- Changes luac executable buildrule("luac").flags.DebugInfo = false -- Adds -s option to luac invocations 5. Premake should a have a set of built-in rules abstracting common platfrom-dependent build actions, e.g. copy symlink_or_copy -- Symlink if platform supports it, copy otherwise make_directory echo -- Write output of some function to file echo_append Some of this rules may have directories as their inputs -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-13 21:57:41
|
I think we're generally in agreement. I will keep an open mind on the file filtering and get the basics implemented so we have something real to talk about. Thanks for the feedback! -st. On Mar 13, 2012, at 4:55 AM, Konstantin Tokarev wrote: > > > 13.03.2012, 04:00, "Jason Perkins" <st...@in...>: >> All good points. It looks like the basic syntax is resilient enough to handle these cases, even if they don't all get supported right away. >> >> I'm going to stick with configuration() as the way to specify the file pattern though. Since that is the approach used to set file-level build actions, and eventually all other file-level configurations, it doesn't make sense to offer a second approach. People are going to try to use configuration() and then not understand why it doesn't work. >> >> Your concerns are valid, but I think configuration() is versatile enough to handle it, and the consistency will make the API easier to learn in general. > > OK, but I still think that "filter" function should be a property of buildrule because configure(function) is too vague. > > Some thoughts about further enhancements of build rules: > > 1. I think that common use case of build rules will be using pre-defined rules from downloadable add-ons for popular programming languages, assemblers, code generators and preprocessors, pluging them to projects and customizing properties. > > How should syntax look like? Something like this? > > -- Add-on > usage "luac" > buildrule { > description = 'Compiling "%(file.abspath)"', > commands = { > 'luac -o "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > > -- premake4.lua > solution "A" > project "B" > configuration "**.lua" > use "luac" > > 2. There is a duplication between commands and outputs. We need context object outfiles: > > buildrule { > description = 'Compiling "%(file.abspath)"', > commands = { > 'luac -o "%(outfiles[1].fullpath)" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > > 3. Customization of add-on buildrule properties for project > > buildrule("rulename").flags = { ... } > > => we need rule names to refer to them. > > 4. There should be one more context object - buildrule itself (e.g., %(rule)). This will allow to use rule properties such as flags in build command, e.g. > > buildrule { > name = "luac", > compiler = "luac", > description = 'Compiling "%(file.abspath)"', > commands = { > '%(rule.compiler) -o %(if not rule.flags.DebugInfo then return "-s" end) "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > ----------------- > > buildrule("luac").compiler = "/usr/local/bin/luac" -- Changes luac executable > buildrule("luac").flags.DebugInfo = false -- Adds -s option to luac invocations > > 5. Premake should a have a set of built-in rules abstracting common platfrom-dependent build actions, e.g. > > copy > symlink_or_copy -- Symlink if platform supports it, copy otherwise > make_directory > echo -- Write output of some function to file > echo_append > > Some of this rules may have directories as their inputs > > -- > Regards, > Konstantin |
From: Jason M. <ko...@gm...> - 2012-03-14 19:07:10
|
On 3/13/2012 1:55 AM, Konstantin Tokarev wrote: > > 13.03.2012, 04:00, "Jason Perkins"<st...@in...>: >> All good points. It looks like the basic syntax is resilient enough to handle these cases, even if they don't all get supported right away. >> >> I'm going to stick with configuration() as the way to specify the file pattern though. Since that is the approach used to set file-level build actions, and eventually all other file-level configurations, it doesn't make sense to offer a second approach. People are going to try to use configuration() and then not understand why it doesn't work. >> >> Your concerns are valid, but I think configuration() is versatile enough to handle it, and the consistency will make the API easier to learn in general. > OK, but I still think that "filter" function should be a property of buildrule because configure(function) is too vague. > > Some thoughts about further enhancements of build rules: > > 1. I think that common use case of build rules will be using pre-defined rules from downloadable add-ons for popular programming languages, assemblers, code generators and preprocessors, pluging them to projects and customizing properties. > > How should syntax look like? Something like this? > > -- Add-on > usage "luac" > buildrule { > description = 'Compiling "%(file.abspath)"', > commands = { > 'luac -o "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > > -- premake4.lua > solution "A" > project "B" > configuration "**.lua" > use "luac" Wouldn't this make more sense? --add-on luacCompile = { description = 'Compiling "%(file.abspath)"', commands = { 'luac -o "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' }, outputs = { '%(cfg.objdir)/%(file.basename).out' } } -- premake4.lua dofile(add-on) --or whatever else you want to do to call the add-on script. solution "A" project "B" configuration "**.lua" buildrule(luacCompile) `usage` is for defining usage projects, so that you can more easily link headers and libraries, to set up dependencies between projects. Overloading it in this case isn't a good idea, especially when we can just use the rules of Lua to easily achieve the same effect. > 2. There is a duplication between commands and outputs. We need context object outfiles: > > buildrule { > description = 'Compiling "%(file.abspath)"', > commands = { > 'luac -o "%(outfiles[1].fullpath)" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > > 3. Customization of add-on buildrule properties for project > > buildrule("rulename").flags = { ... } > > => we need rule names to refer to them. > > 4. There should be one more context object - buildrule itself (e.g., %(rule)). This will allow to use rule properties such as flags in build command, e.g. > > buildrule { > name = "luac", > compiler = "luac", > description = 'Compiling "%(file.abspath)"', > commands = { > '%(rule.compiler) -o %(if not rule.flags.DebugInfo then return "-s" end) "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > ----------------- > > buildrule("luac").compiler = "/usr/local/bin/luac" -- Changes luac executable > buildrule("luac").flags.DebugInfo = false -- Adds -s option to luac invocations This is a needless overcomplication of what should be a simple system. Use Lua to your advantage: just have a global variable somewhere with the location of the Lua compiler in it, as well as flags. Then use those values as part of your command. You don't need to run conditional statements in the `%()` syntax; that just makes implementing the system that much more difficult. That being said, it might not be a bad idea to allow a command to be a Lua function. That is, you can do something like this: commands = { function(context) return --string of the command to use. end }, This would be a lot easier to implement than what you're trying to do. The `context` would just be some kind of object you could query things like `cfg.objdir` and so forth from. |
From: Konstantin T. <an...@ya...> - 2012-03-14 19:51:17
|
14.03.2012, 23:06, "Jason McKesson" <ko...@gm...>: > commands = { > function(context) > return --string of the command to use. > end > }, This syntax is really useful when sting needs complex flag-dependent logic, e.g. commands = { function(context) local flags = "" if context.rule.flags.A then if context.rule.flags.B then flags = "-AB" else flags = "-C" end return "tool " .. flags .. -- input and output follow here end }, Pattern version would require custom buildrule field here getflags = function(flags) local flags = "" if flags.A then if flags.B then return "-AB" else return "-C" end return "" end, commands = { "tool %(rule.getflags(rule.flags) .." -- input and output follow here }, -- Regards, Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-14 19:36:31
|
14.03.2012, 23:06, "Jason McKesson" <ko...@gm...>: > Wouldn't this make more sense? > > --add-on > > luacCompile = { > description = 'Compiling "%(file.abspath)"', > commands = { > 'luac -o "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' > }, > outputs = { > '%(cfg.objdir)/%(file.basename).out' > } > } > > -- premake4.lua > > dofile(add-on) --or whatever else you want to do to call the add-on script. > > solution "A" > project "B" > configuration "**.lua" > buildrule(luacCompile) > > `usage` is for defining usage projects, so that you can more easily link > headers and libraries, to set up dependencies between projects. > Overloading it in this case isn't a good idea, especially when we can > just use the rules of Lua to easily achieve the same effect. I thought the next way: 1) Usage is a special kind of project that copies its fields to projects where it's used 2) buildrule is just one of fields. Why not to copy it too? I think "usage" should have more generic meaning than just "headers and libraries". For example, when using my Qt add-on you write project "A" uses "Qt" -- .... and it not only adds includes and libraries, but also sets up Qt-specific build rules and compiler flags. > >> 2. There is a duplication between commands and outputs. We need context object outfiles: >> >> buildrule { >> description = 'Compiling "%(file.abspath)"', >> commands = { >> 'luac -o "%(outfiles[1].fullpath)" "%(file.fullpath)"' >> }, >> outputs = { >> '%(cfg.objdir)/%(file.basename).out' >> } >> } >> >> 3. Customization of add-on buildrule properties for project >> >> buildrule("rulename").flags = { ... } >> >> => we need rule names to refer to them. >> >> 4. There should be one more context object - buildrule itself (e.g., %(rule)). This will allow to use rule properties such as flags in build command, e.g. >> >> buildrule { >> name = "luac", >> compiler = "luac", >> description = 'Compiling "%(file.abspath)"', >> commands = { >> '%(rule.compiler) -o %(if not rule.flags.DebugInfo then return "-s" end) "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' >> }, >> outputs = { >> '%(cfg.objdir)/%(file.basename).out' >> } >> } >> ----------------- >> >> buildrule("luac").compiler = "/usr/local/bin/luac" -- Changes luac executable >> buildrule("luac").flags.DebugInfo = false -- Adds -s option to luac invocations > > This is a needless overcomplication of what should be a simple system. > Use Lua to your advantage: just have a global variable somewhere with > the location of the Lua compiler in it, as well as flags. Then use those > values as part of your command. You don't need to run conditional > statements in the `%()` syntax; that just makes implementing the system > that much more difficult. I think it's an extremely bad practice to use global variables across bounds of independent modules. Global variable can be redefined in other add-on by accident, while access through methods may throw error or warning. > > That being said, it might not be a bad idea to allow a command to be a > Lua function. That is, you can do something like this: > > commands = { > function(context) > return --string of the command to use. > end > }, > > This would be a lot easier to implement than what you're trying to do. > The `context` would just be some kind of object you could query things > like `cfg.objdir` and so forth from. AFAIU it does the same as %(--string of the command to use), but provides one context table instead of several independent ones -- Regards, Konstantin |
From: Jason M. <ko...@gm...> - 2012-03-15 05:11:44
|
On 3/14/2012 12:36 PM, Konstantin Tokarev wrote: >>> 2. There is a duplication between commands and outputs. We need context object outfiles: >>> >>> buildrule { >>> description = 'Compiling "%(file.abspath)"', >>> commands = { >>> 'luac -o "%(outfiles[1].fullpath)" "%(file.fullpath)"' >>> }, >>> outputs = { >>> '%(cfg.objdir)/%(file.basename).out' >>> } >>> } >>> >>> 3. Customization of add-on buildrule properties for project >>> >>> buildrule("rulename").flags = { ... } >>> >>> => we need rule names to refer to them. >>> >>> 4. There should be one more context object - buildrule itself (e.g., %(rule)). This will allow to use rule properties such as flags in build command, e.g. >>> >>> buildrule { >>> name = "luac", >>> compiler = "luac", >>> description = 'Compiling "%(file.abspath)"', >>> commands = { >>> '%(rule.compiler) -o %(if not rule.flags.DebugInfo then return "-s" end) "%(cfg.objdir)/%(file.basename).out" "%(file.fullpath)"' >>> }, >>> outputs = { >>> '%(cfg.objdir)/%(file.basename).out' >>> } >>> } >>> ----------------- >>> >>> buildrule("luac").compiler = "/usr/local/bin/luac" -- Changes luac executable >>> buildrule("luac").flags.DebugInfo = false -- Adds -s option to luac invocations >> This is a needless overcomplication of what should be a simple system. >> Use Lua to your advantage: just have a global variable somewhere with >> the location of the Lua compiler in it, as well as flags. Then use those >> values as part of your command. You don't need to run conditional >> statements in the `%()` syntax; that just makes implementing the system >> that much more difficult. > I think it's an extremely bad practice to use global variables across bounds of > independent modules. Global variable can be redefined in other add-on by > accident, while access through methods may throw error or warning. It's a *build system*, not an application; it's not that complicated. And if your build system is so big and complex that you can lose track of what globals, add-ons, and so forth you've included, something has gone wrong somewhere. Remember: build rules are supposed to be the exception, not the default. >> That being said, it might not be a bad idea to allow a command to be a >> Lua function. That is, you can do something like this: >> >> commands = { >> function(context) >> return --string of the command to use. >> end >> }, >> >> This would be a lot easier to implement than what you're trying to do. >> The `context` would just be some kind of object you could query things >> like `cfg.objdir` and so forth from. > AFAIU it does the same as %(--string of the command to use), > but provides one context table instead of several independent ones > Yes, and it's also much, *much* easier to implement the way I've put it. The way you've described it, the system has to detect that "rule.compiler" accesses some context data, while "if not rule.flags.DebugInfo then return "-s" end" is a Lua chunk with its own return statement. This requires that Premake actually *parse* the text within the %() segment to figure out if it's just accessing context data (something that you can prepend "return context." to and get a valid Lua chunk) or an actual Lua chunk to be executed. At the very least, it should use different syntax, like "#()" or something. |
From: Konstantin T. <an...@ya...> - 2012-03-15 09:23:18
|
15.03.2012, 09:11, "Jason McKesson" <ko...@gm...>: > It's a *build system*, not an application; it's not that complicated. > And if your build system is so big and complex that you can lose track > of what globals, add-ons, and so forth you've included, something has > gone wrong somewhere. Premake is an application, and it's already complex. Add-ons are supposed to extend *Premake* out-of-the-box capabilities and may be written by 3rd parties. > Remember: build rules are supposed to be the exception, not the default. For my use cases they will be default (e.g., Qt support requires at least 6 build rules). Also remember that build rules can be used to implement support for programming languages other than C/C++, code generators, and preprocessors. > >>> That being said, it might not be a bad idea to allow a command to be a >>> Lua function. That is, you can do something like this: >>> >>> commands = { >>> function(context) >>> return --string of the command to use. >>> end >>> }, >>> >>> This would be a lot easier to implement than what you're trying to do. >>> The `context` would just be some kind of object you could query things >>> like `cfg.objdir` and so forth from. >> AFAIU it does the same as %(--string of the command to use), >> but provides one context table instead of several independent ones > > Yes, and it's also much, *much* easier to implement the way I've put it. I don't think so - loadstring is not difficult to use. > The way you've described it, the system has to detect that > "rule.compiler" accesses some context data, while "if not > rule.flags.DebugInfo then return "-s" end" is a Lua chunk with its own > return statement. This requires that Premake actually *parse* the text > within the %() segment to figure out if it's just accessing context data > (something that you can prepend "return context." to and get a valid Lua > chunk) or an actual Lua chunk to be executed. I think it will always load chunk. Jason: could you clarify this? > At the very least, it should use different syntax, like "#()" or something. Could you explain why "#" is better than "%"? -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-15 10:18:36
|
On Mar 15, 2012, at 5:23 AM, Konstantin Tokarev wrote: > For my use cases they will be default (e.g., Qt support requires at least 6 build > rules). Also remember that build rules can be used to implement support for > programming languages other than C/C++, code generators, and preprocessors. Could you do me a favor and convert a few of your Qt build rules to this new syntax (or some variant of it), and post them to the build rules wiki page? It would be good to have those available as I work through the implementation. >> The way you've described it, the system has to detect that >> "rule.compiler" accesses some context data, while "if not >> rule.flags.DebugInfo then return "-s" end" is a Lua chunk with its own >> return statement. This requires that Premake actually *parse* the text >> within the %() segment to figure out if it's just accessing context data >> (something that you can prepend "return context." to and get a valid Lua >> chunk) or an actual Lua chunk to be executed. > > I think it will always load chunk. Jason: could you clarify this? Jason McKesson is right here, there would need to be some differentiation, otherwise you would always have to write $(return cfg.objdir) instead of $(cfg.objdir). -st. |
From: Konstantin T. <an...@ya...> - 2012-03-15 10:23:30
|
15.03.2012, 14:18, "Jason Perkins" <st...@in...>: > On Mar 15, 2012, at 5:23 AM, Konstantin Tokarev wrote: > >> For my use cases they will be default (e.g., Qt support requires at least 6 build >> rules). Also remember that build rules can be used to implement support for >> programming languages other than C/C++, code generators, and preprocessors. > > Could you do me a favor and convert a few of your Qt build rules to this new syntax (or some variant of it), and post them to the build rules wiki page? It would be good to have those available as I work through the implementation. I've planned to do so when you'll implement some base functionality, but I'm ready to do it ASAP. You can see my old plans on 4 of them here (syntax is somewhat different): https://gist.github.com/1350926 -- Regards, Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-15 11:33:17
|
15.03.2012, 14:18, "Jason Perkins" <st...@in...>: > On Mar 15, 2012, at 5:23 AM, Konstantin Tokarev wrote: > >> For my use cases they will be default (e.g., Qt support requires at least 6 build >> rules). Also remember that build rules can be used to implement support for >> programming languages other than C/C++, code generators, and preprocessors. > > Could you do me a favor and convert a few of your Qt build rules to this new syntax (or some variant of it), and post them to the build rules wiki page? It would be good to have those available as I work through the implementation. https://bitbucket.org/premake/premake-dev/wiki/Qt_build_rules_draft -- Regards, Konstantin |
From: Jason P. <st...@in...> - 2012-03-15 10:40:07
|
Thanks! On Mar 15, 2012, at 6:23 AM, Konstantin Tokarev wrote: > > 15.03.2012, 14:18, "Jason Perkins" <st...@in...>: >> Could you do me a favor and convert a few of your Qt build rules to this new syntax (or some variant of it), and post them to the build rules wiki page? It would be good to have those available as I work through the implementation. > > I've planned to do so when you'll implement some base functionality, but I'm ready to do it ASAP. > > You can see my old plans on 4 of them here (syntax is somewhat different): > > https://gist.github.com/1350926 > > -- > Regards, > Konstantin |
From: Konstantin T. <an...@ya...> - 2012-03-15 10:49:08
|
Also, I don't like explicit quoting like "%(file.fullpath)" in rules. I think quotes should be added automatically, i.e. file.fullpath and so on should contain quoted paths. -- Regards, Konstantin |
From: Jason M. <ko...@gm...> - 2012-03-15 19:54:14
|
On 3/15/2012 3:48 AM, Konstantin Tokarev wrote: > Also, I don't like explicit quoting like "%(file.fullpath)" in rules. I think quotes should be added automatically, i.e. file.fullpath and so on should contain quoted paths. > If they contained quoted paths, what would happen if you need to modify the path? Like "%(file.pathname)/morepath/%(file.basename)" or something like that? |
From: Konstantin T. <an...@ya...> - 2012-03-16 09:28:33
|
15.03.2012, 23:54, "Jason McKesson" <ko...@gm...>: > On 3/15/2012 3:48 AM, Konstantin Tokarev wrote: > >> Also, I don't like explicit quoting like "%(file.fullpath)" in rules. I think quotes should be added automatically, i.e. file.fullpath and so on should contain quoted paths. > > If they contained quoted paths, what would happen if you need to modify > the path? Like "%(file.pathname)/morepath/%(file.basename)" or something > like that? In bash multi-quoted paths like "path"/morepath/"otherpath" work fine, need to check cmd.exe though -- Regards, Konstantin |