xcode4.6 — случайные повторяющиеся символы в xcode (C ++)

Я пытаюсь построить проект C ++ в Xcode 4.6.3.

В моем проекте (начало очень простой игры OpenGL) у меня есть два файла:

textures.h:

#pragma once

#include <GLUT/GLUT.h>

void load(); // load textures

GLuint dirt, water; // variables to store texture handles

textures.cpp:

#include "textures.h"
#include "util.h"
void textures::load() {
dirt = util::loadTexture("/Some/Path/Soil.png");
water = util::loadTexture("/Some/Path/Water_fresh.png");
}

Здесь util.h определяет функцию util :: loadTexture.

Есть два файла, которые включают textures.h. Первый (main.cpp) вызывает функцию load () как часть инициализации и обращается к переменной dirt, чтобы связать текстуру Soil.png. Второй (Chunk.cpp) включает textures.h, но на самом деле пока ничего не получает от него.

Когда я пытаюсь построить проект, он выдает мне следующую ошибку:

duplicate symbol _dirt in:
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o
duplicate symbol _water in:
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o
duplicate symbol _dirt in:
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o
duplicate symbol _water in:
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
/Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o
ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Я понимаю, что это означает, что где-то есть дубликат или заголовок включен несколько раз. Но все мои заголовки используют #pragma once, и я сделал поиск в рабочей области для «грязи» и тому подобное, и нет других определений. Мои другие заголовки работают нормально, даже те, которые включены несколько раз. Я много раз гуглял эту проблему с разными ключевыми словами и смотрел на другие похожие вопросы, но все, что я нашел, было этот ТАК вопрос.

Я встречал другие «случайные» ошибки ранее в XCode — например, один проект продолжал пытаться использовать динамическую библиотеку, которую я удалил и заменил статической. Ошибка осталась, даже когда я создал новый проект. Работало при компиляции вручную из терминала.

Что мне не хватает?

5

Решение

#pragma once не останавливает включение заголовочного файла несколько раз.

Останавливает заголовочный файл несколько раз при компиляции одного файла. У вас есть (как минимум) три файла, поэтому вы объявляете одни и те же переменные 3 раза.

Не помещайте определения переменных в заголовочный файл. Сделай это вместо

// textures.h
extern GLuint dirt, water; // variable declarations// textures.cpp
GLuint dirt, water; // variable definitions

У вас может быть столько объявлений переменных, сколько вы хотите (при условии, что все они идентичны), так что можно помещать объявления в заголовочный файл, вы должны иметь ровно одно определение переменной, поэтому вы помещаете это в файл .cpp.

Необходимо помнить, что каждый файл .cpp компилируется полностью независимо от любого другого файла .cpp, это называется отдельной компиляцией. Итак, ваша идея, что #pragma once остановит включение заголовочного файла одним файлом .cpp только потому, что он был включен в другой файл .cpp, просто не работает. Вы не первый, кто неправильно это понял.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]