I have a question about makefiles, below is my project structure.
enter image description here
Below is my makefile
.PHONY:clean install distclean
INCLUDEPATH = ../include
LIBRARYPATH = ../lib
LIBNAME = ../lib/libglfw.3.3.dylib ../lib/libGL.dylib ../lib/libGLU.dylib
# third part libary
EXTERNALDIR = ../External
IMGUIDIR = ../External/Imgui/include
GLADDIR = ../External/glad/include
IMGUIZMODIR = ../External/Imguizmo
GLFWDIR = ../External/glfw
GLADSRC = ../External/glad/src
IMGUISRC = ../External/Imgui/src
IMGUIZMOSRC = ../External/Imguizmo
CC = gcc
C++ = g++ -std=c++17
C++FLAGS = -c -I$(INCLUDEPATH) -I$(EXTERNALDIR) -I$(IMGUIDIR)-I$(GLADDIR) -I$(IMGUIZMODIR) -I$(GLFWDIR)
CCFLAGS = -c -I$(INCLUDEPATH) -I$(GLADDIR)
LDFLAGS = -L$(LIBRARYPATH) $(LIBNAME)
TARGET = app
INSTALLPATH = /usr/bin/
RM = rm -rf
MV = sudo mv $(TARGET) $(INSTALLPATH)
CCFILES = $(wildcard *.c $(GLADSRC)/*.c)
C++FILES = $(wildcard *.cpp $(IMGUISRC)/*.cpp $(FILEDLGSRC)/*.cpp $(IMGUIZMOSRC)/*.cpp)
OBJFILES = $(patsubst %.c,%.o,$(CCFILES)) $(patsubst %.cpp,%.o,$(C++FILES))
$(TARGET):$(OBJFILES)
$(C++) $^ $(LDFLAGS) -o $#
%.o:%.c
$(CC) $(CCFLAGS) $<
%.o:%.cpp
$(C++) $(C++FLAGS) $<
clean:
$(RM) $(TARGET)
$(RM) $(OBJFILES)
install:
$(MV)
distclean:
$(RM) $(INSTALLPATH) $(TARGET)
echo:
-#echo $(SRCFILE)
-#echo $(DESFILE)
removfile:
-#rm clean
-#rm clean_01
-#rm clean_02
When I run the makefile, I will generate all the .o files in the src/ directory, which will cause the .o files to not be found in the subsequent compilation process and the compilation will fail. Any tips to fix it. For example, how do I put the .o files generated by .cpp in the external directory in the external directory instead of the src directory.
It's just a matter of changing the list of object files and the rules for building them:
OBJFILES = $(patsubst %.c,$(EXTERNALDIR)/%.o,$(CCFILES)) $(patsubst %.cpp,$(EXTERNALDIR)/%.o,$(C++FILES))
$(EXTERNALDIR)/%.o:%.c
$(CC) $(CCFLAGS) $< -o $#
$(EXTERNALDIR)/%.o:%.cpp
$(C++) $(C++FLAGS) $< -o $#
Related
# Makefile to compare sorting routines
BASE = /home/blufox/base
CC = gcc
CFLAGS = -O –Wall
EFILE = $(BASE)/bin/compare_sorts
INCLS = -I$(LOC)/include
LIBS = $(LOC)/lib/g_lib.a \
$(LOC)/lib/h_lib.a
LOC = /usr/local
OBJS = main.o another_qsort.o chk_order.o \
compare.o quicksort.o
$(EFILE): $(OBJS)
#echo “linking …”
#$(CC) $(CFLAGS) –o $# $(OBJS) $(LIBS)
$(OBJS): compare_sorts.h
$(CC) $(CFLAGS) $(INCLS) –c $*.c
# Clean intermediate files
clean:
rm *~ $(OBJS)
variables substitute to form,
gcc -O –Wall -o /home/blufox/base/bin/compare_sorts main.o another_qsort.o chk_order.o compare.o quicksort.o main.c another_qsort.c chk_order.c compare.c
for eg:
$(OBJS) = main.o another_qsort.o chk_order.o compare.o quicksort.o
I have variable in my Makefile:
SRCP = \
main.c \
lib1/src/file1.c \
lib2/src/file2.c
Folders lib1/src and lib2/src may consist other sources, but I need compil only files in SRCP var.
I know one variant:
OBJ_DIR = ./Release/Obj
OBJ = $(SRC:.c=.o)
$(OBJ): $(SRCP)
for source in $(SRCP); do \
$(CC) $(CLAGS) -c $$source -o $(OBJ_DIR)/$#; \
done
But not informative. In console I see $source instead main.c (or any name).
My makefile with errors:
.PHONY: all clean
PROJECT = hello
IAR_TARGET = ./Release
EXE_DIR = $(IAR_TARGET)/Exe
OBJ_DIR = $(IAR_TARGET)/Obj
COMPILE_OPTS = -mcpu=cortex-m3 -mthumb -Wall -g -O0
INCLUDE_DIRS = -I . \
-I lib/inc
SRCP = \
main.c \
lib/src/stm32f10x_tim.c \
lib/src/stm32f10x_adc.c
LIB = -L ./lib/src
SRC := $(notdir $(SRCP))
OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(SRCP:.c=.o)))
CC = arm-none-eabi-gcc
CFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)
# mkdir -p $(EXE_DIR) $(OBJ_DIR)
all: $(EXE_DIR)/$(PROJECT).elf
# Linker invocation
$(EXE_DIR)/$(PROJECT).elf: $(OBJ_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(EXE_DIR)/$(PROJECT).elf
# Rules
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
clean:
rm -rf $(IAR_TARGET)
Error: make: *** No rule to make target 'Release/Obj/main.o', needed by 'Release/Exe/hello.elf'. Stop.
What is the correct version you know?
I don't have any specific experience with IAR projects. But I guess I can help you with the Makefile.
The main changes I propose are:
Change the definition of OBJ_FILES such that it contains a list of the object files with the proper path name, e.g. ./Release/Obj/file1.o. notdir removes the directory, addprefix adds the new directory.
Add a pattern rule how to convert a .c file into a .o file. As object files are a dependency of the final file (a .elf file in this example) and as there are no explicit rules to build the these object file, make will use the pattern rule to build them.
Most likely, GNU make is required for this makefile.
SRCP = \
main.c \
lib/src/stm32f10x_tim.c \
lib/src/stm32f10x_adc.c
OBJ_DIR = ./Release/Obj
OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(SRCP:.c=.o)))
# Linker invocation
$(OUTPUT_DIR)/$(PROJECT).elf: $(OBJ_FILES)
$(CC) $(LDFLAGS) $(OBJ_FILES) $(STD_LIBS) -o $(OUTPUT_DIR)/$(PROJECT).elf
# Rules
$(OBJDIR)/%.o: ./%.c
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR)/%.o: lib/src/%.c
$(CC) $(CFLAGS) -c $< -o $#
I know!
I have list of files with path:
SRCP := \
main.c \
lib/src/stm32f10x_tim.c \
lib/src/stm32f10x_adc.c
How to get .c file with path by object name?
Look:
OBJ_DIR=Release/Obj
# Rules
%.o:
#echo creating $# ...
$(CC) $(CFLAGS) -c $(filter %$(subst .o,.c,$#), $(SRCP)) -o $(OBJ_DIR)/$#
How to work this $(filter %$(subst .o,.c,$#), $(SRCP))?
For example, $# have stm32f10x_adc.o
$(subst .o,.c,$#) change .o to .c, so we have stm32f10x_adc.c. Very important! This string do not have spaces (like I like:) ). I do mistake, when write $(subst .o, .c, $#). It is not clear for me (:
%$(subst .o,.c,$#). % work with filter.
$(filter %$(subst .o,.c,$#), $(SRCP)) take %stm32f10x_adc.c from $(SRCP) with path. And... We have lib/src/stm32f10x_adc.c!
Thankyou for the help!
I have the following Makefile:
SOURCES = part1.cpp part2.cpp main.cpp
OBJECTS = ${SOURCES:.cpp=.o}
DEPS = ${SOURCES:.cpp=.d}
CXX = g++
CXXFLAGS = -Wall -I -std=c++11
ExecutableName = Partsapp
BUILD_DIR = build/host
MahApp: $(BUILD_DIR)/$(DEPS) $(BUILD_DIR)/$(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $(BUILD_DIR)/$(OBJECTS)
build/host/%.d: ./%.cpp
$(CXX) -MT$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
-include build/host/$(DEPS)
clean:
rm -f $(OBJECTS) $(DEPS) MahApp
Now, whenever I try to run it, I get the following error:
No rule to make target 'part2.d', needed by 'MahApp'. Stop.
Now, the funny thing is that it does manage to create part1.d correctly from the pattern matching rule, however after that it just seizes to work, and I just can't figure out why!
Any help would be much appreciated :)
SOURCES = part1.cpp part2.cpp main.cpp
...
DEPS = ${SOURCES:.cpp=.d}
...
BUILD_DIR = build/host
MahApp: $(BUILD_DIR)/$(DEPS) ...
...
DEPS expands to part1.d part2.d main.d, so $(BUILD_DIR)/$(DEPS) expands to build/host/part1.d part2.d main.d, and Make is telling you it can't find part2.d.
The construction you want is:
BUILD_DIR = build/host
DEPS = $(patsubst %.cpp, $(BUILD_DIR)/%.d, $(SOURCES))
(There are other ways to do it.) And the way to examine your variables to see if they are what you think they are is like this:
$(info $(DEPS))
First of all, I'm trying to get used to makefiles but yet I#m new with this. The following file is supposed to, first, compile all ./src/*.cpp files to ./src/*.o (where the filename survives) and afterwards complete compilation with simulation.cpp and linking the whole stuff together. Now, make returns the error message:
make: -c: Command not found
I have literally no clue how to proceed! Would the wildcard-construct even work in the way desired? Thanks a lot for your effort!
#basic stuff
TRUE = 1
FALSE = 0
SHELL := #!/bin/bash
# path names
SRCPATH = ./src/
CLEANPATH = ./res/ \
./crash/
# source files.
MAIN = simulation.cpp
OBJS = $(wildcard $(SRCPATH)*.o)
SRCS = $(wildcard $(SRCPATH)*.cpp)
INCLUDES = $(wildcard $(SRCPATH)*.h)
#GLOBAL MACROS PASSED TO PROGRAM!
MODEL_MRT = $(TRUE) #if true model used is MRT else SRT
PARALLEL = $(TRUE)
GRAVITY = $(TRUE)
# output file name
OUT = simulation
# C++ compiler flags (-g -O2 -Wall)
CXXFLAGS = -g -Wall -O -fopenmp
CXXDEFINES = -D MODEL=$(MODEL_MRT) -D PARALLEL=$(PARALLEL) -D GRAVITY=$(GRAVITY)
# compiler
CXX = g++
$(OUT) : $(OBJS)
$(CXX) $(CXXFLAGS) $(MAIN) $(OBJS) $(CXXDEFINES) -o $(OUT)
$(OBJS) : $(SRCS) $(INCLUDES)
$(CXX) $(CXXFLAGS) -c $(SRCS) -o $(OBJS)
clean : $(OUT)
rm $(OBJS)
rm $(CLEANPATH)/*.*
run : $(OUT) clean
./$(OUT)
.PHONY: clean run
You're tricking make with your SHELL variable, it sees is at empty as it is just a comment.
Change
SHELL := #!/bin/bash
to
SHELL := /bin/bash
This line:
SHELL := #!/bin/bash
is incorrect.
Your makefile should work perfectly well if you leave that line out altogether. If you do need something there, try
SHELL := /bin/bash
I'm trying to debug an issue with a makefile I am working on.. What is confusing is that the target works when I run it from the command line, but does not work in my makefile..
Here is the makefile:
DDS_OUT_DIR = $(PWD)
IDL_DIR=/opt/idl/dds
IDL_TYPES=common.idl
GENERATED_SOURCES = $(IDL_TYPES:%.idl=%Support.cxx) $(IDL_TYPES:%.idl=%Plugin.cxx) $(IDL_TYPES:%.idl=%.cxx)
GENERATED_HEADERS = $(IDL_TYPES:%.idl=%Support.h) $(IDL_TYPES:%.idl=%Plugin.h) $(IDL_TYPES:%.idl=%.h)
OBJS_DIR = obj.$(CPUTYPE)
GENERATED_OBJS = $(GENERATED_SOURCES:%.cxx=$(OBJS_DIR)/%.o)
LIBDIR = ../../lib.$(CPUTYPE)
BINDIR = ../../../../bin.$(CPUTYPE)
CC = $(C_COMPILER)
CXX = $(CPP_COMPILER)
OS = $(shell uname)
DDSCOMMON = ../../Common/src
CFLAGS = -m32 -g
CXXFLAGS = -m32 -g
LDFLAGS = -m32 -static-libgcc
SYSLIBS = -ldl -lnsl -lpthread -lm -lc
DEFINES_ARCH_SPECIFIC = -DRTI_UNIX
DEFINES = $(DEFINES_ARCH_SPECIFIC) $(cxx_DEFINES_ARCH_SPECIFIC)
INCLUDES = -I. -I$(NDDSHOME)/include -I$(NDDSHOME)/include/ndds
INCLUDES += -I$(DDSCOMMON)
LIBS = -L$(NDDSLIBDIR) -L$(LIBDIR) -lrt \
-lnddscppz -lnddscz -lnddscorez $(SYSLIBS) $(OS_SPECIFIC_LIBS)
COMMONLIBSRC = $(DDSCOMMON)/dds_common.cxx
COMMONLIBOBJS = $(DDSCOMMON)/obj.$(CPUTYPE)/%.o
$(shell mkdir -p $(OBJS_DIR) $(DDSCOMMON)/obj.$(CPUTYPE))
default: ${IDL_TYPES} $(GENERATED_OBJS)
$(OBJS_DIR)/%.o : %.cxx %.h $(DDSCOMMON)/dds_common.h
$(CPP_COMPILER) -o $# $(DEFINES) $(INCLUDES) $(CXXFLAGS) -c $<
%.idl:
#echo "Generating CXX from $# ..." $(GENERATED_OBJS); \
$(NDDSHOME)/scripts/rtiddsgen ${IDL_DIR}/$# -d $(DDS_OUT_DIR) -I ${IDL_DIR} -replace -language C++;
if I just do this:
make
The %.idl target is called fine, when that finishes I get this output:
Generating CXX from common.idl ... obj.Linux-i686/commonSupport.o obj.Linux-i686/commonPlugin.o obj.Linux-i686/common.o
Running rtiddsgen version 4.5d, please wait ...
Done
make: *** No rule to make target `obj.Linux-i686/commonSupport.o', needed by `default'. Stop.
But then when I re-run it and everything compiles, so it works fine...
Why is this not working in one step?
commonSupport.cxx seems to depend on common.idl. Tell this to make.
commonSupport.cxx: common.idl
#echo "Generating CXX from $# ..." $(GENERATED_OBJS); \
$(NDDSHOME)/scripts/rtiddsgen ${IDL_DIR}/$# -d $(DDS_OUT_DIR) -I ${IDL_DIR} -replace -language C++;
Or, to ensure all dependencies are right:
$(GENERATED_SOURCES): common.idl
.... steps to make GENERATED_SOURCES from common.idl