Combine C and C++ in Makefile - makefile

I have the following makefile stub. As you can see, I'm trying to pass all .cpp and .c files to the same command line. But I get asdf.c:1: *** missing separator. Stop. I've verified that there are tabs instead of spaces. The error only occurs when I try to combine the C++ and C. Can I make it work?
SRC := $(shell find . -name "*.cpp") $(shell find . -name "*.c")
OBJ := boot.o $(SRC:.cpp=.o) $(SRC:.c=.o)
%.o: %.cpp %.c
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $#
The error only seems to be when I use a .c file. For example:
SRC := $(wildcard *.c)
OBJ := boot.o $(SRC:.c=.o)
%.o: %.c
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $#
gives the same error.
or SRC := $(shell find . -name "*.cpp") asdf.c
The makefile works completely fine until the c file shows up. I've verified this file is the problem because touch test.c and then added test.c to SRC doesn't cause an error.
What could my .c file possibly do to cause make an error?

Related

Compile C source files from tree into build directory with make

I have a Makefile that looks similar to this condensed version:
.PHONY: all
CC = gcc -O3 -fPIC
SRC = $(shell find src -type f -name '*.c')
OBJ = $(addprefix build/, $(notdir $(SRC:.c=.o))
TGT = build/prog
all: $(TGT)
$(TGT): $(OBJ)
$(CC) $+ -o $#
build/%.o: src/a/%.c
$(CC) -c $+ -o $#
build/%.o: src/b/%.c
$(CC) -c $+ -o $#
build/%.o: src/c/d/%.c
$(CC) -c $+ -o $#
I would like to combine the build/%.o rules into one rule because the real makefile has like twenty of these for various paths in the src directory. But whatever I tried nothing works. I'm sure there must be a solution, please enlighten me how this can be done.
As stated in the comment you can make use of GNU make's vpath directive...
.PHONY: all
CC = gcc -O3 -fPIC
SRC = $(shell find src -type f -name '*.c')
OBJ = $(addprefix build/, $(notdir $(SRC:.c=.o))
TGT = build/prog
all: $(TGT)
$(TGT): $(OBJ)
$(CC) $+ -o $#
# Use vpath to give make a colon (or space) separated list
# of directories in which to look for .c files.
#
vpath %.c src/a:src/b:src/c/d
build/%.o: %.c
$(CC) -c $+ -o $#
Since you're using find to locate the source files you could go a step further and use the results of that find to generate the vpath...
.PHONY: all
CC = gcc -O3 -fPIC
SRC = $(shell find src -type f -name '*.c')
OBJ = $(addprefix build/, $(notdir $(SRC:.c=.o))
TGT = build/prog
all: $(TGT)
$(TGT): $(OBJ)
$(CC) $+ -o $#
# Use vpath to give make a colon (or space) separated list
# of directories in which to look for .c files. Make use of
# the $(SRC) variable to generate the list of paths automatically.
#
SRC_DIRS := $(sort $(dir $(SRC)))
vpath %.c $(SRC_DIRS)
build/%.o: %.c
$(CC) -c $+ -o $#

makefile how to output to separate build directory

I have this directory structure:
makefile
src
foo.c
build
My goal is simply to build foo.c and output the build files to the build directory.
I have the following makefile:
SRCS_DIR := ./src
BUILD_DIR := ./build
SRCS := $(shell find $(SRCS_DIR) -name "*.c")
OBJS := $(subst $(SRCS_DIR),$(BUILD_DIR),$(SRCS))
OBJS := $(OBJS:.c=.o)
test.exe: $(OBJS)
gcc $(OBJS) -o $#
%.o: %.c
gcc -c $< -o $#
The problem is the pattern rule. One of the object files is build/foo.o. The problem is that %.c gets turned into build/foo.c, which doesn't exist. What I want %.c to be is src/foo.c instead, but I have no idea how to do that.
The stem of the pattern must match exactly. So if you want a pattern that will put things into a different directory, you have to modify the pattern so that the non-matching parts are not part of the stem. So you can write:
build/%.o : src/%.o
gcc -c $< -o $#
so that the % matches only the common string.

Falty Makefile causes undefined reference and multiple definition errors

I'm on my path to study the wonderful world of Makefiles and this was my first attempt on my own makefile. However I have hit my small brains at a wall with errors and I can not figure the cause, I only know the issue is in the Makefile, I am doing something wrong, because when I compile my "project" manually, it compiles.
cxx := g++
dirs := obj bld_win32 bld_linux
cpp := $(wildcard src/*.cpp)
obj := $(addprefix obj/,$(notdir $(cpp:.cpp=.o)))
ifeq ($(OS), Windows_NT)
target := bld_win32/engine.exe
flags := -mwindows -lopengl32 -openal32 -lgdi32
else
target := bld_linux/engine
flags := -lX11 -lGL -lopenal -lalut
endif
all: precheck $(target)
precheck:
mkdir -p $(dirs)
$(target): $(obj)
$(cxx) -std=c++11 -Wall -o $# $^ $(flags)
obj/%.o: $(cpp)
$(cxx) -c -o $# $<
Your pattern rule is wrong, as you would have noticed if you'd tried to build object files one by one using this makefile. This rule:
obj/%.o: $(cpp)
$(cxx) -c -o $# $<
lists all source files as prerequisites of every object file, and when you try to build any object file, it compiles only the first source file in the list (src/aardvark.cpp, or whatever), so that all of your object files are the same, even though they have different names.
Change it to this:
obj/%.o: src/%.cpp
$(cxx) -c -o $# $<

Makefile mirror build directory

I need to create Makefile that compiles .c files with a lot of subdirs (sources directory goes in around 5 level depth) and I need to place the object files in the mirrored build directory. So far, I have created this Makefile:
CC := gcc.exe
AS := as.exe
CFLAGS = -DCORE_SW_VERSION='"$(CORE_SW_VERSION)"' -Wall -mA6 -c -fmessage-length=0 -Hsdata0
CFLAGS += -fgnu89-inline -mno-volatile-cache $(INCLUDE) -Hon=each_function_in_own_section -Xcrc -std=c99 -O1
CORE_SW_VERSION:=CORE.07.01.04.01.03.01.R
HAL_SW_VERSION:=16.01.06.01.06.00
MODE_CORE := dev
MODE_HAL := dev
OBJDIR := $(shell pwd)/$(TARGET12) #TARGET12 is a make parameter
INCLUDE := $(shell cat ./$(TARGET12)_include.txt)
SOURCEDIR := ../sources
CSRC := $(shell find $(SOURCEDIR) -name '*.c')
EXCLUDES := $(shell cat ./$(TARGET12)_exclude.txt)
OBJ := $(CSRC:.c=.o)
OBJS := $(patsubst ../%.c,$(OBJDIR)/%.o,$(CSRC))
.PHONY: $(TARGET12)
$(TARGET12): $(OBJS)
$(AR) -r $(CORE_SW_VERSION).a $(OBJS)
$(OBJS): $(CSRC)
mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $(patsubst ../%,$(OBJDIR)/%,$#)
If I define rule for $(OBJS) this way, $< is always the first .c file in $(CSRC).
If I define $(OBJS) this way:
$(OBJS): %.o: %.c
mkdir -p $(dir $#)
$(CP) $< $#
I get error that there is no rule to make target for .c file. But I see that make is looking for .c file in build mirrored directory, and it should look at the source dir. Do you maybe know how this could be arranged?
Thanks you in advance!
The rule $(OBJS): %.o: %.c means something like this: when trying to create a .o file, use this rule if the corresponding .c file exists. For example: when make is looking for a way to create $(OBJDIR)/foo.o, it will look for $(OBJDIR)/foo.c.
In your case this file does not exists, so the rule is ignored.
What you want is rather something like this:
$(OBJS): $(OBJDIR)/%.o: $(SOURCEDIR)/%.c
mkdir -p $(dir $#)
$(CP) $< $#
The first rule for $(OBJS) you tried, states that every object file individually depends on all source files. Surely that's not correct.
Your second attempt is better, although the recipe is weird. Fix that and use VPATH to make make find the sources.

Automatic generate target From Source List Make File

I have this directory structure.
app/
src
include
lib/
src
maincode/
main.cc
Makefile
I want to generate automatic target from the source list in makefile. So I don't have to write rule for each file.
Example
source=\
../src/a.cpp
../src/ab.cpp
../lib/src/b.cpp
I want to write rule like
%.o:%.cpp
so that I don't have to repeat rule for each file.
How I can achieve this ?
Edit: the find command should be inside a shell variable
If you are using Linux, I think you can use:
SOURCES=$(shell find . -name *.cpp)
OBJECTS=$(SOURCES:%.cpp=%.o)
%.o: %.cpp
<command to compile>
I like Sagar's answer, though it took me a bit to figure out I what I wanted for an additional rule to cause creation of the objects:
SOURCES=$(shell find . -name *.cpp)
OBJECTS=$(SOURCES:%.cpp=%.o)
all: $(OBJECTS)
%.o: %.cpp
<command to compile dependencies $< into target $# > $< -o $#
CPP = g++
CPPFLAGS = -Wall -pedantic -O2 -g -c
SOURCES := ${wildcard *.cpp}
OBJECTS := ${SOURCES:.cpp=.o}
.PHONY: all clean
.SUFFIXES: .cpp .o
all: main
main: $(OBJECTS)
.cpp.o:
$(CPP) $(CPPFLAGS) $< -o $#
clean:
-rm -fv *.o
For more info see the man

Resources