Repository: conan-io/conan

Issue:
Making premake generator built-in
There seems to be new interest in premake: https://github.com/conan-io/wishlist/issues/162

I think making the generator in https://github.com/memsharded/conan-premake built-in, would be useful.

Also, some open-source library package might need it: https://github.com/bincrafters/community/issues/474

To be discussed.




Discussion:

Resolving patch:
diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py
--- a/conans/client/generators/__init__.py
+++ b/conans/client/generators/__init__.py
@@ -27,6 +27,7 @@
 import traceback
 from conans.util.env_reader import get_env
 from .b2 import B2Generator
+from .premake import PremakeGenerator
 
 
 class _GeneratorManager(object):
@@ -72,6 +73,7 @@ def __getitem__(self, key):
 registered_generators.add("pkg_config", PkgConfigGenerator)
 registered_generators.add("json", JsonGenerator)
 registered_generators.add("b2", B2Generator)
+registered_generators.add("premake", PremakeGenerator)
 
 
 def write_generators(conanfile, path, output):
diff --git a/conans/client/generators/premake.py b/conans/client/generators/premake.py
new file mode 100644
--- /dev/null
+++ b/conans/client/generators/premake.py
@@ -0,0 +1,53 @@
+from conans.model import Generator
+from conans.paths import BUILD_INFO_PREMAKE
+
+
+class PremakeDeps(object):
+    def __init__(self, deps_cpp_info):
+        self.include_paths = ",\n".join('"%s"' % p.replace("\\", "/")
+                                        for p in deps_cpp_info.include_paths)
+        self.lib_paths = ",\n".join('"%s"' % p.replace("\\", "/")
+                                    for p in deps_cpp_info.lib_paths)
+        self.bin_paths = ",\n".join('"%s"' % p.replace("\\", "/")
+                                    for p in deps_cpp_info.bin_paths)
+        self.libs = ", ".join('"%s"' % p for p in deps_cpp_info.libs)
+        self.defines = ", ".join('"%s"' % p for p in deps_cpp_info.defines)
+        self.cppflags = ", ".join('"%s"' % p for p in deps_cpp_info.cppflags)
+        self.cflags = ", ".join('"%s"' % p for p in deps_cpp_info.cflags)
+        self.sharedlinkflags = ", ".join('"%s"' % p for p in deps_cpp_info.sharedlinkflags)
+        self.exelinkflags = ", ".join('"%s"' % p for p in deps_cpp_info.exelinkflags)
+
+        self.rootpath = "%s" % deps_cpp_info.rootpath.replace("\\", "/")
+
+
+class PremakeGenerator(Generator):
+    @property
+    def filename(self):
+        return BUILD_INFO_PREMAKE
+
+    @property
+    def content(self):
+        deps = PremakeDeps(self.deps_build_info)
+
+        template = ('conan_includedirs{dep} = {{{deps.include_paths}}}\n'
+                    'conan_libdirs{dep} = {{{deps.lib_paths}}}\n'
+                    'conan_bindirs{dep} = {{{deps.bin_paths}}}\n'
+                    'conan_libs{dep} = {{{deps.libs}}}\n'
+                    'conan_cppdefines{dep} = {{{deps.defines}}}\n'
+                    'conan_cppflags{dep} = {{{deps.cppflags}}}\n'
+                    'conan_cflags{dep} = {{{deps.cflags}}}\n'
+                    'conan_sharedlinkflags{dep} = {{{deps.sharedlinkflags}}}\n'
+                    'conan_exelinkflags{dep} = {{{deps.exelinkflags}}}\n')
+
+        sections = ["#!lua"]
+        all_flags = template.format(dep="", deps=deps)
+        sections.append(all_flags)
+        template_deps = template + 'conan_rootpath{dep} = "{deps.rootpath}"\n'
+
+        for dep_name, dep_cpp_info in self.deps_build_info.dependencies:
+            deps = PremakeDeps(dep_cpp_info)
+            dep_name = dep_name.replace("-", "_")
+            dep_flags = template_deps.format(dep="_" + dep_name, deps=deps)
+            sections.append(dep_flags)
+
+        return "\n".join(sections)
diff --git a/conans/paths.py b/conans/paths.py
--- a/conans/paths.py
+++ b/conans/paths.py
@@ -34,6 +34,7 @@ def path_shortener(x, _):
 BUILD_INFO_QBS = 'conanbuildinfo.qbs'
 BUILD_INFO_VISUAL_STUDIO = 'conanbuildinfo.props'
 BUILD_INFO_XCODE = 'conanbuildinfo.xcconfig'
+BUILD_INFO_PREMAKE = 'conanbuildinfo.lua'
 CONANINFO = "conaninfo.txt"
 CONANENV = "conanenv.txt"
 SYSTEM_REQS = "system_reqs.txt"


Test patch:
diff --git a/conans/test/generators/premake_test.py b/conans/test/generators/premake_test.py
new file mode 100644
--- /dev/null
+++ b/conans/test/generators/premake_test.py
@@ -0,0 +1,95 @@
+import unittest
+from conans.model.conan_file import ConanFile
+from conans.model.settings import Settings
+from conans.model.env_info import EnvValues
+from conans.model.ref import ConanFileReference
+from conans.model.build_info import CppInfo
+from conans.client.generators import PremakeGenerator
+from conans.test.utils.test_files import temp_folder
+from conans.util.files import save
+import os
+
+
+class PremakeGeneratorTest(unittest.TestCase):
+    def variables_setup_test(self):
+        tmp_folder1 = temp_folder()
+        tmp_folder2 = temp_folder()
+        save(os.path.join(tmp_folder1, "include1", "file.h"), "")
+        save(os.path.join(tmp_folder2, "include2", "file.h"), "")
+        save(os.path.join(tmp_folder1, "lib1", "file.a"), "")
+        save(os.path.join(tmp_folder2, "lib2", "file.a"), "")
+        save(os.path.join(tmp_folder1, "bin1", "file.bin"), "")
+        save(os.path.join(tmp_folder2, "bin2", "file.bin"), "")
+
+        conanfile = ConanFile(None, None)
+        conanfile.initialize(Settings({}), EnvValues())
+        ref = ConanFileReference.loads("MyPkg1/0.1@lasote/stables")
+        cpp_info = CppInfo(tmp_folder1)
+        cpp_info.defines = ["MYDEFINE1"]
+        cpp_info.includedirs = ['include1']
+        cpp_info.libdirs = ['lib1']
+        cpp_info.libs = ['libfoo']
+        cpp_info.bindirs = ['bin1']
+        cpp_info.version = "0.1"
+        cpp_info.cflags = ['-fPIC']
+        cpp_info.cppflags = ['-fPIE']
+        cpp_info.sharedlinkflags = ['-framework Cocoa']
+        cpp_info.exelinkflags = ['-framework QuartzCore']
+        conanfile.deps_cpp_info.update(cpp_info, ref.name)
+        ref = ConanFileReference.loads("MyPkg2/3.2.3@lasote/stables")
+        cpp_info = CppInfo(tmp_folder2)
+        cpp_info.defines = ["MYDEFINE2"]
+        cpp_info.includedirs = ['include2']
+        cpp_info.libdirs = ['lib2']
+        cpp_info.libs = ['libbar']
+        cpp_info.bindirs = ['bin2']
+        cpp_info.version = "3.2.3"
+        cpp_info.cflags = ['-mtune=native']
+        cpp_info.cppflags = ['-march=native']
+        cpp_info.sharedlinkflags = ['-framework AudioFoundation']
+        cpp_info.exelinkflags = ['-framework VideoToolbox']
+        conanfile.deps_cpp_info.update(cpp_info, ref.name)
+        generator = PremakeGenerator(conanfile)
+        content = generator.content
+
+        self.assertIn('conan_cppdefines = {"MYDEFINE2", "MYDEFINE1"}', content)
+        self.assertIn('conan_cppdefines_MyPkg1 = {"MYDEFINE1"}', content)
+        self.assertIn('conan_cppdefines_MyPkg2 = {"MYDEFINE2"}', content)
+
+        inc1 = os.path.join(tmp_folder1, 'include1').replace('\\', '/')
+        inc2 = os.path.join(tmp_folder2, 'include2').replace('\\', '/')
+        self.assertIn('conan_includedirs = {"%s",\n"%s"}' % (inc1, inc2), content)
+        self.assertIn('conan_includedirs_MyPkg1 = {"%s"}' % inc1, content)
+        self.assertIn('conan_includedirs_MyPkg2 = {"%s"}' % inc2, content)
+
+        lib1 = os.path.join(tmp_folder1, 'lib1').replace('\\', '/')
+        lib2 = os.path.join(tmp_folder2, 'lib2').replace('\\', '/')
+        self.assertIn('conan_libdirs = {"%s",\n"%s"}' % (lib1, lib2), content)
+        self.assertIn('conan_libdirs_MyPkg1 = {"%s"}' % lib1, content)
+        self.assertIn('conan_libdirs_MyPkg2 = {"%s"}' % lib2, content)
+
+        bin1 = os.path.join(tmp_folder1, 'bin1').replace('\\', '/')
+        bin2 = os.path.join(tmp_folder2, 'bin2').replace('\\', '/')
+        self.assertIn('conan_bindirs = {"%s",\n"%s"}' % (bin1, bin2), content)
+        self.assertIn('conan_bindirs_MyPkg1 = {"%s"}' % bin1, content)
+        self.assertIn('conan_bindirs_MyPkg2 = {"%s"}' % bin2, content)
+
+        self.assertIn('conan_libs = {"libfoo", "libbar"}', content)
+        self.assertIn('conan_libs_MyPkg1 = {"libfoo"}', content)
+        self.assertIn('conan_libs_MyPkg2 = {"libbar"}', content)
+
+        self.assertIn('conan_cflags = {"-mtune=native", "-fPIC"}', content)
+        self.assertIn('conan_cflags_MyPkg1 = {"-fPIC"}', content)
+        self.assertIn('conan_cflags_MyPkg2 = {"-mtune=native"}', content)
+
+        self.assertIn('conan_cppflags = {"-march=native", "-fPIE"}', content)
+        self.assertIn('conan_cppflags_MyPkg1 = {"-fPIE"}', content)
+        self.assertIn('conan_cppflags_MyPkg2 = {"-march=native"}', content)
+
+        self.assertIn('conan_sharedlinkflags = {"-framework AudioFoundation", "-framework Cocoa"}', content)
+        self.assertIn('conan_sharedlinkflags_MyPkg1 = {"-framework Cocoa"}', content)
+        self.assertIn('conan_sharedlinkflags_MyPkg2 = {"-framework AudioFoundation"}', content)
+
+        self.assertIn('conan_exelinkflags = {"-framework VideoToolbox", "-framework QuartzCore"}', content)
+        self.assertIn('conan_exelinkflags_MyPkg1 = {"-framework QuartzCore"}', content)
+        self.assertIn('conan_exelinkflags_MyPkg2 = {"-framework VideoToolbox"}', content)