27

I want to be able to split up my bin and my code files into separate directories as it is becoming hard to manage in it's current state.

I ideally would like to have

project_dir
|-Makefile
|-run_tests.sh
|
|__source
|  |-program1.cpp
|  |-program2.cpp
|
|__bin
   |-program1
   |-program2

However I am unable to get this to work with my current system without having to manually write out the rules for every program (bear in mind that every program is a separate program, not a series of objects linked together)

#Current make system
BIN=./bin/
SOURCE=./source/

LIST=program1 program2...

all: $(LIST)

%:  $(SOURCE)%.cpp
    $(CC) $(INC) $< $(CFLAGS) -o $(BIN)$@ $(LIBS)

this works except it I it can't see the target in the current path so it think it always rebuilds the binaries even if the source files haven't changed.

My only thought at the moment is to write a program to make a makefile but I don't want to do that.

Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
111111
  • 15,686
  • 6
  • 47
  • 62
  • The traditional approach is to call the source directory `src`, build the binaries in there, and have a separate step `install` in which the binaries are copied to the `bin` directory - there is even a special utility `install` to do that. – reinierpost Feb 07 '12 at 19:23

4 Answers4

29

You were almost there ...

#Current make system
BIN=./bin/
SOURCE=./source/

LIST=$(BIN)/program1 $(BIN)/program2...

all: $(LIST)

$(BIN)/%:  $(SOURCE)%.cpp
    $(CC) $(INC) $< $(CFLAGS) -o $@ $(LIBS)

You can also make the LIST easier by using the following

PROG=program1 program2
LIST=$(addprefix $(BIN)/, $(PROG))
Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
6

Here is a complete ready-to-go version of the Makefile.

Prepare your folder with the following directory

for .o files:/build/ for .cpp files: /src/ for binary files: /bin/

Then use the following Makefile at /

CC          = g++
LD          = g++ 
CFLAG       = -Wall
PROG_NAME   = prog

SRC_DIR     = ./src
BUILD_DIR   = ./build
BIN_DIR     = ./bin
SRC_LIST = $(wildcard $(SRC_DIR)/*.cpp)
OBJ_LIST = $(BUILD_DIR)/$(notdir $(SRC_LIST:.cpp=.o))

.PHONY: all clean $(PROG_NAME) compile

all: $(PROG_NAME)

compile: 
    $(CC) -c $(CFLAG) $(SRC_LIST) -o $(OBJ_LIST)

$(PROG_NAME): compile
    $(LD) $(OBJ_LIST) -o $(BIN_DIR)/$@

clean:
    rm -f $(BIN_DIR)/$(PROG_NAME) $(BUILD_DIR)/*.o

Your final program will be named as prog in the /bin/, everytime you compile the code, binaries will be separated at /build/ so that source code directory will be very neat and clean.

2

Easy solution: Use automake.

If you want to do this by hand, you'll need to employ the vpath directive or the VPATH environment variable. The GNU make manual has a section about them. Put your Makefile directly into the bin directory, set VPATH to the source directory, and implicit rules will work again.

thiton
  • 35,651
  • 4
  • 70
  • 100
0

I have the same case but in C code, and I've tried the solutions above, but no one was valid for me (on Mac OSX OS), so I tried other solutions also found in stackoverflow like: https://stackoverflow.com/a/53138757/2467917 and the result will be like below code (you need to make build folder at the same make file directory and feel free to change the other names of folders in variables to be suitable for your project):

MKDIR    = mkdir
RMDIR    = rm -rf
CC       = clang    
BIN      = build/bin
OBJ      = build/obj
INCLUDE  = include
SRC      = src
CFLAGS   = -Wall -g -I$(INCLUDE)
LDLIBS   = -lm
SRCS     = $(wildcard $(SRC)/*.c)
OBJS     = $(patsubst $(SRC)/%.c,$(OBJ)/%.o,$(SRCS))
EXE      = $(patsubst $(SRC)/%.c,$(BIN)/%.exe,$(SRCS))

.PHONY: all clean

all: $(EXE)

$(EXE): $(OBJS) | $(BIN)

# linker
$(BIN)/%.exe: $(OBJ)/%.o
    $(CC) $(LDFLAGS) $< -o $@ $(LDLIBS)

# compiler  
$(OBJ)/%.o: $(SRC)/%.c | $(OBJ)
    $(CC) $(CFLAGS) -c $< -o $@

$(BIN) $(OBJ):
    $(MKDIR) $@

clean:
    $(RMDIR) $(OBJ) $(BIN)
Zakaria
  • 1,055
  • 12
  • 16