Search code examples
c++oopcompilationg++

How to compile files in different directory in c++?


I'm doing a more complex project in c++, but this example here is the same for what i need and the names of examples will just changed, but, again, is the same thing from what i am doing. Let's say I have this file structure:

|--project/
|--main.cpp
|--include/
|      |--class1.hpp
|      |--class2.hpp
|--impl/
|      |--class1.cpp
|      |--class2.cpp

Class2 has a class1 dependency.

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;
}

That is, my .hpp and .cpp are in different directories, how can I compile classes in different directories?


Solution

  • Just compile from terminal

    See the g++ command help:

    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
    

    You can just compile your code like this:

    g++ -Wall -Iinclude main.cpp impl/class1.cpp impl/class2.cpp -o project
    

    The shown command means:

    1. Enable all warnings
    2. when searching for included headers, the compiler should search not only in system include dirs, but also in include
    3. add all source files
    4. output the executable named project

    But this is too complicated, especially when you need to compile to test multi-times.

    Use an automation tool

    Generally speaking, there are 2 choices: make and cmake

    For your understanding, the following solutions are the simplified solution, but not really elegant

    Make

    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
    

    Put this under your project dir, name it Makefile, and run: 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
    

    A executable named project will show, you can run make clean to remove all .o files and your project executable file.

    CMake

    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)
    

    Put this in project dir and name it CMakeLists.txt. Run:

    cmake -B build # This generate a build dir under `project` dir and names it `build`
    cmake --build build # This builds your project
    

    Your executable file will be placed under build dir