6

Here are my two questions:

  1. I am now learning to manage my code with CVS, and I just want to make a repository for my C++ files, Makefile and bash and python scripts only, not the object files and executables. So I made several subdirectories under my project directory: src, bin, scripts, results and data.

    I put C++ files and Makefile under ~/myproject/src, Bash and Python scripts under ~/myproject/scripts and object and executables under ~/myproject/bin. I am hoping only the files under src and scripts will be updated via CVS. I wonder how you organize your projects? Just hope to follow some good habits.

  2. Since I put my C++ files and Makefile into ~/myproject/src and object and executable files into ~/myproject/bin, I have to specify the directories in Makefile. Here is what I am doing

Makefile:

...
BIN_DIR=/home/myproject/bin/

all: $(BIN_DIR)myexecutable TAGS

TAGS: *.cc *.h
    etags --members --declarations -l c++ *.cc *.h

$(BIN_DIR)myexecutable: $(BIN_DIR)myobject.o
    $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)

Makefile.depend: *.h *.cc Makefile
    $(CXX) -M $(CXXFLAGS) *.cc > Makefile.depend

clean:
    \rm -f $(BIN_DIR)myexecutable $(BIN_DIR)*.o Makefile.depend TAGS`

However this will give error

make: *** No rule to make target /home/myproject/bin/myobject.o', needed by /home/myproject/bin/myexecutable'.

How to specify a different directory for object and executable files from C++ files in Makefile?

Community
  • 1
  • 1
Tim
  • 1
  • 141
  • 372
  • 590
  • 1
    Please indent your excerpt from the Makefile by four spaces. This will give it proper formatting and syntax highlighting. – Magnus Hoff Aug 14 '09 at 12:59
  • It seems there is a bug somewhere which prevent putting code after a list. I've added "Makefile:" as a work around. – AProgrammer Aug 14 '09 at 13:25

5 Answers5

8

If you want to learn make, the GNU make manual is very good, both as a reference and a tutorial. You might want to consider using the patsubst command. The following is a chopped down version of one of my own makefiles that uses it:

OUT = bin/csvfix.exe
CC = g++
IDIR = inc
ODIR = obj
SDIR = src
INC = -Iinc -I../alib/inc
LIBS = ../alib/lib/alib.a -lodbc32 

_OBJS = csved_atable.o \
        csved_case.o \
        csved_cli.o \
        csved_command.o \
        csved_date.o \

OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))

$(ODIR)/%.o: $(SDIR)/%.cpp 
    $(CC) -c $(INC) -o $@ $< $(CFLAGS) 

$(OUT): $(OBJS)
    $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
    strip $(OUT)

clean:
    rm -f $(ODIR)/*.o $(OUT)
Daryl Spitzer
  • 143,156
  • 76
  • 154
  • 173
2
  1. Your directory structure seems sensible.

  2. I would make an explicit rule for executing the compiler, like

TARGET_DIR=bin
SRC_DIR=src
CXX=g++
CXXFLAGS=
ETC=

OBJS=$(TARGET_DIR)/test.o

all: $(OBJS)

$(TARGET_DIR)/%.o: $(SRC_DIR)/%.cc
        $(CXX) -c -o $@ $(CXXFLAGS) $(ETC) $<
Magnus Hoff
  • 21,529
  • 9
  • 63
  • 82
  • I would appreciate a comment about the downvote, so that I might improve myself :) – Magnus Hoff Aug 14 '09 at 13:06
  • Don't know who gave you the vote, not me. :) If you have many .cc files, to specify a rule for each object file is tedious, isn't it? – Tim Aug 14 '09 at 13:12
  • The rule is generic, so it applies to any .cc-file. I have updated the example Makefile-code with a list of target objects. Just specify additional .o-files here, and they will be compiled with the same rule. – Magnus Hoff Aug 14 '09 at 13:17
  • Consider all the thousands of projects that have used CVS very succesfully. –  Aug 14 '09 at 13:24
  • @Neil: Sorry. I was under the impression that everybody agreed CVS is a relic of the past. I might have been wrong. Anyway, this was intended as a helpful tip, but since it is not strictly an answer to anything in the question I have removed the possibly offending tip. – Magnus Hoff Aug 14 '09 at 13:29
  • Linus certainly agrees that CVS is fundamentally broken, and he's the one who decided that the linux kernel would use patch files in preference to existing version control systems, until that finally became unsustainable. Many people disagree with Linus about all sorts of things, although in my experience people who have switched away from CVS have not regretted it. – Steve Jessop Aug 14 '09 at 13:50
  • CVS was certainly unsuitable for developing the Linux kernel, but most projects are not remotely similar to the Linux kernel. I would never advise anyone to use CVS on a project starting today, but in its time it a great a step forward from things like PVCS, and shouldn't be badmouthed. I now use SVN and am investigating Mercurial, but if forced to go back to CVS, I really wouldn't complain too much - I prefer its tagging model to SVN's, for example. –  Aug 14 '09 at 17:08
2
  1. You can keep your files in different directories if you like, but that isn't necessary. Add a file or directory to the CVS repository once, and CVS will retain it indefinitely. From then on you can update it, check it in, whatever. If you don't add an object file to the repository, CVS won't touch it. If you want to add a whole directory tree, and you're in the habit of keeping objects there, just make clean before you do it.

  2. Make is a wonderful tool, but it has some glaring faults. What you're describing is one of the classic problems: Make is good at using a source there to make something here, but not the other way around. Here are a couple of ways to do what you're trying to do.

A) Run make in your binary directory:

    ...
    all: myexecutable TAGS

    myexecutable: myobject.o
        $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)

    VPATH = /home/myproject/src
    ...

cd ~/myproject/bin
make -f ../src/makefile

B) Put the objects on the bin directory by brute force:

    $(BIN_DIR)%.o: %.cc
        $(CXX) $(CXXFLAGS) -c -o $@ $^

This will give you a problem with Makefile.depend, which you can approach several ways.

C) Learn some more advanced Make techniques. You probably shouldn't try this yet.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • If you adopted approach B), how would you approach the problems with the Makefile dependencies? – frankster Jan 18 '11 at 13:31
  • @frankster, I'd probably modify the `Makefile.depend` command to prepend `$(BIN_DIR)` to the names of the object files. A little sed would do. – Beta Jan 18 '11 at 23:37
  • Thanks, @Beta (1) I was wondering if the reason for "Make is good at using a source there to make something here" is the "problem with Makefile.depend" you described in B)? (2) In the way "a problem with Makefile.depend" which you suggested, where would you place makefile? in `src/`, or `bin/`, or the root directory of the project? See https://stackoverflow.com/q/49836438/156458 – Tim Apr 14 '18 at 22:57
0

Use automake and autoconf for building your project.

As for the structure of files just look at any big open-source C++ application. Any KDE application will do fine for that matter. If you find an application that uses C++ and Python even better.

kazanaki
  • 7,988
  • 8
  • 52
  • 79
-5

Why not go for eclipse, which is quite popular and handy for managing large projects. You can make a new project in eclipse, import-export code into the project from other projects, does version control for you as well etc. No need to write your make files, eclipse does it for you with your mentioned preferences in GUI. If you are involved in a C++ project, just install the CDT plugin over eclipse and your are done.

rayimag
  • 893
  • 3
  • 10
  • 18