Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
компиляция и линковка
Почему это важно для SCA/OSA
Зависимость C/C++ входит в продукт не в момент #include, а в момент линковки: компилятор превращает каждую единицу трансляции (.cpp → .o), а линкер сшивает объектные файлы и подставляет внешние библиотеки по флагам -l/-L. Именно на стыке «компиляция → линковка» состав ПО окончательно фиксируется — и именно здесь его проще всего честно зафиксировать. Поздний скан готового бинаря восстанавливает только часть этой картины (динамическую секцию), потому что к финальному артефакту уже не приложена команда сборки.
Для SCA это значит, что полноту перечня компонентов даёт не сканер, а перехват реальных вызовов компилятора и линкера. Если эту точку упустить, неполный SBOM выдаётся за полный, а false negative при матчинге на уязвимости появляется не из-за плохого сканера, а из-за того, что зависимость никогда не была записана.
Как это проявляется
Конвейер виден в verbose-логе сборки. У компиляции и линковки — разные строки, и разный набор флагов, по которым читается состав:
# компиляция: единица трансляции -> объектный файл; интересны -I и -D, но НЕ состав линковки
g++ -c -O2 -I/opt/openssl/include -DUSE_TLS net.cpp -o net.o
# линковка: здесь появляются реальные компоненты (-l, -L, -l:lib*.a)
g++ -o app main.o net.o -L/usr/lib/x86_64-linux-gnu -lssl -lcrypto -lz
Команда -c (только компиляция) даёт -I — путь к заголовкам, но это ещё не зависимость (см. include не равен зависимости). Состав появляется лишь в финальной строке линковки с -o app. Если перехватывать только компиляцию, видны #include, но не библиотеки; если ловить только линковку — наоборот.
Инкрементальная сборка прячет линковку При повторном
makeбез изменений линкер не вызывается — цель уже актуальна (Nothing to be done for 'all'), и строка с-lв лог не попадает. Перехват состава имеет смысл только на чистой пересборке (make cleanили сборка в пустом дереве). Это самая частая причина, по которой build-scan «ничего не нашёл».
Слепая зона или приём
Приём — детерминированно собрать в чистом дереве с перехватом команд компилятора, а не полагаться на флаги конкретной системы сборки (которые везде разные: make V=1, make VERBOSE=1, ninja -v). Кросс-системный способ — обёртка, перехватывающая exec компилятора:
# compile_commands.json: что именно компилировалось и с какими -I/-D
bear -- make # или: compiledb make
# перехват линковки: реальные строки с -l / -L / -static
make clean && make V=1 2>&1 | tee build.log
compile_commands.json фиксирует стадию компиляции (заголовки, дефайны), build.log — стадию линковки (библиотеки). Вместе они закрывают обе половины конвейера. Слепая зона остаётся одна: код, попадающий в бинарь через уже собранные объектные файлы или статические архивы без отдельного -l, — его ловит только разбор линковки и последующий бинарный анализ.
Что делать на проекте
- Всегда снимать состав на чистой пересборке —
make cleanпередmake V=1/VERBOSE=1; инкрементальный лог не годится. - Разделять два артефакта:
compile_commands.json(черезbear/compiledb) для-I/-Dиbuild.logдля строк линковки. - Из лога вытаскивать именно строки линкера (
grep -E 'gcc|g\+\+|c\+\+|ld') и нормализовать список-l— это и есть кандидаты в компоненты. - Сверять число библиотек по
-lс числом сторонних#include: заметное расхождение — сигнал о header-only или статически вшитом коде. - Различать стадии в отчёте: «видели в компиляции» (заголовок) и «видели в линковке» (компонент) — это разный confidence.
- Складывать
build.logв аудиторские артефакты сборки — он доказывает происхождение состава.
Связь
- Модуль: М09. C/C++ legacy
- Практики: П19. C C++ make build inventory · П20. CMake dependency graph
- Нормативка: ГОСТ Р 56939-2024 · NIST SP 800-218 SSDF (PS.3.2, PW.4)
- Смежные заметки 06: include не равен зависимости · динамическая линковка · статическая линковка · ldd readelf objdump · build logs как аудиторский артефакт