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

odbc: conan v2 support + unvendor libltdl #13131

Merged
merged 5 commits into from
Sep 30, 2022
Merged
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
8 changes: 6 additions & 2 deletions recipes/odbc/all/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ sources:
- "http://www.unixodbc.net/unixODBC-2.3.7.tar.gz"
sha256: "45f169ba1f454a72b8fcbb82abd832630a3bf93baa84731cf2949f449e1e3e77"
patches:
"2.3.11":
- patch_file: "patches/0001-duplicated-get-connection.patch"
"2.3.9":
- patch_file: "patches/0001-duplicated-get-connection.patch"
"2.3.7":
- patch_file: "patches/missing-declarations.patch"
base_path: "source_subfolder"
- patch_file: "patches/0001-duplicated-get-connection.patch"
- patch_file: "patches/0002-missing-declarations.patch"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patch fields 🙏

132 changes: 77 additions & 55 deletions recipes/odbc/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from conans import ConanFile, AutoToolsBuildEnvironment, tools
from conans.errors import ConanInvalidConfiguration
import functools
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, replace_in_file, rm, rmdir
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.layout import basic_layout
import os
import shutil

required_conan_version = ">=1.43.0"
required_conan_version = ">=1.52.0"


class OdbcConan(ConanFile):
Expand All @@ -27,84 +29,106 @@ class OdbcConan(ConanFile):
"with_libiconv": True,
}

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

@property
def _user_info_build(self):
return getattr(self, "user_info_build", self.deps_user_info)

def export_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
self.copy(patch["patch_file"])
export_conandata_patches(self)

def configure(self):
if self.options.shared:
del self.options.fPIC
del self.settings.compiler.libcxx
del self.settings.compiler.cppstd
try:
del self.options.fPIC
except Exception:
pass
try:
del self.settings.compiler.cppstd
except Exception:
pass
try:
del self.settings.compiler.libcxx
except Exception:
pass

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

def requirements(self):
self.requires("libtool/2.4.7")
if self.options.with_libiconv:
self.requires("libiconv/1.17")

def validate(self):
if self.settings.os == "Windows":
if self.info.settings.os == "Windows":
raise ConanInvalidConfiguration("odbc is a system lib on Windows")

def build_requirements(self):
self.build_requires("gnu-config/cci.20201022")
self.tool_requires("gnu-config/cci.20210814")

def source(self):
tools.get(**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 = AutotoolsToolchain(self)
yes_no = lambda v: "yes" if v else "no"
tc.configure_args.extend([
"--without-included-ltdl",
f"--with-ltdl-include={self.dependencies['libtool'].cpp_info.includedirs[0]}",
f"--with-ltdl-lib={self.dependencies['libtool'].cpp_info.libdirs[0]}",
"--disable-ltdl-install",
f"--enable-iconv={yes_no(self.options.with_libiconv)}",
"--sysconfdir=/etc",
])
if self.options.with_libiconv:
libiconv_prefix = self.dependencies["libiconv"].package_folder
tc.configure_args.append(f"--with-libiconv-prefix={libiconv_prefix}")
tc.generate()

def _patch_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
tools.patch(**patch)
apply_conandata_patches(self)
# support more triplets
shutil.copy(self._user_info_build["gnu-config"].CONFIG_SUB,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Files copy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideal the Conan api should be doing file io tools.files api

os.path.join(self._source_subfolder, "config.sub"))
os.path.join(self.source_folder, "config.sub"))
shutil.copy(self._user_info_build["gnu-config"].CONFIG_GUESS,
os.path.join(self._source_subfolder, "config.guess"))
os.path.join(self.source_folder, "config.guess"))
# allow external libtdl (in libtool recipe)
replace_in_file(
self,
os.path.join(self.source_folder, "configure"),
"if test -f \"$with_ltdl_lib/libltdl.la\";",
"if true;",
)
libtool_system_libs = self.dependencies["libtool"].cpp_info.system_libs
if libtool_system_libs:
replace_in_file(
self,
os.path.join(self.source_folder, "configure"),
"-L$with_ltdl_lib -lltdl",
"-L$with_ltdl_lib -lltdl -l{}".format(" -l".join(libtool_system_libs)),
)
# relocatable shared libs on macOS
for configure in [
os.path.join(self._source_subfolder, "configure"),
os.path.join(self._source_subfolder, "libltdl", "configure"),
os.path.join(self.source_folder, "configure"),
os.path.join(self.source_folder, "libltdl", "configure"),
]:
tools.replace_in_file(configure, "-install_name \\$rpath/", "-install_name @rpath/")

@functools.lru_cache(1)
def _configure_autotools(self):
autotools = AutoToolsBuildEnvironment(self)
autotools.libs = []
yes_no = lambda v: "yes" if v else "no"
args = [
"--enable-shared={}".format(yes_no(self.options.shared)),
"--enable-static={}".format(yes_no(not self.options.shared)),
"--enable-ltdl-install",
"--enable-iconv={}".format(yes_no(self.options.with_libiconv)),
"--sysconfdir=/etc",
]
if self.options.with_libiconv:
libiconv_prefix = self.deps_cpp_info["libiconv"].rootpath
args.append("--with-libiconv-prefix={}".format(libiconv_prefix))
autotools.configure(configure_dir=self._source_subfolder, args=args)
return autotools
replace_in_file(self, configure, "-install_name \\$rpath/", "-install_name @rpath/")

def build(self):
self._patch_sources()
autotools = self._configure_autotools()
autotools = Autotools(self)
autotools.configure()
autotools.make()

def package(self):
self.copy("COPYING", src=self._source_subfolder, dst="licenses")
autotools = self._configure_autotools()
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
autotools = Autotools(self)
autotools.install()
tools.rmdir(os.path.join(self.package_folder, "share"))
tools.rmdir(os.path.join(self.package_folder, "etc"))
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
tools.remove_files_by_mask(os.path.join(self.package_folder, "lib"), "*.la")
rmdir(self, os.path.join(self.package_folder, "share"))
rmdir(self, os.path.join(self.package_folder, "etc"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rm(self, "*.la", os.path.join(self.package_folder, "lib"))

def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
Expand All @@ -119,26 +143,24 @@ def package_info(self):
# odbc
self.cpp_info.components["_odbc"].set_property("pkg_config_name", "odbc")
self.cpp_info.components["_odbc"].libs = ["odbc"]
self.cpp_info.components["_odbc"].requires = ["odbcltdl"]
self.cpp_info.components["_odbc"].requires = ["libtool::libtool"]
if self.options.with_libiconv:
self.cpp_info.components["_odbc"].requires.append("libiconv::libiconv")

# odbcinst
self.cpp_info.components["odbcinst"].set_property("pkg_config_name", "odbcinst")
self.cpp_info.components["odbcinst"].libs = ["odbcinst"]
self.cpp_info.components["odbcinst"].requires = ["odbcltdl"]
self.cpp_info.components["odbcinst"].requires = ["libtool::libtool"]

# odbccr
self.cpp_info.components["odbccr"].set_property("pkg_config_name", "odbccr")
self.cpp_info.components["odbccr"].libs = ["odbccr"]

self.cpp_info.components["odbcltdl"].libs = ["ltdl"]

if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["_odbc"].system_libs = ["pthread"]
self.cpp_info.components["odbcinst"].system_libs = ["pthread"]
self.cpp_info.components["odbcltdl"].system_libs = ["dl"]

# TODO: to remove in conan v2
bin_path = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(bin_path))
self.output.info(f"Appending PATH environment variable: {bin_path}")
self.env_info.PATH.append(bin_path)
11 changes: 11 additions & 0 deletions recipes/odbc/all/patches/0001-duplicated-get-connection.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/cur/SQLGetDiagRec.c
+++ b/cur/SQLGetDiagRec.c
@@ -101,8 +101,4 @@ SQLRETURN CLGetDiagRec( SQLSMALLINT handle_type,
text_length_ptr);
}

-DMHDBC __get_connection( EHEAD * head )
-{
- return 0;
-}

7 changes: 2 additions & 5 deletions recipes/odbc/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)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
project(test_package LANGUAGES C)

find_package(ODBC REQUIRED)

add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} ODBC::ODBC)
target_link_libraries(${PROJECT_NAME} PRIVATE ODBC::ODBC)
28 changes: 14 additions & 14 deletions recipes/odbc/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
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", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"
test_type = "explicit"

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 layout(self):
cmake_layout(self)

def requirements(self):
self.requires(self.tested_reference_str)

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")
self.run(bin_path, run_environment=True)
self.run("odbcinst --version", run_environment=True)
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")
self.run("odbcinst --version", env="conanrun")
10 changes: 10 additions & 0 deletions recipes/odbc/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(ODBC REQUIRED)

add_executable(${PROJECT_NAME} ../test_package/test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE ODBC::ODBC)
18 changes: 18 additions & 0 deletions recipes/odbc/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"

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")
self.run(bin_path, run_environment=True)
self.run("odbcinst --version", run_environment=True)