Main program written in C++

Reference : Practical Makefiles, by example

void operations();

int main(int argc, const char **argv) {

    operations();
    
    return 0;
}

Function that uses Armadillo also in C++

#include <iostream>
#include <armadillo>

void operations() {
    // Initialize the random generator
    arma::arma_rng::set_seed_random();
    
    // Create a 4x4 random matrix and print it on the screen
    arma::Mat<double> A = arma::randu(4,4);
    std::cout << "A:\n" << A << "\n";
    
    // Multiply A with his transpose:
    std::cout << "A * A.t() =\n";
    std::cout << A * A.t() << "\n";
    
    // Access/Modify rows and columns from the array:
    A.row(0) = A.row(1) + A.row(3);
    A.col(3).zeros();
    std::cout << "add rows 1 and 3, store result in row 0, also fill 4th column with zeros:\n";
    std::cout << "A:\n" << A << "\n";
    
    // Create a new diagonal matrix using the main diagonal of A:
    arma::Mat<double>B = arma::diagmat(A);
    std::cout << "B:\n" << B << "\n";
    
    // Save matrices A and B:
    A.save("A_mat.txt", arma::arma_ascii);
    B.save("B_mat.txt", arma::arma_ascii);
    
}

Build executable exe_armadillo with command line

c++ -c files/obj_armadillo.cpp -I/opt/local/include # create the file obj_armadillo.o
c++ -o exe_armadillo files/main.cpp obj_armadillo.o -L/opt/local/lib -larmadillo # create the executable exe_armadillo.o
  • -I option flag to set headers file directory (.h) needed to build every object files (CXXFLAGS).
  • -L option flag to set library directory (.a) needed only to build executable (LDFLAGS)

Test the program

./exe_armadillo
rm ./exe_armadillo *.o
## A:
##    0.5037   0.8103   0.3284   0.0446
##    0.3764   0.3620   0.1811   0.9196
##    0.4333   0.9092   0.7558   0.9676
##    0.5202   0.1974   0.2192   0.6029
## 
## A * A.t() =
##    1.0201   0.5834   1.2462   0.5209
##    0.5834   1.1513   1.5190   0.8615
##    1.2462   1.5190   2.5218   1.1540
##    0.5209   0.8615   1.1540   0.7212
## 
## add rows 1 and 3, store result in row 0, also fill 4th column with zeros:
## A:
##    0.8966   0.5595   0.4003        0
##    0.3764   0.3620   0.1811        0
##    0.4333   0.9092   0.7558        0
##    0.5202   0.1974   0.2192        0
## 
## B:
##    0.8966        0        0        0
##         0   0.3620        0        0
##         0        0   0.7558        0
##         0        0        0        0

First Makefile


default: exe_armadillo

obj_armadillo.o: files/obj_armadillo.cpp
    c++ -o $@ -c $^ -I/opt/local/include 
    
exe_armadillo: files/main.cpp obj_armadillo.o
    c++ -o $@ $^ -L/opt/local/lib -larmadillo
    
clean:
    rm *.txt *.o exe_armadillo

Test the program

make -f files/Makefile1
./exe_armadillo
make -f files/Makefile1 clean
## c++ -o obj_armadillo.o -c files/obj_armadillo.cpp -I/opt/local/include 
## c++ -o exe_armadillo files/main.cpp obj_armadillo.o -L/opt/local/lib -larmadillo
## A:
##    0.1992   0.0072   0.3641   0.7114
##    0.0285   0.4529   0.9766   0.2345
##    0.1830   0.2280   0.8833   0.1920
##    0.2773   0.2637   0.3530   0.8260
## 
## A * A.t() =
##    0.6784   0.5314   0.4963   0.7733
##    0.5314   1.2147   1.0161   0.6658
##    0.4963   1.0161   0.9025   0.5813
##    0.7733   0.6658   0.5813   0.9533
## 
## add rows 1 and 3, store result in row 0, also fill 4th column with zeros:
## A:
##    0.3057   0.7166   1.3296        0
##    0.0285   0.4529   0.9766        0
##    0.1830   0.2280   0.8833        0
##    0.2773   0.2637   0.3530        0
## 
## B:
##    0.3057        0        0        0
##         0   0.4529        0        0
##         0        0   0.8833        0
##         0        0        0        0
## 
## rm -f *.txt *.o exe_armadillo

Using variables


default: exe_armadillo # default target

CXX                := c++   # := means "change CXX only if it is undefined"
ARMADILLO_INCDIR   = /opt/local/include
ARMADILLO_LIBDIR   = /opt/local/lib
ARMADILLO_INC_FLAGS = -I${ARMADILLO_INCDIR}
ARMADILLO_LIB_FLAGS = -L${ARMADILLO_LIBDIR} -larmadillo

obj_armadillo.o: files/obj_armadillo.cpp
    ${CXX} -c -o $@ $^ ${ARMADILLO_INC_FLAGS} # $@ : target $^: dependencies
    
exe_armadillo: files/main.cpp obj_armadillo.o
    ${CXX} -o $@ $^ ${ARMADILLO_LIB_FLAGS}
    
clean:
    rm *.txt *.o exe_armadillo
make -f files/Makefile2
./exe_armadillo
make -f files/Makefile2 clean
## c++    -c -o obj_armadillo.o files/obj_armadillo.cpp -I/opt/local/include # obj_armadillo.o : target files/obj_armadillo.cpp: dependencies
## c++    -o exe_armadillo files/main.cpp obj_armadillo.o -L/opt/local/lib -larmadillo
## A:
##    0.1632   0.0166   0.9071   0.9214
##    0.9668   0.4183   0.7988   0.8361
##    0.1602   0.1298   0.3475   0.1719
##    0.8506   0.2413   0.9478   0.8199
## 
## A * A.t() =
##    1.6988   1.6597   0.5019   1.7581
##    1.6597   2.4468   0.6305   2.3659
##    0.5019   0.6305   0.1928   0.6379
##    1.7581   2.3659   0.6379   2.3523
## 
## add rows 1 and 3, store result in row 0, also fill 4th column with zeros:
## A:
##    1.8173   0.6597   1.7466        0
##    0.9668   0.4183   0.7988        0
##    0.1602   0.1298   0.3475        0
##    0.8506   0.2413   0.9478        0
## 
## B:
##    1.8173        0        0        0
##         0   0.4183        0        0
##         0        0   0.3475        0
##         0        0        0        0
## 
## rm *.txt *.o exe_armadillo

Add rule to build object files


default: exe_armadillo

CXX                 := c++
ARMADILLO_INCDIR    = /opt/local/include
ARMADILLO_LIBDIR    = /opt/local/lib
ARMADILLO_INC_FLAGS = -I${ARMADILLO_INCDIR}
ARMADILLO_LIB_FLAGS = -L${ARMADILLO_LIBDIR} -larmadillo

CXXFLAGS += ${ARMADILLO_INC_FLAGS}
LDFLAGS  += ${ARMADILLO_LIB_FLAGS}

SRCS = $(wildcard *.cpp)  # List all cpp files
OBJS = $(SRCS:.cpp=.o)    # List all matching object files
    
.cpp.o: # $< the source file .cpp $@ the target .o
    $(CXX) $(CXXFLAGS) -c $< -o $@   
    
exe_armadillo: $(OBJS)
    ${CXX} -o $@ $^ $(CXXFLAGS) ${LDFLAGS}
    
clean:
    rm *.txt *.o exe_armadillo
make -f Makefile3
./exe_armadillo
make -f Makefile3 clean