1 import getopt
, string
, posixpath
, sys
, os
, os
.path
, re
3 # Some global globals...
5 thisProg
= posixpath
.basename(sys
.argv
[0])
6 if not thisProg
: # happy only when running in xemacs ;/
7 thisProg
= 'am_edit.py'
8 cppsuffixes
= ['cpp', 'cc', 'cxx', 'C', 'c++']
9 hExt
= ['h', 'H', 'hh', 'hxx', 'h++']
10 progId
= "KDE tags expanded automatically by " + thisProg
14 topdir
= os
.path
.abspath(os
.curdir
) + "/"
18 def __init__(self
, file):
19 # some useful globals for the subroutines called here
20 self
.headerdirs
= ['.']
21 self
.haveAutomocTag
= 0
25 # lists the objects compiled into $program
27 # lists the sources used for $program
29 # lists the objects compiled when final
31 # the binary name of program variable
33 # lists the idl files used for $program
35 # lists all idl generated files for cleantarget
46 self
.makefileDir
= os
.path
.dirname(self
.makefile
)
50 NoMakefileAmFound
= "found Makefile.in without Makefile.am"
52 def findLine(self
, line
):
54 if type(line
) is types
.StringType
:
55 regexp
= re
.compile(line
)
58 for line
in self
.lines
:
59 match
= regexp
.match(line
)
63 def substituteLine(self
, old
, new
):
65 if type(old
) is types
.StringType
:
66 regexp
= re
.compile(old
)
70 for index
in range(len(self
.lines
)):
71 line
= self
.lines
[index
]
72 match
= regexp
.match(line
)
75 newlines
= string
.split(new
, '\n')
76 self
.lines
[index
:index
+1] = [line
, '#>+ %d' % len(newlines
)] + newlines
79 def addTarget(self
, target
, dependson
):
80 if not self
.target_adds
.has_key(target
):
81 self
.target_adds
[target
] = [dependson
]
83 self
.target_adds
[target
].append(dependson
)
85 def appendLines(self
, newlines
):
86 lines
= string
.split(newlines
, '\n') + ['\n']
87 self
.lines
.extend(['#>+ %d' % len(lines
)] + lines
)
91 while index
< len(self
.lines
):
92 line
= self
.lines
[index
]
93 if line
[0:3] == '#>+':
94 # the +1 is the comment itself
95 linec
= string
.atoi(line
[3:]) + 1
96 del self
.lines
[index
:index
+linec
]
98 if line
[0:3] == '#>-':
99 self
.lines
[index
] = self
.lines
[index
][4:]
102 def initialize(self
):
105 os
.chdir(self
.makefileDir
)
106 self
.printname
= string
.replace(self
.makefile
, topdir
, "")
107 self
.makefile
= os
.path
.basename(self
.makefile
)
109 if not posixpath
.exists("Makefile.am"):
110 raise self
.NoMakefileAmFound
, self
.makefileDir
112 for dir in foreigndirs
:
113 if dir.match(self
.makefileDir
):
114 print 'leaving ' + self
.makefileDir
117 f
= open(self
.makefile
)
123 self
.lines
.append(string
.rstrip(line
))
130 optionline
= re
.compile('^\s*(\w+)\s*=\s*([^\n]*)$')
131 linecontinued
= re
.compile('\\\s*\n')
135 while index
< len(self
.lines
):
136 line
= self
.lines
[index
]
137 if linecontinued
.search(line
):
138 self
.lines
[index
] = linecontinued
.sub(' ', line
) + self
.lines
[index
+1]
143 match
= optionline
.search(line
)
145 self
.options
[match
.group(1)] = match
.group(2)
147 if self
.options
.has_key('KDE_OPTIONS'):
148 options
= string
.split(self
.options
['KDE_OPTIONS'])
149 if 'foreign' in options
:
150 foreigndirs
.append(re
.compile(self
.makefileDir
+ "/.*"))
154 suffixes
= re
.compile('^\.SUFFIXES:(.*)$')
156 for line
in self
.lines
:
157 match
= suffixes
.match(line
)
159 existing_suffixes
= string
.split(match
.group(1))
160 for suffix
in existing_suffixes
:
162 if suffix
[1:] in cppsuffixes
:
163 self
.cxxsuffix
= suffix
[1:]
168 search_real_programs
= {}
170 for option
in self
.options
.keys():
171 if string
.rfind(option
, '_OBJECTS') > 0:
173 program
= option
[0:string
.find(option
, '_OBJECTS')]
174 objs
= self
.options
[option
]
176 variable_in_objects
= 0
178 objlist
= string
.split(objs
)
179 variable
= re
.compile('\$\((\w+)\)')
181 match
= variable
.match(obj
)
182 if match
and not match
.group(1) == 'OBJEXT':
183 variable_in_objects
= 1
186 if variable_in_objects
:
189 if len(program
) > 3 and program
[3] == 'am_':
190 program
= program
[3:]
193 print "found program " + program
195 self
.programs
.append(program
)
196 self
.realobjs
[program
] = objs
198 if self
.options
.has_key(program
+ "_SOURCES"):
199 self
.sources
[program
] = self
.options
[program
+ "_SOURCES"]
201 self
.sources
[program
] = ""
202 sys
.stderr
.write("found program with no _SOURCES: " + program
+ '\n')
205 realprogram
= string
.replace(program
, '_', '.')
206 search_real_programs
[program
] = re
.compile('.*(' + realprogram
+
207 ')(\$\(EXEEXT\)?)?:.*\$\(' +
208 program
+ '_OBJECTS\).*')
210 self
.realname
[program
] = "";
212 for line
in self
.lines
:
213 if string
.find(line
, '_OBJECTS') > 0: # just a random piece to not use at _every_ line
214 for program
in self
.programs
:
215 match
= search_real_programs
[program
].match(line
)
217 self
.realname
[program
] = match
.group(1)
219 def finalTouch(self
):
220 if self
.options
.has_key('DEPDIR'):
221 sys
.stderr
.write(self
.printname
+ " defines DEPDIR. This means you're using automake > 1.4 - this is not supported!")
223 # taken out a random variable
224 self
.substituteLine('bindir\s*=.*', 'DEPDIR = .deps\nbindir = ' + self
.options
['bindir'])
226 self
.appendLines('cvs-clean:\n' +
227 '\t$(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean')
229 self
.appendLines('kde-rpo-clean:\n'+
232 self
.addTarget('clean', 'kde-rpo-clean')
235 def addAllTargets(self
):
236 for target
in self
.target_adds
.keys():
237 match
= self
.findLine(target
+ ':\s*(.*)')
239 self
.substituteLine(match
.re
, target
+ ': ' +
240 string
.join(self
.target_adds
[target
]) +
241 ' ' + match
.group(1))
244 f
= open(self
.makefile
, 'w')
245 for line
in self
.lines
:
250 def tag_automake(self
):
251 match
= self
.findLine('^(.*cd \$\(top_srcdir\)\s+&&\s+\$\(AUTOMAKE\).*)$')
252 if not match
: return 1
253 self
.substituteLine(match
.re
, match
.group(1) + '\n' +
254 '\tcd $(top_srcdir) && python ' +
255 thisProg
+ ' ' + self
.printname
)
258 global use_final
, dryrun
, pathoption
, thisProg
, verbose
260 optlist
, makefiles
= getopt
.getopt(sys
.argv
[1:], 'vhp:n', [
261 'version', 'verbose', 'path=', 'help', 'no-final'])
263 for option
, param
in optlist
:
264 if option
== '--version':
266 print thisProg
+ "$Revision$"
267 print "This is really free software, unencumbered by the GPL."
268 print "You can do anything you like with it except sueing me."
269 print "Copyright 1998 Kalle Dalheimer <kalle\@kde.org>"
270 print "Concept, design and unnecessary questions about perl"
271 print " by Matthias Ettrich <ettrich\@kde.org>"
273 print "Making it useful by Stephan Kulow <coolo\@kde.org> and"
274 print "Harri Porten <porten\@kde.org>"
275 print "Updated (Feb-1999), John Birch <jb.nz\@writeme.com>"
276 print "Current Maintainer Stephan Kulow"
278 if option
== '--verbose' or option
== '-v':
280 if option
== '-p' or option
== '--path':
281 thisProg
= param
+ "/" + thisProg
282 if (not posixpath
.exists(thisProg
)):
283 sys
.stderr
.write(thisProg
+ " doesn't exist\n")
285 if option
== '--help' or option
== '-h':
286 print "Usage " + thisProg
+ " [OPTION] ... [dir/Makefile.in]..."
287 print "Patches dir/Makefile.in generated from automake"
288 print "(where dir can be a full or relative directory name)"
289 print " -v, --verbose verbosely list files processed"
290 print " -h, --help print this help, then exit"
291 print " --version print version number, then exit"
292 print " -p, --path= use the path to am_edit if the path"
293 print " --no-final don't patch for --enable-final"
294 print " called from is not the one to be used"
296 if option
== '--no-final':
302 thisProg
= thisProg
+ " --no-final"
304 if thisProg
[0] == '/' and not pathoption
:
305 sys
.stderr
.write( "Illegal full pathname call performed...\n"
306 "The call to \"" + thisProg
+ "\"\n"
307 "would be inserted in some Makefile.in.\n"
308 "Please use option --path.\n")
311 if len(makefiles
) == 0:
313 makefiles
= find
.find('Makefile.in')
315 for index
in range(len(makefiles
)):
316 if not makefiles
[index
][0] == '/':
317 makefiles
[index
] = os
.path
.normcase(os
.path
.abspath(makefiles
[index
]))
320 for file in makefiles
:
321 makefile
= Makefile(file)
323 makefile
.initialize()
324 makefile
.tag_automake()
325 makefile
.finalTouch()
327 except Makefile
.NoMakefileAmFound
, param
:
328 if verbose
: print Makefile
.NoMakefileAmFound
+ ' in ' + param