Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create linux make/build file

I am moving a C++ project from Windows to Linux and I now need to create a build/make file. I have never created a build/make file before. I also need to include Boost libraries to make it more complicated. It must also be a makefile and I need to learn how to create makefile anyway, so CMake and SCON are out. IDEs are also out because of the use of Boost and all my IDEs (Eclipse, VS, etc.) are only on windows. I must generate a makefile from scratch.

So what are the basics of creating a Linux c++ make file and how to incorporate the Boost libraries in it to have it properly link?

So far, my makefile looks like this. I think CFLAGS and LDFLAGS are compiler and optimization options, but not totally sure.

CC = g++
CFLAGS = -wall -o3 - c
LDFLAGS = -03 -mfp-rounding-mode=n

I am offering a bounty because I am still very lost. In case anyone is feeling adventurous, I need to compile the following in linux

  • simple_ls.h
  • simple_ls.cpp
  • 2dquicksort.h
  • rawr.h
  • rawr.cpp
  • converter.cpp

The headers in simple_ls.h:

#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include "boost/lexical_cast.hpp"

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

The headers in 2dquicksort.h:

#include <stdio.h>
#include <ctype.h>
#include <iostream>

The headers in rawr.h:

#include <iostream> // not required by most systems
#include <fstream>
#include <iomanip>
#include <cstdlib> // or (stdlib.h) for exit()

#include <cmath> 
#include <vector>
#include <limits>
#include <string>

An acceptable answer would be a step-by-step explanation of how makefiles work and how to build them with Boost in Linux without an IDE.

like image 546
Elpezmuerto Avatar asked Aug 26 '10 14:08

Elpezmuerto


People also ask

What is the command to build a make file?

c -I. If you put this rule into a file called Makefile or makefile and then type make on the command line it will execute the compile command as you have written it in the makefile. Note that make with no arguments executes the first rule in the file.

What is make build command in Linux?

The Linux make command is used to build and maintain groups of programs and files from the source code. In Linux, it is one of the most frequently used commands by the developers. It assists developers to install and compile many utilities from the terminal.

What is makefile in Linux?

Makefile is a program building tool which runs on Unix, Linux, and their flavors. It aids in simplifying building program executables that may need various modules. To determine how the modules need to be compiled or recompiled together, make takes the help of user-defined makefiles.


2 Answers

What is a Makefile ? (applied to a Boost project)

The root recursive idea behind Makefile is:

To build a target we need prerequisites (other targets!) and instructions to build

Prerequisites

They are either files, folders or fake targets (usually in .PHONY). Files/folders are tested for existence and modification date.

The target needs to be rebuilt if it has no prerequisite or if older that any of the prerequisites.

Instruction

An Instruction is shell commands, starting with one tab. Each instruction line is one shell instance. The shell command can be continued on next line when the current one ends with backslash \.

Target definition

A target is either a dependency or a rule.

Dependency:

target : prerequisite1 prerequisite2 prerequisiteN

Rule:

target : prerequisite1 prerequisite2 prerequisiteN
    instructions1
    @hidden_batch1 ; \
  hidden_batch2  

With tabs in front of instruction start.

Debug

Debugging a Makefile can become a real headache. Try the following in your Makefile to show traces (with file and line location for warning):

$(info Shell: $(SHELL))
$(warning CXX: $(CXX))

This is helpful when your Makefile contains lots of nested if/else/endif and you're not sure anymore what is the current path.

Makefile Structure

The ideal makefile structure is:

  1. variable setup
  2. target/dependency declarations

The real target-instructions processing starts once the whole Makefile and its include files has been understood (stored in make internal database).

Example

Finally, apply theory to this specific example using Boost and create fake source files to illustrate.

rawr.cpp

#include "rawr.h"

simple_ls.cpp

#include "rawr.h"

converter.cpp

#include <iostream>

#include "rawr.h"
#include "simple_ls.h"
#include "2dquicksort.h"

#include <boost/array.hpp>   // Boost! 

int main(int argc, char **argv)
{
    boost::array<int,4> a = { { 1, 2, 3, 4} };
    std::cout << a[1] << std::endl;
    return 0;
}

Makefile

Don't forget to replace spaces with real Tabs if you copy Makefile source from *stack***overflow** :

sed -i~ -e 's/^    /\t/' Makefile

Makefile source:

## Makefile for C++ project using Boost
#
# @author Cedric "levif" Le Dillau
#
# Some notes:
# - Using ':=' instead of '=' assign the value at Makefile parsing time,
#   others are evaluated at usage time. This discards
# - Use ':set list' in Vi/Vim to show tabs (Ctrl-v-i force tab insertion)
#

# List to '.PHONY' all fake targets, those that are neither files nor folders.
# "all" and "clean" are good candidates.
.PHONY: all, clean

# Define the final program name
PROGNAME := converter

# Pre-processor flags to be used for includes (-I) and defines (-D) 
CPPFLAGS := -DUSE_BOOST

# CFLAGS is used for C compilation options.
CFLAGS := -Wall -O0

# CXXFLAGS is used for C++ compilation options.
CXXFLAGS += -Wall -O0

# LDFLAGS is used for linker (-g enables debug symbols)
LDFLAGS  += -g

# Which Boost modules to use (all)
BOOST_MODULES = \
  date_time     \
  filesystem    \
  graph         \
  iostreams     \
  math_c99      \
  system        \
  serialization \
  regex

# Boost libraries' type (a suffix)
BOOST_MODULES_TYPE := -mt

# Define library names with their type
BOOST_MODULES_LIBS := $(addsuffix $(BOOT_MODULES_TYPE),$(BOOST_MODULES))

# Define the linker argument to use the Boost libraries.
BOOST_LDFLAGS := $(addprefix -lboost_,$(BOOST_MODULES_LIBS))

# Feed compiler/linker flags with Boost's
CPPFLAGS += $(BOOST_CPPFLAGS)
LDFLAGS += $(BOOST_LDFLAGS)

# List the project' sources to compile or let the Makefile recognize
# them for you using 'wildcard' function.
#
#SOURCES = simple_ls.cpp rawr.cpp converter.cpp
SOURCES = $(wildcard *.cpp)

# List the project' headers or let the Makefile recognize
# them for you using 'wildcard' function.
#
#HEADERS = simple_ls.h 2dquicksort.h rawr.h
HEADERS = $(wildcard %.h)

# Construct the list of object files based on source files using
# simple extension substitution.
OBJECTS = $(SOURCES:%.cpp=%.o)

#
# Now declare the dependencies rules and targets
#
# Starting with 'all' make it  becomes the default target when none 
# is specified on 'make' command line.
all : $(PROGNAME)

# Declare that the final program depends on all objects and the Makfile
$(PROGNAME) : $(OBJECTS) Makefile
    $(CXX) -o $@ $(LDFLAGS) $(OBJECTS)

# Now the choice of using implicit rules or not (my choice)...
#
# Choice 1: use implicit rules and then we only need to add some dependencies
#           to each object.
#
## Tells make that each object file depends on all headers and this Makefile.
#$(OBJECTS) : $(HEADERS) Makefile
#
# Choice 2: don't use implicit rules and specify our will
%.o: %.cpp $(HEADERS) Makefile
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(OUTPUT_OPTION) $<

# Simple clean-up target
# notes:
# - the '@' before 'echo' informs make to hide command invocation.
# - the '-' before 'rm' command to informs make to ignore errors.
clean :
    @echo "Clean."
    -rm -f *.o $(PROGNAME)

File list

2dquicksort.h
converter.cpp
Makefile
rawr.cpp
rawr.h
simple_ls.cpp
simple_ls.h

Compilation

make clean all
Clean.
rm -f *.o converter
g++ -Wall -O0 -DUSE_BOOST  -c -o converter.o converter.cpp
g++ -Wall -O0 -DUSE_BOOST  -c -o rawr.o rawr.cpp
g++ -Wall -O0 -DUSE_BOOST  -c -o simple_ls.o simple_ls.cpp
g++ -o converter -g -lboost_date_time -lboost_filesystem -lboost_graph -lboost_iostreams -lboost_math_c99 -lboost_system -lboost_serialization -lboost_regex converter.o rawr.o simple_ls.o

Result

And now, the result of nearly the tiniest Boost program:

./converter
2

No excuse not to use it ! Boost is really a featured C++ toolbox :)

like image 152
levif Avatar answered Nov 07 '22 07:11

levif


A very simple GNU makefile follows:

CPPFLAGS += -Isome_include_path
CXXFLAGS += -O3
LDFLAGS  += -Lsome_link_path -lsome_lib -lboost_filesystem

all: binary_name
binary_name: foo.o bar.o john.o
  • CPPFLAGS are flags that are applied to the C Preprocessor. Things like include paths.
  • CXXFLAGS are flags that are applied to the C++ compiler. Things like optimization levels.
  • LDFLAGS are flags that applied to the linker. Things like external libraries (boost_filesystem) and other libraries. Also, the paths to those libraries.
  • Convention says that there should be a make all rule, which is the default. In make, the first rule is the default.
  • binary_name is the name of your binary.
  • binary_name depends on 3 files: foo.o, bar.o, john.o.
  • We don't include rules for *.o because gnu make has an implicit rule for those.

To use make, you would create a file named Makefile with the contents listed above. To build, you would run make in that directory.

As an aside (and as others have mentioned), I would recommend moving away from make if possible. There are better systems out there. The main benefit of make is that it's everywhere. However, if management requires it, then management requires it.

(Note that the GNU Make += notation is not always portable to other versions of Make. However, make on Linux is GNU Make.)


Given your edit, here's an example with the files that you note. The one caution is that the line beginning with $(CXX) should begin with a TAB character!

LDFLAGS  := -lboost_filesystem
CXXFLAGS := -O3 -Wall
CPPFLAGS :=

all: program
program: simple_ls.o converter.o rawr.o
    $(CXX) -o $< $^ $(LDFLAGS)

simple_ls.o: simple_ls.cpp rawr.h simple_ls.h 2dquicksort.h
converter.o: converter.cpp rawr.h simple_ls.h 2dquicksort.h
rawr.o: rawr.cpp rawr.h simple_ls.h 2dquicksort.h
like image 23
Bill Lynch Avatar answered Nov 07 '22 06:11

Bill Lynch