modifying a cpp make file to .c file is not working - linux

I am trying to modify a makefile that builds cpp to a c file, but I am running into some string substitution problem. I wonder if someone can point out the mistake.
here's a piece of the file:
SOURCES := \
lz4.c \
lz4frame.c \
lz4hc.cpp \
xxhash.c
OBJECTS := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(SOURCES)))
DEPENDS := $(addprefix $(OBJ_DIR)/,$(subst .c,.d,$(SOURCES)))
all: $(OUT_DIR)/$(LIB_NAME)
clean:
rm -rf $(OBJ_DIR)
rm -rf $(OUT_DIR)
$(OUT_DIR)/$(LIB_NAME): $(OBJECTS)
#rm -f $#
$(AR) cr $# $^
$(OBJECTS): $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
#mkdir -p $(#D)
$(CXX) -MMD -MF $(OBJ_DIR)/$*.d -MP -MT'$(OBJ_DIR)/$*.o $(OBJ_DIR)/$*.d' -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
.PHONY: all clean
-include $(DEPENDS)
but when I typed make clean I get this:
Makefile:38: target `Release64/obj/lz4hc.opp' doesn't match the target pattern
or when I try to build I get this:
g++-4.6 -MMD -MF ./Release64/obj/Release64/obj/lz4hc.opp.d -MP -MT'./Release64/obj/Release64/obj/lz4hc.opp.o ./Release64/obj/Release64/obj/lz4hc.opp.d' -c -I../../../include -I../../../thirdparty/include/lz4 -std=c++0x -fPIC -O2 -m64 -o Release64/obj/lz4hc.opp
g++-4.6: fatal error: no input files
compilation terminated.
I think the issue is with this line, but I can't figure out the problem:
OBJECTS := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(SOURCES)))
DEPENDS := $(addprefix $(OBJ_DIR)/,$(subst .c,.d,$(SOURCES)))
thx!

Your sources variable is:
SOURCES := \
lz4.c \
lz4frame.c \
lz4hc.cpp \
xxhash.c
Note the filename lz4hc.cpp. Then you substitute .c with .o, that gives you a filename of lz4hc.opp which is exactly the error you see.
It's not clear if you really want a mix of C and C++ files, or if you just forgot to change the name of one of the files in the variable.

You can split C and C++ sources into separate lists, and use pattern rules to build your sources, e.g.:
SOURCES_C := \
lz4.c \
lz4frame.c \
xxhash.c
SOURCES_CPP:= lz4hc.cpp
SOURCES:=$(SOURCES_C) $(SOURCES_CPP)
OBJECTS_C := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(SOURCES_C)))
OBJECTS_CPP:=$(addprefix $(OBJ_DIR)/,$(subst .cpp,.o,$(SOURCES_CPP)))
OBJECTS:=$(OBJECTS_C) $(OBJECTS_CPP)
DEPENDS_C := $(addprefix $(OBJ_DIR)/,$(subst .c,.d,$(SOURCES_C)))
DEPENDS_CPP := $(addprefix $(OBJ_DIR)/,$(subst .cpp,.d,$(SOURCES_CPP)))
DEPENTS:=$(DEPENDS_C) $(DEPENDS_CPP)
all: $(OUT_DIR)/$(LIB_NAME)
clean:
$(RM) $(OBJECTS) $(DEPENDS)
$(OUT_DIR)/$(LIB_NAME): $(OBJECTS)
#rm -f $#
$(AR) cr $# $^
%.o: %.c
#mkdir -p $(#D)
$(CC) -MMD -MF $(OBJ_DIR)/$*.d -MP -MT'$(OBJ_DIR)/$*.o $(OBJ_DIR)/$*.d' -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
%.o: %.cpp
#mkdir -p $(#D)
$(CXX) -MMD -MF $(OBJ_DIR)/$*.d -MP -MT'$(OBJ_DIR)/$*.o $(OBJ_DIR)/$*.d' -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
.PHONY: all clean
-include $(DEPENDS)

You have a file that ends in .cpp, but your subst commands only deal with names that end in .c. Try:
OBJECTS := $(addprefix $(OBJ_DIR)/,$(subst .c,.o,$(subst .cpp,.o,$(SOURCES))))
DEPENDS := $(addprefix $(OBJ_DIR)/,S(subst .c,.d,$(subst .cpp,.d,$(SOURCES))))

Related

How to create makefile target for obj files generated in temporary directory?

I am trying to learn using makefiles again. I have a directory structure like this:
build
|- Makefile
|- Project files, like visual studio project
tmp
|- $(os name)_$(compiler)
|- *.o and any other intermediate files
bin
|- $(os name)_$(compiler)
|- the compiled binary executable
|- debug info, if any
src
|- *.cpp, *.h
So I made this Makefile after a bit of googling and experimenting:
CXX := g++
CXXFLAGS := -std=c++17 -Wall
LDFLAGS := -lpthread
ASSUMED_OS := unknownOS
SRC_DIR := ../src
EXTENSION :=
# OS detection and extension assignment for windows redacted for brevity
# ... detect OS, set extension to .exe if windows
COMPILE_PATH := $(ASSUMED_OS)_gcc
TMP_DIR := ../tmp/$(COMPILE_PATH)
TARGET_DIR := ../bin/$(COMPILE_PATH)
TARGET := $(TARGET_DIR)/MyProject$(EXTENSION)
# $(wildcard *.cpp /xxx/xxx/*.cpp): get all .cpp files from the current directory and dir "/xxx/xxx/"
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
# $(patsubst %.cpp,%.o,$(SRCS)): substitute all ".cpp" file name strings to ".o" file name strings
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
all: $(TARGET)
# Compile all obj files into an executable
$(TARGET): $(OBJS)
#mkdir -p $(#D)
$(CXX) -o $# $^ $(LDFLAGS)
# Compile all CPP files in separate obj files
%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -rf $(TARGET) ../*.o
.PHONY: all clean
This works, but it creates the .o files next to the sources.
So I tried to change the OBJS variable and replace the path:
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
# Substitute src path for tmp directory path
OBJS := $(patsubst $(SRC_DIR)/%,$(TMP_DIR)/%,$(OBJS))
But then I get an error:
make: *** No rule to make target '../tmp/linux_gcc/Job.o', needed by '../bin/linux_gcc/MyProject'. Stop.
So I tried to create a different target, one that I thought would map the object file names that should be in ../tmp/linux_gcc to the source names from ../src:
# $(wildcard *.cpp /xxx/xxx/*.cpp): get all .cpp files from the current directory and dir "/xxx/xxx/"
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
# $(patsubst %.cpp,%.o,$(SRCS)): substitute all ".cpp" file name strings to ".o" file name strings
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
# Substitute src path for tmp directory path
OBJS := $(patsubst $(SRC_DIR)/%,$(TMP_DIR)/%,$(OBJS))
all: $(TARGET)
# Compile all obj files into an executable
$(TARGET): $(OBJS)
#mkdir -p $(#D)
$(CXX) -o $# $^ $(LDFLAGS)
# Compile all CPP files in separate obj files
$(OBJS): $(SRCS)
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
But when I do that, make always compiles the same cpp file for each .o file:
g++ -std=c++17 -Wall -c ../src/Job.cpp -o ../tmp/linux_gcc/Job.o
g++ -std=c++17 -Wall -c ../src/Job.cpp -o ../tmp/linux_gcc/Worker.o
g++ -std=c++17 -Wall -c ../src/Job.cpp -o ../tmp/linux_gcc/WorkManager.o
I think I am quite close, but how can I get this to work? I think that in the compile command $(CXX) $(CXXFLAGS) -c $< -o $# I need something else than $< for the input file, but I am not sure what.
In your first makefile:
SRC_DIR := ../src
...
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
...
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
...
%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
Yes, this "creates the .o files next to the sources". If you have a source foo.cpp, the variable OBJS will contain ../src/foo.o, and the rule will build it.
In your second attempt you have changed the object, but you haven't changed the rule, so the only way Make knows to build ../tmp/linux_gcc/Job.o is from ../tmp/linux_gcc/Job.cpp, which doesn't exist.
On your third attempt you have the right idea, but there's a flaw in your rule:
$(OBJS): $(SRCS)
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
The variable $(OBJS) is a list of objects, $(SRCS) is a list of sources, so each object depends on all sources. And the automatic variable $< expands to the first item in the prerequisite list, which in this case is ../src/Job.cpp, so no matter which object you choose, Make will try to build it by compiling that source.
This is a job for a static pattern rule:
$(OBJS): $(TMP_DIR)/%.o: $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#

Makefile : How to specify where to generate an object

I would like to specify a repository for an object I generate in my makefile.
I searched for a while but only found elaborate solutions, for a list of objects, while I would like to TARGET ONE OBJECT ONLY.
(makefile is new for me, so the simpler the better)
Here is my code:
///////////////////////////////////
*definition of several directories*
*definition of CC, CFLAGS, CInclude*
cutgen:
$(CC) $(CFlags) -D__LINUX__ $(CDir)cutgen.c -o cutgen
check: cutgen cutcheck.c *list of objects here*
$(CC) $(CFlags) -I $(CHeaderDir) cutcheck.c *list of objects here* -o cutcheck
./cutcheck
cutcheck.c: cutgen test.o
./cutgen $(CDir)test.c -o cutcheck.c
test.o: util.o
$(CC) $(CFlags) -c $(CInclude) $(CDir)test.c
util.o: config.o
$(CC) $(CFlags) -c $(CInclude) $(GenDir)util.c
...
...
stubs.o:
$(CC) $(CFlags) $(CInclude) -c $(StubsDir)stubs.c
clean:
rm -f *.o *~ cutcheck* cutgen
all: check
///////////////////////////////////
Here for example, I would like to generate util.o in the Objects folder.
Any help would be appreciated, thank you in advance !
$(Objects)/util.o: config.o
$(CC) $(CFlags) -c $(CInclude) $(GenDir)util.c -o $#
(And are you sure about that prerequisite? I think $(GenDir)util.c might be better than config.o.)

How do I compile all C files to object files at once to the same directory?

I want to compile all the c files at once. ex) aaa.c,bbb.c -> aaa.o, bbb.o each independent.
My Make
CFLAGS=-std=c99
SRCS=$(wildcard *.c)
all:$(SRCS)
gcc -o $# $^ $(CFLAGS)
but make all command does not work.
How to compile all c file at once?
I changed to under the code, but still not working
CFLAGS=-std=c99
SRCS=$(wildcard *.c)
OBJS:=$(patsubst %.c,%.o,%(SRCS))
all:$(OBJS)
Simplest way: change gcc -o ... to gcc -c -o ...
Better way: make a list of the object files you want to build:
OBJS := $(patsubst %.c,%.o,$(SRCS))
and then all you have to do is:
all: $(OBJS)
simple and working Makefile:
TARGET ?= a.out
SRC_DIRS ?= ./src
INC_DIRS ?= ./include
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)
OBJS := $(addsuffix .o,$(basename $(SRCS)))
DEPS := $(OBJS:.o=.d)
LDLIBS := -L/usr/lib -lstdc++ -lfoo
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o $# $(LDLIBS)
.PHONY: clean
clean:
$(RM) $(TARGET) $(OBJS) $(DEPS)
-include $(DEPS)

Makefile auto-dependency generation

I am trying to see auto generated dependency the makefile is below:
OBJS := main.o
run : $(OBJS)
$(CC) $(OBJS) -o run -lstdc++
-include $(OBJS:.o=.d)
%.o : %.cpp
$(CC) -c $(CFLAGS) $*.cpp -o $*.o
%.d : %.cpp
#set -e; rm -f $#; \
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
echo "creating dependency file."; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# remove compilation products
clean :
rm -f run *.o *.d*
But the makefile generate a huge list of dependency in main.d but the actual needed is the first few lines. So where I am getting wrong?
Try this instead:
OBJS := main.o
run : $(OBJS)
$(CC) $(OBJS) -o run -lstdc++
-include $(OBJS:.o=.d)
%.o : %.cpp
$(CC) -c -MMD -MP $(CFLAGS) $*.cpp -o $*.o
# remove compilation products
clean :
rm -f run *.o *.d*

how to include .h document in makefile

I am programming for a big project, so I cooperate with others.
To make the directory easily managed, my directory is like below:
project:
--include (header files from others supplied for me)
--lib (libraries from others supplied for me)
--L3_CVS (this folder include all my files)
-- Makefile
-- sourceFile (all my source files here)
-- include_private(all header files used only by myself)
-- appl (all my C files here)
My Makefile is below:
####################################################
CROSS_COMPILE=/home/powerpc-wrs-linux-gnu/x86-linux2/powerpc-wrs-linux-gnu-ppc_e500v2-glibc_cgl-
EXTRA_CFLAGS += -g
EXTRA_LDFLAGS +=
LIBSB =-Wl,--start-group -ldiag -ldiag_esw -lacl -ldiagcint -lcint -lsal_appl -lsal_appl_editline -lsal_appl_plat\
-lbcm -lbcm_esw -lbcm_common -lfirebolt -ltitan -ltrident -lhumv -lbradley -lherc -ldraco -lscorpion\
-ltriumph -ltrx -ltriumph2 -lenduro -lkatana -lflexctr -lptp -lsoc_esw -lsoc -lsoc_phy -lsoc_mcm\
-lsoccommon -lsoc_shared -lshared -lsal_core -lsal_core_plat -lcustomer -lsoc_nemo -lsoc_clsbuilder\
-lsoc_sal \
-lbcm_compat -lbcm_rpc -lcpudb -ltrx -lstktask -llubde -ldrivers -ldiscover -lcputrans \
-lrcu -lpthread -lrt -lm -Wl,--end-group
LIBS = -ldiag -lrcu
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar
STRIP = $(CROSS_COMPILE)strip
SRC_PATH := ./SourceFile/appl
HEAD_PATH := ./SourceFile/include-private
INC_DIR = ../include
LIB_PATH = ../lib
APP_NAME = L3appl
SRCS := $(wildcard $(SRC_PATH)/*.c)
export $(SRCS)
OBJS:= $(patsubst %.c,%.o,$(SRCS))
%.d: %.c
#set -e; rm -f $#; \
$(CC) -MM $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
sinclude $(SRCS:.c=.d)
INCLUDES = $(wildcard $(HEAD_PATH)/*.h)
$(APP_NAME):$(OBJS)
$(CC) -c -I$(INC_DIR) $(SRCS)
$(CC) -o $(APP_NAME) $(OBJS) -L$(LIB_PATH) $(LIBSB) -lpthread -lrt -lm
.PHONY:clean
clean:
rm -f $(OBJS) $(APP_NAME)
#################################################
My problem is that when I run make in terminal, it always show : ***No such file or directory
compilation terminated. which seems the .h files in ./SourceFile/include-private do not be included.
But, in fact, I have use "INCLUDES = $(wildcard $(HEAD_PATH)/*.h)" include these .h files.
I don't know where is wrong!
this is my first time to write makefile. So if there are mistakes in my makefile, I would appreciate that you would point them out !
thank you for your help very much!!!!!!!
You should have something like
CFLAGS = -Wall $(OPTIMFLAGS) $(INCLUDEFLAGS)
INCLUDEFLAGS = -I $(INC_DIR) -I $(HEAD_PATH)
OPTIMFLAGS = -g -O
You can use remake to debug your Makefile.
You can try to change $(CC) -c -I$(INC_DIR) $(SRCS) to $(CC) -c -I$(INC_DIR) -include $(INCLUDES) $(SRCS)
or $(CC) -c -I$(INC_DIR) $(SRCS) to $(CC) -c -I$(INC_DIR) -I$(INCLUDES) $(SRCS)
where INCLUDES is ./SourceFile/include-private (only the directory, no .h files)
Edit: Usually you don't have to explicitly include the .h files, but that's what the first change do. The second change does not add the .h files explicitely but provide the compiler another include directory where it could search for necessary .h files.
Refer to GCC man file for more info.
Regards

Resources