Как rustc может скомпилировать исходный код из подстановки процесса bash, а gcc - нет? - PullRequest
0 голосов
/ 11 июня 2018
$ rustc <(echo 'fn main(){ print!("Hello world!");}')
$ ls
63
$ gcc <(echo '#include<stdio.h> int main(){ printf("Hello world!\n"); return 0;}')
/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status

Почему ld не может связать программу?

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Команда gcc в основном является диспетчерским движком.Для каждого входного файла он определяет тип файла из расширения имени файла , а затем передает файл соответствующему процессору.Таким образом, .c файлы компилируются компилятором C, .h файлы собираются в предварительно скомпилированные заголовки, .go файлы отправляются компилятору cgo и так далее.

Если имя файла не имеет расширения или расширение не распознано, gcc предполагает, что это какой-то объектный файл, который должен участвовать в последнем шаге ссылки.Эти файлы передаются в утилиту collect2, которая затем вызывает ld, возможно, дважды.Это будет иметь место в случае подстановки процесса, при которой создаются имена файлов, такие как /dev/fd/63, которые не включают расширения.

ld не использует имя файла для идентификации формата объектного файла.Как правило, он состоит из нескольких различных распознавателей объектных файлов, каждый из которых зависит от своего рода «магического числа» (то есть специального шаблона в начале файла или рядом с ним).Он вызывает этих распознавателей по одному, пока не найдет тот, который с радостью интерпретирует файл.Если файл не распознается как двоичный формат, ld предполагает, что это сценарий компоновщика (который представляет собой простой текстовый файл), и пытается проанализировать его как таковой.

Естественно, между попытками ldнеобходимо перемотать файл, и поскольку подстановка процесса организует передачу канала вместо файла, поиск завершится неудачно.(То же самое произойдет, если вы попытаетесь передать файл через перенаправление stdin в канал, что вы можете сделать: gcc обработает stdin как файл, если вы укажете - в качестве имени файла. Но он настаивает на том, чтобы выскажите ему, что это за файл. См. ниже.)

Поскольку ld не может перемотать файл, произойдет сбой после того, как файл не соответствует его первому предположению.Отсюда и сообщение об ошибке от ld, которое немного вводит в заблуждение, так как вы можете подумать, что файл уже скомпилирован и последующий сбой произошел на этапе ссылки.Это не тот случай;поскольку имя файла не имеет расширения, gcc пропускается непосредственно к фазе соединения и почти сразу завершается неудачей.

В случае замены процесса, каналов, стандартного ввода и файлов с плохим именем, вы все равно можете указать * вручную1029 * что это за файл.Это делается с помощью опции -x, которая задокументирована в разделе руководства GCC о параметрах, управляющих типом вывода (хотя в этом случае опция фактически контролирует тип ввода).

Существует множество ответов на подобные вопросы, распространяющиеся по Интернету, в том числе различные ответы здесь, в StackOverflow, в которых утверждается, что GCC пытается определить язык входных файлов.Он этого не делает и никогда не имеет.(И я сомневаюсь, что это когда-либо произойдет, поскольку некоторые языки, которые он компилирует, достаточно похожи друг на друга, поэтому точное обнаружение будет невозможно.) Единственный компонент, который выполняет автоматическое обнаружение, - это ld, и он делает это только после того, как GCCокончательно решил обработать входной файл как объектный файл или скрипт компоновщика.

0 голосов
/ 11 июня 2018

По крайней мере, в вашем случае вы можете использовать подстановку процесса при указании языка ввода вручную, используя -xc.Тем не менее, вы должны поставить новую строку после оператора include.

$ gcc -xc <(echo '#include<stdio.h>
int main(){ printf("Hello world!\n"); return 0;}')
$ ls
a.out
$ ./a.out 
Hello world!

Для возможной причины, почему это работает, см. Ответ Чарльза и комментарии к этому ответу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...