Hello,
I am currently in the process of fixing and extending the Premake Ninja generator to fit our needs.
An important requirement is the support of per file options. This is requried to support other instruction sets for some files (SSSE3, AVX and so on).
I have implemented the Ninja part of the change but I can't find a good way to merge the file configuration with the project configuration to determine the total command line arguments for a given fileconfig object. Just concatenating both command line argument strings obviously does not work, since some switches can be contradicting.
The current code for determining the command line arguments looks like the following.
I basicly took the original Premake Ninja code and turned the
individual parts of the command line into functions that can take
filecfg object too, but now they don't return the complete commandline. (Instead they return only the changed part like '-mssse3')
local cc = ""
local cxx = ""
local ar = ""
local link = ""
if toolset_name == "msc" then
-- TODO premake doesn't set tools names for msc, do we want to fix it ?
cc = "cl"
cxx = "cl"
ar = "lib"
link = "cl"
else
if (toolset_name == "gcc") and (not cfg.gccprefix) then cfg.gccprefix = "" end
cc = toolset.gettoolname(cfg, "cc")
cxx = toolset.gettoolname(cfg, "cxx")
ar = toolset.gettoolname(cfg, "ar")
link = toolset.gettoolname(cfg, iif(cfg.language == "C", "cc", "cxx"))
end
---------------------------------------------------- figure out settings
local globalincludes = {}
table.foreachi(cfg.includedirs, function(v)
-- TODO this is a bit obscure and currently I have no idea why exactly it's working
globalincludes[#globalincludes + 1] = project.getrelative(cfg.workspace, v)
end)
local buildopt = function(cfg) return ninja.list(cfg.buildoptions) end
local cflags = function(cfg) return ninja.list(toolset.getcflags(cfg)) end
local cppflags = function(cfg) return ninja.list(toolset.getcppflags(cfg)) end
local cxxflags = function(cfg) return ninja.list(toolset.getcxxflags(cfg)) end
local warnings = function(cfg) if toolset_name == "msc" then return ninja.list(toolset.getwarnings(cfg)) else return "" end end
local defines = function(cfg) return ninja.list(table.join(toolset.getdefines(cfg.defines), toolset.getundefines(cfg.undefines))) end
local includes = function(cfg) return ninja.list(toolset.getincludedirs(cfg, globalincludes, cfg.sysincludedirs)) end
local forceincludes = function(cfg) return ninja.list(toolset.getforceincludes(cfg)) end -- TODO pch
local ldflags = function(cfg) return ninja.list(table.join(toolset.getLibraryDirectories(cfg), toolset.getldflags(cfg), cfg.linkoptions)) end
local all_cflags = function(cfg)
return buildopt(cfg) .. cflags(cfg) .. warnings(cfg) .. defines(cfg) .. includes(cfg) .. forceincludes(cfg)
end
local all_cxxflags = function(cfg)
return buildopt(cfg) .. ninja.remove_identical_words(cflags(cfg), cxxflags(cfg)) .. cppflags(cfg) .. warnings(cfg) .. defines(cfg) .. includes(cfg) .. forceincludes(cfg)
end
How can I implement per file configuration the simplest way without breaking it if the available options change?
Also I find it a bit weird that seemingly every Premake target has to concatenate the different command line option groups itself. Is there maybe a better way of doing this all together?