Skip to content

Commit

Permalink
Merge pull request #477 from SpaceIm/feat/kb-h077-apple-shared-reloca…
Browse files Browse the repository at this point in the history
…table

closes #376
  • Loading branch information
uilianries committed Jan 20, 2023
2 parents f1a895f + 3d53c2c commit 8914d76
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
31 changes: 31 additions & 0 deletions hooks/conan-center.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@
import glob
import inspect
import os
import platform
import re
import sys
import subprocess

from logging import WARNING, ERROR, INFO, DEBUG, NOTSET

import yaml
from conan.tools.apple import is_apple_os
from conans import tools
from conans.client.graph.python_requires import ConanPythonRequire
from conans.client.loader import parse_conanfile
from conans.util.runners import check_output_runner
try:
from conans import Settings
except ImportError:
Expand Down Expand Up @@ -87,6 +90,7 @@
"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 @@ -1240,6 +1244,14 @@ def test(out):
for lib in libs:
out.warn("Library '{}' links to system library '{}' but it is not in cpp_info.{}.".format(lib, missing_system_lib, attribute))

@run_test("KB-H077", output)
def test(out):
if not is_apple_os(conanfile):
return
not_relocatable_libs = _get_non_relocatable_shared_libs(conanfile)
if not_relocatable_libs:
out.error(f"install_name dir of these shared libs is not @rpath: {', '.join(not_relocatable_libs)}")


@raise_if_error_output
def post_package_info(output, conanfile, reference, **kwargs):
Expand Down Expand Up @@ -1605,6 +1617,25 @@ def _deplibs_from_shlibs(conanfile, out):
return deplibs


def _get_non_relocatable_shared_libs(conanfile):
if platform.system() != "Darwin":
return None

bad_shared_libs = []

libdirs = [os.path.join(conanfile.package_folder, libdir)
for libdir in getattr(conanfile.cpp.package, "libdirs")]
for libdir in libdirs:
for dylib_path in glob.glob(os.path.join(libdir, "*.dylib")):
command = f"otool -D {dylib_path}"
install_name = check_output_runner(command).strip().split(":")[1].strip()
install_name_dir = os.path.dirname(install_name)
if install_name_dir != "@rpath":
bad_shared_libs.append(os.path.basename(dylib_path))

return bad_shared_libs


_GLIBC_LIBS = {
"anl", "BrokenLocale", "crypt", "dl", "g", "m", "mvec", "nsl", "nss_compat", "nss_db", "nss_dns",
"nss_files", "nss_hesiod", "pthread", "resolv", "rt", "thread_db", "util",
Expand Down
126 changes: 126 additions & 0 deletions tests/test_hooks/conan-center/test_apple_relocatable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import os
import platform
import textwrap

from parameterized import parameterized

from conans import tools

from tests.utils.test_cases.conan_client import ConanClientTestCase


class TestAppleRelocatableSharedLibs(ConanClientTestCase):
def _get_environ(self, **kwargs):
kwargs = super(TestAppleRelocatableSharedLibs, 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

conanfile = textwrap.dedent("""\
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class FooConan(ConanFile):
name = "foo"
url = "fake_url.com"
license = "fake_license"
description = "whatever"
homepage = "homepage.com"
topics = ("fake_topic", "another_fake_topic")
settings = "os", "arch", "compiler", "build_type"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
exports_sources = "CMakeLists.txt", "foo.h", "foo.c"
generators = "CMakeToolchain"
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.cppstd")
self.settings.rm_safe("compiler.libcxx")
def layout(self):
cmake_layout(self)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
cmake = CMake(self)
cmake.install()
def package_info(self):
self.cpp_info.libs = ["foo"]
""")

foo_h = textwrap.dedent("""\
#pragma once
#include "foo_export.h"
FOO_API int foo_test();
""")

foo_c = textwrap.dedent("""\
#include "foo.h"
int foo_test() {return 1;}
""")

@staticmethod
def cmakelists(install_name_dir="@rpath"):
if install_name_dir == "@rpath":
cmake_install_name_dir = ""
else:
cmake_install_name_dir = f"set(CMAKE_INSTALL_NAME_DIR \"{install_name_dir}\")"

return textwrap.dedent(f"""\
cmake_minimum_required(VERSION 3.15)
project(test_relocatable LANGUAGES C)
include(GenerateExportHeader)
include(GNUInstallDirs)
{cmake_install_name_dir}
add_library(foo foo.c)
generate_export_header(foo EXPORT_MACRO_NAME FOO_API)
set_target_properties(foo PROPERTIES C_VISIBILITY_PRESET hidden)
target_include_directories(foo PUBLIC
$<BUILD_INTERFACE:${{PROJECT_SOURCE_DIR}}>
$<BUILD_INTERFACE:${{PROJECT_BINARY_DIR}}>
)
install(FILES ${{PROJECT_SOURCE_DIR}}/foo.h ${{PROJECT_BINARY_DIR}}/foo_export.h
DESTINATION ${{CMAKE_INSTALL_INCLUDEDIR}})
install(TARGETS foo
RUNTIME DESTINATION ${{CMAKE_INSTALL_BINDIR}}
ARCHIVE DESTINATION ${{CMAKE_INSTALL_LIBDIR}}
LIBRARY DESTINATION ${{CMAKE_INSTALL_LIBDIR}})
""")

@parameterized.expand([
(False, "@rpath"),
(False, ""),
(False, "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"),
(True, "@rpath"),
(True, ""),
(True, "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"),
])
def test_relocatable(self, shared, install_name_dir):
tools.save("conanfile.py", content=self.conanfile)
tools.save("CMakeLists.txt", content=self.cmakelists(install_name_dir))
tools.save("foo.h", content=self.foo_h)
tools.save("foo.c", content=self.foo_c)
output = self.conan(["create", ".", "foo/1.0@user/test", "-o", f"foo:shared={shared}"])
if platform.system() == "Darwin" and shared and install_name_dir != "@rpath":
self.assertIn("ERROR: [APPLE RELOCATABLE SHARED LIBS (KB-H077)] install_name dir of these shared libs is not @rpath: libfoo.dylib", output)
else:
self.assertIn("[APPLE RELOCATABLE SHARED LIBS (KB-H077)] OK", output)

0 comments on commit 8914d76

Please sign in to comment.