Я делаю более сложный проект на C++, но этот пример аналогичен тому, что мне нужно, и названия примеров будут просто изменены, но, опять же, это то же самое, что и я. Допустим, у меня есть такая файловая структура:
|--project/
|--main.cpp
|--include/
| |--class1.hpp
| |--class2.hpp
|--impl/
| |--class1.cpp
| |--class2.cpp
Класс2 имеет зависимость класса1.
class1.hpp
#ifndef CLASS1_HPP
#define CLASS1_HPP
class class1 {
private: string name;
}
#endif
class2.hpp
#ifndef CLASS2_HPP
#define CLASS2_HPP
#include "class1.hpp"
class class2 {
private: Class1 class1;
}
#endif
class1.cpp
#include "class1.hpp"
#include <iostream>
(functions implemantations...)
}
class2.cpp
#include "class2.hpp"
#include "class1.hpp"
#include <iostream>
(functions implemantations...)
}
main.cpp
#include "class2.hpp"
#include <iostream>
int main() {
Class2 class2;
(...)
return 0;
}
То есть мои .hpp и .cpp находятся в разных каталогах, как мне скомпилировать классы в разных каталогах?
Хорошо! Есть ли у вас ссылка, которая поможет мне узнать больше об этом? А если я хочу скомпилировать в терминале? для чего я использую?
«Как мне скомпилировать классы в разных каталогах?...» Если вы не используете, скажем, cmake и т. д., вы также можете скомпилировать несколько файлов из определенного каталога одновременно. Ставьте лайк g++ *.cpp -o output
. См. Использование G++ для компиляции нескольких файлов .cpp и .h. Но я настоятельно рекомендую использовать cmake и т. д., чтобы сделать это автоматически.
«А если я хочу скомпилировать в терминале? для чего мне это использовать?» Обычно я использую CMake из терминала.
Независимо от того, какой инструмент автоматизации вы используете, вам необходимо решить две проблемы (1) при компиляции, чтобы каждая директива #include
однозначно разрешалась в правильный заголовок. Все компиляторы командной строки, IDE и соответствующие инструменты автоматизации поддерживают возможность указать «путь включения» (и один и тот же путь включения должен использоваться при компиляции каждого исходного файла). Также необходимо либо обеспечить возможность поиска всех объектных файлов при связывании, либо указав путь для связывания (где искать объекты), либо ссылаясь при связывании на полные имена объектных файлов/библиотек.
См. справку по команде g++
:
gcc -help | grep " \-I"
-I- Restrict all prior -I flags to double-quoted inclusion and remove current directory from include path
-I <dir> Add directory to the end of the list of include search paths
Вы можете просто скомпилировать свой код следующим образом:
g++ -Wall -Iinclude main.cpp impl/class1.cpp impl/class2.cpp -o project
Показанная команда означает:
include
project
Но это слишком сложно, особенно когда вам нужно несколько раз компилировать и тестировать.
Вообще говоря, есть 2 варианта: make и cmake.
Для вашего понимания следующие решения являются упрощенными, но не очень элегантными.
all: main.o class1.o class2.o
gcc -Wall main.o class1.o class2.o -o project
main.o: main.cpp
gcc -c -Wall main.cpp -o main.o
class1.o: impl/class1.cpp
gcc -c -Wall -Iinclude impl/class1.cpp -o class1.o
class2.o: impl/class2.cpp
gcc -c -Wall -Iinclude impl/class2.cpp -o class2.o
clean:
rm -f project main.o class1.o class2.o
Поместите это в свой каталог project
, назовите его Makefile
и запустите: make
❯ make
gcc -c -Wall main.cpp -o main.o
gcc -c -Wall -Iinclude impl/class1.cpp -o class1.o
gcc -c -Wall -Iinclude impl/class2.cpp -o class2.o
gcc -Wall main.o class1.o class2.o -o project
Появится исполняемый файл с именем project
. Вы можете запустить make clean
, чтобы удалить все .o
файлы и ваш project
исполняемый файл.
cmake_minimum_required(VERSION 3.15)
project(project)
add_executable(project
main.cpp
impl/class1.cpp
impl/class2.cpp
)
target_include_directories(project PRIVATE include)
Поместите это в каталог project
и назовите CMakeLists.txt
. Бегать:
cmake -B build # This generate a build dir under `project` dir and names it `build`
cmake --build build # This builds your project
Ваш исполняемый файл будет помещен в каталог build
.
Используйте инструмент автоматизации, такой как cmake и т. д.