I am building a small utility library in c++, and I am adding some examples to it. The project structure looks like this:
MyLib
|__bin
|
|__include
| |__mylib.hpp
|
|__lib
|
|__examples
| |__example.cpp
|
|__src
| |__mylib.cpp
|
|__Makefile
Here is what my Makefile looks like:
LIBK = mylib
LIBS = $(LIBK).a
CXXFLAGS := -Wall -Wextra -std=c++17 -ggdb
BIN := bin
SRC := src
INCLUDE := include
LIB := lib
EXAMPLES := examples
all: lib examples
lib: $(LIB)/$(LIBK)
examples: lib $(BIN)/$(EXAMPLES)
run: clean all
clear
./$(LIB)/$(LIBK)
$(LIB)/$(LIBK): $(SRC)/*.cpp
-mkdir -p lib
$(CXX) -c $(CXXFLAGS) -I$(INCLUDE) -L$(LIB) $^ -o [email protected]
ar rcs $(LIB)/lib$(LIBK).a [email protected]
$(BIN)/$(EXAMPLES): $(EXAMPLES)/*.cpp
-mkdir -p bin
$(CXX) $(CXXFLAGS) -I$(INCLUDE) -L$(LIB) -l$(LIBK) $^ -o $@
clean:
-rm -rf $(BIN)/*
-rm -rf $(LIB)/*
My problem is that everything seems to look fine when I run make, but it fails when I run make -j8 with the following error.
cannot find -lmylib
collect2: error: ld returned 1 exit status
make: *** [Makefile:36: bin/examples] Error 1
make: *** Waiting for unfinished jobs....
ar rcs lib/libmylib.a lib/mylib.o
It seems like the multiple core instruction triggers both compilations at the same time, without waiting for the library to build before launching the job to build the example. I believe I had defined the dependencies correctly, but there is something obviously wrong that I don't seem to be able to find by myself.
EDIT: Seeing that I the original Makefile is fundamentally incorrect, but no answer really provided an alternative one, I created a new one to the best of my knowledge that seems to work. Any constructive and respectful criticism is welcome.
LIBNAME := libIntegration.a
CXX := g++
BIN := bin
SRC := src
INCLUDE := include
LIB := lib
LIBRARIES := -lIntegration
EXECUTABLE := main
LIBRARY_SOURCES := $(SRC)/mxIntegration.o
EXECUTABLE_SOURCES := examples/main.o
CXXFLAGS := -Wall -Wextra -std=c++17 -ggdb -I$(INCLUDE)
all: $(BIN)/$(EXECUTABLE)
run: clean all
clear
./$(BIN)/$(EXECUTABLE)
$(LIB)/$(LIBNAME): $(LIBRARY_SOURCES)
ar rcs $@ $^
$(BIN)/$(EXECUTABLE): $(LIB)/$(LIBNAME)
$(CXX) $(CXXFLAGS) -I$(INCLUDE) -L$(LIB) $(EXECUTABLE_SOURCES) -o $@ $(LIBRARIES)
clean:
-rm -rf $(BIN)/*
-rm -rf $(LIB)/*
$(LIB)/$(LIBK)but thearcommand creates a file$(LIB)/lib$(LIBK).a. This means the commands will always be executed even if no dependency has changed because the expected target file does not exist.