Мои друзья разработали игру C ++ в Visual Studio для Windows, и я хотел бы скомпилировать ее на своем компьютере с Linux x64. Я не очень знаком с C ++, но я пытаюсь g ++ в командной строке. Однако я получаю только кучу неопределенные ссылки ошибки.
Основная структура файла:
Libraries/SFML-2.0/lib
Libraries/SFML-2.0/include
Libraries/SFML_Linux64/lib
Libraries/SFML_Linux64/include
Libraries/Box2D/lib
Libraries/Box2D/include
Libraries/Box2DLinux/lib
Libraries/Box2DLinux/include
Game
Game/lib
Game/includes
Game/... (other subdirectories)
Я попробовал следующую команду:
g++ -Wall Multiplaya/app.cpp -I Libraries/SFML_Linux64/include/ -I Libraries/Box2DLinux/include/ -L Libraries/SFML_Linux64/lib/ -L Libraries/Box2DLinux/lib/
Это тот тип ошибок, которые я получаю (некоторые строки обрезаны и заменены на ...
):
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o: I funktionen "_start":
(.text+0x20): undefined reference to `main'
/tmp/ccFXe37c.o: I funktionen "mp::createNetworkThread(void*)":
app.cpp:(.text+0x10): undefined reference to `worldDataMutex'
app.cpp:(.text+0x15): undefined reference to `sf::Mutex::lock()'
...
/tmp/ccFXe37c.o: I funktionen "mp::App::exec()":
app.cpp:(.text+0x148): undefined reference to `mp::ResourceHandler::instance()'
app.cpp:(.text+0x15a): undefined reference to `mp::ResourceHandler::loadTexture(std::string)'
app.cpp:(.text+0x3d7): undefined reference to `mp::Window::Window(mp::WorldData*)'
app.cpp:(.text+0x406): undefined reference to `mp::Controller::Controller(mp::World*, mp::Window*)'
...
app.cpp:(.text+0x471): undefined reference to `sf::Mutex::unlock()'
app.cpp:(.text+0x4bb): undefined reference to `sf::Thread::launch()'
app.cpp:(.text+0x4d7): undefined reference to `sf::Clock::Clock()'
app.cpp:(.text+0x4e6): undefined reference to `sf::Clock::getElapsedTime() const'
...
collect2: fel: ld returnerade avslutningsstatus 1
(Я надеюсь, что вы можете просмотреть шведский выше.)
Очень любезно с вашей стороны указывать пути к компоновщику. Тем не менее, линкеры — неблагодарные неряхи и обычно не ищите какие-либо библиотечные файлы самостоятельно когда они видят неопределенную ссылку на функцию.
Подобно, undefined reference to `sf::Mutex::lock()
— Бьюсь об заклад, есть libsfml-system.so.2.0
или что-то в Libraries/SFML_Linux64/lib/
каталог, с определением для sf::Mutex::lock()
, Но компоновщик не волнует. Ты должен сказать -lsfml-system
в конце вашего вызова компиляции.
Это сделает g++
понять, чтобы искать функции не только в libstdc++
библиотека, но и в libsfml-system
файл. И если g++
случайно найти такой файл по умолчанию или дополнительный (указывается с -L
flag) библиотечные каталоги, он будет использоваться для разрешения ссылок на вызовы функций.
Но вы должны явно указать ему, какие библиотечные файлы вы хотите добавить, указав только каталоги с библиотеками мало что делает. Итак, попробуйте использовать
g++ -Wall Multiplaya/app.cpp -I Libraries/SFML_Linux64/include/ -I Libraries/Box2DLinux/include/ -L Libraries/SFML_Linux64/lib/ -L Libraries/Box2DLinux/lib/ -lsfml-system
Программы на C ++ состоят из двух этапов: первый этап — это компиляция, а второй — создание ссылок.
Во время компиляции вы превращаете ваши исходные файлы в объектные файлы — вещи, которые содержат скомпилированный машинный код. Теперь есть хитрость, которую вы должны понять. Скажи если есть a.cpp
с
// a.cpp
int f(int x);
int main() {
return f(42);
}
Вы можете скомпилировать это с g++ -c a.cpp
и он получит вам объектный файл a.o
(с скомпилированным кодом), без каких-либо ошибок компиляции. Но ждать! Там нет фактического определения того, что f()
в a.cpp
!
И теперь, когда вы переходите ко второму шагу, ссылки и вызывает g++ -o test a.o
, он будет жаловаться, что есть неопределенная ссылка на f()
, Итак, давайте сделаем b.cpp
с этим текстом:
// b.cpp
int f(int x) {
return 2 * x - 3;
}
скомпилируйте это с g++ -c b.cpp
а затем выполнить связывание как g++ -o test a.o b.o
— и вау, теперь ссылки без ошибок!
Что случилось? Хорошо, когда компилятор видит вызов функции, он помещает в объектный файл не фактический call
инструкция, но заполнитель, который говорит: «вызовите функцию с таким-то именем и такими-то параметрами». И тогда компоновщик берет кучу объектных файлов и сшивает их вместе. Когда он видит такую табличку, он ищет упомянутую функцию в объектных файлах, которые ей дали, и выполняет фактический вызов ей вместо заполнителя.
Итак, сборка программы на C ++ выглядит примерно так:
x.cpp
файл у вас есть, позвоните g++ -c x.cpp <bunch of flags> -I<include directories>
g++ -o resultprogram a.o b.o c.o d.o ... <bunch of flags> -L<library directories> -l<additional libraries>
-l
flag сообщает компоновщику, что если он видит вызов функции, и нигде в указанных объектных файлах (a.o, b.o и т. д.) такая функция не определена, то он должен искать в этой библиотеке. Обратите внимание, что компоновщик не будет смотреть ни в каких объектных файлах и / или библиотеках, кроме тех, которые вы указали (хорошо, он также будет выглядеть в стандартной библиотеке C ++ libstdc++
, но это все).
Тем не менее, этот процесс довольно скучно делать вручную, если у вас есть 10 или более файлов. Вот почему люди используют «файлы проекта» и «системы сборки». Когда Visual Studio строит проект, он выполняет все те шаги, которые я упомянул: он компилирует каждый файл в проекте, а затем связывает результат вместе. В Linux у вас нет Visual Studio, но у вас есть make
полезность. Я полагаю, что есть несколько утилит для преобразования VS-проектов в make-файлы.
Других решений пока нет …