Skip to content

Commit

Permalink
(#12617) pcre: conan v2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
SpaceIm authored Aug 30, 2022
1 parent 9c5c6d4 commit a77260c
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 99 deletions.
7 changes: 0 additions & 7 deletions recipes/pcre/all/CMakeLists.txt

This file was deleted.

7 changes: 7 additions & 0 deletions recipes/pcre/all/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ sources:
"8.41":
url: "https://sourceforge.net/projects/pcre/files/pcre/8.41/pcre-8.41.tar.bz2"
sha256: "e62c7eac5ae7c0e7286db61ff82912e1c0b7a0c13706616e94a7dd729321b530"
patches:
"8.45":
- patch_file: "patches/0001-fix-cmake-8.45.patch"
"8.44":
- patch_file: "patches/0001-fix-cmake-8.41.patch"
"8.41":
- patch_file: "patches/0001-fix-cmake-8.41.patch"
150 changes: 78 additions & 72 deletions recipes/pcre/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from conan import ConanFile
from conan.tools import files
from conan.tools.microsoft import msvc_runtime_flag, is_msvc
from conan.errors import ConanInvalidConfiguration
from conans import CMake, tools
import functools
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.files import apply_conandata_patches, copy, get, replace_in_file, rmdir
from conan.tools.microsoft import is_msvc, is_msvc_static_runtime
import os

required_conan_version = ">=1.50.0"
Expand Down Expand Up @@ -49,16 +48,9 @@ class PCREConan(ConanFile):
"with_stack_for_recursion": True,
}

exports_sources = "CMakeLists.txt"
generators = "cmake", "cmake_find_package"

@property
def _source_subfolder(self):
return "source_subfolder"

@property
def _build_subfolder(self):
return "build_subfolder"
def export_sources(self):
for p in self.conan_data.get("patches", {}).get(self.version, []):
copy(self, p["patch_file"], self.recipe_folder, self.export_sources_folder)

def config_options(self):
if self.settings.os == "Windows":
Expand All @@ -68,8 +60,14 @@ def configure(self):
if self.options.shared:
del self.options.fPIC
if not self.options.build_pcrecpp:
del self.settings.compiler.libcxx
del self.settings.compiler.cppstd
try:
del self.settings.compiler.libcxx
except Exception:
pass
try:
del self.settings.compiler.cppstd
except Exception:
pass
if not self.options.build_pcregrep:
del self.options.with_bzip2
del self.options.with_zlib
Expand All @@ -83,99 +81,107 @@ def requirements(self):
self.requires("zlib/1.2.12")

def validate(self):
if not self.options.build_pcre_8 and not self.options.build_pcre_16 and not self.options.build_pcre_32:
if not self.info.options.build_pcre_8 and not self.info.options.build_pcre_16 and not self.info.options.build_pcre_32:
raise ConanInvalidConfiguration("At least one of build_pcre_8, build_pcre_16 or build_pcre_32 must be enabled")
if self.options.build_pcrecpp and not self.options.build_pcre_8:
if self.info.options.build_pcrecpp and not self.info.options.build_pcre_8:
raise ConanInvalidConfiguration("build_pcre_8 must be enabled for the C++ library support")
if self.options.build_pcregrep and not self.options.build_pcre_8:
if self.info.options.build_pcregrep and not self.info.options.build_pcre_8:
raise ConanInvalidConfiguration("build_pcre_8 must be enabled for the pcregrep program")

def layout(self):
cmake_layout(self, src_folder="src")

def source(self):
files.get(self, **self.conan_data["sources"][self.version],
destination=self._source_subfolder, strip_root=True)
get(self, **self.conan_data["sources"][self.version],
destination=self.source_folder, strip_root=True)

def generate(self):
tc = CMakeToolchain(self)
tc.variables["PCRE_BUILD_TESTS"] = False
tc.variables["PCRE_BUILD_PCRE8"] = self.options.build_pcre_8
tc.variables["PCRE_BUILD_PCRE16"] = self.options.build_pcre_16
tc.variables["PCRE_BUILD_PCRE32"] = self.options.build_pcre_32
tc.variables["PCRE_BUILD_PCREGREP"] = self.options.build_pcregrep
tc.variables["PCRE_BUILD_PCRECPP"] = self.options.build_pcrecpp
tc.variables["PCRE_SUPPORT_LIBZ"] = self.options.get_safe("with_zlib", False)
tc.variables["PCRE_SUPPORT_LIBBZ2"] = self.options.get_safe("with_bzip2", False)
tc.variables["PCRE_SUPPORT_JIT"] = self.options.with_jit
tc.variables["PCRE_SUPPORT_UTF"] = self.options.with_utf
tc.variables["PCRE_SUPPORT_UNICODE_PROPERTIES"] = self.options.with_unicode_properties
tc.variables["PCRE_SUPPORT_LIBREADLINE"] = False
tc.variables["PCRE_SUPPORT_LIBEDIT"] = False
tc.variables["PCRE_NO_RECURSE"] = not self.options.with_stack_for_recursion
if is_msvc(self):
tc.variables["PCRE_STATIC_RUNTIME"] = is_msvc_static_runtime(self)
# Relocatable shared lib on Macos
tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0042"] = "NEW"
# Honor BUILD_SHARED_LIBS since upstream CMakeLists overrides it as a CACHE variable.
# Issue quite similar to https://github.com/conan-io/conan/issues/11840
tc.cache_variables["BUILD_SHARED_LIBS"] = "ON" if self.options.shared else "OFF"
tc.generate()

deps = CMakeDeps(self)
deps.generate()

def _patch_sources(self):
cmake_file = os.path.join(self._source_subfolder, "CMakeLists.txt")
apply_conandata_patches(self)
cmake_file = os.path.join(self.source_folder, "CMakeLists.txt")
# Avoid man and share during install stage
files.replace_in_file(self,
cmake_file, "INSTALL(FILES ${man1} DESTINATION man/man1)", "")
files.replace_in_file(self,
cmake_file, "INSTALL(FILES ${man3} DESTINATION man/man3)", "")
files.replace_in_file(self,
cmake_file, "INSTALL(FILES ${html} DESTINATION share/doc/pcre/html)", "")
replace_in_file(self, cmake_file, "INSTALL(FILES ${man1} DESTINATION man/man1)", "")
replace_in_file(self, cmake_file, "INSTALL(FILES ${man3} DESTINATION man/man3)", "")
replace_in_file(self, cmake_file, "INSTALL(FILES ${html} DESTINATION share/doc/pcre/html)", "")
# Do not override CMAKE_MODULE_PATH and do not add ${PROJECT_SOURCE_DIR}/cmake
# because it contains a custom FindPackageHandleStandardArgs.cmake which
# can break conan generators
files.replace_in_file(self,
cmake_file, "SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)", "")
replace_in_file(self, cmake_file, "SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)", "")
# Avoid CMP0006 error (macos bundle)
files.replace_in_file(self,
cmake_file, "RUNTIME DESTINATION bin", "RUNTIME DESTINATION bin\n BUNDLE DESTINATION bin")

@functools.lru_cache(1)
def _configure_cmake(self):
cmake = CMake(self)
cmake.definitions["PCRE_BUILD_TESTS"] = False
cmake.definitions["PCRE_BUILD_PCRE8"] = self.options.build_pcre_8
cmake.definitions["PCRE_BUILD_PCRE16"] = self.options.build_pcre_16
cmake.definitions["PCRE_BUILD_PCRE32"] = self.options.build_pcre_32
cmake.definitions["PCRE_BUILD_PCREGREP"] = self.options.build_pcregrep
cmake.definitions["PCRE_BUILD_PCRECPP"] = self.options.build_pcrecpp
cmake.definitions["PCRE_SUPPORT_LIBZ"] = self.options.get_safe("with_zlib", False)
cmake.definitions["PCRE_SUPPORT_LIBBZ2"] = self.options.get_safe("with_bzip2", False)
cmake.definitions["PCRE_SUPPORT_JIT"] = self.options.with_jit
cmake.definitions["PCRE_SUPPORT_UTF"] = self.options.with_utf
cmake.definitions["PCRE_SUPPORT_UNICODE_PROPERTIES"] = self.options.with_unicode_properties
cmake.definitions["PCRE_SUPPORT_LIBREADLINE"] = False
cmake.definitions["PCRE_SUPPORT_LIBEDIT"] = False
cmake.definitions["PCRE_NO_RECURSE"] = not self.options.with_stack_for_recursion
if is_msvc(self):
cmake.definitions["PCRE_STATIC_RUNTIME"] = "MT" in msvc_runtime_flag(self)
if tools.is_apple_os(self.settings.os):
# Generate a relocatable shared lib on Macos
cmake.definitions["CMAKE_POLICY_DEFAULT_CMP0042"] = "NEW"
cmake.configure(build_folder=self._build_subfolder)
return cmake
replace_in_file(
self,
cmake_file,
"RUNTIME DESTINATION bin",
"RUNTIME DESTINATION bin\n BUNDLE DESTINATION bin",
)

def build(self):
self._patch_sources()
cmake = self._configure_cmake()
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
self.copy(pattern="LICENCE", dst="licenses", src=self._source_subfolder)
cmake = self._configure_cmake()
copy(self, "LICENCE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
files.rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))

def package_info(self):
self.cpp_info.names["cmake_find_package"] = "PCRE"
self.cpp_info.names["cmake_find_package_multi"] = "PCRE"
suffix = "d" if self.settings.os == "Windows" and self.settings.build_type == "Debug" else ""

if self.options.build_pcre_8:
# pcre
self.cpp_info.components["libpcre"].set_property("pkg_config_name", "libpcre")
self.cpp_info.components["libpcre"].libs = [self._lib_name("pcre")]
self.cpp_info.components["libpcre"].libs = [f"pcre{suffix}"]
if not self.options.shared:
self.cpp_info.components["libpcre"].defines.append("PCRE_STATIC=1")
# pcreposix
self.cpp_info.components["libpcreposix"].set_property("pkg_config_name", "libpcreposix")
self.cpp_info.components["libpcreposix"].libs = [self._lib_name("pcreposix")]
self.cpp_info.components["libpcreposix"].libs = [f"pcreposix{suffix}"]
self.cpp_info.components["libpcreposix"].requires = ["libpcre"]
# pcrecpp
if self.options.build_pcrecpp:
self.cpp_info.components["libpcrecpp"].set_property("pkg_config_name", "libpcrecpp")
self.cpp_info.components["libpcrecpp"].libs = [self._lib_name("pcrecpp")]
self.cpp_info.components["libpcrecpp"].libs = [f"pcrecpp{suffix}"]
self.cpp_info.components["libpcrecpp"].requires = ["libpcre"]
# pcre16
if self.options.build_pcre_16:
self.cpp_info.components["libpcre16"].set_property("pkg_config_name", "libpcre16")
self.cpp_info.components["libpcre16"].libs = [self._lib_name("pcre16")]
self.cpp_info.components["libpcre16"].libs = [f"pcre16{suffix}"]
if not self.options.shared:
self.cpp_info.components["libpcre16"].defines.append("PCRE_STATIC=1")
# pcre32
if self.options.build_pcre_32:
self.cpp_info.components["libpcre32"].set_property("pkg_config_name", "libpcre32")
self.cpp_info.components["libpcre32"].libs = [self._lib_name("pcre32")]
self.cpp_info.components["libpcre32"].libs = [f"pcre32{suffix}"]
if not self.options.shared:
self.cpp_info.components["libpcre32"].defines.append("PCRE_STATIC=1")

Expand All @@ -190,7 +196,7 @@ def package_info(self):
if self.options.with_zlib:
self.cpp_info.components["libpcre"].requires.append("zlib::zlib")

def _lib_name(self, name):
if self.settings.os == "Windows" and self.settings.build_type == "Debug":
return name + "d"
return name
# TODO: to remove in conan v2 once legacy generators removed
# DO NOT port this name to cmake_file_name/cmake_target_name properties, it was a mistake
self.cpp_info.names["cmake_find_package"] = "PCRE"
self.cpp_info.names["cmake_find_package_multi"] = "PCRE"
17 changes: 17 additions & 0 deletions recipes/pcre/all/patches/0001-fix-cmake-8.41.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,13 +68,13 @@
# 2016-03-01 PH applied Chris Wilson's patch for MSVC static build
# 2016-06-24 PH applied Chris Wilson's revised patch (adds a separate option)

-PROJECT(PCRE C CXX)

# Increased minimum to 2.8.0 to support newer add_test features. Set policy
# CMP0026 to avoid warnings for the use of LOCATION in GET_TARGET_PROPERTY.

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0)
CMAKE_POLICY(SET CMP0026 OLD)
+PROJECT(PCRE C CXX)

SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # for FindReadline.cmake

17 changes: 17 additions & 0 deletions recipes/pcre/all/patches/0001-fix-cmake-8.45.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,13 +71,13 @@
# 2021-06-14 PH applied Wolfgang Stöggl's patch for generating pcre-config and
# libpcre*.pc files (Bugzilla #2583)

-PROJECT(PCRE C CXX)

# Increased minimum to 2.8.5 to support GNUInstallDirs. Set policy
# CMP0026 to avoid warnings for the use of LOCATION in GET_TARGET_PROPERTY.

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)
CMAKE_POLICY(SET CMP0026 OLD)
+PROJECT(PCRE C CXX)

# For FindReadline.cmake. This was changed to allow setting CMAKE_MODULE_PATH
# on the command line.
9 changes: 3 additions & 6 deletions recipes/pcre/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_package C)
project(test_package LANGUAGES C)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

find_package(PCRE REQUIRED CONFIG)
find_package(pcre REQUIRED CONFIG)

add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE PCRE::PCRE)
target_link_libraries(${PROJECT_NAME} PRIVATE pcre::pcre)
27 changes: 13 additions & 14 deletions recipes/pcre/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
from conans import ConanFile, CMake, tools
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout
import os


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake", "cmake_find_package_multi"
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"

def build_requirements(self):
if self.settings.os == "Macos" and self.settings.arch == "armv8":
# Workaround for CMake bug with error message:
# Attempting to use @rpath without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being
# set. This could be because you are using a Mac OS X version less than 10.5
# or because CMake's platform configuration is corrupt.
# FIXME: Remove once CMake on macOS/M1 CI runners is upgraded.
self.build_requires("cmake/3.22.0")
def requirements(self):
self.requires(self.tested_reference_str)

def layout(self):
cmake_layout(self)

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self, skip_x64_x86=True):
bin_path = os.path.join("bin", "test_package")
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
arguments = "{}w+ conan-center-index".format("\\" if self.settings.os == "Windows" else "\\\\")
self.run("{} {}".format(bin_path, arguments), run_environment=True)
self.run(f"{bin_path} {arguments}", env="conanrun")
10 changes: 10 additions & 0 deletions recipes/pcre/all/test_v1_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES C)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

find_package(PCRE REQUIRED CONFIG)

add_executable(${PROJECT_NAME} ../test_package/test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE PCRE::PCRE)
18 changes: 18 additions & 0 deletions recipes/pcre/all/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from conans import ConanFile, CMake, tools
import os


class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package_multi"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self):
bin_path = os.path.join("bin", "test_package")
arguments = "{}w+ conan-center-index".format("\\" if self.settings.os == "Windows" else "\\\\")
self.run(f"{bin_path} {arguments}", run_environment=True)

0 comments on commit a77260c

Please sign in to comment.