[Kde-bindings] Progress report on Py*5 binding generation

Stephen Kelly steveire at gmail.com
Thu Apr 21 22:29:24 UTC 2016


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 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.

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.

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.


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?

Thanks,

Steve.


More information about the Kde-bindings mailing list