My C++ program consists of three files:
- two source files 'main.cpp' and 'hellolib.cpp'
- a header file 'hellolib.h'
I am creating a makefile for this program. For my assignment I need one target ('hello') that compiles all source files in an executable. Another target ('obj') should compile all '.cpp' files into objects and link them together in an executable.
When running make I prefer the object files to be created in a seperate folder called 'bin'. The source files are would be in a folder called 'src'. These folders are siblings, the makefile is in it's parent folder.
My makefile works fine but I wish two combine the two targets 'bin/main.o' and 'bin/hellolib.o' into one to reduce the amount of rules, especially for later when I am dealing with more source files. I imagined the replacement would look something like this, but it doesn't seem to work.
It gives me the error: "*** No rule ot make target 'bin/main.o', needed by 'obj'. Stop.
bin/%.o : src/%.cpp
$(CC) -c $< -o $@
Working Makefile:
CC = g++
SOURCES = ./src/main.cpp \
./src/hellolib.cpp
OBJECTS = ./bin/main.o \
./bin/hellolib.o
hello : $(SOURCES)
$(CC) -o $@ $^
obj : $(OBJECTS)
$(CC) -o $@ $^
bin/main.o : src/main.cpp
$(CC) -c $< -o $@
bin/hellolib.o : src/hellolib.cpp
$(CC) -c $< -o $@
clean:
@rm -rf hello obj bin/*.o
main.cpp:
#include "hellolib.h"
int main() {
Hello h("Name");
h.Print();
return 0;
}
hellolib.cpp
#include "hellolib.h"
#include <iostream>
Hello::Hello(std::string name) {
if (name.empty()) {
cout << "Name is not valid!";
return;
}
_name = name;
}
void Hello::Print() {
cout << "Hello " << _name << endl;
}
hellolib.h
#ifndef HELLO_LIB_H
#define HELLO_LIB_H
#include <string>
using namespace std;
class Hello {
std::string _name;
public:
Hello(std::string name);
void Print();
};
#endif