Шаг 1 — Компиляция программ на языке C/C++ Шаг 2 — Отладочная информация Шаг 3 — Компиляция нескольких файлов Шаг 4 — Библиотеки объектных файлов Шаг 5 — Создание статической библиотеки Шаг 6 — Создание динамической библиотеки Шаг 7 — Использование динамических библиотек Шаг 8 — Функции работы с динамическими библиотеками Шаг 9 — Инициализация динамических библиотек
Шаг 10 — Передача опций в программу — getopt
Шаг 11 — Передача длинных опций в программу — getopt_long Шаг 12 — Вывод сообщений об ошибках программы Шаг 13 — Получение информации о пользователе
Шаг 14 — Получение данных из shadow password
Шаг 15 — Работа с паролями системы с помощью функции crypt() Шаг 16 — Получение информации о группах пользователей
Шаг 1 — Компиляция программ на языке C/C++
Компилятор превращает код программы на «человеческом» языке в объектный код понятный компьютеру. Компиляторов под Linux существует много, практически для каждого распространенного языка. Большинство самых востребованных компиляторов входит в набор GNU Compiler Collection , известных под названием GCC ( http://gcc.gnu.org/ ). Изначально аббревиатура GCC имела смысл GNU C Compiler , но в апреле 1999 года сообщество GNU решило взять на себя более сложную миссию и начать создание компиляторов для новых языков с новыми методами оптимизации, поддержкой новых платформ, улучшенных runtime -библиотек и других изменений ( http://gcc.gnu.org/gccmission.html ). Поэтому сегодня коллекция содержит в себе компиляторы для языков C , C++ , Objective C , Chill , Fortran , Ada и Java , как библиотеки для этих языков ( libstdc++ , libgcj , . ). Компиляция программ производится командой: gcc <имя_файла>После этого, если процесс компиляции пройдет успешно, то вы получите загружаемый файл a.out , запустить который можно командой: ./a.out Для примера давайте напишем маленькую простейшую программку: #include int main()< printf(«[http://linux.firststeps.ru]n»); printf(«Our first program for Linux.n»); return 0; >; И запустим ее:
Компиляция кода на Си с помощью gcc на Linux Mint 20
Шаг 2 — Отладочная информация
Любой компилятор по умолчанию снабжает объектный файл отладочной информацией. Компилятор gcc также снабжает файл такой информацией и на результат вы можете посмотреть сами. При компиляции проекта из предыдущего шага у нас появился файл a.out размером 11817 байт (возможно у вас он может быть другого размера).
Вся эта отладочная информация предназначается для отладки программы отладчиком GNU Debugger . Запустить его вы можете командой: gdb a.out При этом запустится отладчик и наша скомпилированная программа. Об отладке мы с вами поговорим отдельно и более подробно.
Компилятор gcc может создавать отладочную информацию в различных объемах и форматах, контролировать которые можно специальными ключами. Посмотреть их подробное описание можно командой man gcc : Debugging Options -a -dletters -fpretend-float -g -glevel -gcoff -gxcoff -gxcoff+ -gdwarf -gdwarf+ -gstabs -gstabs+ -ggdb -p -pg -save-temps -print-file-name=library -print-libgcc-file-name -print-prog-name=program Ключ -g создает отладочню информацию в родном для операционной системы виде, он выбирает между несколькими форматами: stabs , COFF , XCOFF или DWARF . На многих системах данный ключ позволяет использовать специальную информацию, которую умеет использовать только отладчик gdb . Другие ключи позволяют более тонко контролировать процесс встраивания отладочной информации.
Ключ -ggdb включает в исполняемый файл отладочную информацию в родном для ОС виде и дополняет ее специализированной информацией для отладчика gdb . Ключ -gstabs создает отладочную информацию в формате stabs без дополнительных расширений gdb . Данный формат используется отладчиком DBX на большинстве BSD систем. Ключ -gstabs+ дополняет отладочную информацию расширенниями понятными отладчику gdb . Ключ -gcoff создает отладочную информацию в формате COFF , которая используется отладчиком SDB на большинстве систем System V до версии System V R4 . Ключ -gxcoff снабжает файл информацией в формате XCOFF , который используется отладчиком DBX на системах IBM RS/6000 . Использование -gxcoff+ влкючает использование дополнительной информации для gdb . Ключ -gdwarf добавляет инфомацию в формате DWARF приняотм в системе System V Release 4 . Соответственно ключ -gdwarf+ прибавляет возможностей отладчику gdb . Добавление к этим ключам в конце цифры позволяет увеличить или уменьшить уровень отладки, т.е. управлять размером требуемой отладочной информации.
Например ключ: gcc -g3 . Увеличит уровень отладки до 3 , по умолчанию он равен 2 . При первом уровне отладки компилятор включает в файл минимальное количество отладочной информации достаточное для отладки частей программы, которые вы не планировли отлаживать. В эту информацию входит описание функций и внешних переменных, но не включается информация об локальных переменных и номерах строк исходного текста.
Второй уровень — это уровень по умолчанию, включает в файл большинство нужной отладочной информации. Третий уровень позволяет добавить экстра-информацию, такую как определения присутствующих в программе макросов. Выше вы можете увидеть остальные ключи, которые можно использовать.
Большинство этих ключей предназначено для вывода дампа программы во время компиляции и служит не для отладки программы, а для отладки самого компилятора :)) Поэтому о них можно забыть и не вспоминать. Отладочная информация это конечно хорошо, но она может значительно увеличить объем вашего файла (в тричетыре раза). Для создания программ «релизов» существует отдельная программа, позволяющая удалить отладочную информацию из запускаемого файла. Называется эта программа strip . Для того, чтобы полностью очистить файл от отладочной информации, требуется вызвать ее с ключом -s : strip -s a.out После обработки файла этой командой его размер уменьшился практически в три раза и стал 3156 байт. По сравнению с 11 Кб до этого это очень даже хорошо.
Шаг 3 — Компиляция нескольких файлов
Обычно простые программы состоят из одного исходного файла. Дело обстоит несколько сложнее, если эта программа становится большой.
При работе с такой программой может возникнуть несколько достаточно серьезных проблем: • Файл, становясь большим, увеличивает время компиляции, и малейшие изменения в исходном тексте автоматически вынуждают тратить время программиста на перекомпиляцию программы. • Если над программой работает много человек, то практически невозможно отследить сделанные изменения. • Процесс правки и само ориентирование при большом исходном тексте становится сложным и поиск небольшой ошибки может повлечь за собой вынужденное «изучение» кода заново. Это далеко не все пробемы, которые могут возникнуть при наличии программы «монстра».
Поэтому при разработке программ рекомендуется их разбивать на куски, которые функционально ограничены и закончены. В этом значительно помогает сам язык C++ , предоставляя свой богатый синтаксис. Для того, чтобы вынести функцию или переменную в отдельный файл надо перед ней поставить зарезервированное слово extern . Давайте для примера создадим программу из нескольких файлов. Сначала создадим главную программу, в которой будут две внешние процедуры. Назовем этот файл main.c :
#include // описываем функцию f1() как внешнюю extern int f1(); // описываем функцию f2() как внешнюю extern int f2(); int main() < int n1, n2; n1 = f1(); n2 = f2(); printf(«f1() = %dn»,n1); printf(«f2() = %dn»,n2); return 0; >Теперь создаем два файла, каждый из которых будет содержать полное определение внешней функции из главной программы. Файлы назовем f1.c и f2.c : // файл f1.c int f1() < return 2; >// файл f2.c int f2() < return 10; >После этого процесс компиляции программы с помощью gcc будет выглядеть несколько иначе от описанного в «Шаг 1 — Компиляция программ на языке C/C++» . Компилировать можно все файлы одновременно одной командой, перечисляя составные файлы через пробел после ключа -c : gcc -c main.c f1.c f2.c Или каждый файл в отдельности: gcc -c f1.c gcc -c f2.c gcc -c main.c В результате работы компилятора мы получим три отдельных объектных файла: main.o f1.o f2.o
Чтобы их собрать в один файл с помощью gcc надо использовать ключ -o , при этом линкер соберет все файлы в один:
gcc main.o f1.o f2.o -o rezult В результате вызова полученной программы rezult командой: ./rezult На экране появится результат работы: dron:~# ./rezult f1() = 2 f2() = 10 dron:~# Теперь, если мы изменим какую-то из процедур, например f1() : int f1() < return 25; >То компилировать заново все файлы не придется, а понадобится лишь скомпилировать измененный файл и собрать результирующий файл из кусков: dron:~# gcc -c f1.c dron:~# gcc main.o f1.o f2.o -o rezult2 dron:~# ./rezult2 f1() = 25 f2() = 10 dron:~# Таким образом можно создавать большие проекты, которые больше не будут отнимать много времени на компиляцию и поиск ошибок. Однако помните, не стоит также черезчур разбивать программу, иначе у Вас получится несколько десятков файлов, в которых Вы сами рано или поздно запутаетесь. Найдите «золотую середину», например в отдельные файлы помещайте те функции или классы, с которыми Вам приходится больше всего работать при отладке. После того, как функция будет окончательно отлажена, ее вполне можно перенести в более крупный файл.
Шаг 4 — Библиотеки объектных файлов
В прошлом шаге мы научились создавать объектные файлы. Естественно, если каждая функция будет содержаться в отдельном файле, то таких файлов может оказаться десятки или даже сотни. Управлять таким количеством файлов очень сложно. Для этого был придуман механизм создания библиотек объектных файлов.
Библиотека объектных файлов — это файл содержащий несколько объектных файлов, которые будут использоваться вместе в стадии линковки программы. Нормальная библиотека содержит символьный индекс, который состоит из названий функций и переменных и т.д., которые содержатся в библиотеке.
Это позволяет ускорить процесс линковки программы, так как поиск функций и переменных в объектных файлах библиотеки происходит намного быстрее, чем поиск в наборе указанных объектных файлов. Поэтому использование библиотеки позволяет компактно хранить все требуемые объектные файлы в одном месте, и при этом значительно повысить скорость компиляции.
Объектные библиотеки по способу использования разделяются на два вида: • Статические библиотеки • Динамические библиотеки Статическая библиотека — это коллекция объектных файлов, которые присоединяются к программе во время линковки программы. Таким образом статические библиотеки используются только при созданиии программы.
Потом в работе самой программы они не принимают участие, в отличие от динамических библиотек. Динамическая библиотека — это созданная специальным образом библиотека, которая присоединяется к результирующей программе в два этапа. Первый этап, это естественно этап компиляции.
На этом этапе линковщик встраивает в программу описания требуемых функций и переменных, которые присутствуют в библиотеке. Сами объектные файлы из библиотеки не присоединяются к программе. Присоединение этих объектных файлов(кодов функций) осуществляет системный динамический загрузчик во время запуска программы. Загрузчик проверяет все библиотеки прилинкованные с программе на наличие требуемых объектных файлов, затем загружает их в память и присоединяет их в копии запущенной программы, находящейся в памяти. Сложный процесс загрузки динамических библиотек замедляет запуск программы, но у него есть существунный, даже можно сказать неоценимый плюс — если другая запускаемая программа линкована с этой же загруженной динамической библиотекой, то она использует туже копию библиотеки. Это означает, что требуется гораздо
Источник: studfile.net
Как скомпилировать c++ файл?(ubuntu)
создается файл вот сам cpp файл
#include using namespace std; int main(void) < cout
Отслеживать
задан 18 дек 2019 в 15:17
59 1 1 золотой знак 1 1 серебряный знак 7 7 бронзовых знаков
в терминале ./output
18 дек 2019 в 15:23
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Запуск двойным нажатием определяет настройка Вашего проводника.
Есть вероятность, что она запускается в новой сессии терминала, которая Вам не отображается, а Вы думайте что запуск не произошел.
Для запуска данного приложения Вам необходимо начать сессию командной оболочки bash(ну или чего-то еще что у Вас есть zsh, sh) которая будетВам доступна, перейти в дир. с Вашим кодом и вызвать gcc(g++) (ну или LLVM clang) для сборки Вашего кода
g++ ./source.cpp
Ну или смотря что вы хотите от gcc)) Используйте Ваш рецепт из вопроса )) После этого Вы найдете a.out ELF файл
Для запуска Вы должны быть уверенны что стоит x(execute) бит. можете проверить этой командой
ls -l | fgrep a.out
И получить на выходе что-то по типу
-rwxrwxr-x 1 usr usr 9048 dec 18 00:00 a.out
Если есть x биты — то все отлично, его нет, то сначала вызовете
chmod +x ./app
И далее просто запустите его — В линухе по причине безопасности для запуска нужен абсолютный путь — это можно сделать так :
./app — в конкретной директории
/path_to_/app — из любой директории
где ./ укажет текущий путь($pwd)
Совет: не собирайте все командами в оболочке. лучше собирать утилитой make по рецептам указанным в Makefile.
Для этого Вам понадобится makefile — который можно или написать, или генерировать (вариантов тьма, но лучше научиться юзать CMake https://cmake.org/ — там все есть) он поможет Вам организовать сборку больших решений))
CMake генерирует Вам makefile в соответствии с конфигами которые Вы ему напишите )
Самый минимум для CMake CMakeLists.txt
cmake_minimum_required(VERSION 3.16.0-rc3) set(PROJECT_NAME «Test_for_stack») project($ DESCRIPTION «C++» LANGUAGES C CXX) include_directories($) set(SOURCE_CODE_CPP_MAIN $/source.cpp) add_executable($ $)
Или напишите makefile сами ) Вот лайтовый пример makefile
CC := g++-9 CLEAN_COM := rm -rf compile_flags := -std=c++17 -m64 -march=native -Wall -O2 -Wpedantic -pedantic -fno-inline -DNDEBUG app: main.o $(CC) -o app main.o $(compile_flags) main.o: main.cpp $(CC) -E main.cpp $(compile_flags) >> main.i $(CC) -S main.i $(compile_flags) >> main.s $(CC) -c main.s $(compile_flags) >> main.o .PHONY : clean_buf clean_buf : $(CLEAN_COM) main.i main.s main.o .PHONY : clean clean : $(CLEAN_COM) main.i main.s main.o app
Далее просто дерните в дир. где CMakeLists.txt
cmake . make
cmake . cmake. — build
Источник: ru.stackoverflow.com
Установка GCC в Ubuntu
Большинство программ в Linux написаны на C или С++, и если вы хотите собирать их из исходников, то вам обязательно понадобиться компилятор, также он понадобиться, если захотите начать писать свои программы на одном из этих языков.
Существует два основных компилятора в Linux — это GCC и Clang, они похожи по своим возможностям, но так сложилось, что первый считается стандартом для Ubuntu. GCC расшифровывается как GNU Compiler Collection. В этой статье мы рассмотрим, как выполняется установка GCC в Ubuntu, а также рассмотрим базовые приемы работы с этим набором программ в терминале.
Набор компиляторов GCC
Все программы представляют собой набор машинных команд, которые выполняются процессором. Эти команды — последовательность бит. Но писать программы наборами бит очень неудобно, поэтому были придуманы языки программирования высокого уровня. Код на языке программирования хорошо читаем и понятен для человека, а когда из него нужно сделать программу, компилятор ubuntu преобразует все в машинные команды.
В базовую поставку компилятора входят такие программы:
- libc6-dev — заголовочные файлы стандартной библиотеки Си;
- libstdc++6-dev — заголовочные файлы стандартной библиотеки С++;
- gcc — компилятор языка программирования Си;
- g++ — компилятор языка программирования C++;
- make — утилита для организации сборки нескольких файлов;
- dpkg-dev — инструменты сборки пакетов deb.
Все эти пакеты являются зависимостями пакета build-essential, поэтому для установки всего необходимого достаточно установить этот пакет.
Установка GCC в Ubuntu
Если вас устраивает текущая версия GCC, которая есть в официальных репозиториях дистрибутива, то вам достаточно установить пакет build-essential. Для этого выполните команду:
sudo apt -y install build-essential
После завершения установки все необходимое для компиляции программ будет установлено. И вы сможете использовать компилятор. Рассмотрим версии и расположение файлов компилятора:
whereis gcc make
Если необходима более новая версия компилятора, например, на данный момент последняя версия — 11, то можно использовать PPA разработчиков с тестовыми сборками. Для добавления PPA в систему выполните команды:
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt update
Далее установите сам компилятор:
sudo apt -y install gcc-snapshot sudo apt -y install gcc-11g++-11
Это не заменит ваш текущий компилятор на новый. В системе просто появятся 2 версии компиляторов gcc-11 и g++11, которые вы можете использовать для своих программ. Это лучший вариант на данный момент, но если вы хотите все же сделать gcc-9 компилятором по умолчанию, выполните:
sudo update-alternatives —install /usr/bin/gcc gcc /usr/bin/gcc-9 60 —slave /usr/bin/g++ g++ /usr/bin/g++-9
Готово, теперь вы можете проверить версию gcc-6:
Установка GCC в Ubuntu завершена, и можно переходить к сборке программ. Для удаления компилятора достаточно удалить пакет build-essential при помощи команды:
sudo apt purge -y build-essential sudo apt-y autoremove
Использование GCC в Ubuntu
Рассмотрим пример компиляции минимальной программы hello.c для освоения работы с gcc. Вот код программы, откройте любой текстовый редактор и сохраните его в файле с названием hello.c:
#include
int main(void) printf(«Hello, world!n»);
return 0;
>
Теперь запустим сборку программы:
Когда сборка программы будет завершена, на выходе появится файл с названием a.out. a.out –это имя исполняемого файла, которое по умолчанию, сгенерировано при помощи gcc. Далее можно запустить данный файл:
Готово, компилятор прекрасно работает в системе, и теперь можно писать свои программы или собирать чужие.
Выводы
В этой статье мы рассмотрели, как установить gcc в Ubuntu 20.04, это один из самых популярных компиляторов для этой операционной системы. И устанавливается он очень просто, если у вас остались вопросы, спрашивайте в комментариях!
На завершение видео с демонстрацией самого процесса:
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
Источник: losst.pro