C Writing Makefile

Hello guys,

If somebody of you has a small time can assist me please to understand the basic basic basic writing makefile methods ?

Articles, books and tips are welcome. I've already gave a look at some of them.

Obviously it is not easy write makefile. My apologize in advance for my basic question.

Because It's not clear the "starting point", please, can you show in which a way the makefile of the following two cases should be written ?

____________________________________________________________________________
FIRST (The famous "Hello world" program - single file).

C++:
#include <stdio.h>
int main (void)
{
            printf ("Hello GCC!\n");

             return 0;
}

________________________________________________________________________
SECOND (Multiple source files) .

File: main.c
C++:
#include "hello.h"

int main (void)
{
    hello ("world");

    return 0;
}


File: function_hello.c
C++:
#include <stdio.h>
#include "hello.h"

void hello (const char * name)
{
    printf ("Hello, %s!\n", name);
}


File: hello.h
Code:
void hello (const char * name);

__________________________________________________________________________

Thanks very much in advance for you time.
 
This should not be more than two lines.
Makefile:
Code:
main : main.c function_hello.c hello.h
<tab>cc main.c function_hello.c -o main

That <tab> character is important.
 
Weeks or months later when you want to move up to cmake (which builds upon make) ...

CMakeLists.txt:
Code:
cmake_minimum_required(VERSION 3.0)
project(main C)
add_executable(main main.c function_hello.c)
link_directories(/usr/lib /usr/local/lib)
target_link_libraries(main)
 
BSD make differs significantly from GNU make
This should not be more than two lines.


Yes I heard about this difference.

I'm using the FreeBSD clang/clang++ compiler, so I think it is the BSD make (that is, the same 'make' I use when for example I compile the FreeBSD ports: 'make install clean').
Is it right ?


I've understood that writing makefile automates the sequence of compilation commands when the code begins complex and shared among more people of a development equipe.

I think that a makefile follows a structured sintax to realize the sequence of compilation commands.

Are there tutorials (well written) showing step-by-step how to write it, considering basic cases (like unitrunker has shown) to the more complex ones ?



Thanks in advance.
 
I created a template here for when I start non-cmake based projects:
https://github.com/osen/depends

It is not the simplest example though which is annoying because the idea of Makefiles is in theory, really nice and simple.

Unfortunately in practice Makefiles are fine but when it comes to incremental builds or rebuilding if a header has changed, then they become a little bit too complex to make it worthwhile.

I highly recommend cmake unless you are working with something non-standard or cross compilers such as Emscripten, Android NDK or multiple languages.

In general, my template will generate dependencies (via depends.sh) after each build of an object file (in a dumb but good enough and 100% portable way). The main Makefile basically just uses the generated dependency file to know what needs to be rebuilt if a header changes. Then the projects themselves are in the mk folder to demonstrate generating an executable or a library.

Its not great. It is actually pretty ugly but I find it really powerful being able to manually call things like `wx-config` or `pkg-config` within a Makefile. I feel that this is something that CMake or (ugh) GNU Autotools has lost along the way.
 
Make (in all its flavors, whether it be gmake, nmake or BSD make) is pretty horrible. Always has be. Making make file that completely capture all dependencies is hard; making them update automatically is even harder. And making multi-platform make files (which work on different OSes, and with different make implementations) is nearly impossible. For small projects (<100 source files), I've managed to do that (and it works with traditional make and GNU make, on Linux / *BSD / MacOS / AIX), but it is a lot of work, and error prone.

You might want to not even bother learning make, because today there are several much better build systems. I've played a little with Maven and Gradle, and for simple projects they are nice, and I never had the patience to test them on large systems (they probably would become horrible very qiuckly). Recently, there is a new thing, namely Bazel. If your development workflow (no branches, single uniform repository) fits into the Bazel model, it is much nicer than all the other options. I would recommend that you try it.
 
I will respectfully disagree with ralphbsz. Make is wonderfully efficient and portable. Once you start using incompatible extensions (like automake or built ins) then you've painted yourself into a corner. I referenced cmake because all cmake does is generate makefiles. Make does the real work. I do wish more projects used flat makefiles but I'll take a cmake build over autoconf any day.

For small projects, make is all you need.
 
Writing Makefiles has always been a daunting task for me. Note that I only write code as a "hobby".
When the project starts to grow directories and dependencies, I have always been "challenged".

I found that the sndio project (OpenBSD audio server: http://www.sndio.org/) has nice Makefiles (pick sndioctl for example) that helped me a lot clean the mess I used to have.
I tried to read in order to understand the inside-out of the ports infrastructure but that was to much to chew. I suggest you pick a well written project you like and read the Makefiles.

I agree with unitrunker.
I tried to port my android project from Ant to Gradle. Failure. I can't figure what does what (does it need an internet connexion?!).
I guess if you can't deal with make, I am not sure you will be able to deal with Gradle. I know I can't.
 
I tried to port my android project from Ant to Gradle. Failure. I can't figure what does what (does it need an internet connexion?!).
I guess if you can't deal with make, I am not sure you will be able to deal with Gradle. I know I can't.

Haha, yes, I agree. It seems that the android build system now using Gradle means it spends most of its time pissing around doing seemingly random things rather than actually building *my* software ;)

In my experience, most java-centric build systems are terribly over-engineered and sloppy. Even ant where the build scripts needed to be written using XML was... incorrect. Most of the times when I see a bit of software I have to build myself and it is in Java, I just look for a C/C++ alternative purely because of the build system. Arguably Java is an "easier" language but I honestly cannot be bothered with the build system baggage that comes with it.

Android in particular *is* one system when I use Makefiles. I cannot seem to find a build system that allows for an easy integration of the NDK / clang cross compiler and the Java stuff. CMake is supported but it seems needlessly complex because it has to integrate with gradle :(

This sample makes so much more sense (https://github.com/czak/handbuilt-android-project). Yes it is complex and android specific but you actually know what is going on behind the curtain (and doesn't require a sodding internet connection).

I did come across quite a good cmake android project which basically just used Makefile-like rules to build the software. Unfortunately I cannot find it. The pure Makefile one was better anyway.
 
kpedersen
Glad that I am not alone.
Since my Android app is on f-droid, I need to follow their directives. I am not sure what is possible though. Android Studio abstract the complexity of Gradle I guess. But I don't use Android Studio so ...
 
Back
Top