LINUX.ORG.RU

Как в GCC выяснить, какие языки он поддерживает?

 


0

1

Не могу найти опцию, которая бы показала перечень имен «модулей», которые отвечают за разные языки.

Ну, то есть, надо узнать перечень языков в том виде, которые обозначаются термином program в опции -print-prog-name.

Опытным путем найдены обозначения:

  • cc1plus - язык Си++
  • cpp - язык Си (видимо, как-то связано с аббревиатурой C Pre Processor)

А как узнать у gcc, какие еще языки поддерживает текущая инсталляция gcc?

★★★★★

Ответ на: комментарий от EXL

А куда cc1 потерял?

Так я об этом и спрашиваю. Опытным путем установил, что cc1plus - язык Си++, cpp - язык Си. Может я и не прав, а документация свет на этот вопрос не проливает.

А cc1 - это тогда какой язык?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

это не просто название языков, это название тех языков, только тех языков поддержку которых вы включили при сборке компилятора, ну не именно вы , а те кто собирал компилятор.

Assembler
()
Ответ на: комментарий от no-such-file

cpp это cpp, а не Си.

Если ты дашь команду:

`gcc -print-prog-name=cpp` -v

то увидишь пути к Си-шным библиотекам.

А если дашь команду:
`gcc -print-prog-name=cc1plus` -v

то увидишь пути к Си++ библиотекам.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Может я и не прав, а документация свет на этот вопрос не проливает.

Да, ты не прав. Документацию нужно смотреть где-то тут, там всё должно быть: https://gcc.gnu.org/onlinedocs/

Вот из этой самой документации я почему-то до сих пор ясно и отчётливо помню, что:

  • cpp – Препроцессор языков C, C++, Objective-C, Objective-C++ который принимает на вход исходные файлы и порождает .i-файлы.
  • cc1 – Компилятор языка C, принимает на вход препроцессированные .i-файлы и порождает оптимизированные .S-ассемблерные листинги.
  • cc1plus – Компилятор языка C++, принимает на вход препроцессированные .i-файлы и порождает оптимизированные .S-ассемблерные листинги.
  • cc1obj – Компилятор языков Objective-C и Objective-C++, принимает на вход препроцессированные .i-файлы и порождает оптимизированные .S-ассемблерные листинги.
  • as – Ассемблер из комплекта binutils, принимает .S-ассемблерные листинги и порождает объектные файлы .o и .obj с машинным кодом.
  • ar – Простейший склеивающий архиватор, принимает объектные файлы и порождает статические библиотеки .a или .lib
  • ld – Линкер или компоновщик. Принимает объектные файлы и порождает исполняемые файлы .elf или разделяемые библиотеки .so, .dll, .dylib

Всей этой внутренней кухней GCC Internals умело оркестрируют врапперы gcc, g++, g77 и другие.

EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от EXL

cpp – Препроцессор языков C, C++, Objective-C, Objective-C++ который принимает на вход исходные файлы и порождает .i-файлы.

А почему тогда дефолтный перечень include-директорий для инструмента «cpp» не включает в себя пути к системным C++ заголовкам? Как он без них препроцессирует файлы языка C++?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от EXL

Да, и еще. Вот откуда ты выкопал что «cc1obj – Компилятор языков Objective-C и Objective-C++, принимает на вход препроцессированные .i-файлы и порождает оптимизированные .S-ассемблерные листинги»?

Если сделать поиск по всему документу по подстроке «cc1obj», будет найдено всего одно предложение в опции -no-integrated-cpp:

-no-integrated-cpp

  Perform preprocessing as a separate pass before compilation.
  By default, GCC performs preprocessing as an integrated part
  of input tokenization and parsing.
  If this option is provided, the appropriate language front end
  (cc1, cc1plus, or cc1obj for C, C++, and Objective-C,
  respectively) is instead invoked twice, once for preprocessing
  only and once for actual compilation of the preprocessed input.
Никакой другой информации об этом инструменте там просто нет.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

А почему тогда дефолтный перечень include-директорий для инструмента «cpp» не включает в себя пути к системным C++ заголовкам? Как он без них препроцессирует файлы языка C++?

Непонятно почему и зачем ты задаёшь вопросы, ответ на которые можно получить за секунду самостоятельно тем самым «опытным путём» про который ты писал выше.

$ cat h.cpp 

#include <iostream>

using namespace std;

int main(void) {
    cout << "Hello World!" << endl;
    return 0;
}

$ cpp h.cpp > result.i

Результат: http://paste.org.ru/?2a2tz6

Видишь как препроцессировался этот простейший исходник на C++? Так как и должен был препроцессироваться исходник на C++.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Этот эксперимент не отвечает на вопрос каким образом препроцессировался C++ исходник при условии что сам инструмент cpp знает только директории C-заголовков.

Другими словами, вербоз инструмента cpp показывает директории:

$ cpp -v
...
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
А в твоем примере откуда-то появляются
/usr/include/c++/11
/usr/include/x86_64-linux-gnu/c++/11/bits
и т.д.
Как-то это странно.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Вот откуда ты выкопал что «cc1obj – Компилятор языков Objective-C и Objective-C++, принимает на вход препроцессированные .i-файлы и порождает оптимизированные .S-ассемблерные листинги»?

Из своего опыта, а что? Я имел опыт разработки под Apple Mac OS X и iOS в те древние времена, когда они использовали GCC. И внутренние компиляторы cc1obj и cc1objplus были ответственны за поддержку языков программирования Objective-C и Objective-C++ в GCC.

Их и сейчас можно установить в любую Ubuntu, выполнив:

$ sudo apt install gobjc gobjc++

Ещё я забыл про collect2 рассказать, эта утилита вызывается перед вызовом линковщика ld и скорее всего строит таблицу вызовов функций по адресам. Ещё там есть lto1 и lto-wrapper, которые ответственны за оптимизации времени линковки.

Компиляция довольно нетривиальный процесс, поэтому все эти стадии были объединены врапперами gcc, g++, дабы дать программисту удобные интерфейсы.

EXL ★★★★★
()
Ответ на: комментарий от Xintrea

Другими словами, вербоз инструмента cpp показывает директории:

Что тебе мешает выполнить verbose:

$ cpp -v h.cpp > result.i

И увидеть, что никаких странностей нет? При этом verbose-выхлоп пойдёт на консоль (в stderr), а результат препроцессирования в файл (в stdout).

EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от EXL

Из своего опыта, а что?

Просто ты сказал что про cc1obj ты до сих пор ясно и отчётливо помнишь из документации https://gcc.gnu.org/onlinedocs/ и там всё должно быть. А по факту вона как.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от EXL

И увидеть, что никаких странностей нет?

А что я должен там увидеть?

Единственное вменяемое объяснение - это то, что из-под инструмента cpp, который не знает о C++ директориях, вызывается бинарник /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus, который в свою очередь уже знает о C++ директориях (это видно в чистом вербозе cc1plus). И поэтому сборка C++ кода срабатывает.

Но это всего лишь моя догадка, а хотелось бы увидеть ясное и отчетливое тому подтверждение.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

А по факту вона как.

Как? Когда языки Objective-C и Objective-C++ были актуальны, оно там или в манах было и упоминалось. Кстати не только оно, GCC ещё Java мог компилировать и в той директории рядом с cc1, cc1plus ещё и фронтендный Java-компайлер был, название я его забыл за давностью времени.

Вообще у GCC долгая история и все эти ньюансы знать не обязательно, чтобы компилировать программы.

EXL ★★★★★
()
Ответ на: комментарий от Xintrea

А что я должен там увидеть?

То что утилита cpp которая раньше была отдельной программой в современном GCC сегодня такой же враппер, который переправляет свои вызовы внутрь cc1 и cc1plus основываясь на расширении файла (.c или .cpp, .cxx, .C), ну а утилиты cc1 и cc1plus являются фронтендами к соответствующим языкам программирования и именно в них перебросили опции препроцессирования (флажок -E).

Тебе все эти ньюансы исторические зачем, если ты не разработчик GCC, а прикладной разработчик?

EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от EXL

Я просто не понимаю как разработчики мирового уровня проектируют программы. По моим понятиям, если есть команда

gcc -print-prog-name=tool
... значит должна быть команда, которая должна показывать список этих tool. А этого списка получить, оказывается, неоткуда.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

… значит должна быть команда, которая должна показывать список этих tool. А этого списка получить, оказывается, неоткуда.

GCC – модульный проект и этих tool там может быть дохрена. Некоторые из них могут быть завязаны на GCC, а некоторые вообще являться отдельной сущностью. Плюс к тому же там слой Legacy для всяких инструментов типа gcj и подобных.

Общей команды быть не может, потому что к примеру, gcc ничего не знает о gcj или каком-нибудь GNAT.

Разве что командой по типу:

$ ls `dirname $(gcc -print-prog-name=cc1)`

Можно прикинуть что там есть.

EXL ★★★★★
()

а если не мудрствовать, почитать всякое и сделать В-ЛОБ ? https://gcc.gnu.org/onlinedocs/gcc/G_002b_002b-and-GCC.html#G_002b_002b-and-GCC

«GCC is an integrated distribution of compilers for several major programming languages. These languages currently include C, C++, Objective-C, Objective-C++, Fortran, Ada, D, and Go» (это те которые back-ends и глубоко интегрированны)

и ещё немного с front-ends «there are several other front ends that are maintained separately. These support languages such as Mercury, and COBOL» (и ещё полумёртвый gpc)

итого всего 11 штук (и их версии/варианты/поколения).

то есть можно набросать скрипт который просто проверит их наличие и работоспособность. Причём часть сего скрипта есть в виде m4 тестов configure, можно оттуда позаимствовать

хотя честно - не знаю какой практический смысл сего действия. Не представляю жизненной ситуации, когда подобный скрипт (запрос) может понадобиться

MKuznetsov ★★★★★
()
Ответ на: комментарий от EXL

ar – Простейший склеивающий архиватор

А бывает не простейший? А то ЕМНИП в ar не работает опция «сохранять пути файлов», т.е. два .o-файла с одинаковыми именами из разных подкаталогов скормить ему нельзя.

dimgel ★★★★★
()
Ответ на: комментарий от EXL

man я естественно читал, но у меня этот P не работал. ЕМНИП и разными архиваторами пытался список файлов архива вывести, и даже потроха полученного .a hexview-ером смотрел – путей не было.

dimgel ★★★★★
()
Ответ на: комментарий от EXL

Не всё так просто, там ведь недавно добавили Rust, а ту же Java – удалили.

можешь представить себе вариант когда ты в консоле задаёшь вопрос «какие языки поддерживает установленная (к слову коллекция) gcc» ? Если есть COBOL легче станет ??

когда разумны вопросы «поддерживается ли конкретно rust» или «есть ли java». Запросы про конкретные языки конкретного, хоть и гипотетичного проекта. Но подобные запросы как раз и делают всякие configure

MKuznetsov ★★★★★
()
Ответ на: комментарий от dimgel

Следи за руками:

$ cat 1/a.cpp
#include <iostream>

void hello_1(void) {
    std::cout << "Hello 1" << std::endl;
}


$ cat 2/a.cpp
#include <iostream>

void hello_2(void) {
    std::cout << "Hello 2" << std::endl;
}

$ cat b.cpp 
#include "1/a.h"
#include "2/a.h"

int main(void) {
    hello_1();
    hello_2();
    return 0;
}

----------------------------

$ g++ -c 1/a.cpp -o 1/a.o
$ g++ -c 2/a.cpp -o 2/a.o

# First
$ ar rcs lib.a 1/a.o
$ ar rcs lib.a 2/a.o
$ nm lib.a | c++filt | grep "T hello"
0000000000000000 T hello_2()

$ g++ b.cpp lib.a -o b
b.cpp:(.text+0x9) undefined reference to hello_1()

$ rm lib.a

# Second
$ ar rcsP lib.a 1/a.o 
$ ar rcsP lib.a 2/a.o 
$ nm lib.a | c++filt | grep "T hello"
0000000000000000 T hello_1()
0000000000000000 T hello_2()

$ g++ b.cpp lib.a -o b
$ ./b
Hello 1
Hello 2

$ rm lib.a

# Third
$ ar rcs lib.a 1/a.o 2/a.o
$ nm lib.a | c++filt | grep "T hello"
0000000000000000 T hello_1()
0000000000000000 T hello_2()

$ g++ b.cpp lib.a -o b
$ ./b
Hello 1
Hello 2

$ rm lib.a
EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 4)
Ответ на: комментарий от MKuznetsov

можешь представить себе вариант когда ты в консоле задаёшь вопрос «какие языки поддерживает установленная (к слову коллекция) gcc» ?

Так я сам пытаюсь узнать у ТС что он вообще хочет получить и зачем ему это.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Так. Я делал third (потому что $^ в make), но пробовал с P. Зудело у меня подозрение, что там P не нужен, что ему пофиг если у него в архиве два файла с одинаковыми именами лежат. Но зудело походу недостаточно сильно, и до проверки работоспособности этой бредятины дело не дошло. Спасибо.

dimgel ★★★★★
()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от EXL

Следи за руками

(просто к слову пришлось) не все знают, но используемые *.o лучше складывать ar`ом в его архив/библиотеку *.а и потом уже использовать в линковке. А не впрямую кормить линкеру

Вот казалось бы всё едино, все равны, архив как архив; Но через ar бинарь получается меньше - часть работы проделалась на этапе архива и заведомо лишнее позже отсеклось

MKuznetsov ★★★★★
()
Ответ на: комментарий от dimgel

Я не вникал, но возможно мёртвый код отсекается при линковке a-архива автоматом. К примеру, в бинарь при обычной линковке могут попасть o-файлики, которые никак не используются и линкер ничего не будет делать с ними.

В любом случае я думаю что после какого-нибудь strip -s никакой разницы между этими двумя подходами не будет. Или если и будет, то слишком незначительная.

EXL ★★★★★
()
Ответ на: комментарий от EXL

К примеру, в бинарь при обычной линковке могут попасть o-файлики, которые никак не используются и линкер ничего не будет делать с ними.

А, вот это возможно. Но в нынешние времена не актуально, потому что LTO наше фсьо. :)

dimgel ★★★★★
()