# Literate.jl, Documenter.jl, GLMakie.jl and GitHub

**URL:** https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386
**Category:** Performance
**Tags:** literatejl, documentationyml
**Created:** [January 30, 2025, 11:39am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386 "2025-01-30T11:39:51Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 30, 2025, 11:39am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/1 "2025-01-30T11:39:51Z")

</div>

Hi

To create the doc of [Muscade.jl](https://sintef.github.io/Muscade.jl/stable/index.html), I use Literate.jl to run an example, which generates graphics (GLMakie.jl) and \*.md files, that Documenter.jl compiles into \*.html.

This all works fine on my computer, but the [documentation.yml](https://github.com/SINTEF/Muscade.jl/blob/doc/.github/workflows/documentation.yml) job on GITHUB’s server fails: [Failed to precompile GLMakie](https://github.com/SINTEF/Muscade.jl/actions/runs/12598098936/job/35112283842), because dependency [X11](https://github.com/SINTEF/Muscade.jl/actions/runs/12598098936/job/35112283842) (see line 800) is absent on a “headless server”.

My attempts to correct [documentation.yml](https://github.com/SINTEF/Muscade.jl/blob/doc/.github/workflows/documentation.yml) to install X11 have not born fruit (I don’t speak Yaml…). Ask the pros, I looked at how the doc of Interpreter.jl, which contains a figure, is generated: but I can’t find the relevant source code, and its [documentation.yml](https://github.com/fredrikekre/Literate.jl/blob/master/.github/workflows/Documentation.yml) does not refer to X11 at all.

So I try the other way, even though it’s less elegant (updating the doc no longer automatically updates the figure in the doc): Pregenerate the figures, and modify the [example](https://github.com/SINTEF/Muscade.jl/blob/doc/examples/DecayAnalysis.jl) to show the code for graphic generation, but not actually execute it. This _almost_ works. Using the `#md` markup, I get Interpreter.jl not to execute the code… but it generates an `@example` that Documenter.jl executes - so GLMakie, and hence X11 are still required…

So two separate questions, either of which can solve my problem - and teach me something.

1. What is wrong with my [documentation.yml](https://github.com/SINTEF/Muscade.jl/blob/doc/.github/workflows/documentation.yml), how do I get it to install X11 on the server?
2. Is there an elegant way to get Interpreter.jl to a) typeset a snippet of code b) not execute it (as `#md` does) _and_ c) generate MD that will not cause Documenter.jl to execute said snippet?

🙂

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [January 30, 2025, 11:44am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/2 "2025-01-30T11:44:17Z")

</div>

You need xvfb!  
Have a look at the Makie doc setup:

> <https://github.com/MakieOrg/Makie.jl/blob/master/.github/workflows/Docs.yml>

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 30, 2025, 11:56am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/3 "2025-01-30T11:56:17Z")

</div>

> [@sdanisch](#):
>
> xvfb

Looks very promising, thank you. I’ll look into this.

---

<div class="post-metadata">

### Author: ![grahamstark](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/grahamstark/32/5200_2.png) [@grahamstark](https://discourse.julialang.org/u/grahamstark)
#### Post date: [January 30, 2025, 12:30pm UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/4 "2025-01-30T12:30:05Z")

</div>

Perhaps you need CairoMakie rather than GLMakie here?

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 30, 2025, 12:43pm UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/5 "2025-01-30T12:43:41Z")

</div>

Interesting point: the plots we generate _for now_ are 2D and could probably be handled by CairoMakie.jl, and you imply this would not require dependencies to be installed on the server: I haven’t tried.

But we will be creating 3D plots and interactive plots sooner or later, so a solution for GLMakie.jl specifically would be more useful. 🙂

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 30, 2025, 1:29pm UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/6 "2025-01-30T13:29:34Z")

</div>

OK, so I took it for a spin.

Actually I had the line

```julia
        run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev xsettingsd x11-xserver-utils

```

in my \*.yml file from before. I believe it installs `xvfb`, and several other components.

What I did not have is the invocation of `xvfb` before launching Julia, now [amended to](https://github.com/SINTEF/Muscade.jl/blob/doc2/.github/workflows/documentation.yml)

```julia
        run: >
          cd docs;
          DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24'
          julia --color=yes make.jl

```

Even with this change, I get the [error](https://github.com/SINTEF/Muscade.jl/actions/runs/13052989115/job/36417221026)

```julia
The following 1 direct dependency failed to precompile:

GLMakie 

Failed to precompile GLMakie [e9467ef8-e4e7-5192-8a1a-b1aee30e663a] to "/home/runner/.julia/compiled/v1.10/GLMakie/jl_KqVOX0".
┌ Warning: OpenGL/GLFW wasn't loaded correctly or couldn't be initialized.
│ This likely means, you're on a headless server without having OpenGL support setup correctly.
│ Have a look at the troubleshooting section in the readme:
│ https://github.com/MakieOrg/Makie.jl/tree/master/GLMakie#troubleshooting-opengl.
└ @ GLMakie ~/.julia/packages/GLMakie/TH3rf/src/gl_backend.jl:4
ERROR: LoadError: InitError: Exception[GLFW.GLFWError(65550, "X11: The DISPLAY environment variable is missing"), ErrorException("glfwInit failed")]

```

The above contains a Warning and an ERROR, and it is unclear which one causes the other. There is a complaint about `DISPLAY` not set, in spite of the instruction `DISPLAY=:0`.

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [January 30, 2025, 2:15pm UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/7 "2025-01-30T14:15:29Z")

</div>

You need the whole DISPLAY + xvfb setup when compiling the project.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 31, 2025, 6:19am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/8 "2025-01-31T06:19:40Z")

</div>

Isn’t that what

> [@Philippe\_Maincon1](#):
>
> `DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24'`

does? Because I get the above mentionned error message _with this line present in the_ `*.yml` _file_.

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 31, 2025, 7:39am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/9 "2025-01-31T07:39:18Z")

</div>

The error you get in your linked log is that you replaced `make.jl` with `makedocs.jl` and that file doesn’t exist

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 31, 2025, 8:17am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/10 "2025-01-31T08:17:36Z")

</div>

I saw that one (enthusiastic cut and paste…) and corrected it - on my computer at least. I then get the error reported above…

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 31, 2025, 8:20am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/11 "2025-01-31T08:20:14Z")

</div>

I don’t see a new run on CI to check what’s wrong

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 31, 2025, 8:48am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/12 "2025-01-31T08:48:50Z")

</div>

I just pushed (branch `doc2`) to make sure we are on the same page:  
[https://github.com/SINTEF/Muscade.jl/actions/runs/13069211701](https://github.com/SINTEF/Muscade.jl/actions/runs/13069211701)

Thank you for looking into this, I appreciate!

See the “install dependencies” section, about line 800 for the error message.

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 31, 2025, 8:55am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/13 "2025-01-31T08:55:16Z")

</div>

Ah that’s a different step than the one you added the prefix to. So during precompilation after installation, you get the same problem when GLMakie is loaded. Just add the prefix to that command, too, and you should be good.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 31, 2025, 9:09am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/14 "2025-01-31T09:09:42Z")

</div>

OK, here my ignorance of YAML, and not least, of what it expresses, handicaps me. I am afraid you will have to feed me with a teaspoon.

> Ah that’s a different step than the one you added the prefix to. So during precompilation after installation, you get the same problem when GLMakie is loaded. Just add the prefix to that command, too, and you should be good.

Trying to interpret you: (I make a list of statement you could please comment with “true” or “false”

1. Steps have distinct environments.
2. DISPLAY is local to an environment
3. The following is a step

```julia
run: >
          cd docs;
          DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24'
          julia --color=yes make.jl

```

1. This step executes without error, because I define DISPLAY in it
2. The following is a step

```julia
      - name: Upload site as artifact
        uses: actions/upload-artifact@v4
        with:
          name: Docs build
          path: ./docs/build

```

1. But if fails because I do not define DISPLAY in it
2. Do I need to add a `run` clause to this step?

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 31, 2025, 9:46am UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/15 "2025-01-31T09:46:04Z")

</div>

Each `run` specifies a shell command, if you want to run that shell command through `xvfb-run` then you need to prefix it with that. If you take a look at your yaml:

```yml
- name: Install dependencies
  run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy docs
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 
  run: >
    cd docs;
    DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24'
    julia --color=yes make.jl

```

then the `Build and deploy docs` step runs two separate commands. The `>` means all following lines are concatenated into one big line. So you have `cd docs` and then the command `DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --color=yes make.jl` which sets `DISPLAY` and then uses `xvfb-run` to run `julia`. Those are not separate commands even though they appear on two different lines.

But in the previous step `Install dependencies`, you have `run: julia --project=docs/ -e 'using Pkg...` so this runs `julia` without the `xvfb-run` wrapper. When this commands loads GLMakie in precompilation, it fails. So change that one to `DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --project=docs/ ...` as well.

The `Upload site as artifact` step is unrelated to these problems.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [January 31, 2025, 12:51pm UTC](https://discourse.julialang.org/t/literate-jl-documenter-jl-glmakie-jl-and-github/125386/16 "2025-01-31T12:51:39Z")

</div>

YES!!! 😃 That definitely helped. Thanks in particular for your explanation.

Having corrected part of my `documentation.yml` to

```julia
      - name: Install Julia dependencies
        run: > 
          DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24'
          julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'

```

I get the output

```julia
GLMakie Waiting for background task / IO / timer.
[pid 7431] waiting for IO to finish:
 Handle type uv_handle_t->data
 timer 0x2807dec0->0x7fcfff185120
This means that a package has started a background task or event source that has not finished running. For precompilation to complete successfully, the event source needs to be closed explicitly. See the developer documentation on fixing precompilation hangs for more help.
  69831.9 ms ✓ GLMakie
  268 dependencies successfully precompiled in 338 seconds. 9 already precompiled.
  2 dependencies had output during precompilation:
┌ MKL_jll
│ Downloading artifact: IntelOpenMP
└  
┌ GLMakie
│ [pid 7431] waiting for IO to finish:
│ Handle type uv_handle_t->data
│ timer 0x2807dec0->0x7fcfff185120
│ This means that a package has started a background task or event source that has not finished running. For precompilation to complete successfully, the event source needs to be closed explicitly. See the developer documentation on fixing precompilation hangs for more help.
└  

```

No error here, but a somewhat ominous warning about “waiting for IO to finish”.

Executiom of my `make.jl` still has a trivial error “file not found” that I will fix, I am curious whether the not-completed compilation will have an impact: I will update.

Update:  
The doc compiles on the server! Thank you so much!
