0

I'm currently having some trouble with getting org-mode to properly display source code environments in LaTeX exports with the minted package with the outputdir= option. Given the following test document:

#+TITLE: Minted Test

* Export Configuration                                             :noexport:

  #+begin_src emacs-lisp :results output :session :exports both
    ;; Prefer minted for source code export in LaTeX.
    (setq org-latex-listings (quote minted))
  #+end_src

  #+RESULTS:

#+LATEX_CLASS: article
#+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside]
#+LATEX_HEADER: \usepackage{svg}
#+LATEX_HEADER: \usepackage{subcaption}
#+LATEX_HEADER: \usepackage{placeins}
#+LATEX_HEADER: \usepackage{float}
#+LATEX_HEADER: \usepackage[outputdir=build]{minted}

* Introduction

  #+begin_src c++
    int main(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }
  #+end_src

* Conclusions

 Goodbye cruel world!

This exports okay, but without the listing. Removing the [outputdir=build] option makes the listings work, but I would like to keep it if possible. Anything I can do to make Emacs/Org-mode aware of this option?

4
  • Did you get a chance to try the suggestions in the answer? Did it work for you?
    – NickD
    Feb 26, 2023 at 21:17
  • Huh, that's weird, I cannot recall even seeing your answer before now. I'll try to give it a spin soon-ish
    – Xaldew
    Feb 27, 2023 at 12:40
  • That's worrisome. I'm not sure how the notifications work but I hope they are not going astray. Anyway, I'm glad I pinged you. Let me know what you find out.
    – NickD
    Feb 27, 2023 at 15:44
  • 1
    Ahh, I see what happened here. I had a report to finish the 12th, so I probably saw the notification in the morning and clicked on it, but forgot about it as I got to work. But yes, everything seems to work fine, I've also added a relevant comment that could be useful for your answer as well :)
    – Xaldew
    Mar 1, 2023 at 9:17

2 Answers 2

1

The main problem here is that there are many actors involved, each with possibly different ideas about where the input is coming from and where the output is going to.

The main actors are:

  • the Org mode LaTeX exporter itself. In most cases, the exporter produces a .tex file in the default directory of the Org mode buffer. There are some exceptional cases (e.g. if EXPORT_FILE_NAME is defined, or if the Org mode buffer does not have an associated file), which I completely ignore here.

  • in addition, the exporter assumes that the .pdf file will be found in the same directory as the .tex file and will complain if that is not the case.

  • the various processors that are defined in org-latex-pdf-process may have their own idiosyncracies about where they expect their input and where the produce their output. In particular, if org-latex-pdf-process consists of multiple pdflatex, bibtex, makeindex, etc. invocations, they all assume that their input is in the current directory and their output is going to go into the current directory; you will have to tell somehow to each one that you want to use some other directory. However, there are now compound processors like latexmk which take care of these multiple invocations and do the "right thing". Moreover, latexmk in particular takes a --output-directory=<DIR> option and conveniently arranges for all the subordinate processors to do the right thing. Since latexmk figures in the default value of org-latex-pdf-process (that value at least on Linux is ("latexmk -f -pdf -%latex -interaction=nonstopmode -output-directory=%o %f")), I am going to assume that it is to be used here and we can sweep the complications of running individual processor under the latexmk rug and have it deal with them.

  • minted runs the pygmentize processor underneath the covers, producing a .pyg file, which is then read by the next invocation of the LaTeX processor and used to produce the decorated code blocks. Given the [outputdir=<DIR>] option however, whatever it does should be transparent to the Org mode exporter.

For definiteness, I will assume that we will use xelatex as the LaTeX processor and that we will use ./build as the subdirectory where all the build artifacts will go; the .tex file and the .pdf file will end up in the current directory (the parent of the build subdirectory) so that we don't have to modify Org mode sources. The main disadvantage in all of this is the ./build assumption which will affect a couple of different settings: changing the assumption necessitates changing all these settings. You can of course define a single variable for that and use that variable in the various settings, instead of the hardwired ./build.

One more assumption is that org-latex-packages-alist does not contain any minted customization that might conflict with the customization below.

Here's the file above, rearranged a bit to put the initialization code block out of the way at the end and simplified a bit to get rid of unnecessary stuff:

#+TITLE: Minted Test

#+LATEX_CLASS: article
#+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside]

* Introduction

  #+begin_src c++
    int main(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }
  #+end_src

* Conclusions

 Goodbye cruel world!

 
* Export Configuration                                 noexport:

  #+begin_src emacs-lisp
    ;; Prefer minted for source code export in LaTeX.
    (setq org-latex-listings (quote minted))

    ;; Prefex `xelatex' as the LaTeX processor.
    (setq org-latex-compiler "xelatex")

    ;; Make sure that LaTeX knows about the `minted' package: we take care
    ;; of it in `org-latex-packages-alist' and we do *NOT* want to include
    ;; it explicitly as a #+LATEX_HEADER, since the options may differ, in
    ;; which case the two inclusions will conflict.
    (setq org-latex-packages-alist '(("outputdir=./build" "minted" nil)))

    ;; `org-latex-pdf-process' is a list of shell commands. We take advantage of that
    ;; to:
    ;;   - create the `build' subdirectory if it is not present
    ;;   - run `latexmk' with the proper options (in particular `-shell-escape' which i
    ;;     necessary in order to allow the LaTeX processor to run an external program,
    ;;     like `pygmentize' in the case of `minted'; and `-output-directory' to allow
    ;;     all the artifacts to be sent there)
    ;;   - finally, move the `.pdf' file to the parent directory of the `build' subdirectory
    ;;     so that the exporter will be able to find it and not complain.
    ;; Note also that `%latex' is replaced by the value of `org-latex-compiler' so we use
    ;; `xelatex' as our LaTeX processor.
    (setq org-latex-pdf-process '("mkdir -p build"
                                  "latexmk -f -pdf -%latex -shell-escape -interaction=nonstopmode -output-directory=%o/build %f"
                                  "mv %o/build/%b.pdf %O"))
  #+end_src

Do C-c C-c on the setup code and then export with C-c C-e l o to show the .pdf file. For me, it works without any errors.

2
  • 1
    A great and thorough answer! I did find a separate solution elsewhere that you could add: Modern(-ish) versions of latexmk have the options -emulate-aux-dir -aux-directory=build, which places everything but the result files (i.e., the PDF) in the build directory, which may be a tiny bit cleaner :)
    – Xaldew
    Mar 1, 2023 at 9:21
  • If your method works better for you, it is likely to work better for others as well: so provide your own answer describing it. I, for one, would try it out and upvote. And you might want to change your mind and accept that answer as well: it doesn't always happen, but the ideal should always be that the objectively best answer should be the accepted one.
    – NickD
    Mar 1, 2023 at 13:13
0

As written in the comments above, another possible solution is to use the relatively new LaTeX feature -aux-directory=DIR. The purpose of this is quite simple: Put everything but the final results (i.e., the PDF) in the specified directory.

However, as LaTeX is a pretty old system, not all parts of it may support this option. Modern versions of latexmk have built-in support to emulate the necessary behaviors however, but another flag is necessary for that, namely -emulate-aux-dir.

Pulling this together, we can create an example file like this:

#+LATEX_CLASS: article
#+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside]
#+LATEX_HEADER: \usepackage[outputdir=build]{minted}

* Introduction

  #+begin_src c++
    int main(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }
  #+end_src

* Conclusions

 Goodbye cruel world!

* Export Configuration                                 :noexport:

  #+begin_src emacs-lisp
    (setq org-latex-listings (quote minted))
    (setq org-latex-compiler "xelatex")
      (setq org-latex-pdf-process
            (list (concat "latexmk -shell-escape -emulate-aux-dir -aux-directory=build -bibtex "
                          "-f -pdf -%latex -interaction=nonstopmode -output-directory=%o %f"))))
  #+end_src

Also, please see @NicKD's answer for thorough explanation of the Org machinery that happens in the background to make all of this possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.