Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rename PremakeDeps to PremakeMultiDeps and add single configuration PremakeDeps #17355

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conan/internal/api/install/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"XcodeDeps": "conan.tools.apple",
"XcodeToolchain": "conan.tools.apple",
"PremakeDeps": "conan.tools.premake",
"PremakeMultiDeps": "conan.tools.premake",
"MakeDeps": "conan.tools.gnu",
"SConsDeps": "conan.tools.scons",
"QbsDeps": "conan.tools.qbs",
Expand Down
3 changes: 2 additions & 1 deletion conan/tools/premake/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from conan.tools.premake.premake import Premake
from conan.tools.premake.premakedeps import PremakeDeps
from conan.tools.premake.premakedeps import PremakeDeps
from conan.tools.premake.premakemultideps import PremakeMultiDeps
256 changes: 50 additions & 206 deletions conan/tools/premake/premakedeps.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,8 @@
import itertools
import glob
import re

from conan.internal import check_duplicated_generator
from conans.model.build_info import CppInfo
from conans.util.files import save

# Filename format strings
PREMAKE_VAR_FILE = "conan_{pkgname}_vars{config}.premake5.lua"
PREMAKE_CONF_FILE = "conan_{pkgname}{config}.premake5.lua"
PREMAKE_PKG_FILE = "conan_{pkgname}.premake5.lua"
PREMAKE_ROOT_FILE = "conandeps.premake5.lua"

# File template format strings
PREMAKE_TEMPLATE_UTILS = """
function conan_premake_tmerge(dst, src)
for k, v in pairs(src) do
if type(v) == "table" then
if type(conandeps[k] or 0) == "table" then
conan_premake_tmerge(dst[k] or {}, src[k] or {})
else
dst[k] = v
end
else
dst[k] = v
end
end
return dst
end
"""
PREMAKE_TEMPLATE_VAR = """
include "conanutils.premake5.lua"

t_conandeps = {{}}
t_conandeps["{config}"] = {{}}
t_conandeps["{config}"]["{pkgname}"] = {{}}
t_conandeps["{config}"]["{pkgname}"]["includedirs"] = {{{deps.includedirs}}}
t_conandeps["{config}"]["{pkgname}"]["libdirs"] = {{{deps.libdirs}}}
t_conandeps["{config}"]["{pkgname}"]["bindirs"] = {{{deps.bindirs}}}
t_conandeps["{config}"]["{pkgname}"]["libs"] = {{{deps.libs}}}
t_conandeps["{config}"]["{pkgname}"]["system_libs"] = {{{deps.system_libs}}}
t_conandeps["{config}"]["{pkgname}"]["defines"] = {{{deps.defines}}}
t_conandeps["{config}"]["{pkgname}"]["cxxflags"] = {{{deps.cxxflags}}}
t_conandeps["{config}"]["{pkgname}"]["cflags"] = {{{deps.cflags}}}
t_conandeps["{config}"]["{pkgname}"]["sharedlinkflags"] = {{{deps.sharedlinkflags}}}
t_conandeps["{config}"]["{pkgname}"]["exelinkflags"] = {{{deps.exelinkflags}}}
t_conandeps["{config}"]["{pkgname}"]["frameworks"] = {{{deps.frameworks}}}

if conandeps == nil then conandeps = {{}} end
conan_premake_tmerge(conandeps, t_conandeps)
"""
PREMAKE_TEMPLATE_ROOT_BUILD = """
includedirs(conandeps[conf][pkg]["includedirs"])
bindirs(conandeps[conf][pkg]["bindirs"])
defines(conandeps[conf][pkg]["defines"])
"""
PREMAKE_TEMPLATE_ROOT_LINK = """
libdirs(conandeps[conf][pkg]["libdirs"])
links(conandeps[conf][pkg]["libs"])
links(conandeps[conf][pkg]["system_libs"])
links(conandeps[conf][pkg]["frameworks"])
"""
PREMAKE_TEMPLATE_ROOT_FUNCTION = """
function {function_name}(conf, pkg)
if conf == nil then
{filter_call}
elseif pkg == nil then
for k,v in pairs(conandeps[conf]) do
{function_name}(conf, k)
end
else
{lua_content}
end
end
"""
PREMAKE_TEMPLATE_ROOT_GLOBAL = """
function conan_setup(conf, pkg)
conan_setup_build(conf, pkg)
conan_setup_link(conf, pkg)
end
"""
PREMAKE_FILE = "conandeps.premake5.lua"


# Helper class that expands cpp_info meta information in lua readable string sequences
Expand Down Expand Up @@ -111,81 +35,19 @@ def _format_flags(flags):


class PremakeDeps(object):
"""
PremakeDeps class generator
conandeps.premake5.lua: unconditional import of all *direct* dependencies only
"""

def __init__(self, conanfile):
"""
:param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.
"""

self._conanfile = conanfile

# Tab configuration
self.tab = " "

# Return value buffer
self.output_files = {}
# Extract configuration and architecture form conanfile
self.configuration = conanfile.settings.build_type
self.architecture = conanfile.settings.arch

def generate(self):
"""
Generates ``conan_<pkg>_vars_<config>.premake5.lua``, ``conan_<pkg>_<config>.premake5.lua``,
and ``conan_<pkg>.premake5.lua`` files into the ``conanfile.generators_folder``.
"""

check_duplicated_generator(self, self._conanfile)
# Current directory is the generators_folder
generator_files = self.content
for generator_file, content in generator_files.items():
save(generator_file, content)

def _config_suffix(self):
props = [("Configuration", self.configuration),
("Platform", self.architecture)]
name = "".join("_%s" % v for _, v in props)
return name.lower()

def _output_lua_file(self, filename, content):
self.output_files[filename] = "\n".join(["#!lua", *content])

def _indent_string(self, string, indent=1):
return "\n".join([
f"{self.tab * indent}{line}" for line in list(filter(None, string.splitlines()))
])

def _premake_filtered(self, content, configuration, architecture, indent=0):
"""
- Surrounds the lua line(s) contained within ``content`` with a premake "filter" and returns the result.
- A "filter" will affect all premake function calls after it's set. It's used to limit following project
setup function call(s) to a certain scope. Here it is used to limit the calls in content to only apply
if the premake ``configuration`` and ``architecture`` matches the parameters in this function call.
"""
lines = list(itertools.chain.from_iterable([cnt.splitlines() for cnt in content]))
return [
# Set new filter
f'{self.tab * indent}filter {{ "configurations:{configuration}", "architecture:{architecture}" }}',
# Emit content
*[f"{self.tab * indent}{self.tab}{line.strip()}" for line in list(filter(None, lines))],
# Clear active filter
f"{self.tab * indent}filter {{}}",
]

@property
def content(self):
check_duplicated_generator(self, self._conanfile)

self.output_files = {}
conf_suffix = str(self._config_suffix())
conf_name = conf_suffix[1::]

# Global utility file
self._output_lua_file("conanutils.premake5.lua", [PREMAKE_TEMPLATE_UTILS])

# Extract all dependencies
host_req = self._conanfile.dependencies.host
test_req = self._conanfile.dependencies.test
Expand All @@ -196,70 +58,52 @@ def content(self):
+ list(test_req.items()) \
+ list(build_req.items())

# Process dependencies and accumulate globally required data
pkg_files = []
dep_names = []
config_sets = []
for require, dep in full_req:
dep_name = require.ref.name
dep_names.append(dep_name)

# Convert and aggregate dependency's
dep_aggregate = dep.cpp_info.aggregated_components()
all_cpp_info = CppInfo()

# Generate config dependent package variable and setup premake file
var_filename = PREMAKE_VAR_FILE.format(pkgname=dep_name, config=conf_suffix)
self._output_lua_file(var_filename, [
PREMAKE_TEMPLATE_VAR.format(pkgname=dep_name,
config=conf_name, deps=_PremakeTemplate(dep_aggregate))
])

# Create list of all available profiles by searching on disk
file_pattern = PREMAKE_VAR_FILE.format(pkgname=dep_name, config="_*")
file_regex = PREMAKE_VAR_FILE.format(pkgname=re.escape(dep_name), config="_(([^_]*)_(.*))")
available_files = glob.glob(file_pattern)
# Add filename of current generations var file if not already present
if var_filename not in available_files:
available_files.append(var_filename)
profiles = [
(regex_res[0], regex_res.group(1), regex_res.group(2), regex_res.group(3)) for regex_res in [
re.search(file_regex, file_name) for file_name in available_files
]
]
config_sets = [profile[1] for profile in profiles]

# Emit package premake file
pkg_filename = PREMAKE_PKG_FILE.format(pkgname=dep_name)
pkg_files.append(pkg_filename)
self._output_lua_file(pkg_filename, [
# Includes
*['include "{}"'.format(profile[0]) for profile in profiles],
])

# Output global premake file
self._output_lua_file(PREMAKE_ROOT_FILE, [
# Includes
*[f'include "{pkg_file}"' for pkg_file in pkg_files],
# Functions
PREMAKE_TEMPLATE_ROOT_FUNCTION.format(
function_name="conan_setup_build",
lua_content=PREMAKE_TEMPLATE_ROOT_BUILD,
filter_call="\n".join(
["\n".join(self._premake_filtered(
[f'conan_setup_build("{config}")'], config.split("_", 1)[0], config.split("_", 1)[1], 2)
) for config in config_sets]
)
),
PREMAKE_TEMPLATE_ROOT_FUNCTION.format(
function_name="conan_setup_link",
lua_content=PREMAKE_TEMPLATE_ROOT_LINK,
filter_call="\n".join(
["\n".join(self._premake_filtered(
[f'conan_setup_link("{config}")'], config.split("_", 1)[0], config.split("_", 1)[1], 2)
) for config in config_sets]
)
),
PREMAKE_TEMPLATE_ROOT_GLOBAL
])

return self.output_files
# merge all dependencies
for require, dep in full_req:
all_cpp_info.merge(dep.cpp_info.aggregated_components())

ret = {} # filename -> file content

template = ('conan_includedirs = {{{deps.includedirs}}}\n'
'conan_libdirs = {{{deps.libdirs}}}\n'
'conan_bindirs = {{{deps.bindirs}}}\n'
'conan_libs = {{{deps.libs}}}\n'
'conan_system_libs = {{{deps.system_libs}}}\n'
'conan_defines = {{{deps.defines}}}\n'
'conan_cxxflags = {{{deps.cxxflags}}}\n'
'conan_cflags = {{{deps.cflags}}}\n'
'conan_sharedlinkflags = {{{deps.sharedlinkflags}}}\n'
'conan_exelinkflags = {{{deps.exelinkflags}}}\n'
'conan_frameworks = {{{deps.frameworks}}}\n')

sections = ["#!lua"]

sections.extend(
['conan_build_type = "{0}"'.format(str(self._conanfile.settings.build_type)),
'conan_arch = "{0}"'.format(str(self._conanfile.settings.get_safe("arch"))),
""])

deps = _PremakeTemplate(all_cpp_info)
all_flags = template.format(deps=deps)
sections.append(all_flags)
sections.append(
"function conan_setup()\n"
" configurations{conan_build_type}\n"
" architecture(conan_arch)\n"
" includedirs{conan_includedirs}\n"
" libdirs{conan_libdirs}\n"
" links{conan_libs}\n"
" links{conan_system_libs}\n"
" links{conan_frameworks}\n"
" defines{conan_defines}\n"
" bindirs{conan_bindirs}\n"
" buildoptions{conan_cflags}\n"
" buildoptions{conan_cxxflags}\n"
" linkoptions{conan_sharedlinkflags}\n"
" linkoptions{conan_exelinkflags}\n"
"end\n")
ret[PREMAKE_FILE] = "\n".join(sections)

return ret
Loading