Каков наилучший способ устранить предупреждение компоновщика MS Visual C ++: «предупреждение LNK4221»? - PullRequest
17 голосов
/ 01 декабря 2009

У меня есть исходный файл CPP, который использует # if / # endif для полной компиляции в определенных сборках. Однако при этом выдается следующее предупреждение.

warning LNK4221: no public symbols found; archive member will be inaccessible

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

Каков наилучший способ избавиться от этого предупреждения (без простого подавления предупреждения в командной строке компоновщика)?

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

Еще одно требование: исправление должно быть в состоянии противостоять сборкам отдельных файлов или сборке Unity (объединить сборки файлов CPP), поскольку одна из наших конфигураций сборки - это массовая сборка (например, сборка Unity, но группы групповых файлов вместо один главный файл единства).

Ответы [ 3 ]

20 голосов
/ 01 декабря 2009

Использовать анонимное пространство имен:

namespace { char dummy; };

Символы в таком пространстве имен имеют внешнюю связь, поэтому в таблице экспорта будет что-то. С другой стороны, само имя пространства имен будет отличаться (вы можете думать о нем как о «случайно сгенерированном») для каждой единицы перевода, так что никаких столкновений.

12 голосов
/ 01 декабря 2009

ОК, исправление, которое я собираюсь использовать, - это предложение Павла с небольшим изменением. Причина, по которой я использую это исправление, заключается в том, что это простой макрос для вставки, и он будет работать как в массовых сборках / единстве сборки, так и в обычных сборках:

Общий заголовок:

// The following macro "NoEmptyFile()" can be put into a file
// in order suppress the MS Visual C++ Linker warning 4221
//
// warning LNK4221: no public symbols found; archive member will be inaccessible
//
// This warning occurs on PC and XBOX when a file compiles out completely
// has no externally visible symbols which may be dependant on configuration
// #defines and options.

#define NoEmptyFile()   namespace { char NoEmptyFileDummy##__LINE__; }

Файл, который может полностью скомпилироваться:

NoEmptyFile()
#if DEBUG_OPTION
      // code
#endif // DEBUG_OPTION
1 голос
/ 01 марта 2017

(хотя обсуждение уже старое, и я не могу комментировать напрямую @ ответ Адисака), я думаю, что для этого нужна дополнительная магия расширения макроса:

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define NONEMPTY_TRANSLATION_UNIT char TOKENPASTE2(NoEmptyFileDummy, __LINE__);
...