Лабораторная работа 1 для студентов курса “Программирование на основе классов и шаблонов” 2 семестра кафедры ИУ5 МГТУ им Н.Э. Баумана.
Целью лабораторной работы является формирование у студентов практических навыков проектирования и использования статических библиотек на языке программирования C++ с применением системы автоматизации сборки CMake, а также освоение принципов разработки кроссплатформенных программных приложений.
В ходе выполнения лабораторной работы студенты должны закрепить знания по модульной организации программного кода и компоновке программных проектов.
Зайдите в свою локальную директорию с репозиторием для выполнения лабораторных работ. Заберите ветку с соответствующей лабораторной работой из общего репозитория:
git pull upstream
или
git pull upstream lab_1
Переключитесь на ветку с текущей лабораторной работой:
git checkout lab_1
Свяжите ветку локального репозитория с вашим удаленным репозиторием:
git push --set-upstream origin lab_1
В рамках лабораторной работы необходимо:
Создать проект статической библиотеки с использованием системы сборки CMake.
Реализовать в библиотеке набор функций или класс, обеспечивающий заданную функциональность.
Создать консольное приложение на языке C++, использующее разработанную статическую библиотеку.
Подключить библиотеку к приложению и продемонстрировать корректность её работы.
Обеспечить возможность сборки и запуска проекта в операционных системах семейства Linux.
Вариант 1
Реализовать в библиотеке операции умножения и деления. Предусмотреть обработку деления на ноль.
Вариант 2
Создать библиотеку утилит для обработки аргументов командной строки.
Вариант 3
Реализовать в библиотеке функции для работы с массивом чисел (поиск минимального, максимального значения и вычисление среднего).
Вариант 4
Добавить в библиотеку функцию возведения числа в степень без использования стандартных библиотечных функций.
Вариант 5
Реализовать функции для генерации псевдослучайных чисел и заполнения ими массива.
Вариант 6
Реализовать в библиотеке функции для вычисления факториала.
Вариант 7
Создать библиотеку для работы со строками (конкатенация, определение длины строки) без использования стандартных библиотечных функций.
Вариант 8
Реализовать в библиотеке функции для сортировки массива целых чисел.
Вариант 9
Создать библиотеку для статистической обработки данных (среднее значение, медиана, дисперсия).
Вариант 10
Добавить в библиотеку функции для поиска элемента в массиве (линейный поиск).
Вариант 11
Реализовать библиотеку для работы с датами (сравнение дат, вычисление разницы между датами).
Вариант 12
Создать библиотеку для работы с геометрическими фигурами (вычисление площади и периметра).
Вариант 13
Реализовать функции для перевода целых чисел из одной системы счисления в другую.
Вариант 14
Создать библиотеку утилит для обработки аргументов командной строки.
Вариант 15
Реализовать библиотеку вспомогательных функций для работы с файлами (чтение и запись текстовых данных).
Вариант 16
Добавить в библиотеку функции для вычисления наибольшего общего делителя и наименьшего общего кратного двух чисел.
Вариант 17
Добавить в библиотеку функции для проверки числа на простоту и разложения числа на простые множители.
Заголовочный файл (mylib.h).
В нём объявления функций — что библиотека умеет:
#ifndef MYLIB_H
#define MYLIB_H
int add(int a, int b);
int sub(int a, int b);
#endif
Файл реализации (mylib.cpp).
Здесь реализация функций:
#include "mylib.h"
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
Компиляция в объектный файл:
g++ -c mylib.cpp
где флаг -с только компилировать, но не линковать.
g++ переводит mylib.cpp в объектный файлmylib.oУпаковка в статическую библиотеку:
ar rcs libmylib.a mylib.o
ar (archiver) - инструмент для создания статических библиотек в Linux / Unix.
Файл libmylib.a — это статическая библиотека.
rcs:
ar всё равно создаст, но будет ворчать предупреждением)итог
ar rcs libmylib.a mylib.o
Теперь libmylib.a — статическая библиотека.
Файл программы (main.cpp)
#include "mylib.h"
#include <iostream>
int main() {
std::cout << add(3, 4);
}
Компиляция программы:
g++ main.cpp -L. -lmylib -o app
где:
mylib.a-l + mylib-L. где искать библиотеку: «ищи библиотеку в текущей папке»код библиотеки попадёт внутрь app, компоновщик сам выберет подходящий файл.
или принудительно
g++ main.cpp ./libmylib.a -o app
Компиляция с поддержкой динамической загрузки:
g++ -fPIC -c mylib.cpp
где флаг -fPIC - Position Independent Code
Почему это нужно:
.so может быть загружена в разные адреса разными процессамиСоздание .so:
g++ -shared -o libmylib.so mylib.o
где флаг -shared указание линковщику -> «собери shared library, а не исполняемый файл»
результат: libmylib.so это динамическая библиотека.
Компиляция программы:
g++ main.cpp -L. -lmylib -o app
Флаги:
-L. — где искать библиотеки (текущая папка)-lmylib — ищет libmylib.so (сначала .so, потом .a)-o app — имя исполняемого файла.ВАЖНО
На этапе компиляции библиотека должна быть найдена,
но на этапе запуска — тоже.
Перед запуском:
export LD_LIBRARY_PATH=.
./app
LD_LIBRARY_PATH — список директорий, где динамический загрузчик ищет .so во время запуска.
(или положить .so в стандартную папку)
Коротко
| Флаг / переменная | Зачем |
|---|---|
-fPIC |
Код можно загружать по любому адресу |
-shared |
Собрать .so, а не исполняемый файл |
-L |
Где искать библиотеки при линковке |
-l |
Какую библиотеку подключать |
LD_LIBRARY_PATH |
Где искать .so при запуске |
Главная идея CMake:
CMake не компилирует код сам.
Он генерирует инструкции для компилятора:
project/
│
├── CMakeLists.txt
├── main.cpp
├── mylib.h
└── mylib.cpp
Самый простой CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# создаём библиотеку
add_library(mylib mylib.cpp)
# создаём исполняемый файл
add_executable(app main.cpp)
# связываем программу с библиотекой
target_link_libraries(app mylib)
Сборка проекта
mkdir build
cd build
cmake ..
cmake --build .
Результат:
библиотека собирается автоматически
программа с ней связывается
Статическая или динамическая библиотека
По умолчанию CMake решает сам (обычно динамическая).
можно явно указать:
add_library(mylib STATIC mylib.cpp) - статическая
add_library(mylib SHARED mylib.cpp) - динамическая
Где тут -l и -L? - их нет.
CMake:
Как CMake понимает, какие .h подключать
Если заголовок рядом: #include "mylib.h"— всё работает автоматически.
Если в отдельной папке:target_include_directories(mylib PUBLIC include) путь, где лежат .h файлы библиотеки.
Отчёт по лабораторной работе должен содержать:
Титульный лист с указанием дисциплины, номера лабораторной работы, ФИО студента и группы.
Цель лабораторной работы.
Формулировку задания и номер варианта.
Краткие теоретические сведения по теме работы (выполняются рукописно, разборчивым почерком, на отдельном листе бумаги).
Описание структуры проекта и используемых файлов.
Исходный код разработанной статической библиотеки и основного приложения.
Результаты выполнения программы (скриншоты или вывод в консоль).
Выводы по результатам выполненной работы.
Что такое статическая библиотека и в чём её назначение?
В чём различие между статическими и динамическими библиотеками?
На каком этапе происходит подключение статической библиотеки к программе?
Назначение файлов заголовков в библиотеке.
Основные команды CMake для создания библиотек и исполняемых файлов.
Для чего используется команда target_link_libraries?
Преимущества и недостатки статических библиотек.
Что означает кроссплатформенность программного обеспечения?