Code Monkey home page Code Monkey logo

easymake's Introduction

Getting Started with Easymake

Introduction

Easymake is a generic makefile for C/C++ on linux system. For simple C/C++ applications, you don’t even need to write a single line of makefile code to build your target with easymake.

Features description:

  • Automatic C/C++ sources (*.c and *.cpp) file detection.
  • Auto dependency generation and meɪntənəns, to accelerate the build time.
  • Simple unit testing supported. Easy management of more than one entry point (the main function) in the project.
  • VPATH fully supported.

The following examples will show you how to build you program with easymake step by step. Do not be frightened by such a long article, most of the part in the following section is about writing a simple C/C++ program. easymake is very easy to learn, just as the 'easy' in the name.

Getting Started

This chapter shows you how to use easymake in a simple program. Suppose we want to write a simple program, that take to number input by user and then shows the sum. The source code of this program is in the directory samples/basics.

Write C/C++ code

This program is simple enough that I should skip the program design and show our code directly, and after that we will focuse on our topic.

File: main.cpp

#include <iostream>

#include "math/add.h"

using namespace std;

int main(){
        cout<<"please enter two integer:"<<endl;

        int a,b;
        cin>>a>>b;

        cout<<"add("<<a<<","<<b<<") returns "<<add(a,b)<<endl;
}

File: math/add.h

#ifndef ADD_H
#define ADD_H

int add(int,int);

#endif

File: math/add.cpp

#include "math/add.h"

int add(int a,int b){
        return a+b;
}

Build Our Program with Easymake

I keep this program simple so that we could use command-line to build it directly. If you are familliar with makefile syntax, you may also write a makefile from scratch to build it in seconds. Now you may wonder how we build the program with easymake? Don't worry, I will show all the three methods for you to make it clear and you could compare these methods directly.

Build with Command Line

g++ -c -o main.o main.cpp
g++ -c -o add.o math/add.cpp -I.
g++ -o target main.o add.o

Or just use a single command g++ -o target main.cpp math/add.cpp -I. to build the program.

Type ls, and then ./target you should see the result of our program:

[root@VM_6_207_centos basics]# ls
add.o  bin  main.cpp  main.o  makefile  math  target
[root@VM_6_207_centos basics]# ./target
please enter two integer:
5
3
add(5,3) returns 8

Build with Makefile from Scratch

Create a new file name Makefile and write our code as below:

target: main.o add.o
        g++ -o target main.o add.o

main.o: main.cpp
        g++ -c -o main.o main.cpp -I.

add.o: math/add.cpp
        g++ -c -o add.o math/add.cpp -I.

The result is pretty much the same:

[root@VM_6_207_centos basics]# make
g++ -c -o main.o main.cpp -I.
g++ -c -o add.o math/add.cpp -I.
g++ -o target main.o add.o
[root@VM_6_207_centos basics]# ls
add.o  main.cpp  main.o  makefile  math  target
[root@VM_6_207_centos basics]# ./target
please enter two integer:
8
9
add(8,9) returns 17

The advantage of using makefile is, if you properly specify the dependencies, you don’t have to compile every source file in your project every time. But maintaining the dependencies manually is very tedious and error-prone, as the project grows larger and larger, even if you program is a clean modulization design. For example, suppose we want to add a multiply.cpp and multiply.h for the app being able to show the multiplication of two numbers, then we have to modify our makefile build our program. Morever, if the header file add.h is modified, the multiply.cpp don’t need to be re-compiled, thus we shoud add more code in the makefile the specify the dependencies between .cpp files and .h files. So now I guess you could see the motivation of writing a generic makefile automatically maintaining dependencies for us.

Build with Easymake

In this example, simply including the easymake.mk is enough. Now edit our makefile as below:

include ../../easymake.mk

Simply type make to build our program. And then I will show you more details so you could understand how our program is built.

[root@VM_6_207_centos basics]# ls
main.cpp  makefile  math
[root@VM_6_207_centos basics]# make
g++ -c -o bin/main.o main.cpp  -I.
entry detected
g++ -c -o bin/math/add.o math/add.cpp  -I.
g++ -o bin/target bin/main.o bin/math/add.o
BUILD_ROOT/TARGET: bin/target
ENTRY: main.cpp
[root@VM_6_207_centos basics]# ./bin/target
please enter two integer:
3
5
add(3,5) returns 8

You may have noticed that the main differences from previous examples is the entry detected, BUILD_ROOT/TARGET: bin/target and ENTRY: main.cpp in the output. The bin/target is our program. As for the entry, I will explain it later.

Take the look at our directory structure:

[root@VM_6_207_centos basics]# tree .
.
├── bin
│   ├── easymake_current_entry_file
│   ├── easymake_detected_entries
│   ├── easymake_entries_tmp.d
│   ├── main.d
│   ├── main.o
│   ├── math
│   │   ├── add.d
│   │   └── add.o
│   └── target
├── main.cpp
├── makefile
└── math
 ├── add.cpp
 └── add.h

3 directories, 12 files

Easymake use a folder bin as the BUILD_ROOT for generating code so that our source folder won’t be polluted. Those *.d and easymake_* files are generated by easymake to maintain the dependencies. The *.d file is makefile syntax, take a look at main.d for example:

[root@VM_6_207_centos basics]# cat bin/main.d
bin/main.o: main.cpp math/add.h

math/add.h:

These dependencies are auto generated by easy make, so every time the math/add.h is modified, It will caused the main.o to be re-generated. Actually you don’t need to understand all these issues in order to use easy make, so we should just ignore these extra-generated files. If you’re intrested, take a look at the source code in easymake.mk. I believe the code is well-commented and easy enough for understanding.

User Options

Suppose you want to build the program with gcc compiler’s -O2 optimization and linker’s -static options. Now you need to write a bit of codes the change the options. Here’s our new makefile:

COMPILE_FLAGS   += -O2
LINK_FLAGS      += -static

include ../../easymake.mk

Now rebuild the program:

[root@VM_6_207_centos basics]# make clean
rm -f \$(find bin -name \*.o)
rm -f \$(find bin -name \*.d)
rm -f \$(find bin -name \*.a)
rm -f \$(find bin -name \*.so)
rm -f \$(find bin -name \*.out)
rm -f bin/target
[root@VM_6_207_centos basics]# make
g++ -c -o bin/main.o main.cpp -O2  -I.
 entry detected
g++ -c -o bin/math/add.o math/add.cpp -O2  -I.
g++ -o bin/target bin/main.o bin/math/add.o  -static
BUILD_ROOT/TARGET: bin/target
ENTRY: main.cpp

Besides, there’re more options available to make easymake flexible. Try make help command and you will see them. Look at the informatin in the basic settings and user settings. The other parts is not necessary here.

[root@VM_6_207_centos basics]# make help
---------------------
basic settings:
SETTINGS_ROOT       : build_settings
BUILD_ROOT          : bin
TARGET              : target
VPATH               :
CPPEXT              : cpp
CEXT                : c
GCC                 : gcc
GXX                 : g++
LINKER              : g++
---------------------
user settings files:
build_settings/entry_list
build_settings/compile_flags
build_settings/compile_search_path
build_settings/link_flags
build_settings/link_search_path
---------------------
user settings:
ENTRY_LIST          :
ENTRY               :
COMPILE_FLAGS       : -O2
COMPILE_SEARCH_PATH :  .
LINK_FLAGS          : -static
LINK_SEARCH_PATH    :
CPPSOURCES          : main.cpp math/add.cpp
CSOURCES            :
---------------------
internal informations:
   ...
   ...
   ...

The Entry for Tests

Suppose we need to add a multiply function to the previous program. First we write a C++ function to do the multiplication, and then before we modify the main.cpp, we should test the multiplication function to make sure the new add module is OK. The following example shows you how to do this with easymake. You could find the source code in the folder samples/entries.

Write Multiply Module

File math/multiply.h:

#ifndef MULTIPLY_H
#define MULTIPLY_H

#include "stdint.h"

int64_t multiply(int32_t,int32_t);

#endif

File math/multiply.cpp:

#include "math/multiply.h"

int64_t multiply(int32_t a,int32_t b){
        return (int64_t)a*(int64_t)b;
}

Write Test Code

Type mkdir test and then vim test/multiply.cpp to write our test code. For simplicity, just print the result of 8 multiplied by 8 int the main function.

#include "math/multiply.h"

#include <iostream>

using namespace std;

int main(){
        cout<<"multiply(8,8)="<<multiply(8,8)<<endl;
}

Build Our Test

In this case, simply type make, and then ./bin/target you will see the output of our test code.

[root@VM_6_207_centos entries]# make
g++ -c -o bin/main.o main.cpp -O2  -I.
    entry detected
g++ -c -o bin/math/add.o math/add.cpp -O2  -I.
g++ -c -o bin/math/multiply.o math/multiply.cpp -O2  -I.
g++ -c -o bin/test/multiply.o test/multiply.cpp -O2  -I.
    entry detected
g++ -o bin/target bin/math/add.o bin/math/multiply.o bin/test/multiply.o  -static
BUILD_ROOT/TARGET: bin/target
ENTRY: test/multiply.cpp
[root@VM_6_207_centos entries]# ./bin/target
multiply(8,8)=64
[root@VM_6_207_centos entries]#

Notice that main.cpp and test/multiply.cpp are both properly compiled, but only test/multiply.cpp is linked into our target. The value of ENTRY has changed into test/multiply.cpp. With easymake, any source file with a main function will be automatically detected and considered as entry file. Among the entries, only one of them is picked by easymake and linked into the target. Note that an ENTRY dosen’t necessary need to have a main function and dosen’t even need to exist as a file, in some occations, building an so for example, this ENTRY is picked so that other entries won’t be linked into the target.

Now you must be wondering why? How did easymake decide to pick test/multiply.cpp rather than main.cpp? Behind the magic is the timestamps of the entry files. If there’s more than one entry and the user did’t specify which one to pick, The entry file with the newest timestamp will be picked by easymake automatically.

If you need to specify the ENTRY explicitly, pick main.cpp for example, use the command make ENTRY=main.cpp simply make ENTRY=m :

[root@VM_6_207_centos entries]# make ENTRY=main.cpp
g++ -o bin/target bin/main.o bin/math/add.o bin/math/multiply.o  -static
BUILD_ROOT/TARGET: bin/target
ENTRY: main.cpp

Now we’ve test our multiply module, We can Modify the main.cpp and glue the module into our program. The following step is omit here for abbreviation. You could look into the samples/entries folder if need to.

easymake's People

Contributors

roxma avatar

Watchers

James Cloos avatar George He avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.