Marcos Alvarez
Marcos Alvarez

Reputation: 13

Handle Dependencies When Building With Multiple Cores

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)/*

Upvotes: 0

Views: 68

Answers (1)

MadScientist
MadScientist

Reputation: 100926

This is a super-bizarre makefile. I'm not sure why you even bother to use make at all, because you are always recompiling every source file whenever any source file changes.

But, just to deal with your specific question your error message says:

cannot find -lmylib

so clearly the example is being built before the library is done. So, let's look at the rule for building examples:

$(BIN)/$(EXAMPLES): $(EXAMPLES)/*.cpp

Here you list the source files as prerequisites of the target. But nowhere have you listed the library as a prerequisite. So, make has no idea that you need to wait for the library to be built, and you definitely haven't defined that dependency.

Upvotes: 3

Related Questions