views:

37

answers:

1

I'm looking to save myself some effort further down the line by making a fairly generic makefile that will put together relatively simple C++ projects for me with minimal modifications required to the makefile.

So far I've got it so it will use all .cpp files in the same directory and specified child directories, place all these within a matching structure in a obj subdir and place the resulting file in another subdir called bin. Pretty much what I want.

However, trying to get it so that the required obj and bin directories is created if they don't exist is providing akward to get working cross-platform - specifically, I'm just testing with Win7 & Ubuntu (can't remember version), and can't get it to work on both at the same time. Windows misreads mkdir -p dir and creates a -p directory and obviously the two platforms use \ and / respectively for the path seperator - and I get errors when using the wrong one.

Here is a few selected portions of the makefile that are relevant:

#manually edited directories (in this EG with forward slashes)
SRC_DIR = src src/subdir1 src/subdir2

#automagic object directories + the "fixed" bin directory
OBJ_DIR = obj $(addprefix obj/,$(SRC_DIR))
BIN_DIR = bin

#example build target
debug: checkdirs $(BIN)

#at actual directory creation
checkdirs: $(BIN_DIR) $(OBJ_DIR)
$(BIN_DIR):
    @mkdir $@

$(OBJ_DIR):
    @mkdir -p $@

This has been put together by me over the last week or so from things I've been reading (mostly on SO), so if happens to be I'm following some horrible bad practice or anything of that nature please let me know.

Question in a nut shell:
Is there a simple way to get this directory creation to work from a single makefile in a way that provides as much portability as possible?

+1  A: 

Windows mkdir always does what Unix mkdir does with the -p switch on. And you can deal with the backslash problem with $(subst). So, on Windows, you want this:

$(BIN_DIR) $(OBJ_DIR):
        mkdir $(subst /,\\,$@)

and on Unix you want this:

$(BIN_DIR) $(OBJ_DIR):
        mkdir -p -- $@

Choosing between these is not practical to do within a makefile. This is what Autoconf is for.

As a side note, never, ever use the @command feature in your makefiles. There will come a day when you need to debug your build process on a machine you do not have direct access to, and on that day, you will regret it.

Zack
@Zack, OK, that's handy, minimising the required differences between versions is what I'm aiming for until I move on to learning any sort of auto based version. But, would you please mind briefly explaining what the `@command` feature *does*? As said in my question, I have built the makefile from various sources with minimal previous knowledge, so must have pulled it from *somewhere*, but now can't remember from where or the relevance...
DMA57361
If you stick an `@` in front of any Makefile command, Make doesn't print the command to the terminal before it executes it. This *seems* like a great feature -- less noise scrolling by, yay -- until you have to debug your build process using only that terminal transcript, and then you are in a world of hurt.
Zack
@Zack Ah, good to know. I'll be avoiding that then. Thanks.
DMA57361