Wildcard usage in make file - makefile

I currently have a build system based on a makefile that was originally auto-generated. I've made some changes over time for various functions. Each subdirectory in the project has a separate makefile (subdir.mk). However, each instance of subdir.mk explicitly lists the files in that subdirectory. I'd like to modify the files to do a wildcard build of all files in the directory, so that the files don't have to be updated if new files are added. I've copied one current file below. Any suggestions on how (or if) I can modify these files to do wildcard builds? I'm not a make expert (altho if I live through my current project I'd like to become one). Thanks.
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../Src/Tasks/BankWriteTask.c \
../Src/Tasks/CommTask.c \
../Src/Tasks/SrvTask.c \
../Src/Tasks/WatchdogTask.c
OBJS += \
./Src/Tasks/BankWriteTask.o \
./Src/Tasks/CommTask.o \
./Src/Tasks/SrvTask.o \
./Src/Tasks/WatchdogTask.o
C_DEPS += \
./Src/Tasks/BankWriteTask.d \
./Src/Tasks/CommTask.d \
./Src/Tasks/SrvTask.d \
./Src/Tasks/WatchdogTask.d
# Each subdirectory must supply rules for building sources it contributes
Src/Tasks/%.o: ../Src/Tasks/%.c
arm-atollic-eabi-gcc -c -mthumb -mcpu=cortex-m3 -std=gnu11 -D__weak=__attribute__((weak)) -D__packed=__attribute__((__packed__)) -DUSE_HAL_DRIVER -DSTM32L152xE -DCONFIG_DEBUG -DCONFIG_RELEASE=1 -I..\Config -I..\Inc -I..\Inc\Sys -I..\Inc\StmHal -I..\Inc\Driver -I..\Inc\Lib -I..\Inc\Business -I..\Inc\Tasks -I..\Drivers\CMSIS\Include -I..\Drivers\CMSIS\Device\ST\STM32L1xx\Include -I..\Drivers\STM32L1xx_HAL_Driver\Inc -I..\Drivers\STM32L1xx_HAL_Driver\Inc\Legacy -I..\Middlewares\Third_Party\FreeRTOS\Source\include -I..\Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS -I..\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3 -I..\Middlewares\Third_Party\FreeRTOS-Plus\Source\FreeRTOS-Plus-CLI -I..\Middlewares\ST\STM32_Cryptographic\Inc -I..\Middlewares\ST\STM32_Cryptographic\Inc\HASH\SHA256 -I..\Middlewares\Third_Party\TraceRecorder\include -I..\Middlewares\Third_Party\TraceRecorder\streamports\Jlink_RTT -I..\Middlewares\Third_Party\TraceRecorder\streamports\Jlink_RTT\include -I../Inc -I../Drivers/STM32L1xx_HAL_Driver/Inc -O0 -ffunction-sections -fdata-sections -g -fstack-usage -Wall -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#)" -specs=nano.specs -o "$#" "$<"

First notice that there is a lot of redundancy in these lists of files:
C_SRCS += \
../Src/Tasks/BankWriteTask.c \
../Src/Tasks/CommTask.c \
../Src/Tasks/SrvTask.c \
../Src/Tasks/WatchdogTask.c
OBJS += \
./Src/Tasks/BankWriteTask.o \
./Src/Tasks/CommTask.o \
./Src/Tasks/SrvTask.o \
./Src/Tasks/WatchdogTask.o
C_DEPS += \
./Src/Tasks/BankWriteTask.d \
./Src/Tasks/CommTask.d \
./Src/Tasks/SrvTask.d \
./Src/Tasks/WatchdogTask.d
which you can reduce with the Make function patsubst:
NEW_C_SRCS := \
../Src/Tasks/BankWriteTask.c \
../Src/Tasks/CommTask.c \
../Src/Tasks/SrvTask.c \
../Src/Tasks/WatchdogTask.c
C_SRCS += $(NEW_C_SRCS)
OBJS += $(patsubst ../%.c,./%.o,$(NEW_C_SRCS))
C_DEPS += $(patsubst ../%.c,./%.d,$(NEW_C_SRCS))
And if the four files listed in C_SRCS are the only ".c" files in ../Src/, instead of typing them into the makefile by hand you can have Make find them automatically with the wildcard function:
NEW_C_SRCS := $(wildcard ../Src/Tasks/*.c)
That said, wildcard-building can work in a tightly-controlled source tree like the one you seem to be using, but it can cause headaches otherwise; modifying one line in a makefile when you add or remove a source file is not much work.

Related

Why is Makefile not including the header?

I'm trying to make a library for my project but I am very very new to Makefiles. I tried several configurations and adding -I but none worked.
I have the following three:
libft/
../includes/
....libft.h
../lst
....ft_lstnew.c
....ft_lstadd_front.c
....ft_lstadd_back.c
.... [...]
../src
....ft_isalpha.c
....ft_isalnum.c
.... [...]
And the following makefile:
NAME=libft.a
LIBSO=libft.so
CC=gcc
CFLAGS=-Wall -Wextra -Werror
SRC_DIR=src/
BONUS_DIR=lst/
OBJ_DIR=obj/
SRC_FILES= ft_bzero.c \
ft_isalmun.c \
ft_isalpha.c \
ft_isascii.c \
ft_isdigit.c \
ft_isprint.c \
ft_memchr.c \
ft_memcpy.c \
ft_memmove.c \
ft_memset.c \
ft_strchr.c \
ft_strlcat.c \
ft_strlcpy.c \
ft_strlen.c \
ft_strncmp.c \
ft_strrchr.c \
ft_tolower.c \
ft_toupper.c
BONUS_FILES=ft_lstadd_back.c \
ft_lstadd_front.c \
ft_lstdelone.c \
ft_lstclear.c \
ft_lstiter.c \
ft_lstlast.c \
ft_lstmap.c \
ft_lstnew.c \
ft_lstsize.c
SRC_PATH=$(addprefix $(SRC_DIR), $(SRC_FILES))
BONUS_PATH=$(addprefix $(BONUS_DIR), $(BONUS_FILES))
SRC_NAMES=$(SRC_FILES:.c=.o)
BONUS_NAMES=$(BONUS_FILES:.c=.o)
SRC_PATH_O=$(addprefix $(SRC_DIR), $(SRC_NAMES))
BONUS_PATH_O=$(addprefix $(BONUS_DIR), $(BONUS_NAMES))
HDR_NAME=libft.h
HDR_DIR=includes/
HDR= $(addprefix $(HDR_DIR),$(HDR_NAME))
all: $(NAME)
$(NAME): $(SRC_PATH_O)
ar rc $# $<
ranlib $#
$(OBJ_DIR):
mkdir $#
$(OBJ_DIR)%.o: $(SRC_DIR)%.c $(HDR_NAME)
$(CC) $(CFLAGS) -c $< -o $# -I $(HDR)
clean:
rm -rf $(OBJ_DIR)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re
And I keep getting this each time I type make on the terminal:
gcc -Wall -Wextra -Werror -c -o src/ft_bzero.o src/ft_bzero.c
src/ft_bzero.c:1:10: fatal error: libft.h: No such file or directory
1 | #include "libft.h"
| ^~~~~~~~~
compilation terminated.
make: *** [<builtin>: src/ft_bzero.o] Error 1
Am I missing something? It's literally my first time.
Yes, you're missing some things.
First, look at the command line make shows:
gcc -Wall -Wextra -Werror -c -o src/ft_bzero.o src/ft_bzero.c
Note that the output here is not right for the recipe of the pattern rule you created: there's no -I option, and the object file is being written to src/ not obj/.
From this you should realize that your pattern rule is not being used at all, and instead make is using its built-in rule for building object files.
Why isn't your pattern rule being used? Let's look at it:
$(OBJ_DIR)%.o: $(SRC_DIR)%.c $(HDR_NAME)
what is this after variable expansion?
obj/%.o: src/%.c libft.h
This pattern (like all patterns) can only match if ALL the prerequisites either already exist or can be built. The src/%.c exists, after the pattern substitution. What about libft.h? No, that doesn't exist. What does exist is includes/libft.h but that's not the same thing.
So, this rule fails to match and make goes back to using its default rules.
If you want to say that every object file depends on that header, you have to use the correct path to the header file when you write the pattern.
Next, this is wrong:
$(CC) $(CFLAGS) -c $< -o $# -I $(HDR)
What is $(HDR)? It's the name of the file: include/libft.h. You don't include header file names with -I; you include directories that headers are looked for in. So you need $(HDR_DIR) here instead.

makefile explicitly linking multiple dynamic libraries

I'm trying to put together a simple makefile example like so:
FLAGS = -std=c++14
INC= -I/usr/local/include
LI = -L/usr/local/lib
LIB = /usr/local/lib/
LIBS = $(LIB)libboost_filesystem-mt.a \
$(LIB)libboost_filesystem-mt.dylib \
$(LIB)libboost_filesystem.a \
$(LIB)libboost_filesystem.dylib \
$(LIB)libboost_system-mt.a \
$(LIB)libboost_system-mt.dylib \
$(LIB)libboost_system.a \
$(LIB)libboost_system.dylib
default:
g++ main.cpp $(FLAGS) $(INC) $(LI) $(LIBS) -o assemble
./assemble
clean:
rm assemble
Is there a way to not have to prepend $(LIB) so many times? That's the only way I can get this to work right now (the above doesn't).
If you want the linker to search the path you have to add libraries using the -l flag. So instead of adding libboost_system-mt.a to your link line, you have to add -lboost_system-mt to your link line. Then the linker will search the paths provided by -L.
I'm not sure about the dylib stuff; I don't do much with OS X.
In any event, if you're using GNU make you can do this:
LIBNAMES := filesystem-mt filesystem system-mt system
LIBS := $(foreach N,$(LIBNAMES),$(LIB)libboost_$N.a $(LIB)libboost_$N.dylib)

make/gcc/clang looking for file with a blank filename, gives error

I have OSX 10.11.4, Xcode 7.3.1.
Using make -- calls gcc -- calls clang, I get this error where clang is looking for a file whose name is a space!
Make error 1: clang: error: no such file or directory: ' '.
That is a space!
I have no idea how to fix this. The makefile formatting is correct.
Here is the end of the output from make:
gcc -g -v -Wall -I/usr/local/include -I/opt/local/include -I/Users/m/BioPrep \
-o mod \
../mshell/runit0.o \
../mshell/tline.o \
../mshell/getshm.o \
../mshell/callLSODA.o \
../mshell/extras.o \
../mshell/nrutil.o \
../mshell/exten.o \
../choosedisp/choosedisp_main.o \
../choosedisp/choosedisp_cb.o \
../choosedisp/choosedisp_fm.o \
../connectdisps/connectdisps.o \
../connectdisps/opwsock.o \
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
clang: error: no such file or directory: ' '
make: *** [mod] Error 1
======================= Here is the contents of the Makefile:
# This is Makefile with all graphics code removed so that a compilation of mod can proceed
# "MakefileA" has the graphics files present but commented (#) out
CC = gcc
CFLAGS = -g -v -Wall
INCL = -I/usr/local/include -I/opt/local/include -I/Users/prowat/BioPrep
LIBS = -L/usr/local/lib -L/opt/local/lib -lX11 -lforms
mod: model.o \
../mshell/runit0.o \
../mshell/tline.o \
../mshell/getshm.o \
../mshell/callLSODA.o \
../mshell/extras.o \
../mshell/nrutil.o \
../mshell/exten.o \
../choosedisp/choosedisp_main.o \
../choosedisp/choosedisp_cb.o \
../choosedisp/choosedisp_fm.o \
../connectdisps/connectdisps.o \
../connectdisps/opwsock.o \
../lsoda/liblsoda.a`
cd ../mshell; make objs`
cd ../choosedisp; make objs`
cd ../connectdisps; make objs`
$(CC) $(CFLAGS) $(INCL) \
-o mod \
../mshell/runit0.o \
../mshell/tline.o \
../mshell/getshm.o \
../mshell/callLSODA.o \
../mshell/extras.o \
../mshell/nrutil.o \
../mshell/exten.o \
../choosedisp/choosedisp_main.o \
../choosedisp/choosedisp_cb.o \
../choosedisp/choosedisp_fm.o \
../connectdisps/connectdisps.o \
../connectdisps/opwsock.o \
model.o \
-L../lsoda -llsoda \
$(LIBS) \
-lm
=====================
Please use proper formatting: for code blocks, indent by 4 spaces. The backticks are only used for fixed-width fonts inside normal text.
You may have looked for spaces, but you need to look again. Based on the output make has shown you versus your makefile, it's pretty clear that there is at least one space after the backslash at the end of this line:
../connectdisps/opwsock.o \
You can tell this because if there were no spaces after this backslash then it would be continuing to the next line and make whould show the rest of the compile line:
model.o \
-L../lsoda -llsoda \
$(LIBS) \
-lm
Since those lines are missing from the output make provided, you can be sure that there's something about the opwsock.o line which is preventing make from recognizing the backslash/newline at the end.

libtool did not generate a lo file when everything is there

I'm new to using libtool. However, this problem seems to be weird. Everything is there but the libtool said "libtool: link: 'cuda_transfer.lo' is not a valid libtool object". However, the rule for generating this lo file is right there in the Makefile. Besides, the two header files are also right in where they are supposed to be and do work. Any idea about what is going wrong?
cuda_transfer.lo: particles_cuda.h ../../include/psc_particles_cuda.h
The other two places in Makefile where cuda_transfer.lo appeared are followed
libsubdir_la_DEPENDENCIES = cuda_transfer.lo \
libsubdir_la_LIBADD = \
cuda_transfer.lo \
The .c.lo: segment is following:
.c.lo:
$(AM_V_CC)depbase=`echo $# | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
$(LTCOMPILE) -MT $# -MD -MP -MF $$depbase.Tpo -c -o $# $< &&\
$(am__mv) $$depbase.Tpo $$depbase.Plo
# $(AM_V_CC)source='$<' object='$#' libtool=yes \
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
# $(AM_V_CC_no)$(LTCOMPILE) -c -o $# $<
How to interpret this human-unfriendly code. = =
Below is the code segment suggested by Brett.
noinst_LTLIBRARIES = libsubdir.la
libsubdir_la_SOURCES = \
psc_fields_cuda.c \
psc_particles_cuda.c \
psc_push_particles_cuda.c \
psc_push_fields_cuda.c \
psc_bnd_cuda.c \
psc_bnd_particles_cuda.c \
psc_bnd_fields_cuda.c \
b40c/kernel_utils.h \
b40c/radixsort_kernel_common.h \
b40c/radixsort_key_conversion.h \
b40c/radixsort_reduction_kernel.h \
b40c/radixsort_scanscatter_kernel.h \
b40c/radixsort_scanscatter_kernel3.h \
b40c/radixsort_scanscatter_kernel4.h \
b40c/radixsort_spine_kernel.h \
b40c/vector_types.h \
cuda_common.h \
cuda_sort2.h \
cuda_sort2_spine.h \
particles_cuda.h \
psc_bnd_cuda.h \
psc_bnd_cuda_fields.h \
psc_cuda.h
libsubdir_la_LIBADD = \
cuda_transfer.lo \
cuda_spine.lo \
cuda_sort2.lo \
cuda_sort3.lo \
cuda_exchange_particles.lo \
cuda_exclusive_scan_2.lo \
cuda_push_part_yz_1vb.lo
The only thing that looks like a generating rule about cuda_transfer.lo is
cuda_transfer.lo: particles_cuda.h ../../include/psc_particles_cuda.h
try this:
yum -y install libtool*
then make clean and restart again
Well, it's better not to read configure.ac ever :-) But if you still wish, configure.ac is a combination of m4 preprocessor code and ordinary (bourne) shell snippets. You may check info m4 and info autoconf, the docs are pretty decent.
The hard part of your question, regarding the .lo file. It seems that your makefile contains dependency chain for it, but no explicit build-rules. You may try to locate a common rule for compiling .c -> .lo, like this:
.c.lo:
$(AM_V_CC)$(LTCOMPILE) -MT $# -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $# $<
$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
...
Install latest libtool. Delete the .lo file and use 'make' again.

Include path being ignored in a gnu make file

The makefile is included below. It's just a long list of object files and two targets. The problem seems to be that the $(INC) is being ignored for the first target. For example, the output starts with "g++ -c -o main.o main.cpp" instead of "g++ -I/usr/home/jrm/tmp/proteus_beta -c -o main.o main.cpp".
TIA
PROG = proteus
# list of object files
OBJS = main.o \
dataset.o \
genetic_codes.o \
likelihood_engine.o \
options.o \
parsimony.o \
parsimony_engine.o \
seq.o \
site_collection.o \
site_pattern.o \
tools.o \
optare/crs.o \
optare/point.o \
optare/newton_1d.o \
optare/golden_section.o \
models/model.o \
models/DNA/DNA_model.o \
models/DNA/DNA_ssm.o \
models/CODON/CODON_model.o \
models/CODON/CODON_modelA.o \
models/CODON/CODON_modelB.o \
models/CODON/CODON_modelC.o \
models/CODON/CODON_modelD.o \
models/CODON/CODON_M0.o \
models/CODON/CODON_M1.o \
models/CODON/CODON_M2.o \
models/CODON/CODON_M3.o \
models/CODON/CODON_M0gtr.o \
models/CODON/CODON_FEBC1.o \
models/CODON/CODON_FEBC1b.o \
models/CODON/FESC/CODON_FESC1.o \
models/CODON/CODON_nh/CODON_M0nh1.0 \
models/CODON/CODON_nh/CODON_M1nh1.0 \
models/CODON/CODON_nh/CODON_M1nh1.0 \
models/CODON/CODON_nh/CODON_M3nh1.0 \
models/CODON/CODON_nh/CODON_M0nh2.0 \
models/CODON/CODON_nh/CODON_MmodelAnh2.0 \
matrices/matrix.o \
matrices/DNA_matrix.o \
matrices/CODON_matrix.o \
matrices/AA_matrix.o \
matrices/int_matrix.o \
matrices/str_matrix.o \
matrices/eigen.o \
incidere/slice_sampler.o \
dendrology/forestry.o \
dendrology/node.o \
dendrology/DNA_node.o \
dendrology/tree.o \
alphabetia/alphabet.o \
alphabetia/DNA_alphabet.o \
alphabetia/CODON_alphabet.o \
alphabetia/AA_alphabet.o
CC = g++
INC=-I/home/jrm/tmp/proteus_beta
.C.o:
$(CC) $< -c $(INC)
$(PROG): $(OBJS)
$(CC) -o $# $(OBJS) -lm
According to your post, you have a file named main.cpp, not a file named main.C. But you provide an implicit rule for converting .C files to .o. Make will compile main.cpp using its built-in rule for .cpp to .o compilation. You have two options to do what you want:
(1) Change your implicit rule to .cpp.o (and consider using new-style rules, i.e. %.cpp: %.o)
(2) Declare a CXXFLAGS variable (which is automatically included in Make's C++ compilation implicit rule) such as the following:
CXXFLAGS = $(INC)
and then remove your .C.o implicit rule.
The second option will simplify your makefile, and it will work with C++ files, regardless of the extension.
Do your source files end with .C or .cpp?
The compilation rule for .C.o lists $(INC) after the other parts of the rule, not where you expect the output to come:
CC = g++
INC = -I/home/jrm/tmp/proteus_beta
.C.o:
$(CC) $< -c $(INC)
You should see:
g++ file.C -c -I/home/jrm/tmp/proteus_beta
But it appears to be ignoring your rule altogether. You mention main.cpp; that will never be compiled by your rule.
So, is .C a recognized suffix? Are your source files .C files? Are you running on a case-insensitive file-system? Why are you setting the C compiler (CC) -- you've probably got case problems with your source.

Resources