[Kde-bindings] Progress report on Py*5 binding generation
Shaheed Haque
srhaque at theiet.org
Thu Apr 21 23:29:26 UTC 2016
Hi Steve,
On 21 April 2016 at 23:29, Stephen Kelly <steveire at gmail.com> wrote:
> Shaheed Haque wrote:
>
> >> To that end, in addition to sip/kselectionproxymodel.sip I now have:
> >>
> >> $ cat sip/kitemmodelsmod.sip
> >>
> >> %Module PyKDE5.kitemmodels
> >>
> >> %ModuleHeaderCode
> >> #pragma GCC visibility push(default)
> >> %End
> >>
> >> %Import QtCore/QtCoremod.sip
> >>
> >> %Include kselectionproxymodel.sip
> >>
> >>
> >> Is this what I am supposed to do? Here is the output I get when
> >> attempting to use it:
> >
> > Yeeessss...it is a bit tricky...
> >
> > First, if you use the "-v" flag to the sip_compiler.py, it will show you
> > the exact command like for SIP and later the C++ compiler/linker. That
> > might help you see what is going on.
>
> Yes, that's good, thanks.
>
> > The %Feature thing you may be able to ignore. It is used along with the
> > SIP compiler's -x (lower case X) option to try to work around the problem
> > where in KF5, you often get AAAmod.sip and BBBmod.sip which need to
> import
> > each other
>
> You have alluded to this several times, but you have never stated which
> modules form a cycle like this. Which KF5 libraries have this cycle?
>
I think there are many of these. One example is this one:
sip/KIOCore/KIOCoremod.sip:%Import KIOCore/kio/kiomod.sip
sip/KIOCore/kio/kiomod.sip:%Import KIOCore/KIOCoremod.sip
This was the first one I happened on, and there are others. I have not
tried to track down the exact root cause but I guess that this does not
often show up in normal C++ development because of the effect of header
guard macros.
> > ...I used the SIP compiler's -X (upper case X) option to extract the
> > %Extract data, and generate the "-I foo -I bar" paths for the C++
> > compiler. So, you can just put a %Extract section like this into your
> > file:
> >
> > %Extract(id=includes)
> > /usr/include/KF5/KDBusAddons
> > /usr/include/x86_64-linux-gnu/qt5/QtCore
> > /usr/include/x86_64-linux-gnu/qt5/QtDBus
> > %End
>
> As the file might be generated by cmake, this might work, but it seems
> easier to pass the include directories on the command line. The includes
> will be different on each platform.
>
That is correct, but AFAIK, this is just a build time dependency. Once the
modules are built, nobody will care. However, I'm sensitive that my
ignorance about how CMake is used by packagers might make the current
approach suboptimal.
> After hacking the sip_compiler a bit I can do this:
>
> ./sip_compiler.py -v --includes "/usr/include/x86_64-linux-
> gnu/qt5,/usr/include/x86_64-linux-gnu/qt5/QtCore" --select
> @kitemmodelsmod.sip sip cxx
>
>
> My hacking is quite dirty, but you can extract feature requests from it,
> namely, don't require the include/extract stuff.
>
For me, and for now at least, it is important to be able to run on a large
body of code without generating anything by hand so generating xxxmod.sip
files by hand (with or without the %Extract) is not practical. Perhaps a
CLI option would be acceptable?
> The makefile manipulation stuff can be ignored, because the SIP generated
> makefiles won't play nicely with cmake, but should be easily able to
> generate our own makefiles/ninja build files.
>
OK. Once we get there, then maybe some of the stuff above might be worth
reconsidering too.
> diff --git a/sip_generation/sip_compiler.py
> b/sip_generation/sip_compiler.py
> index 057dfe9..715f9c4 100755
> --- a/sip_generation/sip_compiler.py
> +++ b/sip_generation/sip_compiler.py
> @@ -133,20 +133,23 @@ class CxxDriver(object):
> if line.startswith("%Module"):
> feature_list = os.path.join(self.input_dir,
> "modules.features")
> tmp = set()
> - with open(feature_list, "rU") as f:
> - for feature in f:
> - if feature not in tmp:
> - tmp.add(feature)
> - o.write(feature)
> + # with open(feature_list, "rU") as f:
> + # for feature in f:
> + # if feature not in tmp:
> + # tmp.add(feature)
> + # o.write(feature)
> logger.debug(modified_source)
> feature = sip_file.replace(os.path.sep, "_").replace(".", "_")
> - cmd = [self.sipconfig.sip_bin, "-c", full_output, "-b",
> build_file, "-x", feature, "-X",
> - INCLUDES_EXTRACT + ":" + module_includes] +
> self.pyqt_sip_flags + sip_roots + [modified_source]
> + cmd = [self.sipconfig.sip_bin, "-c", full_output, "-b",
> build_file, "-x", feature] + self.pyqt_sip_flags + sip_roots +
> [modified_source]
> self._run_command(cmd)
> #
> # Create the Makefile.
> #
> - module_includes = self.includes + open(module_includes,
> "rU").read().split("\n")
> + module_includes = self.includes
> + try:
> + module_includes += open(module_includes,
> "rU").read().split("\n")
> + except:
> + pass
> self.sipconfig._macros["INCDIR"] = " ".join(module_includes)
> makefile = sipconfig.SIPModuleMakefile(self.sipconfig,
> build_file, makefile=make_file)
> #
> @@ -155,6 +158,9 @@ class CxxDriver(object):
> # ".dll" extension on Windows).
> #makefile.extra_libs = ["KParts"]
> #
> + makefile.extra_cxxflags = ["-std=c++14"]
> + makefile.extra_lflags = ["-std=c++14", "-Wl,--fatal-warnings",
> "-Wl,--no-undefined"]
> + makefile.extra_libs = ["m /usr/lib/x86_64-linux-
> gnu/libQt5Core.so /usr/lib/x86_64-linux-gnu/libKF5ItemModels.so
> /usr/lib/x86_64-linux-gnu/libpython2.7.so"]
> makefile.generate()
> self._run_command(["make", "-f", os.path.basename(make_file)],
> cwd=full_output)
> except Exception as e
>
>
> With that done here is my output:
>
> $ ./sip_compiler.py -v --includes "/usr/include/x86_64-linux-
> gnu/qt5,/usr/include/x86_64-linux-gnu/qt5/QtCore" --select
> @kitemmodelsmod.sip sip cxx
> 2016-04-22 00:23:01,282 __main__ INFO: Creating cxx/
> 2016-04-22 00:23:01,283 __main__ DEBUG: cxx/kitemmodelsmod.sip.tmp
> 2016-04-22 00:23:01,283 __main__ INFO: /usr/bin/sip -c cxx/ -b
> cxx/module.sbf -x kitemmodelsmod_sip -x VendorID -t WS_X11 -t Qt_5_4_2 -x
> Py_v3 -I/usr/share/sip/PyQt5 -Isip cxx/kitemmodelsmod.sip.tmp
> 2016-04-22 00:23:01,728 __main__ INFO: make -f module.Makefile
> g++ -c -std=c++14 -g -O2 -fstack-protector-strong -Wformat -Werror=format-
> security -D_FORTIFY_SOURCE=2 -fPIC -Wall -W -DNDEBUG -I. -
> I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-
> gnu/qt5/QtCore -I/usr/include/python2.7 -o sipkitemmodelscmodule.o
> sipkitemmodelscmodule.cpp
> g++ -c -std=c++14 -g -O2 -fstack-protector-strong -Wformat -Werror=format-
> security -D_FORTIFY_SOURCE=2 -fPIC -Wall -W -DNDEBUG -I. -
> I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-
> gnu/qt5/QtCore -I/usr/include/python2.7 -o
> sipkitemmodelsKSelectionProxyModel.o sipkitemmodelsKSelectionProxyModel.cpp
> g++ -std=c++14 -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-Bsymbolic-
> functions -Wl,-z,relro -shared -Wl,--version-script=kitemmodels.exp -o
> kitemmodels.so sipkitemmodelscmodule.o sipkitemmodelsKSelectionProxyModel.o
> -lm /usr/lib/x86_64-linux-gnu/libQt5Core.so /usr/lib/x86_64-linux-
> gnu/libKF5ItemModels.so /usr/lib/x86_64-linux-gnu/libpython2.7.so
>
> That created the cxx/kitemmodels.so library
>
> $ ls cxx/
> kitemmodels.exp sipAPIkitemmodels.h
> kitemmodelsmod.sip.tmp sipkitemmodelscmodule.cpp
> kitemmodels.so* sipkitemmodelscmodule.o
> module.Makefile sipkitemmodelsKSelectionProxyModel.cpp
> module.sbf sipkitemmodelsKSelectionProxyModel.o
> pythontest.py*
>
> $ cat cxx/pythontest.py
> #!/usr/bin/env python
>
> from PyQt5 import QtCore
>
> import kitemmodels
>
> $ ./cxx/pythontest.py
> Traceback (most recent call last):
> File "./cxx/pythontest.py", line 5, in <module>
> import kitemmodels
> SystemError: dynamic module not initialized properly
>
>
> Is there some other step to take before that import will work?
>
Only to pick up the code I pushed earlier tonight [1]. This brings a slight
change the in the CLI for the sip_compiler.py. The second argument ("cxx"
above) is now optional and defaulted from the project rules "project_name".
For KF5, the latter is PyKF5, and the net effect of the changes is that you
get the following by default:
- a directory PyKF5
- containing a __init__.py
- and all the .so files such as KItemModels.so
- and a disposable tmp directory
so that you can then just say "from PyKF5 import KItemModels". You'll
notice that in support of this, there is a temporary list of hardcoded
libraries to link against (a quick hack just to get us going).
Thanks, Shaheed
[1] See
https://www.riverbankcomputing.com/pipermail/pyqt/2016-April/037331.html
for the details.
> Thanks,
>
> Steve.
> _______________________________________________
> Kde-bindings mailing list
> Kde-bindings at kde.org
> https://mail.kde.org/mailman/listinfo/kde-bindings
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kde-bindings/attachments/20160422/15a962e4/attachment-0001.html>
More information about the Kde-bindings
mailing list