rename executable and all .o files when compiling using positioning flags

Hi!
I have a working make file and want to change change the naming of the output and exectuables files. Unfortuneately, I not so familiar with make files, and this one came from somewhere else. I understand that it should generate the .o files and then an executable to which they are linked. I read that I should use the -c and -o option, but I am having problems with the exact syntax in this particular example. Namely because of the cryptic (to me) use of the positional parameter @. Maybe someone could explain the usage of @ here in their response.

Here is the working version:
1
2
3
4
5
6
7
8
9
10
 OBJS = file1.o file2.o

vpath %.cpp	folderwithcppfiles

TARGET = progTarget

all:	$(TARGET)

progTarget: $(OBJS) file3.o
		 $(CXX) $(CXXFLAGS) -o $@ $@.o $(OBJS) $(LIBS)			


Here is the changed version of that last line I am working on:


1
2
progTarget: $(OBJS) file3.o
		 $(CXX) $(CXXFLAGS) -c $@.cpp -o $@.o $(OBJS) $(LIBS)


This doesn't work of course. What is the correct syntax?

Thanks in advance!
I've reposted the makefile without the incorrect white space and tabs. These are really important in a makefile.
1
2
3
4
5
6
7
8
9
10
OBJS = file1.o file2.o

vpath %.cpp	folderwithcppfiles

TARGET = progTarget

all:	$(TARGET)

progTarget: $(OBJS) file3.o
	 $(CXX) $(CXXFLAGS) -o $@ $@.o $(OBJS) $(LIBS)


This is the makefile fixed:
1
2
3
4
5
6
7
8
9
10
OBJS = file1.o file2.o

vpath %.cpp	folderwithcppfiles

TARGET = progTarget
LDFLAGS = $(LIBS)

all:	$(TARGET)

$(TARGET): $(OBJS) file3.o

If you compile file3.o, it should be move to the OBJS macro.

It's not a good idea to put the .cpp files in a different directory (and then rely on vpath).

Don't understand make? See http://www.cplusplus.com/articles/jTbCpfjN/

Having done all that, it's not clear what your problem is. What file do you want to add? What target do you want to change?
Last edited on
Hi! thanks for the advice on make files. The file3 is separate because it links to all the others I think. Not sure if it separated just to indicate that, or whether there is some syntactic reason.

Anyway, what I want is to set the names of the output files different from the cpp file names and where do I set the executable name?

This may be a bad idea, but I'll be compiling on multiple machines and want a compiled version of the code for each machine and in the same folder so I have to change the names.
Last edited on
Anyway, what I want is to set the names of the output files different from the cpp file names
You can, but you're bending the rules, and discarding a lot of the work that's gone into setting up defaults (and taking on that work yourself).

What do you want to set the names to?

... and where do I set the executable name?
 
TARGET = progTarget
Last edited on
What I don't get is that the .cpp files names are never explicitly stated so I figure that the default must be to look for the filenames of the .o files and that if you want to make them different you have to use the -c option to state the .cpp files explicitly to override the default. Then you can set the .o files to what ever you want. But so far I can't get it to work because I don't fully understand the use of @. in the given make file. Can you explain what is going on with the @?
Last edited on
What I don't get is that the .cpp files names are never explicitly stated

Did you read the link I posted?

so I figure that the default must be to look for the filenames of the .o files

That's right so far.

... and that if you want to make them different you have to use the -c option to state the .cpp files explicitly to override the default.

Wrong.

If you want to change them, you need to redefine the rule that describes the compile step. The rule is COMPILE.cc. If you change the name of the target file, you also need to modify the link rule (LINK.cc) too. It's just not worth it. The whole point of GNU Make's built-in rules are to help in a standard way. But when you go for these customisations, you're just making life tricky.

Perhaps if you explained why you need this changed, I can be more helpful.
Last edited on
Ok. This may be a bad idea, but I'll be compiling on multiple machines and I want a compiled version of the code for each machine and in the same folder so I have to change the names so they don't overwrite each other.

I could just copy the code into another folder but I wanted to have only one version of the cpp files.

Maybe I could generate the .o and executable in a folder, with one folder for each machine.
Last edited on
I think that's not the best.

It is common to define custom obj files, but that's for when you need to compile the same file differently. For example, compiling for a program or static lib is different that compiling for a shared lib, so it's not uncommon to set up a special rule and extension for a shared lib.

I'll think about your specific problem a bit further.
Last edited on
Ok, here we go.

I've created a simple project that builds into specified directories.

$ cat GNUmakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ARCH ?= $(shell uname -m)

CXX_FILES := hello.cpp

O_FILES = $(patsubst %.cpp,$(ARCH)/%.o,$(CXX_FILES))

TARGET = $(addprefix $(ARCH)/,greeting)

CXXFLAGS = -DARCH=\"$(ARCH)\"

.PHONY: PRE

all: PRE $(TARGET)

PRE:
        $(shell test -d $(ARCH) || mkdir -p $(ARCH))

$(ARCH)/%.o: %.cpp
        $(COMPILE.cc) $(OUTPUT_OPTION) $<

$(TARGET): $(O_FILES)
        $(LINK.cc) -o $@ $^ 


$ cat hello.cpp
1
2
3
4
5
6
7
8
9
10
#include <iostream>

int main()
{
#ifdef ARCH
    std::cout << "hello " << ARCH << std::endl;
#else
    std::cout << "hello" << std::endl;
#endif
}


This is a default build.
$ make
g++ -DARCH=\"x86_64\"   -c -o x86_64/hello.o hello.cpp
g++ -DARCH=\"x86_64\"    -o x86_64/greeting x86_64/hello.o


Here I specify ARCH as me.
$ make ARCH=\"kbw\"
g++ -DARCH=\""kbw"\"   -c -o "kbw"/hello.o hello.cpp
g++ -DARCH=\""kbw"\"    -o "kbw"/greeting "kbw"/hello.o


This is the directory listing.
$ find .
.
./GNUmakefile
./kbw
./kbw/greeting
./kbw/hello.o
./x86_64
./x86_64/greeting
./x86_64/hello.o
./hello.cpp

Wow. Ok. It'll take me some time to understand all this.

My workaround was to just make a directory and cp the make file there and run it. Does the same thing except there is a make file in every folder.
I'll explain. File GNUmakefile:

First of all, GNU make looks for a make file called GNUmakefile, then Makefile, then makefile. I use GNUmakefile because the make file is specifically a GNU makefile, rather than a generic one.

ARCH ?= $(shell uname -m) Specify a defailt for ARCH, the result of uname -m

CXX_FILES := hello.cpp List of C++ source files.

O_FILES = $(patsubst %.cpp,$(ARCH)/%.o,$(CXX_FILES))Generate a list of object files in directory ARCH.

TARGET = $(addprefix $(ARCH)/,greeting) Generate a target file in directory ARCH.

CXXFLAGS = -DARCH=\"$(ARCH)\" Pass ARCH in quotes to the CPP files at compilation.

.PHONY: PRE We need a dummy step to run first, call it PRE. It doesn't create a program, it just a place holder, a phony target.

all: PRE $(TARGET) The first target, all. It depends on PRE and TARGET.

1
2
PRE:
        $(shell test -d $(ARCH) || mkdir -p $(ARCH))
Before we begin, create the output directory.

1
2
$(ARCH)/%.o: %.cpp
        $(COMPILE.cc) $(OUTPUT_OPTION) $<
We need to tell the build how to make a $(ARCH)/*.o file. It's made from a *.cpp file using the default rules.

1
2
$(TARGET): $(O_FILES)
        $(LINK.cc) -o $@ $^ 
And this is how we link, default rules again.
Last edited on
Topic archived. No new replies allowed.