From 86edd27446916ad2c748a4ef6e8fa1132fead554 Mon Sep 17 00:00:00 2001 From: Hoildkv <42310255+xq114@users.noreply.github.com> Date: Fri, 8 Oct 2021 22:39:37 +0800 Subject: [PATCH] support libxml2 python interface (#652) * support libxml2 python interface * upload patch file * fix libxml2 without iconv * use package:is_plat * remove unused PYTHONPATH --- packages/l/libiconv/port/xmake.lua | 13 +-- packages/l/libxml2/patches/2.9.12/msvc.patch | 79 ++++++++++++++++ packages/l/libxml2/xmake.lua | 98 +++++++++++++++++--- 3 files changed, 169 insertions(+), 21 deletions(-) create mode 100644 packages/l/libxml2/patches/2.9.12/msvc.patch diff --git a/packages/l/libiconv/port/xmake.lua b/packages/l/libiconv/port/xmake.lua index 03742f053..94881983c 100644 --- a/packages/l/libiconv/port/xmake.lua +++ b/packages/l/libiconv/port/xmake.lua @@ -198,8 +198,7 @@ int test() { char* cs = nl_langinfo(CODESET); return !cs; }]]) configvar_check_csnippets("HAVE_ENVIRON_DECL=0", [[extern struct {int foo;} environ; void test() {environ.foo = 1;}]], {includes = has_config("__HAVE_UNISTD_H") and "unistd.h" or "stdlib.h", default = 1}) -target("libcharset") - set_prefixname("") +target("charset") set_kind("$(kind)") add_defines("HAVE_CONFIG_H") if is_kind("shared") then @@ -217,10 +216,9 @@ target("libcharset") end) target_end() -target("libiconv") - set_prefixname("") +target("iconv") set_kind("$(kind)") - add_deps("libcharset", {inherit = false}) + add_deps("charset", {inherit = false}) add_defines("HAVE_CONFIG_H", "NO_XMALLOC", "IN_LIBRARY") if is_kind("shared") then add_defines("BUILDING_LIBICONV", "BUILDING_DLL") @@ -241,8 +239,7 @@ target("libiconv") end) target_end() -target("libicrt") - set_prefixname("") +target("icrt") set_kind("static") add_includedirs(".", "srclib", {public = true}) set_configdir(".") @@ -257,7 +254,7 @@ target("libicrt") target("iconv_no_i18n") set_kind("binary") - add_deps("libiconv", "libicrt") + add_deps("iconv", "icrt") if has_config("installprefix") then add_defines("INSTALLDIR=\"" .. path.join(get_config("installprefix"), "bin"):gsub("\\", "\\\\") .. "\"") add_defines("LOCALEDIR=\"" .. path.join(get_config("installprefix"), "share", "locale"):gsub("\\", "\\\\") .. "\"") diff --git a/packages/l/libxml2/patches/2.9.12/msvc.patch b/packages/l/libxml2/patches/2.9.12/msvc.patch new file mode 100644 index 000000000..f663469ed --- /dev/null +++ b/packages/l/libxml2/patches/2.9.12/msvc.patch @@ -0,0 +1,79 @@ +diff --git a/python/types.c b/python/types.c +--- a/python/types.c ++++ b/python/types.c +@@ -21,16 +21,66 @@ + + #if PY_MAJOR_VERSION >= 3 + #include ++#ifdef _WIN32 ++#include ++#else + #include + #include ++#endif + + FILE * + libxml_PyFileGet(PyObject *f) { +- int fd, flags; ++ int fd; + FILE *res; + const char *mode; + + fd = PyObject_AsFileDescriptor(f); ++#ifdef _WIN32 ++ PyObject *modeObj, *modeBytes; ++ ++ modeObj = PyObject_GetAttrString(f, "mode"); ++ if (!modeObj) ++ return(NULL); ++ ++ /* using f.mode to replace posix fcntl(), see ++ * https://gist.github.com/novocaine/09d5c00e67fd0aa13cfc */ ++ if (PyUnicode_Check(modeObj)) { ++ modeBytes = PyObject_CallMethod( ++ modeObj, "encode", "ascii", "namereplace"); ++ if (!modeBytes) { ++ Py_DECREF(modeObj); ++ return(NULL); ++ } ++ mode = PyBytes_AsString(modeBytes); ++ if (!mode) { ++ Py_DECREF(modeObj); ++ return(NULL); ++ } ++ Py_DECREF(modeBytes); ++ } else if (PyBytes_Check(modeObj)) { ++ mode = PyBytes_AsString(modeObj); ++ if (!mode) { ++ Py_DECREF(modeObj); ++ return(NULL); ++ } ++ } else { ++ Py_DECREF(modeObj); ++ return(NULL); ++ } ++ ++ Py_DECREF(modeObj); ++ ++ fd = _dup(fd); ++ if (fd == -1) ++ return(NULL); ++ res = _fdopen(fd, mode); ++ if (!res) { ++ _close(fd); ++ return(NULL); ++ } ++ return(res); ++#else ++ int flags; + /* + * Get the flags on the fd to understand how it was opened + */ +@@ -76,6 +126,7 @@ libxml_PyFileGet(PyObject *f) { + return(NULL); + } + return(res); ++#endif + } + + void libxml_PyFileRelease(FILE *f) { diff --git a/packages/l/libxml2/xmake.lua b/packages/l/libxml2/xmake.lua index 120a43d4e..effed6079 100644 --- a/packages/l/libxml2/xmake.lua +++ b/packages/l/libxml2/xmake.lua @@ -11,6 +11,11 @@ package("libxml2") add_versions("2.9.10", "aafee193ffb8fe0c82d4afef6ef91972cbaf5feea100edc2f262750611b4be1f") add_versions("2.9.12", "c8d6681e38c56f172892c85ddc0852e1fd4b53b4209e7f4ebf17f7e2eae71d92") + add_patches("2.9.12", path.join(os.scriptdir(), "patches", "2.9.12", "msvc.patch"), "b978048ad1caf9c63e3b2eee685ea2e586812d80deb1e47b18ad2cae36edd201") + + add_configs("iconv", {description = "Enable libiconv support.", default = false, type = "boolean"}) + add_configs("python", {description = "Enable the python interface.", default = false, type = "boolean"}) + add_includedirs("include/libxml2") if is_plat("windows") then add_syslinks("wsock32", "ws2_32") @@ -22,22 +27,46 @@ package("libxml2") add_syslinks("m") end - on_load("windows", function (package) - if not package:config("shared") then - package:add("defines", "LIBXML_STATIC") + on_load("windows", "macosx", "linux", "iphoneos", "android", function (package) + if package:is_plat("windows") then + if not package:config("shared") then + package:add("defines", "LIBXML_STATIC") + end + else + if package:gitref() then + package:add("deps", "autoconf", "automake", "libtool", "pkg-config") + end end - end) - - on_load("macosx", "linux", "iphoneos", "android", function (package) - if package:gitref() then - package:add("deps", "autoconf", "automake", "libtool", "pkg-config") + if package:config("python") then + if not package:is_plat(os.host()) then + raise("libxml2 python interface does not support cross-compilation") + end + if not package:config("iconv") then + raise("libxml2 python interface requires iconv to be enabled") + end + package:add("deps", "python 3.x", {private = true}) + end + if package:config("iconv") then + package:add("deps", "libiconv") end end) on_install("windows", function (package) os.cd("win32") - os.vrun("cscript configure.js iso8859x=yes iconv=no compiler=msvc cruntime=/%s debug=%s prefix=\"%s\"", package:config("vs_runtime"), package:debug() and "yes" or "no", package:installdir()) + local args = {"configure.js", "iso8859x=yes", "zlib=no", "compiler=msvc"} + table.insert(args, "cruntime=/" .. package:config("vs_runtime")) + table.insert(args, "debug=" .. (package:debug() and "yes" or "no")) + table.insert(args, "iconv=" .. (package:config("iconv") and "yes" or "no")) + table.insert(args, "python=" .. (package:config("python") and "yes" or "no")) + table.insert(args, "prefix=" .. package:installdir()) + if package:config("iconv") then + table.insert(args, "include=" .. package:dep("libiconv"):installdir("include")) + table.insert(args, "lib=" .. package:dep("libiconv"):installdir("lib")) + end + os.vrunv("cscript", args) import("package.tools.nmake").install(package, {"/f", "Makefile.msvc"}) + os.tryrm(path.join(package:installdir("bin"), "run*.exe")) + os.tryrm(path.join(package:installdir("bin"), "test*.exe")) os.tryrm(path.join(package:installdir("lib"), "libxml2_a_dll.lib")) if package:config("shared") then os.tryrm(path.join(package:installdir("lib"), "libxml2_a.lib")) @@ -45,15 +74,28 @@ package("libxml2") os.tryrm(path.join(package:installdir("lib"), "libxml2.lib")) os.tryrm(path.join(package:installdir("bin"), "libxml2.dll")) end + package:addenv("PATH", package:installdir("bin")) + if package:config("python") then + os.cd("../python") + io.replace("setup.py", "/opt/include", package:dep("libiconv"):installdir("include"):gsub("\\", "\\\\"), {plain = true}) + io.replace("setup.py", "WITHDLLS = 1", "WITHDLLS = 0", {plain = true}) + if not package:config("shared") then + io.replace("setup.py", "libdirs = [", format("libdirs = [\n'%s',", package:dep("libiconv"):installdir("lib"):gsub("\\", "\\\\")), {plain = true}) + io.replace("setup.py", "platformLibs = []", "platformLibs = ['iconv','wsock32','ws2_32']", {plain = true}) + io.replace("setup.py", "\"xml2\"", "\"xml2_a\"", {plain = true}) + io.replace("setup.py", "macros = []", "macros = [('LIBXML_STATIC','1')]", {plain = true}) + else + os.cp(path.join(package:installdir("bin"), "libxml2.dll"), path.join(package:installdir("lib"), "site-packages", "libxml2.dll")) + end + os.vrun("python setup.py install --prefix=\"" .. package:installdir() .. "\"") + package:addenv("PYTHONPATH", path.join(package:installdir("lib"), "site-packages")) + end end) on_install("macosx", "linux", "iphoneos", "android", function (package) local configs = {"--disable-dependency-tracking", - "--with-pic", - "--without-python", "--without-lzma", - "--without-zlib", - "--without-iconv"} + "--without-zlib"} if package:config("shared") then table.insert(configs, "--enable-shared=yes") table.insert(configs, "--enable-static=no") @@ -61,9 +103,39 @@ package("libxml2") table.insert(configs, "--enable-shared=no") table.insert(configs, "--enable-static=yes") end + if package:config("iconv") then + table.insert(configs, "--with-iconv=" .. package:dep("libiconv"):installdir()) + else + table.insert(configs, "--without-iconv") + end + if package:config("python") then + table.insert(configs, "--with-python") + else + table.insert(configs, "--without-python") + end + if package:config("pic") ~= false then + table.insert(configs, "--with-pic") + end import("package.tools.autoconf").install(package, configs) + package:addenv("PATH", package:installdir("bin")) + if package:config("python") then + os.cd("python") + io.replace("setup.py", "\"/usr/include\",\n\"/usr/local/include\",\n\"/opt/include\",", "\"" .. package:dep("libiconv"):installdir("include") .. "\",", {plain = true}) + if not package:config("shared") then + io.replace("setup.py", "libdirs = [", format("libdirs = [\n'%s',", package:dep("libiconv"):installdir("lib")), {plain = true}) + io.replace("setup.py", "platformLibs = [\"m\",\"z\"]", "platformLibs = [\"iconv\",\"m\"]", {plain = true}) + else + io.replace("setup.py", "platformLibs = [\"m\",\"z\"]", "platformLibs = [\"m\"]", {plain = true}) + end + os.vrun("python setup.py install --prefix=\"" .. package:installdir() .. "\"") + local pythonver = package:dep("python"):version() + package:addenv("PYTHONPATH", path.join(package:installdir("lib"), format("python%s.%s", pythonver:major(), pythonver:minor()), "site-packages")) + end end) on_test(function (package) + if package:config("python") then + os.vrun("python3 -c \"import libxml2\"") + end assert(package:has_cfuncs("xmlNewNode", {includes = {"libxml/parser.h", "libxml/tree.h"}})) end)