I'm trying to compile a C code (that was generated using Cython
) as follows
gcc (uv run python3-config --cflags --ldflags) some_file.c -o some_file.o
However, I don't think substitution is working in quite a way I would expect it to. Using set -U fish_trace 1
I can see that the following
> gcc '-I/usr/include/python3.12 -I/usr/include/python3.12 -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O2 -Wall' '-L/usr/lib/python3.12/config-3.12-x86_64-linux-gnu -L/usr/lib/x86_64-linux-gnu -ldl -lm ' some_file.c -o some_file.o
some_file.c:16:10: fatal error: Python.h: No such file or directory
16 | #include "Python.h"
| ^~~~~~~~~~
compilation terminated.
The quotes seem to be the issue here, the code would run fine (a different error, but not related to this question) if I remove the quotes and run that command. I tried using tr -d \'
but that does nothing. My guess is that it may have something to do with the substituted command returning a list of strings instead of single string. string collect
or string join ' '
didn't work for me.
I was able to use
uv run python3-config --ldflags --cflags | xargs gcc some_file.c -o some_file.o
to solve my issue but I'm looking to understand what's exactly happening with my first command.
The -config family of tools, like pkg-config, are some of the very few commands that expect their output to be split on spaces.
They print things like
-I/usr/include/python3.12 -I/usr/include/python3.12
on a single line. (that of course means they are unable to support paths with spaces)
Fish will split command substitutions on newlines, which is usually the correct thing to do, but in this case will mangle the output, passing it all as one long argument (as if it where in ''
quotes).
You can explicitly split on spaces by adding string split -n " "
, like
gcc (uv run python3-config --cflags --ldflags | string split -n " ") some_file.c -o some_file.c
This is specifically called out in fish's FAQ. The -n
will make it ignore empty elements, like bash would do here.