premake / premake-core

Premake
https://premake.github.io/
BSD 3-Clause "New" or "Revised" License
3.22k stars 620 forks source link

Filter command from within module #894

Closed rhythmchicago closed 7 years ago

rhythmchicago commented 7 years ago

Hi!

I've been modifying a qt module for premake to add in a post-build command to copy in the required DLLs from the binary directory. I've got everything working, except I can't filter postbuildcommand by configuration and platform. Using the postbuildcommand works fine, but when I try to filter it by configuration and platform (or anything), the command never executes.

I need to be able to filter by configuration and platform for this to work. Is there any way to accomplish such filtering from a module?

Thank you in advance!

..
premake.override(premake.fileconfig, "addconfig",  qt.customAddFileConfig)
..

function premake.extensions.qt.customAddFileConfig(base, fcfg, cfg)
    ...
    premake.extensions.qt.genCopyScript(cfg)
end

function` premake.extensions.qt.genCopyScript(cfg)

    local dirPath = "dir " .. cfg.qtbinpath  .. "\\*.dll"
    local copyPath

    -- Opens a file in write mode
    local batFileName = "updateqt_" .. cfg.buildcfg .. "_" .. cfg.platform  .. ".bat"
    file = io.open(batFileName, "w")
    -- sets the default output file as test.lua
    io.output(file)

    for key,value in pairs(cfg.qtmodules) do 

        if cfg.qtsuffix == nil then
            copyPath = "copy " .. cfg.qtbinpath .. "/" .. cfg.qtprefix .. value .. ".dll"
                .. " " .. cfg.targetdir .. "\r\n"
        else
            copyPath = "copy " .. cfg.qtbinpath .. "/" .. cfg.qtprefix .. value 
                .. cfg.qtsuffix .. ".dll"
                .. " " .. cfg.targetdir .. "\r\n"           
        end
        local strWrite = copyPath.gsub(copyPath, "/", "\\" )
        io.write(strWrite)

    end

    -- closes the open file
    io.close(file)

    local strPlatform = "platforms:" .. cfg.platform

        -- THIS FILTER COMMAND DOESN'T WORK
    filter { cfg.buildcfg, strPlatform }
        postbuildcommands { os.realpath(batFileName) }
    filter{}

end -- function
tvandijck commented 7 years ago

premake.fileconfig.addconfig is executed during the oven.bake stage, this is not a time where you can still add filters and call other api's like the postbuildcommands, as they have already been baked.

based on this code, I'm not sure what you are trying to accomplish though, since you are filtering on the current config and current platform... that will generally just not do anything...

I think in this case you just have to do something like

cfg.postbuildcommand = os.realpath(batfilename)

and inject it straight into the config, instead of going through the API.

rhythmchicago commented 7 years ago

That didn't work, but I see what you're saying.

I iterated the cfg table and I don't see postbuildcommand. Is it a sub-item of one these that I can access?

targetextension .exe
platform        x64
project table: 02AA97C8
name    Release|x64
tags    table: 02AD5980
toolset msc-v141
qtlibpath       c:/qt/5.9.1/msvc2017_64/lib
targetdir       C:/Users/ThomasBitskyJr/Documents/srcroot/Ux/Daedalus.Qt/bin/release
buildcfg        Release
shortname       release_x64
libdirs table: 02AD61C8
links   table: 02AD6498
action  vs2017
files   table: 02B24728
architecture    x86_64
qtenabled       true
terms   table: 02AD5AC0
_basedir        C:/Users/ThomasBitskyJr/Documents/srcroot/Ux/Daedalus.Qt/DaedalusQtTest
longname        Release|x64
_cfgset table: 02AD59F8
qtbinpath       c:/qt/5.9.1/msvc2017_64/bin
includedirs     table: 02AD5D18
kind    WindowedApp
qtmodules       table: 02AD63A8
workspace       table: 02AA9750
buildtarget     table: 02AD6128
location        C:/Users/ThomasBitskyJr/Documents/srcroot/Ux/Daedalus.Qt/DaedalusQtTest
environ table: 02AD58E0
defines table: 02AD6A10
qtprefix        Qt5
qtincludepath   c:/qt/5.9.1/msvc2017_64/include
linktarget      table: 02AD5CF0
solution        table: 02AA9750
global  table: 02AA98E0
qtpath  c:/qt/5.9.1/msvc2017_64
system  windows
rhythmchicago commented 7 years ago

I couldn't get the above suggestion to work, but I found solution by taking advantage of tokens.

The qt.enable() function must be called from any project wanting to use Qt. It's called early on in the script process, so I simply used tokens and the postbuildcommands keyword to call the generated batch files post-build. I try to keep anything "generated" in its own directory so that it's easy to configure a .gitignore file. I chose to keep all the script files in one directory at the "solution" level, instead of a separate script directory for each project. Therefore, I needed the _WORKING_DIR variable.

function premake.extensions.qt.enable()

    local qt = premake.extensions.qt

    -- enable Qt for the current config
    qtenabled ( true )

    -- setup our overrides if not already done
    if qt.enabled == false then
        qt.enabled = true
        premake.override(premake.oven, "bakeFiles", qt.customBakeFiles)
        premake.override(premake.oven, "bakeConfig", qt.customBakeConfig)
        premake.override(premake.fileconfig, "addconfig",  qt.customAddFileConfig)
    end

    --
    -- NEW
    -- Support updating the bin directories with the QT libraries
    -- post-build
    --

    local scriptExtension

    if os.ishost("linux") then
        scriptExtension = ".sh"
    elseif os.ishost("windows") then
        scriptExtension = ".bat"
    end 

    local path = os.realpath(_WORKING_DIR .. "/.basebuild")

    local cmd = path .. "/updateqt_%{cfg.buildcfg}_%{cfg.platform}" .. scriptExtension

    local cmdOut
    if os.ishost("windows") then
        cmdOut = cmd.gsub(cmd, "/", "\\" )
    else
        cmdOut = cmd
    end     

    filter{}
    postbuildcommands { cmdOut }    

end

After that, much of the function I posted above is the same. I simply generate batch files to copy the required DLLs for the selected configuration and platform, placing them in the generated script directory. When the project is built, the files will be automatically copied.

function premake.extensions.qt.genCopyScript(cfg)

    local cmd
    local copyKeyword
    local fileExtension
    local lineEnd
    local scriptExtension

    if os.ishost("linux") then
        copyKeyword = "cp "     
        fileExtension = ".so"
        lineEnd = "\n"
        scriptExtension = ".sh"
    elseif os.ishost("windows") then
        copyKeyword = "copy "       
        fileExtension = ".dll"
        lineEnd = "\r\n"
        scriptExtension = ".bat"
    end     

    -- make sure the build script directory exists
    if os.isdir(".basebuild") == false then
        os.mkdir(".basebuild")
    end

    -- Opens a file in write mode
    local batFileName = "./.basebuild/updateqt_" .. cfg.buildcfg .. "_" .. cfg.platform  .. scriptExtension
    file = io.open(batFileName, "w")
    -- sets the default output file as test.lua
    io.output(file)

    for key,value in pairs(cfg.qtmodules) do 

        if cfg.qtsuffix == nil then
            cmd = copyKeyword .. cfg.qtbinpath .. "/" .. cfg.qtprefix .. value .. fileExtension
                .. " " .. cfg.targetdir .. lineEnd
        else
            cmd = copyKeyword .. cfg.qtbinpath .. "/" .. cfg.qtprefix .. value 
                .. cfg.qtsuffix .. fileExtension
                .. " " .. cfg.targetdir .. lineEnd          
        end

        local cmdOut
        if os.ishost("windows") then
            cmdOut = cmd.gsub(cmd, "/", "\\" )
        else
            cmdOut = cmd
        end     

        io.write(cmdOut)    

    end

    -- closes the open file
    io.close(file)  

end -- function

While it seems like a trivial improvement, when you're juggling multiple versions and platforms of Qt on the same machine, it can be a big help to have the libraries automatically copied. This plugin is also automatically selecting only the files I need, so it helps with building the installer properly.

It needs a little more tweaking to be cross-platform, but it works on Windows with VS2017. I don't have a Linux image handy right now, so I'll revisit that later.