Что такое правильное соглашение об именах для библиотек MSVC, статических библиотек и библиотек импорта - PullRequest
11 голосов
/ 26 января 2010

Что такое стандартное или «самое популярное» соглашение об именах для сборок библиотеки MSVC.

Например, для следующих платформ библиотека foo имеет следующие соглашения:

Linux / gcc:

shared: libfoo.so
import: ---
static: libfoo.a

Cygwin / GCC:

shared: cygfoo.dll
import: libfoo.dll.a
static: libfoo.a

Windows / MinGW:

shared: libfoo.dll
import: libfoo.dll.a
static: libfoo.a

Что следует использовать для buidls MSVC? Насколько я знаю, обычно это имена foo.dll и foo.lib, но как вы обычно отличаете библиотеку импорта от статической?

Примечание: Я спрашиваю, потому что CMake создает весьма неприятное столкновение между ними, называя и библиотеку импорта, и статическую библиотеку foo.lib. См. отчет об ошибке . Ответ будет помогите мне убедить разработчиков исправить эту ошибку.

Ответы [ 6 ]

5 голосов
/ 28 января 2010

Как уже упоминалось, нет стандартов, но есть популярные соглашения. Я не уверен, как однозначно судить о том, что является самым популярным соглашением. В дополнение к номенклатуре статических и импортных библиотек, о которой вы спрашивали, существует аналогичное различие между именами библиотек Release и библиотек Debug, особенно в Windows.

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

Обычно я использую foo.dll и foo.lib для общей библиотеки в Windows и foo_static.lib для статической библиотеки, когда я хочу иметь как общую, так и статическую версии. Я видел, как другие использовали это соглашение, поэтому оно может быть «самым популярным».

Поэтому я бы порекомендовал следующее дополнение к вашей таблице:

Windows / MSVC:

shared: foo.dll
import: foo.lib
static: foo_static.lib

Тогда в cmake вы можете либо

add_library(foo_static STATIC foo.cpp)

или

add_library(FooStatic STATIC foo.cpp)
set_target_properties(FooStatic PROPERTIES OUTPUT_NAME "foo_static") 

если по какой-то причине вы не хотите использовать «foo_static» в качестве символического имени библиотеки.

4 голосов
/ 04 февраля 2010

Вы различаете библиотеку и .dll по расширению. Но вы различаете библиотеку импорта и статическую библиотеку по имени файла , а не по расширению.

Не будет ни одного случая, когда существует библиотека импорта для набора кода, который был построен как статическая библиотека, или где статическая библиотека существует для библиотеки DLL. Это две разные вещи.

Единого стандартного соглашения о именах MSVC не существует. Как правило, имя библиотеки, оканчивающееся на «D», часто является отладочной сборкой кода библиотеки, msvcrtd.dll против msvcrt.dll, но кроме этого стандартов нет.

2 голосов
/ 02 февраля 2010

Как уже говорили другие, не существует единого стандарта для именования файлов в Windows.

Для нашей полной базы продуктов, которая охватывает 100-е годы exe, dll и static libs, мы успешно использовали следующее в течение многих лет, и это избавило от многих недоразумений. По сути, это сочетание нескольких методов, которые я видел в течение многих лет.

В двух словах: все наши файлы имеют префикс и суффикс (не считая самого расширения). Все они начинаются с «ом» (в зависимости от названия нашей компании), а затем имеют комбинацию из 1 или 2 символов, которая приблизительно идентифицирует область кода.

Суффикс объясняет, к какому типу встроенных файлов они относятся, и включает до трех букв, используемых в комбинации, в зависимости от сборки, которая включает Unicode, Static, Debug (сборки по умолчанию являются Dll и не имеют явного идентификатора суффикса). Когда мы запустили эту систему, Unicode не был таким распространенным, и нам приходилось поддерживать сборки Unicode и Non-Unicode (до Windows 2000 OS), теперь все построено исключительно на Unicode, но мы все еще используем одну и ту же номенклатуру.

Так что типичный "набор" файлов .lib может выглядеть как

omfThreadud.lib (Unicode/Debug/Dll)
omfThreadusd.lib (Unicode/Static/Debug)
omfThreadu.lib (Unicode/Release/Dll)
omfThreadus.lib (Unicode/static)

Все файлы встроены в общую папку bin, что устраняет многие проблемы dll-hell для разработчиков, а также упрощает настройку параметров компилятора / компоновщика - все они указывают на одно и то же местоположение с использованием относительных путей и никогда не требуется ручное (или автоматическое) копирование библиотек, в которых нуждается проект. Наличие этих суффиксов также устраняет любую путаницу в отношении того, какой тип файла у вас может быть, и гарантирует, что у вас не может быть смешанного сценария, когда вы записываете отладочную DLL в выпускной комплект или наоборот. Все exe-файлы также используют аналогичный суффикс (Unicode / Debug) и встраиваются в одну и ту же папку bin.

Существует также одна отдельная папка «include», каждая библиотека имеет один заголовочный файл в папке include, который соответствует имени библиотеки / dll (например, omfthread.h). Этот файл #include включает все остальные элементы, которые выставлено этой библиотекой. Это будет проще, если вы хотите использовать функциональность, которая есть в foo.dll, вы просто #include "foo.h"; наши библиотеки сильно сегментированы по областям функциональности - фактически у нас нет никаких dll «швейцарского армейского ножа», поэтому включение всех функций библиотеки имеет смысл. (Каждый из этих заголовков также включает другие обязательные заголовки, будь то наши внутренние библиотеки или SDK других поставщиков)

Каждый из этих включаемых файлов внутренне использует макросы, которые используют # pramga для добавления соответствующего имени библиотеки в строку компоновщика, так что отдельные проекты не должны быть связаны с этим. Большинство наших библиотек могут быть построены статически или в виде DLL, и #define OM_LINK_STATIC (если определено) используется для определения того, чего хочет отдельный проект (мы обычно используем DLL, но в некоторых случаях статические библиотеки, встроенные в .exe, делают больше смысла для развертывания или других причин)

#if defined(OM_LINK_STATIC)
 #pragma comment (lib, OMLIBNAMESTATIC("OMFTHREAD"))
#else
 #pragma comment (lib, OMLIBNAME("OMFTHREAD"))
#endif

Эти макросы (OMLIBNAMESTATIC & OMLIBNAME) используют _DEBUG, чтобы определить, какой это тип сборки, и сгенерировать правильное имя библиотеки для добавления в строку компоновщика.

Мы используем общее определение в статической и dll-версиях библиотеки для управления правильным экспортом класса / функций в сборках dll. Каждый класс или функция, экспортируемые из библиотеки, украшены этим макросом (имя которого совпадает с базовым именем библиотеки, хотя это в значительной степени неважно)

class OMUTHREAD_DECLARE CThread : public CThreadBase

В DLL-версии настроек проекта мы определяем OMFTHREAD_DECLARE = ​​__declspec (dllexport), в статической версии библиотеки мы определяем OMFTHREAD_DECLARE как пусто .

В заголовочном файле библиотеки мы определяем его в зависимости от того, как клиент пытается с ним связаться

#if defined(OM_LINK_STATIC)
 #define OMFTHREAD_DECLARE
#else
 #define OMFTHREAD_DECLARE __declspec(dllimport)
#endif

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

2 голосов
/ 29 января 2010

Стандартных правил именования для библиотек не существует. Традиционные имена библиотек имеют префикс lib. У многих компоновщиков есть опции для добавления lib к имени библиотеки в командной строке.

Статические и динамические библиотеки обычно определяются по расширению файла; хотя это не обязательно. Таким образом, libmath.a будет статической библиотекой, тогда как libmath.so или libmath.dll будет динамической библиотекой.

Распространенным соглашением об именах является добавление категории библиотеки к имени. Например, отладочная статическая математическая библиотека может быть «libmathd.a» или в Windows «lib_math_debug». Некоторые магазины также добавляют Unicode в качестве атрибута имени файла.

Если хотите, вы можете добавить _msvc к имени библиотеки, чтобы указать, что библиотека требуется или была создана MSVC (чтобы отличаться от GCC и других инструментов). Популярное соглашение при работе с несколькими платформами заключается в размещении объектов и библиотек в папках, специфичных для платформы. Например, папка ./linux/ будет содержать объекты и библиотеки для Linux и аналогично ./msw/ для платформы Microsoft Windows.

Это проблема стиля. Вопросы стиля часто рассматриваются как религиозные: ни один из них не является неправильным, универсального стиля нет, и они являются индивидуальным предпочтением. Какую бы систему вы ни выбрали, просто будьте последовательны.

2 голосов
/ 29 января 2010

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

Мое соглашение состоит в том, чтобы называть мои динамические и статические .lib одинаковыми, но помещать их в разные каталоги, если проект поддерживает статические и динамические связи. Например:

foo-static
   foo.lib

foo
   foo.lib
   foo.dll

Библиотека для ссылки зависит от выбора каталогов библиотеки, поэтому она почти полностью отделена от остальной части процесса сборки (она не появится в исходном коде, если вы используете средство MSVC #pragma comment(lib,"foo.lib"), и не не отображаются в списке библиотек импорта для компоновщика).

Я видел это довольно много раз. Кроме того, я думаю, что проекты, основанные на MSVC / Windows, имеют тенденцию чаще придерживаться одного официального типа связывания - статического, или динамического. Но это только мое личное наблюдение.

Короче говоря: Windows / MSVC

shared: foo.dll
import: foo.lib
static: foo.lib

Вы должны быть в состоянии использовать этот шаблон на основе каталогов с CMAKE (никогда не использовал его). Кроме того, я не думаю, что это «ошибка». Это просто отсутствие стандартизации. CMAKE делает (imho) правильную вещь , а не , чтобы установить псевдостандарт, если всем это нравится по-разному.

1 голос
/ 27 октября 2015

Насколько я знаю, до сих пор нет никаких соглашений в отношении этого. Вот пример того, как я это делаю:

{Проект} {подмодуль} {Платформа} {Архитектура} {CompilerRuntime} _ {BuildType} .lib / длл

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

Project: содержит имя / идентификатор проекта. Желательно как можно короче. т.е. "днк"

SubModule: необязательно. содержит имя модуля Желательно как можно короче. то есть "dna_audio"

Платформа: определяет платформу, для которой скомпилирован бинарный файл. то есть "win32" (Windows), "winrt", "xbox", "android".

Архитектура: описывает архитектуру, для которой скомпилирован бинарный файл. то есть "x86", "x64", "arm". Там, где имена архитектуры равны для разных битов, используйте ее имя, за которым следует битность. то есть. "name16", "name32", "name64"

CompilerRuntime: необязательно. Не все двоичные файлы ссылаются на время выполнения компилятора, но если они это делают, они включены здесь. то есть "vc90" (Visual Studio 2008), "gcc". Где применимо квартира может быть включена, например, "vc90mt"

BuildType: необязательно. Это может содержать буквы (в любом желаемом порядке), каждый из которых что-то говорит о специфике сборки. d = отладка (опускается, если освобождается) t = статическая (опускается, если динамическая) a = ansi (опускается, если unicode)

Примеры (при условии, что проект называется «ДНК»): dna_win32_x86_vc90.lib / длл dna_win32_x64_vc90_d.lib / длл dna_win32_x86_vc90_sd.lib dna_audio_win32_x64_vc90.lib / длл dna_audio_winrt_x64_vc110.lib / длл

...