Ver Fonte

support libxml2 python interface (#652)

* support libxml2 python interface

* upload patch file

* fix libxml2 without iconv

* use package:is_plat

* remove unused PYTHONPATH
Hoildkv há 3 anos atrás
pai
commit
86edd27446

+ 5 - 8
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("\\", "\\\\") .. "\"")

+ 79 - 0
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 <stdio.h>
++#ifdef _WIN32
++#include <io.h>
++#else
+ #include <unistd.h>
+ #include <fcntl.h>
++#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) {

+ 85 - 13
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)