Make wildcard function is truncating result - makefile

I have a project that works on Mac and Emscripten and now adding Windows support. I installed Jetbrains Clion which comes bundled with MinGW. Trying to build a simple application didn't work and now debugging the makefile. For some reason wildcard seems to be truncating the filename. I checked the filenames and looked for hidden special characters but all seems ok. Any ideas what I'm doing wrong?
EDIT:
Adding text in addition to image (which works fine on macOS)
ifeq ($(findstring _win, $(MAKECMDGOALS)), _win)
PLATFORM := win
APPNAME := $(subst _win,,$(MAKECMDGOALS))
$(warning APPSRCDIR is $(APPSRCDIR))
$(warning APPNAME is $(APPNAME))
# gather the application files
$(warning $(wildcard $(APPSRCDIR)/$(APPNAME)/*.c))
APPOBJS := $(patsubst %.c, %.o, $(notdir $(filter-out $(wildcard $(APPSRCDIR)/$(APPNAME)/*.*.c),$(wildcard $(APPSRCDIR)/$(APPNAME)/*.c))))
$(warning APPOBJS is $(APPOBJS))
APPOBJS += $(patsubst %.c, %.o, $(notdir $(wildcard $(APPSRCDIR)/$(APPNAME)/*.win.c)))
$(warning APPOBJS is $(APPOBJS))
APPOBJS := $(addprefix $(BUILDDIR)/$(APPNAME)/$(PLATFORM)/, $(APPOBJS))
$(warning APPOBJS is $(APPOBJS))
endif

Related

Understanding and modifying slightly this makefile

I have been editing this makefile but it's mostly trial and error.
Basically I have n .c files in the same directory. I want the first one (that has a fixed name) to be compiled and linked using my makefile hacks, that incorporate different .o files in the linking step, and all the other ones to be compiled and linked using only the LIBS (without the other .o files).
This is the 'main' makefile:
MAKEFILE_BASE = ./Build-Assets/Makefile
MAKEFILE_CONTROLLERS = ./Controllers/Makefile
.PHONY: default clean release release-clean
default: release
clean: release-clean
release:
$(MAKE) -f $(MAKEFILE_CONTROLLERS) # This generates the .o files, and it works well
$(MAKE) -f $(MAKEFILE_BASE).Release
release-clean:
$(MAKE) -f $(MAKEFILE_BASE).Release clean
And this is the 'Makefile.Release' that handles the compilation/linking of those .c files.
TARGET = $(notdir $(shell pwd))
LIBS = -lm -lev3dev-c -pthread
D_BIN = Build-Assets
ifeq ($(OS),Windows_NT)
LIBS := $(LIBS) -lws2_32
D_BIN := $(D_BIN)/mingw
endif
D_H = ../../source/ev3
CFLAGS = $(addprefix -I, $(D_H)) -O2 -std=gnu99 -W -Wall -Wno-comment
ifeq ($(OS),Windows_NT)
CC = gcc
else
CC = arm-linux-gnueabi-gcc
endif
ifeq ($(OS),Windows_NT)
E_BIN = .exe
else
E_BIN =
endif
F_BIN = $(TARGET)$(E_BIN)
OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))
.PHONY: default all clean
default: $(F_BIN)
all: default
$(OBJECTS): $(D_BIN)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(F_BIN) $(OBJECTS)
$(F_BIN): $(OBJECTS)
$(info VAR is $#)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f $(D_BIN)/*.o
-rm -f $(F_BIN)
This also gives the output file the name of the main folder (though I don't understand where he does that?).
When linking this throws the 'multiple main' error (I don't have the ARM device at hand, so I can't provide the full error).
This is the folder hierarchy so that hopefully I can solve all your doubts..
# Main folder (This is the name that the compiled exe has)
## Controllers
-- .c & .h files
-- Makefile
## Build-Assets
-- all .o go here to clean up the folders
- Makefile (The one I call)
- main.c (this needs to be compiled with the .o in build-assets, name can be either main or main folder)
- gcheck.c (this needs to be compiled with only the LIBS, name of executable should be filename)
- ... other .c files, same as gcheck.c
Regarding "where the target name as the name of the directory" comes from, it's here:
TARGET = $(notdir $(shell pwd))
This runs the shell command pwd to get the full path of the current directory, then uses notdir to strip off the parent directory. Then the rule to link the executable uses this:
F_BIN = $(TARGET)$(E_BIN)
...
$(F_BIN): $(OBJECTS)
Regarding why you get multiple main errors, it's because you added your new .c file with the new main to the same directory and rather than the makefile listing a specific set of source files to compile and link, it uses wildcard to grab all the source files:
OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))
These $(wildcard *.c) functions will expand to all the *.c files in these directories including any new ones you added. Then they will all be linked into the target, which gives you two different object files containing main.
You'll have to change this to list just the files you want, or put your files somewhere else, or remove your files from the list using make's filter-out function, or something like that.

In creating a makefile with subdirectories in windows, % wildcard stops working

This is in reference to the second response here:
How to generate a Makefile with source in sub-directories using just one makefile
The solution works great for me except for when the make rules are called. They never seem to make any once make-goal is called since the files don't exist in the build directory yet. I tested this by creating empty files in the build directory (just anyting.o) and the make rule is then found
my conclusion is that the % wildcard character is only looking for what is in the directory, and can't find the file so it doesnt make a build rule for it, and thus fails to continue. There are two possible solutions:
1) Find a way to make dummy object files that are overwritten when the compiler actually starts
2) Make make "realize" that the wild card is for anything put into the make-goal function, not what is already in the directory
any pointers?
As far as I know, I am the first one to have this issue
\
MODULES := calibration calibration/settings camera/nikon camera ommon
SRC_DIR := $(addprefix src/, $(MODULES)) src
SDK_INCLUDES := include $(addprefix include/, $(MODULES))
BUILD_DIR := build $(addprefix build/, $(MODULES))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp))
OBJ := $(patsubst src/%.cpp,build/%.o, $(SRC))
# OpenCV directories, change according to your own installation
CV_INCLUDE_DIR = C:\Users\a0225122\Downloads\opencv\build\include
CV_LIB_DIR = C:\Users\a0225122\Downloads\opencv\bin\lib
CV_LIBS = -llibopencv_core249 \
-llibopencv_highgui249 \
-llibopencv_imgproc249 \
-llibopencv_features2d249 \
-llibopencv_calib3d249
CV_FLAGS = -I$(CV_INCLUDE_DIR) -L$(CV_LIB_DIR) $(CV_LIBS)
HID_API_INCLUDE_DIR := 3rd_party/hidapi-master/hidapi/hid.h
# Compiler instructions
CXXFLAGS = -std=c++11 -Wall -I $(SDK_INCLUDE_DIR) -I $(CV_INCLUDE_DIR) -I $(HID_API_INCLUDE_DIR) -L $(CV_LIB_DIR) $(CV_LIBS) -L $(FLYCAP_LIB_DIR) $(FLYCAP_LIBS)
# Clean up instructions
ifdef SystemRoot #This is windows
CXX = mingw32-g++
RM = del /Q
FixPath = $(subst /,\,$1)
BUILD_DIR := $(call FixPath, $(BUILD_DIR))
SRC_DIR := $(call FixPath, $(SRC_DIR))
SDK_INCLUDES := $(call FixPath, $(SDK_INCLUDES))
SRC := $(call FixPath, $(SRC))
OBJ := $(call FixPath, $(OBJ))
CXXFLAGS := $(call FixPath, $(CV_FLAGS))
define make-goal
$1\%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $$< -o $$#
endef
else #more ifeqs can be added for more OS's but this should be fine
CXX = g++
RM = rm -f
define make-goal
$(1)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $$< -o $$#
endef
endif
vpath %.cpp $(SRC_DIR)
SDK_LIBS = lib_core.a
default: SDK.exe
.PHONY: clean
clean:
$(RM) build *.a
#executable generation
SDK.exe: $(SDK_LIBS)
$(CXX) $(CXXFLAGS) $^ -o $#
lib_core.a: checkdirs $(OBJ)
ar rcs lib_core.a $(OBJ)
checkdirs: $(BUILD_DIR)
$(BUILD_DIR):
mkdir $#
#$(OBJ): $(SRC)
# $(CXX) $(CXXFLAGS) -c $^ -o $#
$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))
Your first problem is that you cannot use backslashes in GNU make rules, except in recipes (make just sends the recipe to the shell, it doesn't interpret the recipe except for $). All GNU make targets, prerequisites, etc. must use forward slashes, all the time, even on Windows.
Almost all Windows applications will accept forward-slashes as directory separators properly. For the few that don't, you can use your function FixPath, but you must use it inside the recipe, not in the target or prerequisite lists.
Once you've resolved that issue if you still have problems, post what you have and we'll look.

How to have a sometimes empty dependency in makefiles?

I have the following rule:
EXECS = $(sort $(patsubst %.cpp,%$(EXESUFFIX), $(patsubst %.c,%$(EXESUFFIX), $(filter-out $(IGNORESRCS), $(EXECSRCS)))))
SRCS = $(sort $(filter-out $(EXECSRCS), $(filter-out $(IGNORESRCS), $(wildcard *.c) $(wildcard *.cpp) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.cpp) $(wildcard $(DIR)/*.c) ) )))
#OBJS = $(addprefix $(OBJDIR), $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS))))
OBJS = $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS)))
RESOURCE_SRCS= $(sort $(filter-out $(IGNORESRCS), $(wildcard *.rc) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.rc) ) ))
RESOURCES = $(patsubst %.rc,%$(OBJSUFFIX), $(RESOURCE_SRCS))
%$(EXESUFFIX) : %.cpp $(LIBS) $(RESOURCES)
$(CXX) $(DEFINES) $(CFLAGS) $(INCLUDES) $(LIBPATH) -o $(BINDIR)/$* $< $(RESOURCES) $(LIBINCLUDES)
The problem is that $(RESOURCES) doesnt exist for all platforms. The %$(EXESUFFIX) : %.cpp rule doesnt run, instead it tries to run g++ exec.cpp -o exec which as far as I can tell isnt a rule that I declared anywhere.
How do I get the rule to still build despite the fact that it is empty (and build the resources if it is not empty)?
If the variable is empty it has no effect on the rule. It should just work as written. What is the actual error you're seeing?
ETA:
Your question is very unclear in what, exactly, you mean by $(RESOURCES) doesn't exist. My answer was assuming you meant that the variable was empty. But given your comment below about how the makefile behaves, I now suspect what you mean is that the variable is still set to a list of files, but that those files are not present.
Because they're not there, and make doesn't know how to build them, make decides that this pattern rule cannot be used at all and it chooses a different rule.
If you want these files to only have any impact if they exist, then you can use the $(wildcard ...) function to expand only to those files that exist:
%$(EXESUFFIX) : %.cpp $(LIBS) $(wildcard $(RESOURCES))
$(CXX) ...
One critical point here: the contents of $(RESOURCES) MUST be source files. They cannot be derived files (files that are supposed to be created by make). If they are derived, the situation is far more complex.

Problems with substitution

I'm having trouble getting path substitution working correctly. I have a bunch of source files in SOURCES:
#echo $(SOURCES)
foo.c bar.cpp bah.cxx
And I want a list of object files:
# Imaginary only because nothing works
#echo $(OBJECTS)
foo.o bar.o bah.o
I'm trying to build the list of OBJECTS with patsubst. First, this produces a list of source files and object files. Besides being wrong, it causes a duplicate of _main which fails a link.
OBJECTS = $(patsubst %.c, %.o, ${SOURCES}) $(patsubst %.cc, %.o, ${SOURCES}) \
$(patsubst %.cpp, %.o, ${SOURCES}) $(patsubst %.cxx, %.o, ${SOURCES})
Second, this performs no substitutions. Not only is it wrong, I get back the original list in SOURCES.
OBJECTS = $(patsubst %.c %.cc %.cpp %.cxx, %.o, ${SOURCES})
Third, this produces the original list of source files:
OBJECTS = $(patsubst %.*, %.o, ${SOURCES})
I also tried using the following, which seems to multiply the files like rabbits:
OBJECTS = $(SOURCES:.c=.o) $(SOURCES:.cc=.o) \
$(SOURCES:.cpp=.o) $(SOURCES:.cxx=.o)
How does one perform a simple substitution of extensions when using a portable make?
Tom's answer is correct. Etan's will work too. A shorter solution would be:
$(addsuffix .o,$(basename $(SOURCES))
If you have a filter-like function you can use that. Otherwise you can do it in stages:
SOURCES := foo.c bar.cpp bah.cxx
O := $(SOURCES)
$(info $(O))
O := $(patsubst %.c,%.o,$(O))
$(info $(O))
O := $(patsubst %.cpp,%.o,$(O))
$(info $(O))
O := $(patsubst %.cxx,%.o,$(O))
$(info $(O))
The problem with your first (and third since that is effectively identical) attempt is that patsubst leaves untouched any words in the input that do not match the pattern. So when you built OBJECTS up from multiple calls to patsubst you were duplicating (in each piece) all the SOURCSE entries that didn't match that pattern.
The problem with the second is that patsubst doesn't take multiple patterns so nothing matches that erroneous pattern and so you get SOURCES back entirely unmodified.
First, I don't think patsubst is portable. It is a GNU make feature.
I think one answer to your question is nested subsitutions, like:
$(patsubst %c,%.o,$(patsubst %.cc,%.o,$(patsubst .....)))

makefile: search for files in subdirectories

So I have a GCC command for which I want to use a SIMPLE makefile. Never worked on makefile before and still having problems after referring the tutorial.
So the command on terminal is
link4#link4-VirtualBox:~/link4/G2/G2 module/src$ gcc -I.src/L4COMM -I.src/L4SERIAL -I.src/L4SYSTEM -I.src/main.c -I.src/L4COMM/l4comm.c -I.src/L4SERIAL/l4serial.c ./src/bypass.c ./src/input.c
This works fine, but when I create a makefile, I'm unable to make it search for the files 'l4comm.c and l4serial.c' which are in src/L4COMM and src/L4SERIAL respectively.
This is what my makefile looks like:
CC =gcc
INCLUDE = -I/src/L4COMM \
-I/src/L4SERIAL
VPATH = -I/src/L4COMM \
-I/src/L4SERIAL
cfiles := $(patsubst %.c, %.o, $(wildcard *.c))
hfiles := $(patsubst %.h, %.o, $(wildcard *.h))
g2make: $(cfiles)
$(CC) $(INCLUDE) -o main.c l4comm.c l4serial.c bypass.c input.c
Want the makefile to look for files in the sub directories
Just as I used the 'cfiles/hfiles' to check for changes, I want to wildcard to also check for the files in the sub directories.
Help appreciated! :)
You can use this g2make:
$(CC) $(INCLUDE) -o .src/main.c ./src/L4COMM/l4comm.c ./src/L4SERIAL/l4serial.c ./src/bypass.c ./src/input.c

Resources