0

My custom compiler for a toy language uses Cranelift to generate object code, that I can write into a file main.o. To make this object file into an executable file, I invoke GCC with gcc -o main main.o.

However, I would like to pipe the code directly into GCC in order not to have a temporary object file written to disk, so I make my compiler write object code to the standard output. Using - as a filename does not work because the -x option does not appear to have any values for object files.

Using some kind of shell redirect also does not work: gcc -o main <(compiler) errors out with /usr/bin/ld: /proc/self/fd/11: file not recognized: Illegal seek. (Note that this does work when GCC itself works on the file, for example with gcc -xc <(echo "int main(){}") -o main, but not when the file is passed to LD. The -pipe option also doesn't seem to make a difference.)

Is there any way to use GCC to link object code piped into it?

2 Answers 2

4

ld needs a seekable file so you can't use a pipe. The <(...) Korn shell process substitution expands to the path of a pipe.

You need zsh and its =(...) one or fish and its (...|psub -f) to get the path to a regular seekable file (created in $TMPPREFIX or $TMPDIR under the hood).

gcc -o main =(compiler) # zsh
gcc -o main (compiler|psub -f) # fish

If ld needs the path of the file to end in .o, in zsh, set TMPSUFFIX=.o.

In other shells, you can create the temp file by hand, you could even call gcc on it and even redirect compiler's output to it after it has already been deleted. In Korn/POSIX-like shells:

file=$(mktemp) && {
  rm -f -- "$file" &&
    compiler >&3 3>&- 4<&- &&
    gcc -o main /dev/fd/4 3>&-
} 3> "$file" 4<> "$file"

Note that gcc itself creates many temp files for its own processing so it's pointless to want to try and avoid creating an extra one here.

2
  • Ah nice answer, just didn't see it until I finished typing mine. Especially think the last sentence is very true: if you're gcc, saving yourself from a single temporary file doesn't make too much sense. Commented Apr 26, 2023 at 7:56
  • Guess I'm going back to a temporary file based-solution then. Didn't know about this ZSH syntax either. Thank you.
    – Altareos
    Commented Apr 28, 2023 at 8:11
2

You can't pipe an object file to your compiler. As the error shows, that can't work because gcc tried to seek in it, and that is not an operation a pipe supports. (It works on source code just because gcc was written with specific lexing/parsing, that really seems to consume input sequentially.)

So, an anonymous temporary file must do!

 gcc -o main =(yourcompiler)

would solve your problem:

If =(...) is used instead of <(...), then the file passed as an argument will be the name of a temporary file containing the output of the list process. This may be used instead of the < form for a program that expects to lseek (see lseek(2)) on the input file.

But: it's a feature of zsh only, not the more common bash, so I don't know whether you want to use that or just portable write into an object file and link that - like anyone with a makefile, or ninja script, or a generator for these, would do.

Also note that if your compiler takes an intermediate code as input, maybe you actually want to change it to be an llvm backend? That way, you could load it as plugin into clang and just compile source code to object file directly, or even do a combined linking & compilation run at once.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .