[PyKDE] How to contribute to sip ?
Gerard Vermeulen
gerard.vermeulen at grenoble.cnrs.fr
Tue Feb 28 16:39:07 GMT 2006
On Tue, 28 Feb 2006 10:18:31 -0600
Nigel Stewart <ns at fluent.com> wrote:
>
> >> It could be argued that SIP is part of a broader toolchain
> >
> > What does this have to do with SIP again? I don't remember GCC not
> > generating the object files if the source code is not changed.
>
> A compiler takes one input file and creates one output file.
>
> The granularity of SIP is different, it's taking multiple
> inputs (via %Import) and creating multiple outputs. This
> design poses a "choke point". I think being time-stamp
> friendly is a way for SIP to compensate for this.
>
> > So, why can't you configure your build system so that it doesn't call SIP in
> > the first place if the header file has not changed?
>
> Here is the scenario - the header foo.h is changed, triggering
> SIP to regenerate the bindings. In most cases, the change to
> foo.h doesn't affect the code that SIP outputs. Of the 250
> .cpp files generated by SIP, 10 depend on foo.h. However,
> all 250 are rebuilt due to SIP changing the time stamp.
>
> That's a 25x slowdown that provides me more time to surf the
> PyKDE mailing list... :-)
>
> Perhaps our situation is not typical, it doesn't affect our
> developers that _depend_ on our SIP bindings. But it certainly
> affects development _upstream_ of the SIP bindings.
>
> Imagine someone hacking away at Qt and depending on PyQt
> based regression tests to know if they've broken anything...
> That's my day-to-day situation in a nutshell...
>
My configure.py scripts put the the output of sip in a temporary
directory and they use the following function to copy the new files
to the build directory:
def lazy_copy_file(source, target):
'''Lazy copy a file to another file:
- check for a SIP time stamp to skip,
- check if source and target do really differ,
- copy the source file to the target if they do,
- return True on copy and False on no copy.
'''
if not os.path.exists(target):
shutil.copy2(source, target)
return True
sourcelines = open(source).readlines()
targetlines = open(target).readlines()
# global length check
if len(sourcelines) != len(targetlines):
shutil.copy2(source, target)
return True
# skip a SIP time stamp
if (len(sourcelines) > 3
and sourcelines[3].startswith(' * Generated by SIP')
):
line = 4
else:
line = 0
# line by line check
while line < len(sourcelines):
if sourcelines[line] != targetlines[line]:
shutil.copy2(source, target)
return True
line = line + 1
return False
# lazy_copy_file()
The function is invoked by code like this:
lazy_copies = 0
for pattern in ('*.c', '*.cpp', '*.h', '*.sbf'):
for source in glob.glob(os.path.join(tmp_dir, pattern)):
target = os.path.join(build_dir, os.path.basename(source))
if lazy_copy_file(source, target):
print "Copy %s -> %s." % (source, target)
lazy_copies += 1
print "%s file(s) lazily copied." % lazy_copies
If you are using g++, you should look into ccache.samba.org.
This gives additional speed-ups of about a factor 10.
Gerard
More information about the PyQt
mailing list