#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006 (ita) "LaTeX/PDFLaTeX support" import os, re import Utils, Params, Action, Object, Runner, Scan from Params import error, warning, debug, fatal tex_regexp = re.compile('^\\\\include{(.*)}', re.M) #tex_regexp = re.compile('^[^%]*\\\\bringin{(.*)}', re.M) class tex_scanner(Scan.scanner): def __init__(self): Scan.scanner.__init__(self) def scan(self, node, env, curdirnode): variant = node.variant(env) fi = open(node.abspath(env), 'r') content = fi.read() fi.close() found = tex_regexp.findall(content) nodes = [] names = [] if not node: return (nodes, names) abs = curdirnode.abspath() for path in found: #print 'boo', name filepath = os.path.join(abs, path) ok = 0 try: os.stat(filepath) ok = filepath except: pass if not ok: for k in ['.tex', '.ltx']: try: debug("trying %s%s" % (filepath, k), 'tex') os.stat(filepath+k) ok = filepath+k path = path+k except: pass if ok: node = curdirnode.find_source(path) nodes.append(node) else: print 'could not find', filepath names.append(path) debug("found the following : %s and names %s" % (nodes, names), 'tex') return (nodes, names) g_tex_scanner = tex_scanner() g_bibtex_re = re.compile('bibdata', re.M) def tex_build(task, command='LATEX'): env = task.m_env if env['PROMPT_LATEX']: exec_cmd = Runner.exec_command_interact com = '%s %s' % (env[command], env.get_flat(command+'FLAGS')) else: exec_cmd = Runner.exec_command com = '%s %s %s' % (env[command], env.get_flat(command+'FLAGS'), '-interaction=batchmode') node = task.m_inputs[0] reldir = node.bld_dir(env) srcfile = node.srcpath(env) lst = [] for c in Utils.split_path(reldir): if c: lst.append('..') sr = Utils.join_path_list(lst + [srcfile]) sr2 = Utils.join_path_list(lst + [node.m_parent.srcpath(env)]) aux_node = node.change_ext('.aux') idx_node = node.change_ext('.idx') hash = '' old_hash = '' nm = aux_node.m_name docuname = nm[ : len(nm) - 4 ] # 4 is the size of ".aux" latex_compile_cmd = 'cd %s && TEXINPUTS=%s:$TEXINPUTS %s %s' % (reldir, sr2, com, sr) warning('first pass on %s' % command) ret = exec_cmd(latex_compile_cmd) if ret: return ret # look in the .aux file if there is a bibfile to process try: file = open(aux_node.abspath(env), 'r') ct = file.read() file.close() #print '---------------------------', ct, '---------------------------' fo = g_bibtex_re.findall(ct) # yes, there is a .aux file to process if fo: bibtex_compile_cmd = 'cd %s && BIBINPUTS=%s:$BIBINPUTS %s %s' % (reldir, sr2, env['BIBTEX'], docuname) warning('calling bibtex') ret = exec_cmd(bibtex_compile_cmd) if ret: error('error when calling bibtex %s' % bibtex_compile_cmd) return ret except: error('erreur bibtex scan') pass # look on the filesystem if there is a .idx file to process try: idx_path = idx_node.abspath(env) os.stat(idx_path) makeindex_compile_cmd = 'cd %s && %s %s' % (reldir, env['MAKEINDEX'], idx_path) warning('calling makeindex') ret = exec_cmd(makeindex_compile_cmd) if ret: error('error when calling makeindex %s' % makeindex_compile_cmd) return ret except: error('erreur file.idx scan') pass i = 0 while i < 10: # prevent against infinite loops - one never knows i += 1 # watch the contents of file.aux old_hash = hash try: hash = Params.h_md5_file(aux_node.abspath(env)) except: error('could not read aux.h -> %s' % aux_node.abspath(env)) pass # debug #print "hash is, ", hash, " ", old_hash # stop if file.aux does not change anymore if hash and hash == old_hash: break # run the command warning('calling %s' % command) ret = exec_cmd(latex_compile_cmd) if ret: error('error when calling %s %s' % (command, latex_compile_cmd)) return ret # 0 means no error return 0 latex_vardeps = ['LATEX', 'LATEXFLAGS'] def latex_build(task): return tex_build(task, 'LATEX') pdflatex_vardeps = ['PDFLATEX', 'PDFLATEXFLAGS'] def pdflatex_build(task): return tex_build(task, 'PDFLATEX') g_texobjs = ['latex','pdflatex'] class texobj(Object.genobj): s_default_ext = ['.tex', '.ltx'] def __init__(self, type='latex'): Object.genobj.__init__(self, 'other') global g_texobjs if not type in g_texobjs: Params.niceprint('type %s not supported for texobj' % type, 'ERROR', 'texobj') import sys sys.exit(1) self.m_type = type self.outs = '' # example: "ps pdf" self.prompt = 1 # prompt for incomplete files (else the batchmode is used) self.deps = '' def apply(self): tree = Params.g_build outs = self.outs.split() self.env['PROMPT_LATEX'] = self.prompt deps_lst = [] if self.deps: deps = self.to_list(self.deps) for filename in deps: n = self.path.find_source(filename) if not n in deps_lst: deps_lst.append(n) for filename in self.source.split(): base, ext = os.path.splitext(filename) if not ext in self.s_default_ext: continue node = self.path.find_source(filename) if not node: fatal('cannot find %s' % filename) if self.m_type == 'latex': task = self.create_task('latex', self.env, 20) task.set_inputs(node) task.set_outputs(node.change_ext('.dvi')) elif self.m_type == 'pdflatex': task = self.create_task('pdflatex', self.env, 20) task.set_inputs(node) task.set_outputs(node.change_ext('.pdf')) else: fatal('no type or invalid type given in tex object (should be latex or pdflatex)') task.m_scanner = g_tex_scanner task.m_env = self.env task.m_scanner_params = {'curdirnode':self.path} # add the manual dependencies if deps_lst: variant = node.variant(self.env) outnode = task.m_outputs[0] try: lst = tree.m_depends_on[variant][node] for n in deps_lst: if not n in lst: lst.append(n) except: tree.m_depends_on[variant][node] = deps_lst if self.m_type == 'latex': if 'ps' in outs: pstask = self.create_task('dvips', self.env, 40) pstask.set_inputs(task.m_outputs) pstask.set_outputs(node.change_ext('.ps')) if 'pdf' in outs: pdftask = self.create_task('dvipdf', self.env, 40) pdftask.set_inputs(task.m_outputs) pdftask.set_outputs(node.change_ext('.pdf')) elif self.m_type == 'pdflatex': if 'ps' in outs: pstask = self.create_task('pdf2ps', self.env, 40) pstask.set_inputs(task.m_outputs) pstask.set_outputs(node.change_ext('.ps')) def detect(conf): v = conf.env for p in 'tex latex pdflatex bibtex dvips dvipdf ps2pdf makeindex'.split(): conf.find_program(p, var=p.upper()) v[p.upper()+'FLAGS'] = '' v['DVIPSFLAGS'] = '-Ppdf' return 1 def setup(env): Action.simple_action('tex', '${TEX} ${TEXFLAGS} ${SRC}', color='BLUE') Action.simple_action('bibtex', '${BIBTEX} ${BIBTEXFLAGS} ${SRC}', color='BLUE') Action.simple_action('dvips', '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}', color='BLUE') Action.simple_action('dvipdf', '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}', color='BLUE') Action.simple_action('pdf2ps', '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}', color='BLUE') Action.Action('latex', vars=latex_vardeps, func=latex_build) Action.Action('pdflatex', vars=pdflatex_vardeps, func=pdflatex_build) Object.register('tex', texobj)