organize project and specify directory for object files in Makefile
Asked Answered
A

5

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?

Ambrosane answered 14/8, 2009 at 12:52 Comment(2)
Please indent your excerpt from the Makefile by four spaces. This will give it proper formatting and syntax highlighting.Hominoid
It seems there is a bug somewhere which prevent putting code after a list. I've added "Makefile:" as a work around.Plantaineater
N
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.

Nardi answered 14/8, 2009 at 14:33 Comment(3)
If you adopted approach B), how would you approach the problems with the Makefile dependencies?Ought
@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.Nardi
Thanks, @Nardi (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://mcmap.net/q/1736771/-where-do-i-place-the-makefile-of-a-project-closed/156458Ambrosane
I
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)
Interfile answered 14/8, 2009 at 13:30 Comment(0)
H
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) $<
Hominoid answered 14/8, 2009 at 13:1 Comment(7)
I would appreciate a comment about the downvote, so that I might improve myself :)Hominoid
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?Ambrosane
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.Hominoid
Consider all the thousands of projects that have used CVS very succesfully.Interfile
@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.Hominoid
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.Voleta
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.Interfile
N
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.

Nardi answered 14/8, 2009 at 14:33 Comment(3)
If you adopted approach B), how would you approach the problems with the Makefile dependencies?Ought
@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.Nardi
Thanks, @Nardi (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://mcmap.net/q/1736771/-where-do-i-place-the-makefile-of-a-project-closed/156458Ambrosane
U
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.

Unashamed answered 14/8, 2009 at 13:21 Comment(0)
A
-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.

Annotation answered 14/8, 2009 at 13:3 Comment(1)
Does not answer the question at all.Sister

© 2022 - 2024 — McMap. All rights reserved.