Makefile not prompting compiler to use optimization flag - bash

I have a simple makefile that I am using in bash to compile a C++ program and its associated .h files, not every .h file has a .cpp file associated with it. I wrote a makefile where each dependency was called out explicitly and the CFLAG macro was used for each specific dependency and it did compile with the -O3 flag and ran nearly 3 times faster. However, when I use this simpler, but somewhat more sophisticated makefile, it does not compile with the -O3 flag even though it is clearly included with the CFLAG macro. Can someone point out to me what I am missing, I would greatly appreciate it.
OBJS = main.o Output_Files.o Calendar.o Random_Number_Generator.o \
Algorithm.o Statistics.o
DEPS = Output_Files.h Calendar.h Random_Number_Generator.h Algorithm.h \
Statistics.h
CC=c++
CFLAGS=-c -Wall -O3
all: economics
%o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $# $<
economics: $(OBJS)
$(CC) $(OBJS)
main.o: main.cpp Data_Parser.h PDF_and_CDF.h
$(CC) $(CFLAGS) main.cpp

The rule:
%o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $# $<
should be written with an extra dot:
%.o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $<
Also, you don't want $# in the command line, or (if you must have it) you need to prefix it with -o.
The makefile is not using the faulty rule but instead uses the default rule for building C++ object files, and that most probably doesn't use $(CFLAGS) but uses $(CXXFLAGS) instead.
CC is the macro for the C compiler, not the C++ compiler. Normally, that is CXX. Also, the rule to build economics actually creates a.out and not economics.
I'd prefer it if you wrote:
SRCS = main.cpp Output_Files.cpp Calendar.cpp Random_Number_Generator.cpp \
Algorithm.cpp Statistics.cpp
OBJS = ${SRCS:.cpp=.o}
…
economics: $(OBJS)
$(CC) -o $# $(OBJS)
Putting it all together gives this new.makefile:
SRCS = main.cpp Output_Files.cpp Calendar.cpp Random_Number_Generator.cpp \
Algorithm.cpp Statistics.cpp
OBJS = ${SRCS:.cpp=.o}
DEPS = Output_Files.h Calendar.h Random_Number_Generator.h Algorithm.h \
Statistics.h
CC = c++
CFLAGS = -c -Wall -O3
all: economics
%.o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $<
economics: $(OBJS)
$(CC) -o $# $(OBJS)
main.o: main.cpp Data_Parser.h PDF_and_CDF.h
$(CC) $(CFLAGS) main.cpp
Running make -n with the old makefile
$ make -n -f old.makefile
c++ -c -Wall -O3 main.cpp
c++ -c -o Output_Files.o Output_Files.cpp
c++ -c -o Calendar.o Calendar.cpp
c++ -c -o Random_Number_Generator.o Random_Number_Generator.cpp
c++ -c -o Algorithm.o Algorithm.cpp
c++ -c -o Statistics.o Statistics.cpp
c++ -o economics main.o Output_Files.o Calendar.o Random_Number_Generator.o Algorithm.o Statistics.o
$
Running make -n with the new makefile
$ make -n -f new.makefile
c++ -c -Wall -O3 main.cpp
c++ -c -Wall -O3 Output_Files.cpp
c++ -c -Wall -O3 Calendar.cpp
c++ -c -Wall -O3 Random_Number_Generator.cpp
c++ -c -Wall -O3 Algorithm.cpp
c++ -c -Wall -O3 Statistics.cpp
c++ -o economics main.o Output_Files.o Calendar.o Random_Number_Generator.o Algorithm.o Statistics.o
$
This is still an abnormal way of writing the make rules on a number of grounds, one being the $(CC) vs $(CXX) change. Normally, the -c option is not included in $(CFLAGS) or $(CXXFLAGS). Normally, you include $(CFLAGS) or $(CXXFLAGS) in the link line too (because some of the flags might affect linking). Often, you need libraries and related flags in the linker line too.
This leads to a more orthodox naming convention:
SRCS = main.cpp Output_Files.cpp Calendar.cpp Random_Number_Generator.cpp \
Algorithm.cpp Statistics.cpp
OBJS = ${SRCS:.cpp=.o}
DEPS = Output_Files.h Calendar.h Random_Number_Generator.h Algorithm.h \
Statistics.h
CXX = c++
CXXFLAGS = -Wall -O3
LDFLAGS =
LDLIBS =
all: economics
%.o: %.cpp $(DEPS)
$(CXX) -c $(CXXFLAGS) $<
economics: $(OBJS)
$(CXX) -o $# $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
main.o: main.cpp Data_Parser.h PDF_and_CDF.h
$(CXX) -c $(CXXFLAGS) main.cpp

Related

GNU makefiles remaking existing targets

I have a simple makefile on my machine:
# Compiler: g++ for C++ source files
CC = g++
# Compiler flags:
CFLAGS = -std=c++14 -Wall -Wextra -pedantic -O0 -c
foo.o: foo.cpp
$(CC) $(CFLAGS) $?
bar.o: bar.cpp
$(CC) $(CFLAGS) $?
foobar: foo.o bar.o
$(CC) -o $# $?
When I run make it remakes each target, even if it already exists. I want the makefile to ignore existing targets. What am I doing wrong?
Doing this fixed my problem:
# Compiler: g++ for C++ source files
CC = g++
# Compiler flags:
CFLAGS = -std=c++14 -Wall -Wextra -pedantic -O0 -c
all: foo.o bar.o foobar
foo.o: foo.cpp
$(CC) $(CFLAGS) $<
bar.o: bar.cpp
$(CC) $(CFLAGS) $<
foobar: foo.o bar.o
$(CC) -o $# $^
and also
touch makefile

Why does my Makefile with pattern rules not create debugging symbols for main?

I am using this auto-generated Makefile with pattern rules, that I oviously do not understand yet. I want to create debuggins symbols and then debug main, but it doesn't work. There is a -g flag. Adding $(LDFLAGS) statement above after $(ODIR) does not print one as expcted.
IDIR =./include
CC=g++
CFLAGS = -I$(IDIR)
LDFLAGS = -g
ODIR=./
LIBS=
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
main: $(OBJ)
$(CC) $(LDFLAGS) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o
This is the terminal output
g++ -c -o Source.o Source.cpp
g++ -g -o Source Source.o -I./include
Your sources are C++ (.cpp) but your Makefile contains explicit instructions for building C files. Make is therefore falling back to its built in implicit rules.
Also note that by convention those rules use $(CXX) to refer to the C++ compiler, with $(CXXFLAGS) replacing $(CFLAGS), and the -I flag belongs in $(CPPFLAGS):
IDIR =./include
CPPFLAGS = -I$(IDIR)
CXXFLAGS = -g
ODIR=.
LIBS=
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.cpp
$(CXX) -c -o $# $(CPPFLAGS) $(CXXFLAGS) $<
main: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJ)
If you were to do away with the ODIR handling and use the conventional variable names you could do without the explicit .o: .cpp rule altogether.

Compiling with nvcc and g++

I'm using Nvidia's nvcc compiler to compile a .cpp file which will contain device code (but only contains host code now). The program I am using is written in C and C++ and uses gcc/g++ to compile with and g++ is used to link the final executable together. Originally, when I run my program using -Ofast, it runs in about 2 seconds, but I factored in nvcc to compile 1 .cpp file and the rest with gcc/g++, have g++ link it together, the program takes about 8 seconds to run. If I compile more .cpp files with nvcc, it slows down even more (~10 seconds). I tried adjusting my make file to compile everything with nvcc but I received too many errors from the C code. Only the C++ code seems to be able to run without errors when compiled with nvcc. Does nvcc not optimise the host code? Why does this happen? What is the best way to structure the program?
Makefile
CC = gcc
CCPP = g++
NVCC = /vol/cuda/8.0.61/bin/nvcc
#preprocessor defines
DEFINES = -DUSE_ZLIB
OPTFLAGS = -Ofast
#CFLAGS = -ansi -pedantic -Wall -Werror -fPIC
#CFLAGS = -ansi -pedantic -Wall -fPIC
CFLAGS = -ansi $(OPTFLAGS)
NVFLAGS = -x c++ -Wno-deprecated-gpu-targets -ccbin g++
NVLINKFLAGS = -L/vol/cuda/8.0.61/lib64/ -lcuda -lcudart
#NVLINKFLAGS += -L/vol/cuda/8.0.61/lib -lcuda -lcudart
CPPFLAGS = $(OPTFLAGS) -I./include $(DEFINES)
LINKFLAGS = -lz
all : simple
objs = src/tourtre.o \
src/ctArc.o \
src/ctBranch.o \
src/ctComponent.o \
src/ctNode.o \
src/ctQueue.o \
src/ctNodeMap.o \
examples/simple/obj/Data.o \
examples/simple/obj/Mesh.o \
examples/simple/obj/main.o
simple : $(objs)
$(CCPP) $(CPPFLAGS) -o simple $^ $(LINKFLAGS) $(NVLINKFLAGS)
src/tourtre.o : src/tourtre.c include/tourtre.h src/ctMisc.h include/ctArc.h include/ctNode.h src/ctComponent.h include/ctNode.h src/ctQueue.h src/ctAlloc.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctArc.o : src/ctArc.c include/tourtre.h src/ctMisc.h include/ctArc.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctBranch.o : src/ctBranch.c include/tourtre.h src/ctMisc.h include/ctBranch.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctComponent.o : src/ctComponent.c include/tourtre.h src/ctMisc.h src/ctComponent.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctNode.o : src/ctNode.c include/tourtre.h src/ctMisc.h include/ctNode.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctQueue.o : src/ctQueue.c include/tourtre.h src/ctMisc.h src/ctQueue.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctNodeMap.o : src/ctNodeMap.c src/ctNodeMap.h include/ctNode.h src/ctQueue.h src/sglib.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
examples/simple/obj/Data.o: examples/simple/src/Data.cpp examples/simple/src/Data.h examples/simple/src/Global.h
$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
examples/simple/obj/Mesh.o: examples/simple/src/Mesh.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h
$(NVCC) $(NVFLAGS) -c $< -o $#
examples/simple/obj/main.o: examples/simple/src/main.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h
$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
clean :
-rm -rf src/*.o examples/simple/obj/*.o doc/html
Add -Xcompiler -ansi -Xcompiler -Ofast to NVFLAGS so that the host compiler gets the same (optimization) flags from nvcc as when run directly.

CFLAGS are ignored in Makefile

I am using the following makefile to build my project:
CC = /usr/bin/g++
CFLAGS = -Wall -pedantic -std=c++0x
LDFLAGS =
OBJ = main.o pnmhandler.o pixmap.o color.o
pnm: $(OBJ)
$(CC) $(CFLAGS) -o pnm $(OBJ) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $<
As I run make I get the following error:
/usr/include/c++/4.9.1/bits/c++0x_warning.h:32:2: error: #error This
file requires compiler and library support for the ISO C++ 2011
standard. This support is currently experimental, and must be enabled
with the -std=c++11 or -std=gnu++11 compiler options.
As I can read from the following line, the CFLAGS are not properly included, but I have no idea what I am doing wrong:
g++ -c -o main.o main.cpp
Also tried -std=c++11 and -std=gnu++11, without any results. Any ideas?
If I run make -Bn, I get:
g++ -c -o main.o main.cpp
g++ -c -o pnmhandler.o pnmhandler.cpp
g++ -c -o pixmap.o pixmap.cpp
g++ -c -o color.o color.cpp
/usr/bin/g++ -Wall -pedantic -std=c++0x -o pnm main.o pnmhandler.o pixmap.o color.o
EDIT: Replacing the rule %.o: %.c with %.o: %.cpp fixes my problem.
The reason you see
g++ -c -o main.o main.cpp
is that Make is invoking its standard rule to create the object file:
%.o: %.cpp
# recipe to execute (built-in):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
The command expands to
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $# $<
Instead of setting CC and CFLAGS in your makefile, you should set CXX and CXXFLAGS, which are meant for C++ rather than C. That allows the built-in rule above to work for you, and then you just need to make sure the right linker is used, e.g. with
pnm: LINK.o=$(LINK.cc)
pnm: $(OBJ)
You also don't need the %.o: %.c rule, as you have no C sources.
Complete Makefile:
CXX = /usr/bin/g++
CXXFLAGS = -Wall -pedantic -std=c++0x
OBJ = main.o pnmhandler.o pixmap.o color.o
pnm: LINK.o=$(LINK.cc)
pnm: $(OBJ)
clean::
$(RM) pnm
.PHONY: clean

variable error in makefile

I have Makefile in Ubuntu12.10 as below.
when I run it by make command, it shows as
g++ -c -o myprog1.o myprog1.cpp
It seems the variables CFLAGS and CINCLUDE do not work.
Can any one help me to check it?
Thanks,
RM = rm -f
CC = gcc
AR = ar rc
CFLAGS= -Wall -g -O2 -std=c++11 -fPIC
CINCLUDE= -I. -I../include
OBJECTS= myprog1.o myprog2.o
STATIC_LIB = libctest.a
$(STATIC_LIB): $(OBJECTS)
$(AR) $(STATIC_LIB) $(OBJECTS)
%.o : %.c
$(CC) -c $(CFLAGS) $(CINCLUDE) $< -o $#
clean:
$(RM) $(OBJECTS)
$(RM) $(STATIC_LIB)
The problem is that you have a make rule for %.o : %.c but not for %.o : %.cpp. When you run the make, the implicit make rule for '%.cpp' runs, but the implicit rule doesn't contain references to CFLAGS or CINCLUDE.
Since your source is in c++, you probably want to add another rule for c++ compilation and set up the CXX variables appropriately.
CXXFLAGS = $(CFLAGS)
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $(CINCLUDE) $< -o $#

Resources