Makefile with multiple outcomes - matlab

This is my first attempt to write a makefile and therefore there is a lot of room for improvements. I need to generate several mex functions for matlab on mac using the package sedumi and intel compiler studio.
Here is the makefile
# define matlab dir
MDIR = /Applications/MATLAB_R2017b.app
# compiles mex files using g++
#CC = gcc
# compiler flags for g++
#CCFLAGS = -O3 -fpic
# to use the intel compiler instead, uncomment CC and CCFLAGS below:
# compiles mex file using the intel compiler
CC = icc
# compiler flags for intel compiler
CCFLAGS = -O3 -fPIC -D__amd64
# Figure out which platform we're on
UNAME = $(shell uname -s)
# Linux
ifeq ($(findstring Linux,${UNAME}), Linux)
# define which files to be included
CINCLUDE = -I$(MDIR)/extern/include -Ic++ -shared
# define extension
EXT = mexa64
endif
# Mac OS X
ifeq ($(findstring Darwin,${UNAME}), Darwin)
# define which files to be included
CINCLUDE = -L$(MDIR)/bin/maci64 -Ic++ -shared -lmx -lmex -lmat -lmwblas
# define extension
EXT = mexmaci64
# CCFLAGS += -std=c++11
endif
SRC:=$(wildcard *.c)
*.o: $(SRC)
for i in $(SRC) ; do \
$(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $$i -o $${i%.c}.o; \
done
OBJ0:=bwblkslv.o sdmauxFill.o sdmauxRdot.o
OBJ1:=choltmpsiz.o
all:
$(CC) $(CCFLAGS) $(CINCLUDE) $(OBJ0) -o bwblkslv.$(EXT)
$(CC) $(CCFLAGS) $(CINCLUDE) $(OBJ1) -o choltmpsiz.$(EXT)
# clean up
clean:
rm -f *.o *.$(EXT)
As it is, Makefile works just fine. make and then make all return the mex functions needed within matlab.
I have OBJ0 to OBJ37 and although adding the lines solves the problem I wonder if there is a simpler way to accomplish the same results.
Many thanks.
Ed
PS. Thanks to the author of https://github.com/jtilly/mex for parts of the makefile.

There are several aspects that you could improve:
Use make automatic variables ($#, $<, $^...)
Use a more make-oriented style for your C compilations, thanks to a make pattern rule:
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
%.o: %.c
$(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $< -o $#
This has several advantages over you shell loop. The most important one being that only one compilation is run when only one C file changes. With your solution all C files are recompiled when only one changes. Moreover, *.o is a wildcard that expands to existing object files. Not what you want, usually. Note that in your case you could also use a static pattern rule:
$(OBJ): %.o: %.c
$(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $< -o $#
which looks almost the same but limits the rule to the specified list of targets $(OBJ).
Use a macro and foreach-eval-call to instantiate the linker rules:
.PHONY: all clean
EXTS :=
# $(1): variable name
define MY_rule
$(1)_EXT := $$(patsubst %.o,%.$$(EXT),$$(firstword $$($(1))))
EXTS += $$($(1)_EXT)
$$($(1)_EXT): $$($(1))
$$(CC) $$(CCFLAGS) $$(CINCLUDE) $$^ -o $$#
endef
OBJVARS := OBJ0 OBJ1 ... OBJ37
OBJ0 := bwblkslv.o sdmauxFill.o sdmauxRdot.o
OBJ1 := choltmpsiz.o
$(foreach v,$(OBJVARS),$(eval $(call MY_rule,$(v))))
all: $(EXTS)
clean:
rm -f $(OBJ) $(EXTS)
Note the $$ to escape the first expansion added by eval. For example, the first iteration of foreach instantiates the following rule:
OBJ1_EXT := $(patsubst %.o,%.$(EXT),$(firstword $(OBJ1))
EXTS += $(OBJ1_EXT)
$(OBJ1_EXT): $(OBJ1)
$(CC) $(CCFLAGS) $(CINCLUDE) $^ -o $#
An easy way to design the macro consists in writing first what you want with, for instance, the OBJ1 variable, replace each $ by $$ and finally replace OBJ1 by $(1).

Related

How to make a Linux Makefile work on Windows?

(Disclaimer: I am not at all a computer science genius, far from that. I may use bad terminology and I appologize.)
I need to run some tests using the google test library and I was provided with a Makefile to handle the execution but it won't run on my Windows machine (I use Visual Studio). It was made for a Linux environment so I'm not sure what i would need to modify in order to run it. I have used MinGW to run Makefiles of my own making in the past.
Here's how the Makefile looks like:
CC=g++
CFLAGS=-c -Wall -ggdb -I.
LDFLAGS=
SOURCES=main.c singlelinklist.c
TESTS=single_test.cpp
#TODO: Need a more elegant way of specifying objects and tests
GTESTDIR=~/environment/googletest
OBJECTS=$(SOURCES:.cpp=.o)
FLAGS = -Iinclude
#all: $(SOURCES) $(EXECUTABLE)
# These next lines do a bit of magic found from http://stackoverflow.com/questions/2394609/makefile-header-dependencies
# Essentially it asks the compiler to read the .cpp files and generate the needed .h dependencies.
# This way if any .h file changes the correct .cpp files will be recompiled
depend: .depend
.depend: $(SOURCES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ >> ./.depend;
include .depend
# End .h file magic
#$(EXECUTABLE): $(OBJECTS)
# $(CC) $(LDFLAGS) $(OBJECTS) -o $#
#.cpp.o:
# $(CC) $(CFLAGS) $< -o $#
clean:
# rm -rf *o $(EXECUTABLE) test_executable
rm -f ./.depend
rm $(GTESTDIR)/libgtest.a
rm $(GTESTDIR)/gtest-all.o
# Google test section
$(GTESTDIR)/libgtest.a:
$(CC) -isystem $(GTESTDIR) -I $(GTESTDIR) -pthread -c $(GTESTDIR)/gtest/gtest-all.cc -o $(GTESTDIR)/gtest-all.o
ar -rv $(GTESTDIR)/libgtest.a $(GTESTDIR)/gtest-all.o
# This will also recompile if any source file is changed.
test_executable: $(GTESTDIR)/libgtest.a $(TESTS) depend
$(CC) -isystem $(GTESTDIR) -pthread -ggdb $(TESTS) $(GTESTDIR)/gtest/gtest_main.cc $(GTESTDIR)/libgtest.a -o test_executable
test: test_executable
./test_executable --gtest_print_time=0
And here's how my workspace is structured.
(Seems like I can't embed pictures).

Error in Makefile calling sed with comment character

I'm trying to build lstrip, a Lua utility for compressing Lua source code. I'm trying to build for Lua 5.1.3 on OS X v10.10.3.
I have downloaded and extracted the Lua 5.1.3 source code and modified the Makefile for lstrip to point to this directory. However, when I run make, I get this output:
cc -I/usr/local/src/lua-5.1.3/src -I/usr/local/src/lua-5.1.3/src -O2 -Wall -Wextra -O2 -c -o lstrip.o lstrip.c
lstrip.c:33:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, char* argv[])
^
1 warning generated.
sed '/void luaX_next/i#include "proxy.c"' /usr/local/src/lua-5.1.3/src/llex.c > llex.c
sed: 1: "/void luaX_next/i#inclu ...": command i expects \ followed by text
make: *** [llex.c] Error 1
This is what the relevant Makefile command looks like:
llex.c:
sed '/void luaX_next/i#include "proxy.c"' $(LUASRC)/$# > $#
I think that this is because the # in the sed command is being treated like an actual comment, but I'm not sure.
How can I fix the Makefile, or manually run the steps, to get lstrip built?
Full copy of the Makefile follows, in case it matters:
# makefile for lstrip
# change these to reflect your Lua installation (Lua 5.1!)
LUA= /usr/local/src/lua-5.1.3
LUAINC= $(LUA)/src
LUALIB= $(LUA)/src
LUASRC= $(LUA)/src
# no need to change anything below here
CFLAGS= $(INCS) $(WARN) -O2 $G
WARN= -O2 -Wall -Wextra
INCS= -I$(LUAINC) -I$(LUASRC)
LIBS= -L$(LUALIB) -llua -lm
MYNAME= lstrip
MYLIB= $(MYNAME)
T= $(MYNAME)
OBJS= $(MYNAME).o llex.o
TEST= test.lua
all: test
test: $T
$T $(TEST)
$T: $(OBJS)
$(CC) -o $# $(OBJS) $(LIBS)
llex.c:
sed '/void luaX_next/i#include "proxy.c"' $(LUASRC)/$# > $#
llex.o: proxy.c
clean:
-rm -f $(OBJS) core core.* a.out $(MYNAME)
# eof
Hand-build solution:
cp /usr/local/src/lua-5.1.3/src/llex.c .
Hand-edit llex.c to add the line #include "proxy.c" before the line starting with void luaX_next (line 446 for me).
Now run make, which will succeed.
You can find the answer in the sed manual, and it is in the Makefile lines
llex.c:
sed '/void luaX_next/i#include "proxy.c"' $(LUASRC)/$# > $#
Some variable expansion takes place here:
$(LUASRC) is expanded to the variable set above -> $(LUA)/src. Recurse as needed.
$# is replaced with the current target (llex.c)
So this recipe says:
In order to obtain the target llex.c (which will be processed later through other recipes), apply a stream editing command to the file $LUASRC/llex.c and write it to llex.c.
The stream editing command is: look for text "void luaX_next", before printing it, insert line "#include "proxy.c"".
Problem is, the command to do this is not "i" but "i\(newline)", which conflicts with a requirement of Makefiles that recipes must be on a single line.
I suspect that in order to fix your Makefile you need to use a different command than sed; awk can fit the bill although it's a bit more complex.
This line works in Mac OS X and in Linux:
sed '/void luaX_next/{h;s/.*/#include "proxy.c"/;p;g;}' $(LUASRC)/$# > $#

C make file is really confusing me

I'm working on learning C from a family member who's very adept as far as I know.
I'm using MingW on windows 7 with a fresh install of windows and having some difficulties getting things to work properly. I've made a make file and am using Deitel C for programmers with an introduction to C11, and have typed up the examples from the book in chapter three. I'm fairly certain I've managed to get that portion correct, and the makefile I'm using seems to be correct but it gives me a strange error that I don't understand.
C -o ex01 -O3 -Wall -Werrors -static -pedantic-errors -g main.o
make: C: Command not found
make: * [ex01] Error 127
this is the exact error I keep getting, I'm not sure if there's something wrong with the makefile or if it's something wrong with settings...
RM=rm
CC=gcc
LINK=$CC
CFLAGS = -O3 -Wall -Werrors -static -pedantic-errors -g
all: main.o ex01
clean:
(Tab)$(RM) -f main.o ex01.exe
main.o: main.c
(Tab)$(CC) -o main.o $(CFLAGS) -c main.c
ex01: main.o
(Tab)$(LINK) -o ex01 $(CFLAGS) main.o
this is almost exactly the makefile I'm using, asside from the (Tab) in place of actual tabs. I hope this is enough information to get some help, I suspect it's something wrong with my settings, I've had to set up paths to my library and gcc location. I'm just not sure where else to set up a path that could rectify this error.
#Keltar's comment nailed it exactly: LINK=$CC should be LINK=$(CC).
In make's syntax, $() is the proper way to deference a variable. The line LINK=$(CC) means set the variable LINK to whatever the CC variable is set to. After that instruction, their values will be the same.

make: *** No rule to make target `main.o'

here is the output from the console in Eclipse:
**** Build of configuration Debug for project FatFstest ****
make all
make: *** No rule to make target `main.o', needed by `FatFstest.elf'. Stop.
I am trying to build a project using the AVR plugin for Eclipse to test the FatFs library. I first imported the FatFs code then created main.c file to implement it. After I tried building it the first time, I added the src folder of my project to my the directories list in Properties > AVR Compiler > Directories, and I still get the build error. Any help?
Here is my makefile:
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include subdir.mk
-include src/subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
ifneq ($(strip $(ASM_DEPS)),)
-include $(ASM_DEPS)
endif
ifneq ($(strip $(S_DEPS)),)
-include $(S_DEPS)
endif
ifneq ($(strip $(S_UPPER_DEPS)),)
-include $(S_UPPER_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
LSS += \
FatFstest.lss \
SIZEDUMMY += \
sizedummy \
AVRDUDEDUMMY += \
avrdudedummy \
# All Target
all: FatFstest.elf secondary-outputs
# Tool invocations
FatFstest.elf: $(OBJS) $(USER_OBJS)
#echo 'Building target: $#'
#echo 'Invoking: AVR C Linker'
avr-gcc -Wl,-Map,FatFstest.map -mmcu=atmega328p -o"FatFstest.elf" $(OBJS) $(USER_OBJS) $(LIBS)
#echo 'Finished building target: $#'
#echo ' '
FatFstest.lss: FatFstest.elf
#echo 'Invoking: AVR Create Extended Listing'
-avr-objdump -h -S FatFstest.elf >"FatFstest.lss"
#echo 'Finished building: $#'
#echo ' '
sizedummy: FatFstest.elf
#echo 'Invoking: Print Size'
-avr-size --format=avr --mcu=atmega328p FatFstest.elf
#echo 'Finished building: $#'
#echo ' '
avrdudedummy: FatFstest.elf
#echo 'Invoking: AVRDude'
/usr/local/CrossPack-AVR-20100115/bin/avrdude -pm328p -Uflash:w:FatFstest.hex:a
#echo 'Finished building: $#'
#echo ' '
# Other Targets
clean:
-$(RM) $(OBJS)$(C_DEPS)$(ASM_DEPS)$(ELFS)$(LSS)$(AVRDUDEDUMMY)$(S_DEPS)$(SIZEDUMMY)$(S_UPPER_DEPS) FatFstest.elf
-#echo ' '
secondary-outputs: $(LSS) $(SIZEDUMMY) $(AVRDUDEDUMMY)
.PHONY: all clean dependents
.SECONDARY:
-include ../makefile.targets
main.c
#include <diskio.h>
#include <ff.h>
#include <stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
subdir.mk
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../src/diskio.c \
../src/ff.c \
../src/main.c
OBJS += \
./src/diskio.o \
./src/ff.o \
./src/main.o
C_DEPS += \
./src/diskio.d \
./src/ff.d \
./src/main.d
# Each subdirectory must supply rules for building sources it contributes
src/%.o: ../src/%.c
#echo 'Building file: $<'
#echo 'Invoking: AVR Compiler'
avr-gcc -I"/Users/nathannewcomb/Documents/Puzzles/FatFstest/src" -Wall -g2 -gstabs -O0 -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega328p -DF_CPU=1000000UL -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -c -o"$#" "$<"
#echo 'Finished building: $<'
#echo ' '
objects.mk
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
USER_OBJS :=
LIBS :=
sources.mk
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
O_SRCS :=
C_SRCS :=
S_UPPER_SRCS :=
S_SRCS :=
OBJ_SRCS :=
ASM_SRCS :=
OBJS :=
C_DEPS :=
ASM_DEPS :=
ELFS :=
LSS :=
AVRDUDEDUMMY :=
S_DEPS :=
SIZEDUMMY :=
S_UPPER_DEPS :=
# Every subdirectory with source files must be described here
SUBDIRS := \
src \
It happened to me too, simply moving main.cpp in an another folder.
I try to clean out the project, but the problem persist, so I have deleted Debug folder, re-compile and it works!
Don't put the main.c in a directory, put it at the top of its project
I added the src folder of my project to my the directories list in
Properties > AVR Compiler > Directories
Remove this /Users/nathannewcomb/Documents/Puzzles/FatFstest/src folder and try to compile again.
In the subdir.mk file, the line :
avr-gcc -I"/Users/nathannewcomb/Documents/Puzzles/FatFstest/src" -Wall -g2 -gstabs -O0 -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega328p -DF_CPU=1000000UL -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -c -o"$#" "$<"
should be become :
avr-gcc -Wall -g2 -gstabs -O0 -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega328p -DF_CPU=1000000UL -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -c -o"$#" "$<"
This src folder is already added in source.mk file :
# Every subdirectory with source files must be described here
SUBDIRS := \
src \
quoting eclipse - http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Fconcepts%2Fcdt_c_makefile.htm
Q2. My Console view says No rule to make target 'X'.
make -k clean all
make: * No rule to make target 'clean'.
make: * No rule to make target 'all'.
By default, the make program looks for a file most commonly called "Makefile" or "makefile". If it cannot find such a file in the working directory, or if that file is empty or the file does not contain rules for the command line goals ("clean" and "all" in this case), it will normally fail with an error message similar to those shown.
If you already have a valid Makefile, you may need to change the working directory of your build. The default working directory for the build command is the project's root directory. You can change this by specifying an alternate Build Directory in the Make Project properties. Or, if your Makefile is named something else (eg. buildFile.mk), you can specify the name by setting the default Build command to make -f buildFile.mk.
If you do not have a valid Makefile, create a new file named Makefile in the root directory. You can then add the contents of the sample Makefile (above), and modify it as appropriate.

SCons: GCC Ignoring -c

I'm using a MinGW-based GCC cross-compiler to compile a project which uses SCons as its build system.
The Python is a native 2.6.2 version, not specifically compiled for MinGW (or Cygwin).
However, I am running into a problem with the build:
F:/pedigree/compilers/bin/i686-elf-gcc -o build\src\user\applications\apptest\ma
in.obj -c -std=gnu99 -march=i486 -fno-builtin -m32 -g0 -O3 -Wno-long-long -Wnest
ed-externs -Wall -Wextra -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-long-
long -Wno-variadic-macros -Wno-unused -Wno-unused-variable -Wno-conversion -Wno-
format -Wno-empty-body -fno-stack-protector -DTHREADS -DDEBUGGER -DDEBUGGER_QWER
TY -DSERIAL_IS_FILE -DECHO_CONSOLE_TO_SERIAL -DKERNEL_NEEDS_ADDRESS_SPACE_SWITCH
-DADDITIONAL_CHECKS -DBITS_32 -DKERNEL_STANDALONE -DVERBOSE_LINKER -DX86 -DX86_
COMMON -DLITTLE_ENDIAN -D__UD_STANDALONE__ -DINSTALLER -Isrc\subsys\posix\includ
e -Ibuild\src\user\applications\apptest -Isrc\user\applications\apptest src\user
\applications\apptest\main.c
f:/pedigree/compilers/bin/../lib/gcc/i686-elf/4.4.1/../../../../i686-elf/bin/ld.
exe: crt0.o: No such file: No such file or directory
If I add -c to the CFLAGS, I get a compiled object called "main.obj -c" (there's a space between obj and -c there).
Does anyone have any idea what's happening? Is there anything I can do to solve this?
The project uses the POSIX platform to enforce progarm and object file extensions, however the POSIX platform in SCons defines a function "escape":
def escape(arg):
"escape shell special characters"
slash = '\\'
special = '"$()'
arg = string.replace(arg, slash, slash+slash)
for c in special:
arg = string.replace(arg, c, slash+c)
return '"' + arg + '"'
When it escapes the backslashes, it wreaks havoc in the Windows environment. Changing to a neutral platform, and specifying the extensions explicitly, fixes the problem.