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

libxml2: fix mingw on Linux + double quotes + libxml2 does not create cmake targets #2714

Closed
wants to merge 11 commits into from
7 changes: 7 additions & 0 deletions recipes/libxml2/all/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ sources:
"2.9.10":
sha256: aafee193ffb8fe0c82d4afef6ef91972cbaf5feea100edc2f262750611b4be1f
url: http://xmlsoft.org/sources/libxml2-2.9.10.tar.gz
patches:
"2.9.9":
- patch_file: "patches/2.9.9-0001-fix-install-mingw.patch"
base_path: "source_subfolder"
"2.9.10":
- patch_file: "patches/2.9.10-0001-fix-install-mingw.patch"
base_path: "source_subfolder"
207 changes: 134 additions & 73 deletions recipes/libxml2/all/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ class Libxml2Conan(ConanFile):
homepage = "https://xmlsoft.org"
license = "MIT"
settings = "os", "arch", "compiler", "build_type"
exports_sources = "patches/**"
generators = "pkg_config"

# from ./configure and ./win32/configure.js
default_options = {'shared': False,
'fPIC': True,
'include_utils': True,
default_options = {"shared": False,
"fPIC": True,
"include_utils": True,
"c14n": True,
"catalog": True,
"docbook": True,
Expand Down Expand Up @@ -56,43 +57,41 @@ class Libxml2Conan(ConanFile):
_autotools = None
_source_subfolder = "source_subfolder"

def requirements(self):
if self.options.zlib:
self.requires("zlib/1.2.11")
if self.options.lzma:
self.requires("xz_utils/5.2.4")
if self.options.iconv:
self.requires("libiconv/1.16")
if self.options.icu:
self.requires("icu/64.2")

def build_requirements(self):
if self.settings.compiler != "Visual Studio" and tools.os_info.is_windows and os.environ.get("CONAN_BASH_PATH", None) is None:
self.build_requires("msys2/20190524")

@property
def _is_msvc(self):
return self.settings.compiler == 'Visual Studio'
return self.settings.compiler == "Visual Studio"

@property
def _is_mingw(self):
return self.settings.compiler == 'gcc' and self.settings.os == 'Windows'

def source(self):
tools.get(**self.conan_data["sources"][self.version])
os.rename("libxml2-{0}".format(self.version), self._source_subfolder)
return self.settings.compiler == "gcc" and self.settings.os == "Windows"

def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC

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

def requirements(self):
if self.options.zlib:
self.requires("zlib/1.2.11")
if self.options.lzma:
self.requires("xz_utils/5.2.4")
if self.options.iconv:
self.requires("libiconv/1.16")
if self.options.icu:
self.requires("icu/68.1")

def source(self):
tools.get(**self.conan_data["sources"][self.version])
os.rename("libxml2-{0}".format(self.version), self._source_subfolder)

@contextmanager
def _msvc_build_environment(self):
with tools.chdir(os.path.join(self._source_subfolder, 'win32')):
with tools.chdir(os.path.join(self._source_subfolder, "win32")):
with tools.vcvars(self.settings):
with tools.environment_append(VisualStudioBuildEnvironment(self).vars):
yield
Expand All @@ -109,8 +108,8 @@ def _build_msvc(self):
"cruntime=/%s" % self.settings.compiler.runtime,
"debug=%s" % debug,
"static=%s" % static,
'include="%s"' % ";".join(self.deps_cpp_info.include_paths),
'lib="%s"' % ";".join(self.deps_cpp_info.lib_paths)]
"include='%s'" % ";".join(self.deps_cpp_info.include_paths),
"lib='%s'" % ";".join(self.deps_cpp_info.lib_paths)]

for name in self._option_names:
cname = {"mem-debug": "mem_debug",
Expand All @@ -120,7 +119,7 @@ def _build_msvc(self):
value = "yes" if value else "no"
args.append("%s=%s" % (cname, value))

configure_command = ' '.join(args)
configure_command = " ".join(args)
self.output.info(configure_command)
self.run(configure_command)

Expand All @@ -130,49 +129,88 @@ def fix_library(option, package, old_libname):
libs = []
for lib in self.deps_cpp_info[package].libs:
libname = lib
if not libname.endswith('.lib'):
libname += '.lib'
if not libname.endswith(".lib"):
libname += ".lib"
libs.append(libname)
tools.replace_in_file("Makefile.msvc",
"LIBS = $(LIBS) %s" % old_libname,
"LIBS = $(LIBS) %s" % ' '.join(libs))
"LIBS = $(LIBS) %s" % " ".join(libs))

fix_library(self.options.zlib, 'zlib', 'zlib.lib')
fix_library(self.options.lzma, 'lzma', 'liblzma.lib')
fix_library(self.options.iconv, 'libiconv', 'iconv.lib')
fix_library(self.options.icu, 'icu', 'advapi32.lib sicuuc.lib sicuin.lib sicudt.lib')
fix_library(self.options.icu, 'icu', 'icuuc.lib icuin.lib icudt.lib')
fix_library(self.options.zlib, "zlib", "zlib.lib")
fix_library(self.options.lzma, "lzma", "liblzma.lib")
fix_library(self.options.iconv, "libiconv", "iconv.lib")
fix_library(self.options.icu, "icu", "advapi32.lib sicuuc.lib sicuin.lib sicudt.lib")
fix_library(self.options.icu, "icu", "icuuc.lib icuin.lib icudt.lib")

self.run("nmake /f Makefile.msvc libxml libxmla libxmladll")

if self.options.include_utils:
self.run("nmake /f Makefile.msvc utils")


def _package_msvc(self):
with self._msvc_build_environment():
self.run("nmake /f Makefile.msvc install-libs")

if self.options.include_utils:
self.run("nmake /f Makefile.msvc install-dist")

def _build_mingw(self):
with tools.chdir(os.path.join(self._source_subfolder, "win32")):
debug = "yes" if self.settings.build_type == "Debug" else "no"
static = "no" if self.options.shared else "yes"

args = [
"cscript",
"configure.js",
"compiler=mingw",
'prefix="{}"'.format(self.package_folder),
"debug={}".format(debug),
"static={}".format(static),
'include="{}"'.format(" -I".join(self.deps_cpp_info.include_paths)),
'lib="{}"'.format(" -L".join(self.deps_cpp_info.lib_paths))
]

for name in self._option_names:
cname = {"mem-debug": "mem_debug",
"run-debug": "run_debug",
"docbook": "docb"}.get(name, name)
value = getattr(self.options, name)
value = "yes" if value else "no"
args.append("%s=%s" % (cname, value))

configure_command = " ".join(args)
self.output.info(configure_command)
self.run(configure_command, run_environment=True)

with tools.environment_append({"CFLAGS": tools.get_env("CFLAGS", "") + " -DIN_LIBXML"}):
self.run("mingw32-make -f Makefile.mingw {} -j{}".format("libxml" if self.options.shared else "libxmla", tools.cpu_count()), run_environment=True)

if self.options.include_utils:
self.run("mingw32-make -f Makefile.mingw utils -j{}".format(tools.cpu_count()), run_environment=True)

def _package_mingw(self):
tools.mkdir(os.path.join(self.package_folder, "include", "libxml2"))
with tools.chdir(os.path.join(self._source_subfolder, "win32")):
self.run("mingw32-make -f Makefile.mingw install-libs")

if self.options.include_utils:
self.run("mingw32-make -f Makefile.mingw install-dist")

def _configure_autotools(self):
if self._autotools:
return self._autotools
self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
if not tools.os_info.is_windows:
self._autotools.fpic = self.options.fPIC
full_install_subfolder = tools.unix_path(self.package_folder) if tools.os_info.is_windows else self.package_folder
# fix rpath
if self.settings.os == "Macos":
tools.replace_in_file(os.path.join(self._source_subfolder, "configure"), r"-install_name \$rpath/", "-install_name ")
configure_args = ['--prefix=%s' % full_install_subfolder]
configure_args = ["--prefix=%s" % full_install_subfolder]
if self._autotools.fpic:
configure_args.extend(['--with-pic'])
configure_args.extend(["--with-pic"])
if self.options.shared:
configure_args.extend(['--enable-shared', '--disable-static'])
configure_args.extend(["--enable-shared", "--disable-static"])
else:
configure_args.extend(['--enable-static', '--disable-shared'])
configure_args.extend(["--enable-static", "--disable-shared"])

for name in self._option_names:
value = getattr(self.options, name)
Expand All @@ -189,6 +227,8 @@ def _configure_autotools(self):
return self._autotools

def _patch_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
tools.patch(**patch)
# Break dependency of install on build
for makefile in ("Makefile.mingw", "Makefile.msvc"):
tools.replace_in_file(os.path.join(self._source_subfolder, "win32", makefile),
Expand All @@ -199,65 +239,86 @@ def build(self):
self._patch_sources()
if self._is_msvc:
self._build_msvc()
elif self._is_mingw:
self._build_mingw()
else:
autotools = self._configure_autotools()
autotools.make(["libxml2.la"])

if self.options.include_utils:
autotools.make(["xmllint", "xmlcatalog", "xml2-config"])
ext = ".exe" if self.settings.os == "Windows" else ""
autotools.make(["xmllint" + ext, "xmlcatalog" + ext, "xml2-config"])
Comment on lines +249 to +250
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be a function since it's duplicated here


def package(self):
# copy package license
self.copy("COPYING", src=self._source_subfolder, dst="licenses", ignore_case=True, keep_path=False)
if self._is_msvc:
self._package_msvc()
# remove redundant libraries to avoid confusion
if not self.options.shared:
os.remove(os.path.join(self.package_folder, "bin", "libxml2.dll"))
os.remove(os.path.join(self.package_folder, "lib", "libxml2_a_dll.lib"))
os.remove(os.path.join(self.package_folder, "lib", "libxml2_a.lib" if self.options.shared else "libxml2.lib"))
for pdb_file in glob.glob(os.path.join(self.package_folder, "bin", "*.pdb")):
os.remove(pdb_file)
elif self._is_mingw:
self._package_mingw()
if self.options.shared:
os.remove(os.path.join(self.package_folder, "lib", "libxml2.a"))
os.rename(os.path.join(self.package_folder, "lib", "libxml2.lib"),
os.path.join(self.package_folder, "lib", "libxml2.a"))
else:
os.remove(os.path.join(self.package_folder, "bin", "libxml2.dll"))
os.remove(os.path.join(self.package_folder, "lib", "libxml2.lib"))
else:
autotools = self._configure_autotools()
autotools.make(["install-libLTLIBRARIES", "install-data"])

if self.options.include_utils:
autotools.make(["install","xmllint", "xmlcatalog", "xml2-config"])
ext = ".exe" if self.settings.os == "Windows" else ""
autotools.make(["xmllint" + ext, "xmlcatalog" + ext, "xml2-config"])

os.unlink(os.path.join(self.package_folder, 'lib', 'libxml2.la'))
os.remove(os.path.join(self.package_folder, "lib", "libxml2.la"))
for prefix in ["run", "test"]:
for test in glob.glob(os.path.join(self.package_folder, "bin", prefix + "*")):
os.remove(test)
tools.rmdir(os.path.join(self.package_folder, "share"))
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))

for prefix in ["run", "test"]:
for test in glob.glob("%s/bin/%s*" % (self.package_folder, prefix)):
os.remove(test)
for header in ["win32config.h", "wsockcompat.h"]:
self.copy(pattern=header, src=os.path.join(self._source_subfolder, "include"),
dst=os.path.join("include", "libxml2"), keep_path=False)
if self._is_msvc:
# remove redundant libraries to avoid confusion
if not self.options.shared:
os.unlink(os.path.join(self.package_folder, "bin", "libxml2.dll"))
os.unlink(os.path.join(self.package_folder, 'lib', 'libxml2_a_dll.lib'))
os.unlink(os.path.join(self.package_folder, 'lib', 'libxml2_a.lib' if self.options.shared else 'libxml2.lib'))

pdb_files = glob.glob(os.path.join(self.package_folder, 'bin', '*.pdb'), recursive=True)
for pdb in pdb_files:
os.unlink(pdb)

tools.rmdir(os.path.join(self.package_folder, 'share'))
tools.rmdir(os.path.join(self.package_folder, 'lib', 'cmake'))
tools.rmdir(os.path.join(self.package_folder, 'lib', 'pkgconfig'))

def package_info(self):
if self._is_msvc:
self.cpp_info.libs = ['libxml2' if self.options.shared else 'libxml2_a']
self.cpp_info.libs = ["libxml2" if self.options.shared else "libxml2_a"]
else:
self.cpp_info.libs = ['xml2']
self.cpp_info.libs = ["xml2"]
self.cpp_info.includedirs.append(os.path.join("include", "libxml2"))
if not self.options.shared:
self.cpp_info.defines = ["LIBXML_STATIC"]

if self.settings.os == "Linux":
self.cpp_info.system_libs = ["m"]
if self.options.threads:
self.cpp_info.system_libs.append("pthread")
elif self.settings.os == "Windows":
if self.options.ftp or self.options.http:
self.cpp_info.system_libs.extend(["ws2_32", "wsock32"])

self.cpp_info.names["pkg_config"] = "libxml-2.0"
self.cpp_info.filenames["cmake_find_package"] = "LibXml2"
madebr marked this conversation as resolved.
Show resolved Hide resolved
self.cpp_info.filenames["cmake_find_package_multi"] = "libxml2"
self.cpp_info.names["cmake_find_package"] = "LibXml2"
self.cpp_info.names["cmake_find_package_multi"] = "LibXml2" # undefined upstream, chosen to be LibXml2 here (don't depend on this!)
self.cpp_info.names["cmake_find_package"] = "LibXml2"
self.cpp_info.names["cmake_find_package_multi"] = "LibXml2" # undefined upstream, chosen to be LibXml2 here (don't depend on this!)

# FIXME: libxml2 package itself creates libxml2-config.cmake file

if self.options.include_utils:
bindir = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(bindir))
self.env_info.PATH.append(bindir)

if self.settings.os == "Linux" or self.settings.os == "Macos":
self.cpp_info.system_libs.append('m')
if self.settings.os == "Windows":
self.cpp_info.system_libs.append('ws2_32')
self.cpp_info.names["cmake_find_package"] = "LibXml2"
self.cpp_info.names["cmake_find_package_multi"] = "LibXml2"
self.cpp_info.names["pkg_config"] = "libxml-2.0"
# FIXME: cmake creates LibXml2::xmllint imported target for the xmllint executable
56 changes: 56 additions & 0 deletions recipes/libxml2/all/patches/2.9.10-0001-fix-install-mingw.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
--- a/win32/Makefile.mingw
+++ b/win32/Makefile.mingw
@@ -35,1 +35,1 @@
-CPP = gcc.exe -E
+CPP ?= gcc.exe -E
@@ -42,1 +42,1 @@
-CC = gcc.exe
+CC ?= gcc.exe
@@ -62,1 +62,1 @@
-LD = gcc.exe
+LD = $(CC)
@@ -94,1 +94,1 @@
-AR = ar.exe
+AR ?= ar.exe
@@ -246,18 +246,17 @@ distclean : clean
rebuild : clean all

install-libs : all
- cmd.exe /C "if not exist $(INCPREFIX)\libxml2 mkdir $(INCPREFIX)\libxml2"
- cmd.exe /C "if not exist $(INCPREFIX)\libxml2\libxml mkdir $(INCPREFIX)\libxml2\libxml"
- cmd.exe /C "if not exist $(BINPREFIX) mkdir $(BINPREFIX)"
- cmd.exe /C "if not exist $(LIBPREFIX) mkdir $(LIBPREFIX)"
- cmd.exe /C "copy $(XML_SRCDIR)\include\libxml\*.h $(INCPREFIX)\libxml2\libxml"
- cmd.exe /C "copy $(BINDIR)\$(XML_SO) $(SOPREFIX)"
- cmd.exe /C "copy $(BINDIR)\$(XML_A) $(LIBPREFIX)"
- cmd.exe /C "copy $(BINDIR)\$(XML_IMP) $(LIBPREFIX)"
- cmd.exe /C "copy $(BINDIR)\xml*.exe $(BINPREFIX)"
+ cmd.exe /C if not exist $(INCPREFIX)\libxml2 mkdir $(INCPREFIX)\libxml2
+ cmd.exe /C if not exist $(INCPREFIX)\libxml2\libxml mkdir $(INCPREFIX)\libxml2\libxml
+ cmd.exe /C if not exist $(BINPREFIX) mkdir $(BINPREFIX)
+ cmd.exe /C if not exist $(LIBPREFIX) mkdir $(LIBPREFIX)
+ cmd.exe /C copy $(XML_SRCDIR)\include\libxml $(INCPREFIX)\libxml2\libxml
+ cmd.exe /C copy $(BINDIR)\$(XML_SO) $(SOPREFIX)
+ cmd.exe /C copy $(BINDIR)\$(XML_A) $(LIBPREFIX)
+ cmd.exe /C copy $(BINDIR)\$(XML_IMP) $(LIBPREFIX)
+ cmd.exe /C copy $(BINDIR)\xml*.exe $(BINPREFIX)

install : install-libs
- cmd.exe /C "copy $(BINDIR)\*.exe $(BINPREFIX)"

install-dist : install-libs
cmd.exe /C "copy $(BINDIR)\xml*.exe $(BINPREFIX)"
@@ -322,11 +322,11 @@
ifeq ($(STATIC),1)
$(BINDIR)/%.exe : $(UTILS_SRCDIR)/%.c
$(CC) -DLIBXML_STATIC $(CFLAGS) -o $(subst .c,.o,$(UTILS_INTDIR)/$(<F)) -c $<
- $(LD) $(LDFLAGS) -o $@ $(subst .c,.o,$(UTILS_INTDIR)/$(<F)) -l$(XML_BASENAME) $(LIBS)
+ $(LD) $(LDFLAGS) -o $@ $(subst .c,.o,$(UTILS_INTDIR)/$(<F)) $(BINDIR)/$(XML_A) $(LIBS)
else
$(BINDIR)/%.exe : $(UTILS_SRCDIR)/%.c
$(CC) $(CFLAGS) -o $(subst .c,.o,$(UTILS_INTDIR)/$(<F)) -c $<
- $(LD) $(LDFLAGS) -o $@ $(subst .c,.o,$(UTILS_INTDIR)/$(<F)) -l$(XML_BASENAME) $(LIBS)
+ $(LD) $(LDFLAGS) -o $@ $(subst .c,.o,$(UTILS_INTDIR)/$(<F)) $(BINDIR)/$(XML_IMP) $(LIBS)
endif

# Builds xmllint and friends. Uses the implicit rule for commands.
Loading