Skip to content

Commit

Permalink
Merge branch 'master' into feat/kb-h077-apple-shared-relocatable
Browse files Browse the repository at this point in the history
  • Loading branch information
uilianries authored Jan 20, 2023
2 parents f1515f0 + f1a895f commit 3d53c2c
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 0 deletions.
39 changes: 39 additions & 0 deletions hooks/conan-center.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"KB-H073": "TEST V1 PACKAGE FOLDER",
"KB-H074": "STATIC ARTIFACTS",
"KB-H075": "REQUIREMENT OVERRIDE PARAMETER",
"KB-H076": "EITHER STATIC OR SHARED OF EACH LIB",
"KB-H077": "APPLE RELOCATABLE SHARED LIBS",
}

Expand Down Expand Up @@ -1159,6 +1160,13 @@ def test(out):
if not _static_files_well_managed(conanfile, conanfile.package_folder):
out.error("Package with 'shared=False' option did not contain any static artifact")

@run_test("KB-H076", output)
def test(out):
libs_both_static_shared = _get_libs_if_static_and_shared(conanfile)
if len(libs_both_static_shared):
out.error("Package contains both shared and static flavors of these "
f"libraries: {', '.join(libs_both_static_shared)}")

@run_test("KB-H020", output)
def test(out):
if conanfile.name in ["cmake", "msys2", "strawberryperl", "android-ndk", "emsdk"]:
Expand Down Expand Up @@ -1380,6 +1388,37 @@ def _static_files_well_managed(conanfile, folder):
return True


def _get_libs_if_static_and_shared(conanfile):
# TODO: to improve. We only check whether we can find the same lib name with a static or
# shared extension. Therefore:
# - it can't check anything useful for cl like compilers (Visual Studio, clang-cl, Intel-cc) for the moment
# - it can't detect a bad packaging if static & shared flavors have different names
static_extension = "a"
import_lib_extension = "dll.a"
shared_extensions = ["so", "dylib"]

static_libs = set()
shared_libs = set()

libdirs = [os.path.join(conanfile.package_folder, libdir)
for libdir in getattr(conanfile.cpp.package, "libdirs")]
for libdir in libdirs:
# Collect statib libs.
# Pay attention to not pick up import libs while collecting static libs !
static_libs.update([re.sub(fr"\.{static_extension}$", "", os.path.basename(p))
for p in glob.glob(os.path.join(libdir, f"*.{static_extension}"))
if not p.endswith(f".{import_lib_extension}")])

# Collect shared libs and import libs
for ext in shared_extensions + [import_lib_extension]:
shared_libs.update([re.sub(fr"\.{ext}$", "", os.path.basename(p))
for p in glob.glob(os.path.join(libdir, f"*.{ext}"))])

result = list(static_libs.intersection(shared_libs))
result.sort()
return result


def _files_match_settings(conanfile, folder, output):
header_extensions = ["h", "h++", "hh", "hxx", "hpp"]
visual_extensions = ["lib", "dll", "exe", "bat"]
Expand Down
108 changes: 108 additions & 0 deletions tests/test_hooks/conan-center/test_packaging_static_shared.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import os
import textwrap

from parameterized import parameterized

from conans import tools

from tests.utils.test_cases.conan_client import ConanClientTestCase


class TestPackagingStaticSharedLibraries(ConanClientTestCase):
conanfile_test_artifacts = textwrap.dedent("""\
from conan import ConanFile
import os
class AConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
options = {"shared": [True, False], "status": [True, False]}
default_options = {"shared": False, "status": True}
def package(self):
libdir = os.path.join(self.package_folder, "lib")
os.makedirs(libdir)
if self.options.status:
if self.options.shared:
open(os.path.join(libdir, "libfoo.so"), "w")
else:
open(os.path.join(libdir, "libfoo.a"), "w")
else:
if self.options.shared:
open(os.path.join(libdir, "libfoo.a"), "w")
else:
open(os.path.join(libdir, "libfoo.so"), "w")
def package_info(self):
self.cpp_info.libs = ["foo"]
""")

conanfile_test_static_or_shared = textwrap.dedent("""\
from conan import ConanFile
import os
class AConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
options = {"shared": [True, False], "status": [True, False]}
default_options = {"shared": False, "status": True}
def package(self):
libdir = os.path.join(self.package_folder, "lib")
os.makedirs(libdir)
if self.options.status:
if self.options.shared:
open(os.path.join(libdir, "libfoo.so"), "w")
open(os.path.join(libdir, "libbar.so"), "w")
open(os.path.join(libdir, "libfoobar.dll.a"), "w")
else:
open(os.path.join(libdir, "libfoo.a"), "w")
open(os.path.join(libdir, "libbar.a"), "w")
open(os.path.join(libdir, "libfoobar.a"), "w")
else:
open(os.path.join(libdir, "libfoo.a"), "w")
open(os.path.join(libdir, "libfoo.so"), "w")
open(os.path.join(libdir, "libbar.a"), "w")
open(os.path.join(libdir, "libfoobar.a"), "w")
open(os.path.join(libdir, "libfoobar.dll.a"), "w")
def package_info(self):
self.cpp_info.libs = ["foo"]
""")

def _get_environ(self, **kwargs):
kwargs = super(TestPackagingStaticSharedLibraries, self)._get_environ(**kwargs)
kwargs.update({
"CONAN_HOOKS": os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
os.pardir, "hooks", "conan-center")
})
return kwargs

@parameterized.expand([(True, True), (True, False), (False, True), (False, False)])
def test_artifacts(self, shared, hook_ok):
tools.save("conanfile.py", content=self.conanfile_test_artifacts)
output = self.conan([
"create", ".", "name/version@user/test",
"-o", f"name:shared={shared}",
"-o", f"name:status={hook_ok}",
])
if hook_ok:
self.assertIn("[SHARED ARTIFACTS (KB-H015)] OK", output)
self.assertIn("[STATIC ARTIFACTS (KB-H074)] OK", output)
elif shared:
self.assertIn("ERROR: [SHARED ARTIFACTS (KB-H015)] Package with 'shared=True' option did not contain any shared artifact", output)
self.assertIn("[STATIC ARTIFACTS (KB-H074)] OK", output)
else:
self.assertIn("[SHARED ARTIFACTS (KB-H015)] OK", output)
self.assertIn("ERROR: [STATIC ARTIFACTS (KB-H074)] Package with 'shared=False' option did not contain any static artifact", output)

@parameterized.expand([(True, True), (True, False), (False, True), (False, False)])
def test_either_shared_or_static(self, shared, hook_ok):
tools.save("conanfile.py", content=self.conanfile_test_static_or_shared)
output = self.conan([
"create", ".", "name/version@user/test",
"-o", f"name:shared={shared}",
"-o", f"name:status={hook_ok}",
])
if hook_ok:
self.assertIn("[EITHER STATIC OR SHARED OF EACH LIB (KB-H076)] OK", output)
else:
self.assertIn("ERROR: [EITHER STATIC OR SHARED OF EACH LIB (KB-H076)] Package contains both shared and static flavors of these libraries: libfoo, libfoobar", output)

0 comments on commit 3d53c2c

Please sign in to comment.