[IPOL discuss] New tool to create Makefiles

Nicolas Limare nicolas.limare at cmla.ens-cachan.fr
Tue Oct 25 06:31:53 CEST 2011


Hi,

> I've created a small tool to help creating Makefiles to those who doesn't
> know how to do it, or want to do it fastly.
>
> I hope this is helpful.

Good idea, I think it is helpful. Maybe mention it in the wiki?

I want to suggest some modifications:

* use default GNU make variables:
  - CC and CXX as the compilers, not gcc and g++. CC and CXX are
    always set to the default compilers, and can be redefined for
    other compilers when we call make: make CC=clang
  - CPPFLAGS for the C preprocessor options
  - CFLAGS/CXXFLAGS for the C/C++ compiler options
  - LDFLAGS for the link options
  -> http://www.gnu.org/software/automake/manual/make/Implicit-Variables.html

* for the default make target, only use standard compiler option. -Ox
  works on every compiler I know, -fomit-frame-pointer doesn't. With
  standard compiler options, it should work on any system (at least
  Linux and Mac) without needing to touch the makefile.

* handle the optimization flags in a specific variable, so I can
  override it: make COPT="-O3 -ffast-math -fomit-frame-pointer"

* put the "strict compilation flags" in another specific variable, and
  only use them for a specific make target (I use "lint" in my
  makefiles), because these options are note portable across
  compilers

* explicitely mention the output file name in every compiler
  invocation

* add the link flags (-lpng...) after the object names in the link
  step, the order matters

* use the C++ compiler to link the object files it there were some C++
  source files, otherwise use the C compiler

* "make clean" only removes the temporary files, "make distclean" also
  removes the executable

* use "default" as the default make target, and "all" as the "complete
  build" make target

* run this script with /bin/sh, /bin/bash is not required

* I think that in your script, the user choices for the compiler
  options are not used (cf. lines 60 and 61)

* I think shell command capture is easier to understand with
  $(parenthesis) than with `backquotes`, but it's probably just a
  matter of personal taste

* I also think you should include a license statement for your script,
  not for the makefiles generated by your script.

I wrote all that (excepted the license part) in an updated version
proposed in attachment to this message.

8<----------8<----------8<----------8<----------8<----------8<----------

I also attach a generic Makefile that does similar things. It is
not as user-friendly as your script, because one has to understand the
make syntax to customize it, and it uses lots of make shortcuts to
avoid redundancy, but it can help people who know this syntax to start
with their projects.

The C/C++ source files are detected with the $(wildcard ...) GNU make
command. The dependencies are automatically generated with $(CC) -MM[1].
The default targets should work with any compiler. Two special targets
are available:
- make lint, to check the ANSI compliance of your code
- make debug, to generate an executable with debugging info

You will need to customize at least two variables: BIN (your
executable output) and LDLIBS (external libraries). Then use it with
these invocations (can be used combined):

- build/rebuild the program
  make

- force rebuild
  make -B

- cleanup everything
  make distclean

- build with another compiler and options
  make CC=my_c_compiler CFLAGS="my_c_flags"

- build with optimization options
  make CC=gcc COPT="-O3 -ffast-math -ftree-vectorize-ftree -funroll-loops"

- build for debugging
  make debug

- check the source
  make lint

Hidden bonus: you can add "make -B lint; make distclean" in your git
hooks (.git/hooks/pre-commit) to automatically check all the code you
record in git.

[1] This option is understood by gcc-compatible compilers, including
icc and clang, but not by suncc.

-- 
Nicolas LIMARE - CMLA - ENS Cachan    http://www.cmla.ens-cachan.fr/~limare/
IPOL - image processing on line                          http://www.ipol.im/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: create_makefile.sh
Type: application/x-sh
Size: 3034 bytes
Desc: not available
URL: <http://tools.ipol.im/mailman/archive/discuss/attachments/20111025/1952be86/attachment.sh>
-------------- next part --------------
# -*- makefile -*-
# Copyright 2011 Nicolas Limare <nicolas.limare at cmla.ens-cachan.fr>
#
# Copying and distribution of this file, with or without
# modification, are permitted in any medium without royalty provided
# the copyright notice and this notice are preserved.  This file is
# offered as-is, without any warranty.

# generic makefile for C and C++ code
#
# It should work with any C and C++ compiler, and any code using a set
# of C and C++ files to build a single executable. You need to
# customize, at least,
# - the BIN variable with the name of your executable program file
# - the LDLIBS variable with the libraries used (-lm -lpng...)

# compiler optimization
COPT	= -O2
CXXOPT	= -O2
# compiler options
CFLAGS	= $(COPT) 
CXXFLAGS	= $(CXXOPT) 
# preprocessor options (NDEBUG disables assert())
CPPFLAGS	= -I. -DNDEBUG
# linker options (-Lxxx for the library path)
LDFLAGS	= 

# C/C++ source files (autodetected in the current directory)
CSRC	= $(wildcard *.c)
CXXSRC	= $(wildcard *.cpp)
# C/C++ object files
COBJ	= $(CSRC:.c=.o)
CXXOBJ	= $(CXXSRC:.c=.o)

# libraries (use the -lfoo -lbar syntax)
LDLIBS	= 
# binary output
BIN	= a.out

# default target
default	: all
all	: $(BIN)

# dependencies
-include Makefile.dep
Makefile.dep	: $(CSRC) $(CXXSRC)
	echo > $@
ifneq ($(CSRC),)
	$(CC) -MM $(CSRC) >> $@
endif
ifneq ($(CXXSRC),)
	$(CXX) -MM $(CXXSRC) >> $@
endif

# C files
%.o	: %.c
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
# C++ files
%.o	: %.cpp
	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@

# final link
$(BIN)	:  $(COBJ) $(CXXOBJ)
ifeq ($(CXXOBJ),)
	$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@
else
	$(CXX) $^ $(LDFLAGS) $(LDLIBS) -o $@
endif

# utilities
clean	: 
	$(RM) $(COBJ) $(CXXOBJ)

distclean	: clean
	$(RM) $(EXEC)

debug	:
	$(MAKE) CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \
		CFLAGS="$(CFLAGS) -g" \
		CXXFLAGS="$(CXXFLAGS) -g"

CSTRICT	= -ansi -pedantic -Wall -Wextra -Werror
CXXSTRICT	= -ansi -pedantic -Wall -Wextra -Werror
lint: 
	$(MAKE) CFLAGS="$(CFLAGS) $(CSTRICT)" \
		CXXFLAGS="$(CXXFLAGS) $(CXXSTRICT)"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://tools.ipol.im/mailman/archive/discuss/attachments/20111025/1952be86/attachment.pgp>


More information about the discuss mailing list