46

I'm currently using doxygen to generate some documentation for a project, and doxygen generate some LaTeX code that then can be used to generate a nice pdf.

But let's say I would like to write another document, and in that document include the doxygen generated LaTeX code as a part of that document.

How would I do that? Has anybody done this type of stuff?


My try is to get the code, generate the LaTeX code without the "header". So I end up with a dir called code/doc/latex/, seen from the place where I have my own main.tex.

And try in include that LaTeX code from my main.tex with input.

\input{ code/doc/latex/refman.tex }

But when I try to include the code/doc/latex/refman.tex (the doxygen, main.tex), he complains that he can't find the other LaTeX files that was generated by doxygen. It seems like he is searching in the same dir as my main.tex and not in code/doc/latex/.

This is more or less how the refman.tex looks like:

\chapter{Todo List}
\label{todo}
\hypertarget{todo}{}
\input{todo}
\chapter{Class Index}
\input{annotated}
\chapter{File Index}
\input{files}
\chapter{Class Documentation}
\include{struct__offsetChannel}
\include{struct__offsetPixel}
\include{struct__tPixel}
...
...

Any ideas would be welcome.

A solution could be to write a script that edits all the generated LaTeX code, and simply adds this path but this seems like a overly complicated solution.


Update:

The error I get is like this one

! LaTeX Error: File `todo.tex' not found.

Update:

If I change all the \input \include and \includegraphics like this it works.

\input{todo} -> \input{code/doc/latex/todo}

But there must be a way to make LaTeX understand that he should look into the code/doc/latex/ for the code?

Display Name
  • 46,933
Johan
  • 2,204
  • Try \input{ ./code/doc/latex/refman.tex } – yannisl Oct 26 '10 at 15:53
  • Still the same error "! LaTeX Error: File `todo.tex' not found." – Johan Oct 26 '10 at 15:57
  • Can you just configure doxygen to give you the document you want? – Matthew Leingang Oct 26 '10 at 16:12
  • Don't think so... but I'm not sure. – Johan Oct 26 '10 at 16:25
  • 4
    (I'm putting this in a comment as I'm not sure it's really answering the question, but it may be so it at least warrants a comment.) It seems as though the issue is simply telling TeX where to find stuff. One (hackish) way to do that is to redefine the \input command: \let\oldinput=\input \def\input#1{\oldinput{code/doc/latex/#1}}. You should probably put things back where they were after including the doxygen generated file, and this might break other things, unfortunately. – Andrew Stacey Oct 26 '10 at 18:11
  • cool idea, but I think a search and replace script will be a little nicer. – Johan Oct 26 '10 at 18:22
  • 3
    @Johan: a better title for this question would be "How to tell TeX where to find \include s of \include s." By saying that the question is about doxygen, you may have turned away some people who could otherwise have given an answer. – Willie Wong Oct 27 '10 at 00:07
  • I think this question can be simplified. Who can do this? :-) – Display Name Jun 03 '11 at 11:03
  • You could also have a look at the TEXINPUTS environment variable. See e.g. http://tex.stackexchange.com/questions/93712/definition-of-the-texinputs-variable – Neal Young Jun 20 '14 at 16:28
  • Future note: new LaTeX versions have \l_file_search_path_seq which affects \input etc. as well. – user202729 Nov 25 '22 at 09:04

4 Answers4

47

I'm fuzzy on the details, but the import package should do what you want. Off the top of my head, I think the syntax is

\usepackage{import}
...
\subimport{code/doc/latex/}{refman.tex}

Update: Thanks Willie for pointing out \subimport which seems to be the better command to use here over \import.

The commands \import{full_path}{file} and \subimport{path_extension}{file} set up input through standard LaTeX mechanisms (\input, \include and \includegraphics) to load files relative to the \import-ed directory. There are also \includefrom, \subincludefrom, and * variants of the commands. The author is Donald Arseneau.

  • 6
    \import takes, IIRC, the full path as the first argument. To use relative paths I think you need to use \subimport. – Willie Wong Oct 27 '10 at 00:11
  • I think it should be the final solution. – Display Name Jun 03 '11 at 11:20
  • By the way, use \subimport* if you have files named the same in your document root as in the sub-import root, such as todo.tex in the example. – Geoff May 22 '13 at 20:44
  • 1
    While it fixes the issue with relative graphics, it still doesn't recognize the bibliographies relative paths. How do I fix that? – thc Mar 07 '17 at 22:34
  • 1
    @thc: this answer helped me with my bib files as well: https://tex.stackexchange.com/questions/79058/can-a-default-path-be-set-globally-for-input-akin-to-graphicspath – maja zaloznik Aug 08 '18 at 16:06
  • This works really well with the beamer class (not tested on bibliography though). For multiple insertions, I defined an \inputfile command like so \newcommand{\inputfile}[1]{\subimport{\MainDir/\SubDir}{#1}}: this way if I restructure the directories, I only need to fix one path in the master file. – PatrickT Jan 10 '22 at 03:34
15

I have written my own package for this purpose.

Now there is one important new command available: \inputpaths

\inputpaths specifies the directories where \include and \input can look for the given file. By default \inputpaths is empty and therefore \include and \input have the same behavior as the normal commands.

The redefined \include and \input use the root-directory. If the file is not in the root-directory than the commands looking for the file in the specified directories.

Example:

File structure:
./main.tex
./file2.tex
./dir1/file1.tex
./dirN/file3.tex

Contents of file1.tex:

\usepackage{inputx}
...
\inputpaths{dir1,...,dirN}
...
\begin{document}

\include{file1}
\input{file2}

\end{document}

Contents of dir1/file1.tex:

\input{file3}
\input{dirN/file3}

Contents of file2.tex:

file2: Hello World!

Contents of dirN/file3.tex:

file3: Hello World!

Output:

file3: Hello World!
file3: Hello World!
file2: Hello World!

The inputx package source:


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Author: Blackstev
% Email: blackstev@hotmail.com
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ProvidesPackage{inputx}[2011/06/28 v1.0 inputx style for better file includings]
\typeout{2011/06/28 v1.0 inputx style for better file includings}

%{{{    use package
%}}}

\makeatletter

\newif\ifBreak
\Breakfalse

\gdef\inputpaths#1{\gdef\@inputpaths{#1}}
\gdef\@inputpaths{}

\newcommand{\forAllInputpaths}[2][\path]{\@for#1:=\@inputpaths\do{#2}}

\gdef\printinputpaths{
    \forAllInputpaths[\path]{Path: \path}
}



%{{{ redefine include
\global\let\old@include\include
\gdef\includex#1{
    \IfFileExists{#1.tex}
    {
        \old@include{#1}
    }
    {
        \forAllInputpaths[\path]
        {
            \ifBreak
            \else
                \IfFileExists{\path/#1.tex}
                {
                    \old@include{\path/#1}
                    \Breaktrue
                }
                {}
            \fi
        }
        \ifBreak
        \else 
            % \PackageError{includex}{'#1' can not be resolved}{'#1' can not be resolved. It is not in \@includepaths}
            \old@include{#1}
        \fi
        \Breakfalse
    }
}
\gdef\include#1{\includex{#1}}
%}}}
%{{{ redefine input
% original definition of input: \def\input{\@ifnextchar\bgroup\@iinput\@@input}
\global\let\old@input\@@input
\gdef\@@input#1{\old@input#1}
\gdef\inputx#1{
      \IfFileExists{#1.tex}
      {
          \@@input{#1}%
      }
    {
        \forAllInputpaths[\path]
        {
            \ifBreak
            \else
                \IfFileExists{\path/#1.tex}
                {
                    \@@input{\path/#1}
                    \Breaktrue
                }
                {}
            \fi
        }
        \ifBreak
        \else 
            %\PackageError{includex}{'#1' can not be resolved}{'#1' can not be resolved. It is not in \@includepaths}
            \@@input{#1}
        \fi
        \Breakfalse
    }
}
\def\input{\@ifnextchar\bgroup\inputx\@@input}
%}}}
\makeatother
blackstev
  • 151
  • Hi, Can you make it work with .bib files? Apparently, it is not supported yet. Many thanks :-) – hola May 11 '17 at 22:15
  • This looks rather bad. https://tex.stackexchange.com/q/7453/250119 Better to use \input@path. https://tex.stackexchange.com/q/79058/250119 – user202729 Feb 24 '24 at 10:05
8

If you use rubber, you can simply add a directives such as these to your Latex source:

% rubber: path code/doc/latex
% rubber: path ../foo/bar

After that, \input and friends will be able to locate files also in code/doc/latex and ../foo/bar (relative to the current working directory).

Rubber implements this by setting the TEXINPUTS environment variable appropriately before invoking pdflatex, latex, etc.

Jukka Suomela
  • 20,795
  • 13
  • 74
  • 91
  • 2
    Nice solution. One caveat: if you are using TEXINPUTS and have multiple different files of the same name but in different subdirectories, you will run into a problem with this method. – Willie Wong Oct 27 '10 at 09:23
-1

The quick fix for this is to create a search and replace script, and for the sake of the question I will put this here as a alternative (even if it not the most optimal thing to do).

Enter the Doxygen LaTeX dir and run this bash script.

#!/bin/bash 

for f in *.tex ;
do
    sed 's/\(\\includegraphics\[.*\]\){\(.*\)}/\1{code\/doc\/latex\/\2}/' $f |\
    sed 's/\(\\include\){\(.*\)}/\1{code\/doc\/latex\/\2}/' |\
    sed 's/\(\\input\){\(.*\)}/\1{code\/doc\/latex\/\2}/' |\
    sed 's/\(\\end{document}\)/%\1/' > $f.tmp ;
    mv $f.tmp $f;
done
Display Name
  • 46,933
Johan
  • 2,204
  • 2
    -1 @Johan: You should use import package that has been explained in Will's answer. Changing relative paths in the imported files to absolute paths is a bad practice. – Display Name Jun 03 '11 at 13:14
  • 1
    -1 Bad practice, yes. A document should be able to compile even if something is moved to a different location. Some might even suggest that instead of working with relative paths one can make a copy of the objects to include. But, then again you would have to make a copy every time your source updates. For projects like these I've sometimes used the operating systems symlinks instead. Stuff can still go wrong if somethings moved, but at least its an easier fix than going for absolute paths. – DrJay Dec 04 '12 at 08:41