Visual Studio 2010 странное "предупреждение LNK4042"

Меня только что избили (довольно тяжело) по голове каким-то нетривиальным предупреждением из Visual Studio 2010 (C++).

Компиляция дала следующий вывод:

1 Debug \ is.obj: предупреждение LNK4042: объект указан более одного раза; дополнения игнорируются
1 Debug\make.obj: предупреждение LNK4042: объект указан более одного раза; дополнения игнорируются
1 Debug\view.obj: предупреждение LNK4042: объект указан более одного раза; дополнения игнорируются
1 identity.obj: ошибка LNK2019: неразрешенный внешний символ void __cdecl test::identity::view(void) (?view@identity@test@@YAXXZ) упоминается в функции void __cdecl test::identity::identity(void) (? Тождественное @0test@@YAXXZ)
1 identity.obj: ошибка LNK2019: неразрешенный внешний символ void __cdecl test::identity::make(void) (?make@identity@test@@YAXXZ) упоминается в функции void __cdecl test::identity::identity(void) (? Тождественное @0test@@YAXXZ)
1 range.obj: ошибка LNK2019: неразрешенный внешний символ void __cdecl test::range::is(void) (?is@range@test@@YAXXZ) ссылка на функцию void __cdecl test::range::range(void) (? Диапазон @0test@@YAXXZ)

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

Моя иерархия папок выглядит так:

src/
  identity/
    is.cpp
    make.cpp
    view.cpp
  range/
    is.cpp
    make.cpp
    view.cpp

как и иерархия в решении (я всегда настраиваю ее так, чтобы она имитировала "реальную" структуру папок).

И диагностические выводы:

Debug\is.obj
Debug\make.obj
Debug\view.obj

Наряду с предупреждением о том, что .obj был дважды передан компоновщику, и этот будет проигнорирован.

Больше не ищите: Visual аккуратно сгладил иерархию папок и поэтому не может аккуратно скомпилировать исходный код.

На данный момент я просто думаю о переименовании файлов, которые должны охватить проблему...

... но есть ли способ заставить Visual Studio НЕ сгладить иерархию файлов?

11 ответов

Решение

Просто хотел опубликовать то, что я считаю ответом, если вы откроете свойства для всего проекта и измените значение в C/C++ -> Output Files -> "Object File Name" быть следующим:

$ (IntDir) /% (RelativeDir) /

Я полагаю, что в VS 2010 это устранит неоднозначность всех объектных файлов (так как я полагаю, что windows не позволит вам ни при каких сумасшедших обстоятельствах иметь два файла с одинаковыми именами в одном каталоге). Пожалуйста, также проверьте детали здесь.

У меня была похожая проблема с предупреждением компоновщика LNK4042: объект указан более одного раза; Экстры игнорируются. В моем случае Visual Studio пыталась скомпилировать заголовочные и исходные файлы с одинаковыми именами. MyClass.h а также MyClass.cpp, Это произошло потому, что я переименовал .cpp подать в .h и Visual Studio запутался. Я заметил проблему, посмотрев журналы компилятора в Debug каталог. Чтобы решить просто удалить .h файл из проекта, затем добавьте его снова.

Щелкните правой кнопкой мыши файл.cpp в окне обозревателя решений, выберите Свойства, C/C++, Выходные файлы, Имя файла объекта. По умолчанию $(IntDir)\Вот что делает уплощение. Весь файл.obj будет помещен в $(IntDir), каталог "Debug" в конфигурации отладки.

Вы можете изменить настройку, скажем, $(IntDir)\is2.obj, Или выберите все файлы из одной группы (используйте Shift+ клик) и измените настройку, скажем, $(IntDir)\identity\

Или вы можете изменить имя файла.cpp, чтобы файлы.obj не перезаписывали друг друга. Наличие файлов с одинаковым именем в двух каталогах немного странно.

Или вы можете создавать несколько проектов, например, проекты.lib для файлов в идентичности и диапазоне. Обычно делается в проектах makefile, например. Это, однако, делает управление настройками компиляции и ссылки более сложным, если вы не используете листы свойств проекта.

Щелкните правой кнопкой мыши файл заголовка -> Свойство -> ItemType (выберите заголовок C/C++). Сделайте то же самое с файлом Cpp, но выберите C/C++ COmpiler (это работает для меня)

В качестве альтернативы удалению и созданию нового файла вы можете изменить параметры компиляции / включения.

Перейдите к файлу project.vcxproj, откройте его в редакторе, найдите строку, похожую на HTML <ItemGroup>,

Это должно выглядеть примерно так:

<ItemGroup>
<ClCompile Include="implementation.cpp" />
</ItemGroup>

а также

<ItemGroup>
<ClInclude Include="declaration.hpp" />
</ItemGroup>`

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

Я использую $(IntDir)\%(Directory)\ в C/C++ -> Выходные файлы -> "Имя файла объекта".

У меня была эта проблема с stdafx.cpp. Каким-то образом stdafx.cpp был продублирован, поэтому появился второй StdAfx.cpp (обратите внимание на другой случай).

После того как я удалил StdAfx.cpp все работало нормально!

Использование VS 2010.

Я имел обыкновение иметь в одном проекте файлы .c и .cpp с одинаковыми именами файлов. Файлы были в папках повсюду, и решения, предоставленные другими, создали беспорядок и ад папки (в моем случае). Даже сборки Release перезаписывают сборки Debug!

Хорошим (не идеальным) решением было бы использование $ (ParentName), но по какой-то непонятной причине он был удален из более поздних версий Visual Studio (2015+).

Теперь я успешно использую: $(IntDir)%(Filename)%(Extension).obj

который по крайней мере отделяет встроенные объектные файлы .c от .cpp.

Я хотел бы указать на одну возможную причину, по которой ItemType из .h file изменится с C/C++ header к C/C++ compiler:

  1. в Solution Explorer окно VS (2019 здесь), щелкните правой кнопкой мыши имя проекта, выберите Add -> New Item;
  2. Выберите C++ File (.cpp) шаблон, но введите в поле ввода имени и щелкните OK добавить его;
  3. Тогда вы столкнетесь с LNK4042 предупреждение, если something.h файл должен быть включен более чем в один .cpp файлы.

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

Затем я вспомнил, что когда я изначально создавал этот заголовок, я случайно выбрал «add->new item->c++ file», и хотя я назвал его «something.h», похоже, Visual Studio посчитала их оба одинаковыми типами файлов. из-за неправильного действия я добавил его. Это стало очевидным при изучении журналов вывода сборки.

РЕШЕНИЕ (с использованием VS Community 2019)

  1. Сначала сделайте резервную копию проекта (на всякий случай).
  2. Щелкните правой кнопкой мыши файл заголовка с нарушением и выберите «Исключить из проекта» (это не удалит их; проект VS просто проигнорирует их).
  3. Сделайте то же самое для соответствующего файла .c или .cpp.
  4. Сделайте сборку-> Очистить проект
  5. Сделайте Build-> Rebuild on project - конечно будут ошибки ---
  6. Щелкните правой кнопкой мыши заголовочные файлы-> Добавить-> Существующий элемент, затем выберите файл .h
  7. Щелкните правой кнопкой мыши Исходные файлы-> Добавить-> Существующий элемент, выберите файл .c или .cpp.
  8. Сделайте Build-> Rebuild on project.

Это полностью очистило его для меня, избавив меня от многих раздражающих ошибок компоновщика, включая LNK4042 из заголовка этого вопроса.

Я разрешил это, изменив имена файлов в моем проекте. Было два файла с именами main.c и main.cpp. Я поменял один из них и заработал.

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