how to execute make file
You don't tend to execute the make file itself, rather you execute make
, giving it the make file as an argument:
make -f pax.mk
If your make file is actually one of the standard names (like makefile
or Makefile
), you don't even need to specify it. It'll be picked up by default (if you have more than one of these standard names in your build directory, you better look up the make
man page to see which takes precedence).
Makefile: use multiple makefiles
any way, I show you something and hope can help you:
all:
@$(MAKE) -C subfolder
or if you want to use *.mk as your sub makefile, you can write:
all:
@$(MAKE) -C busfolder -f somename.mk
I show you my example, my DIR looks like:
TOPDIR-- Makefile
|
|-- debug
| |-- debug.c
| |-- debug.h
| |-- debug.mk
| |-- instrument.c
| `-- uart_print.c
|-- driver
| |-- driver.c
| |-- driver_ddi.c
| |-- driver_ddi.h
| |-- driver.h
| `-- driver.mk
|-- include
| `-- common.h
|-- Makefile
|-- mw
| |-- manager.c
| `-- mw.mk
|-- root
| |-- main.c
| `-- root.mk
and my TOP makefile looks like:
MAKE_DIR = $(PWD)
ROOT_DIR := $(MAKE_DIR)/root
DRV_DIR := $(MAKE_DIR)/driver
INCLUDE_DIR := $(MAKE_DIR)/include
DEBUG_DIR := $(MAKE_DIR)/debug
INC_SRCH_PATH :=
INC_SRCH_PATH += -I$(ROOT_DIR)
INC_SRCH_PATH += -I$(DRV_DIR)
INC_SRCH_PATH += -I$(INCLUDE_DIR)
INC_SRCH_PATH += -I$(DEBUG_DIR)
LIB_SRCH_PATH :=
LIB_SRCH_PATH += -L$(MAKE_DIR)/libs
COLOR_ON = color
COLOR_OFF =
CC = $(COLOR_ON)gcc
#CC = $(COLOR_OFF)gcc
LD = ld
LINT = splint
LIBS := -ldriver -ldebug -lmw -lm -lpthread
CFLAGS :=
CFLAGS += $(INC_SRCH_PATH) $(LIB_SRCH_PATH)
CFLAGS += -Wall -O -ggdb -Wstrict-prototypes -Wno-pointer-sign -finstrument-functions -fdump-rtl-expand
CFLAGS += -DDEBUG -D_REENTRANT
LDFLAGS :=
export MAKE_DIR CC LD CFLAGS LDFLAGS LIBS LINT INC_SRCH_PATH
all:
@$(MAKE) -C debug -f debug.mk
@$(MAKE) -C driver -f driver.mk
@$(MAKE) -C mw -f mw.mk
@$(MAKE) -C root -f root.mk
.PHONY: clean
clean:
@$(MAKE) -C debug -f debug.mk clean
@$(MAKE) -C driver -f driver.mk clean
@$(MAKE) -C mw -f mw.mk clean
@$(MAKE) -C root -f root.mk clean
it will call sub DIR *.mk during the compile. The sub DIR makefile, I just write a simple example for you reference:
LIB = $(MAKE_DIR)/libs/yourmodulename.a
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
$(LIB): $(OBJS)
@mkdir -p ../libs
@$(AR) cr $@ $^
@echo " Archive $(notdir $@)"
$(OBJS): $(SRCS)
@$(CC) $(CFLAGS) -c $^
@echo " CC $(OBJS)"
.PHONY: clean
clean:
@$(RM) -f $(LIB) $(OBJS)
@$(RM) -f *.expand
@echo " Remove Objects: $(OBJS)"
for the makefile, which generate the final target file(like a.out) is little bit different, because I use the sub makefile to generate LIB file, and I use a root.mk to generate final target:
PROG = ../prog/DEMO
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
$(PROG): $(SRCS)
@mkdir -p ../prog
@$(CC) $^ $(CFLAGS) -Wl,-Map=$(PROG).map $(LIBS) -o $@
@echo " Generate Program $(notdir $(PROG)) from $^"
.PHONY: clean
clean:
@$(RM) -f $(OBJS) $(PROG)
@$(RM) -f *.expand
@$(RM) -rf ../prog ../libs
@echo " Remove Objects: $(OBJS)"
@echo " Remove Libraries: $(notdir $(PROG))"
How to use makefiles in Visual Studio?
A UNIX guy probably told you that. :)
You can use makefiles in VS, but when you do it bypasses all the built-in functionality in MSVC's IDE. Makefiles are basically the reinterpret_cast of the builder. IMO the simplest thing is just to use Solutions.
What do the makefile symbols $@ and $ mean?
$@
is the name of the target being generated, and $<
the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.
For example, consider the following declaration:
all: library.cpp main.cpp
In this case:
$@
evaluates toall
$<
evaluates tolibrary.cpp
$^
evaluates tolibrary.cpp main.cpp
Any interesting uses of Makefiles to share?
Make's parallelism is particularly handy for shell scripting. Say you want to get the 'uptime' of a whole set of hosts (or basically perform any slow operation). You could do it in a loop:
cat hosts | while read host; do echo "$host: $(ssh $host uptime)"; done
This works, but is slow. You can parallelise this by spawning subshells:
cat hosts | while read host; do (echo "$host: $(ssh $host uptime)")&; done
But now you have no control over how many threads you spawn, and CTRL-C won't cleanly interrupt all threads.
Here is the Make solution: save this to a file (eg. showuptimes
) and mark as executable:
#!/usr/bin/make -f
hosts:=$(shell cat)
all: ${hosts}
${hosts} %:
@echo "$@: `ssh $@ uptime`"
.PHONY: ${hosts} all
Now running cat hosts | ./showuptimes
will print the uptimes one by one. cat hosts | ./showuptimes -j
will run them all in parallel. The caller has direct control over the degree of parallelisation (-j
), or can specify it indirectly by system load (-l
).
How to write loop in a Makefile?
The following will do it if, as I assume by your use of ./a.out
, you're on a UNIX-type platform.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Test as follows:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
produces:
1
2
3
4
For bigger ranges, use:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
This outputs 1 through 10 inclusive, just change the while
terminating condition from 10 to 1000 for a much larger range as indicated in your comment.
Nested loops can be done thus:
target:
num1=1 ; while [[ $$num1 -le 4 ]] ; do \
num2=1 ; while [[ $$num2 -le 3 ]] ; do \
echo $$num1 $$num2 ; \
((num2 = num2 + 1)) ; \
done ; \
((num1 = num1 + 1)) ; \
done
producing:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Add .so and .a libraries to Makefile
Lets consider your /usr/local/lib/libYARP_OS.a
.
What you can do is, have -L/usr/local/lib/
in your makefile as one of the variables. And then you can have -lYARP_OS
appended to the LDLIBS.
-L is for path to the lib and -l is the lib name here libYARP_OS.a
will be passed as -lYARP_OS
.
On the command line you would do something like: gcc -o main main.c -L/usr/local/lib/ -lYARP_OS
. This should give you an idea.
How to install and use make in Windows?
make
is a GNU command so the only way you can get it on Windows is installing a Windows version like the one provided by GNUWin32. Anyway, there are several options for getting that:
The most simple choice is using Chocolatey. First you need to install this package manager. Once installed you simlpy need to install
make
(you may need to run it in an elevated/admin command prompt) :choco install make
Other recommended option is installing a Windows Subsystem for Linux (WSL/WSL2), so you'll have a Linux distribution of your choice embedded in Windows 10 where you'll be able to install
make
,gcc
and all the tools you need to build C programs.For older Windows versions (MS Windows 2000 / XP / 2003 / Vista / 2008 / 7 with msvcrt.dll) you can use GnuWin32.
An outdated alternative was MinGw, but the project seems to be abandoned so it's better to go for one of the previous choices.
Related Topics
How to Access Private Members from Outside the Class Without Using Friends
C99 Stdint.H Header and Ms Visual Studio
How to Safely Pass Objects, Especially Stl Objects, to and from a Dll
How to Track Down a "Double Free or Corruption" Error
Catching Exception: Divide by Zero
Testing Stream.Good() or !Stream.Eof() Reads Last Line Twice
How to Implement the Factory Method Pattern in C++ Correctly
C++ Deprecated Conversion from String Constant to 'Char*'
How Are Virtual Functions and Vtable Implemented
How to Return an Array from a Function
Why Are Standard Iterator Ranges [Begin, End) Instead of [Begin, End]
C++11 Return Value Optimization or Move