Лучшие практики в отношении связывания статических библиотек и структуры каталогов проектов в C

У меня есть проект на C, и из-за характера приложения, которое я создаю, я решил статически связать libconfig с моим окончательным двоичным файлом, чтобы минимизировать внешние зависимости, необходимые для его использования. Раньше я динамически связывал библиотеки только с помощью стандартного метода, просто используя флаги, указывающие на /usr/lib и /usr/include, оставляя нетронутой структуру каталогов моего личного проекта.

Однако на этот раз я скомпилировал статический libconfig.a и включил его в свою структуру каталогов, а Makefile использовал его для связывания, а также необходимый файл заголовка для библиотеки, помещенный в мой каталог include/, который содержит файлы заголовков для моей библиотеки. исходные .c файлы проектов. Видеть:

project/
├── LICENSE
├── Makefile
├── README.md
├── bin/
├── include/
│   ├── headerfile1.h
│   ├── headerfile2.h
│   └── libs
│       └── libconfig.h
├── lib/
│   └── libconfig.a
├── obj/
└── src
    ├── srcfile1.c
    └── srcfile2.c

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

Не уверен, действительно ли это здесь по теме... Основная проблема, ИМХО, заключается в том, что у вас есть каталог со смешанным исходным кодом, содержащий внешний инструмент. Это означает, что 1/ вы привязываете свой исходный код к определенной цепочке сборки и 2/ вам придется следить за изменениями версий libconfig. Я понимаю, что это может облегчить перенос вашего кода на новую машину, использующую ту же систему, включая цепочку сборки, но что, если вам придется использовать его, скажем, в системе FreeBSD (при условии, что вы в настоящее время используете Linux)?

Serge Ballesta 01.05.2024 12:06

Вы можете рассмотреть Категорический императив: Что бы произошло, если бы все захотели свести к минимуму свои зависимости и поместить в свои пакеты статические сборки и замороженные заголовки своих зависимостей? В любом случае, вы предоставите пакет, который невозможно собрать из исходного кода, и какой смысл заставлять пользователей компилировать исходный код? Лучше просто снабдить свой исполняемый файл libconfig статически связанным, если вы настаиваете на том, чтобы он не был динамической зависимостью, и вы будете рады отделить свою программу от исходного кода libconfig.

Mike Kinghan 01.05.2024 12:27

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

Zsargul 01.05.2024 13:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У меня есть проект на C, и из-за характера приложения, которое я создаю, я решил статически связать libconfig с моим окончательным двоичным файлом, чтобы минимизировать внешние зависимости, необходимые для его использования.

Иногда это делается, чаще всего в форме статического связывания всех зависимостей.

Еще одна вещь, которая кажется более распространенной, — это динамическое связывание двоичного дистрибутива программного обеспечения с частными версиями общих библиотек, которые он предоставляет сам (включая сторонние библиотеки). Лично мне это не очень нравится, но у этого есть некоторые преимущества.

Однако это совершенно отдельные вопросы от того, как устроен исходник проекта и что в него входит.

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

Не существует стандартов для организации систем проектирования и сборки. В лучшем случае существуют свободные условности.

Один из способов, с помощью которого некоторые проекты справляются со сторонними зависимостями, которые, как они подозревают, у других могут возникнуть трудности с получением, — это объединение исходного кода для этих зависимостей. Затем они также настроят свою систему сборки для создания зависимости. Иногда у них будет (и, по моему мнению, они всегда должны быть) простые средства для сборки на основе библиотек, предоставляемых системой, вместо использования связанной копии. Это в значительной степени ортогонально связыванию — в сочетании с этим вы можете выполнять как статическое, так и динамическое связывание.

Другой способ работы проектов со сторонними зависимостями, особенно с теми, которые легко доступны, — это просто документировать их зависимости вместе с инструкциями о том, как их получить при необходимости.


НО если libconfig — единственная зависимость, которая вас беспокоит, то я думаю, вы делаете много шума из ничего. Это широко распространенная библиотека с открытым исходным кодом, с долгой историей и до сих пор поддерживаемая, с тщательно подобранными версиями, доступными во всех наиболее популярных дистрибутивах Linux, и при необходимости ее легко собрать из исходного кода.

libconfig действительно моя единственная зависимость, как вы упомянули. Я решил просто задокументировать инструкции по ручной сборке libconfig, если кто-то действительно хочет скомпилировать программу из исходного кода. Это казалось «чище», чем наличие каталога с несколькими исходными кодами (или, скорее, просто моего исходного кода, сопровождаемого предварительно созданной статической библиотекой).
Zsargul 01.05.2024 16:50

Кроме того, я не уверен, правильно ли я вас понял в отношении «Иногда у людей есть простые средства для сборки на основе библиотек, предоставляемых системой». Как это можно сделать, если пользователю необходимо установить внешнюю библиотеку типа libconfig?

Zsargul 01.05.2024 17:41

@Zsargul, «библиотеки, предоставляемые системой», следует отличать от тех, которые входят в комплект вашего программного обеспечения. Если вы используете, скажем, apt или dnf для установки библиотеки, то установленная библиотека интегрируется и предоставляется системой. Полагаю, можно выделить установки персональных библиотек как третью категорию, но на практике требования к их поддержке мало чем отличаются от требований к поддержке системных библиотек.

John Bollinger 01.05.2024 19:12

Другие вопросы по теме