0

I have this structure for my project:

root
|____Makefile
|
|___src
|     |____*.cpp  
|
|___includes
|      |___*.h
|
|___obj
|___tmp
|___bin

The problem is that when i try to make i got this error:

g++ -std=c++11 obj/book.o -o bin/main
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

My main.cpp is inside src than i have a file .h where i declare a struct and some function and a .cpp where i define everything. In the main and in the cpp i do

#include "../includes/myfile.h"

How i can compile and fix this problem? Here is my makefile:

CXX = g++
CXXFLAGS = -std=c++11 -I..
LDFLAGS = -std=c++11
EXECUTABLE= bin/main
SOURCES = $(wildcard src/*.cpp)
HEADERS = $(wildcard includes/*.h)
OBJECTS = $(patsubst src/%.cpp, obj/%.o, $(SOURCES))

BASE = $(USER)

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) $(LDFLAGS) $< -o $@

obj/%.o: src/%.cpp
    $(CXX) -c $(CXXFLAGS) $< -o $@

clean: 
    rm $(OBJECTS)

rmproper:
    rm $(OBJECTS) $(EXECUTABLE)

pdf:
    a2ps Readme.txt makefile $(HEADERS) $(SOURCES) -o /tmp/out.ps
    ps2pdf /tmp/out.ps $(BASE).pdf

zip:
    zip $(BASE).zip Readme.txt makefile $(HEADERS) $(SOURCES)
gmdev
  • 2,725
  • 2
  • 13
  • 28
mat656
  • 129
  • 1
  • 7
  • It seems you're linking a single object file into a single executable file, and that object file (and the source file the generated it) doesn't have a `main` function. Are youre `Makefile` supposed to build and link *multiple* source (and object) files? Is the output you show the *full* build log? If you remove the object files and build again, can you copy-paste the *full* output into your question? – Some programmer dude Sep 23 '18 at 15:11
  • 4
    The problem is here: `$(EXECUTABLE): $(OBJECTS) $(CXX) $(LDFLAGS) $< -o $@`. `$<` is the first prerequisite, i.e. the first object file. What you want is `$^` to list all object files. – Johan Boulé Sep 23 '18 at 15:14
  • In `$(EXECUTABLE): $(OBJECTS)` rule, I believe you want to replace `$<` with `$^`. The former is "the first file from the list", the latter is "all files from the list". – Igor Tandetnik Sep 23 '18 at 15:14
  • 1
    @JohanBoulé Should be easier to write an actual answer now. :) – Some programmer dude Sep 23 '18 at 15:19
  • In a nutshell: you are not linking the object file defining the function. See the other comments. – Jesper Juhl Sep 23 '18 at 15:22
  • @Someprogrammerdude Yes, the user πάντα ῥεῖ was far too quick at marking it as a duplicate. The problem was actually in the makefile, not in the source code. – Johan Boulé Sep 23 '18 at 15:30

1 Answers1

5

The problem is here:

$(EXECUTABLE): $(OBJECTS)
    $(CXX) $(LDFLAGS) $< -o $@

$< is the first prerequisite, i.e. the first object file in your $(OBJECTS) list (which happens to be book.o according to your error message). What you want to pass is the whole list of object files, which can be accomplished by using either $^, or even $(OBJECTS) in place of $<.

gmdev
  • 2,725
  • 2
  • 13
  • 28
Johan Boulé
  • 1,936
  • 15
  • 19