Is a makefile really needed

I have been programming in c/c++ for a while now, and I have never once used a makefile. I know that it is supposed to be useful when you are dealing with a large project, but I have always been able to compile, build and execute my program using only

gcc main.c -o run

and if I am working with an external library (gtk+, for example) I make a simple bash script that looks like:

#!/bin/bash
echo compiling....
gcc main.c `pkg-config --cflags --libs gtk+-3.0` -o run

So what I’m asking is do I need to learn how to make a makefile?

2

First, a Makefile for make is really useful when you build a program from several translation units (i.e. several *.c or *.cc files which are #include-ing some other header files) which are linked together (it is not very useful for a single source file tiny program). It organizes the various compilation steps of the translation units (and avoid running useless compilations again). See also this answer to a related question.

During the debugging phase, compile with all warnings and debug info (e.g. gcc -Wall -Wextra -g for C code compiled by GCC…) and learn how to use your debugger, e.g. GDB and memory leak detectors like valgrind…. Be scared of undefined behavior. With a recent GCC 5 compiler (at end of 2015), you may also want to use (occasionally) various -fsanitize= debugging options. Have some good testing procedures. For production and benchmarking, ask for compiler optimizations (e.g. add -march=native -O2 to your GCC compiler flags). For C++11 code, replace gcc with g++ -std=c++11; in your GNU Makefile, use CC & CFLAGS variables for C and CXX & CXXFLAGS for C++.

As soon as you are writing some not-tiny program in C or C++ (e.g. more than ten thousand lines of source code), you’ll want to organize it in several translation units (at least to avoiding very long build times while working on it, and preferably to group together related code or features). Notice that with C++ the usual included header files are themselves quite big, so having tiny translation units slows the overall build process.

The size, organization, name, and purpose of a translation unit (i.e. of a foo.c or bar.cc file) is a matter of habits and conventional. Some people prefer having many tiny files (of a few dozen lines). I like having source files of several thousand lines. The recent version of GCC compiler, and the recent Linux kernel have dozens of human-written C or C++ source files bigger than ten thousand lines. Both are quite large software (many millions of source lines)

Then, you could build such a program using some other builder (like omake or scons, or ninja etc…), or even using a shell script (BTW, the GNU make distribution contains a shell script to build it on systems without any make yet!).

But yes, I believe you should learn GNU make (and you may even want to take advantage of recent GNU make features, e.g. Guile scriptability). Here is an example of Makefile, and another one.

Notice that for historical reasons the tab character is significant for make, so you need a specific mode in your editor.

In many cases, e.g. for configuration reasons, the Makefile is generated (e.g. with autoconf or cmake).

In several cases some *.c files or some header *.h included by them are generated by other programs (like SWIG, GNU bison, etc…)

You should look into the source code of several free software programs (e.g. GNU make itself! See also sourceforge, github, etc… to find some) and try building them. That would teach you a lot.

So you don’t need make (or some other builder) yet, just because your programs are very tiny. As soon as they will grow, you’ll need some building process. Notice that large programs (a web browser, an optimizing compiler, an OS kernel) have often many millions lines of source code organized in at least hundreds of translation units, and often have some generated C/C++ code (by some script in awk, python, guile, etc…, or a specialized program itself coded in C++, or an external generator like ANTLR or gperf) for application-specific metaprogramming or aspect-oriented programming purposes.

PS. Some other programming languages (Ocaml, Haskell, Go, SML, …) know about modules and have very different builders.

10

If you use a modern IDE(*) you will probably never have to look at a makefile in your life, even though the IDE generally will generate one for you on the fly.

Makefiles were a needed skill when I started out 30+ years ago. I rarely see them nowadays (and, if you do need one, there are makefile generators).

In short, don’t learn a skill until you need it, or can anticipate needing it. Use the timer saved by not learning makefile to learn something else which will make you a better developer.


(*) and if you are not, you are missing out on a ton of helpful features, like code completion (often with pop up documentation of the completions), code navigation, integrated debugger, integrated unit test, GUI designers, refactoring, et al

4

Do you have a specific need for make?

Tools like make are all about automation – being able to repeat a process flawlessly, time after time, as efficiently as possible. Check out this thread on github regarding a JavaScript development framework and the potential choice of using make as the build tool:

https://github.com/ericelliott/cloverfield/issues/2#issuecomment-68798159

Whatever tool you choose, you should use it because you have a particular purpose in mind, not because you “should be doing it”. You’ll see in the github thread that the tooling discussion centers on identifying and meeting specific criteria that the developers want in a task runner.

Other answers in the thread suggest reasons to use make with C programming. Do those benefits sound like things you need?

If you choose to use make, I agree with SHiNKiROU, learn make yourself before you use tools to build Makefiles. I learned a little bit of make during the github discussion, and it was very enlightening.

Checkout the section on make in The Art of Unix Programming. It explains the motivation behind make and why we have tools that generate Makefiles.

To summarize, the creator of make had a time when he wasted time debugging a working program because he forgot to manually recompile an object code. Make is an automated tool that determines what files need to be recompiled based on timestamps and the dependencies between files. Make is crucial for multi-file projects. You need to learn how to write Makefile in order to declare the dependencies between the files. I recommend you to write medium-sized, manageable Makefiles before learning how to use tools that generate Makefiles.

Don’t forget about GCC option “-MMD” and the line “-include *.d” at the end of your Makefiles. This option tells GCC to also generate an additional .d file for each compilation unit. This file contains a single line of text, in Make compatible syntax. It specifies additional dependencies for a make target based on any local includes in the source. The reason for this is because .c files can include other files. Without this, make generally won’t know what other files (like header files) are depended on by a given .c file. Therefore, if you update a header file in your project, make will not automatically rebuild the .c files that include it. This can lead to strange bugs during development, especially if a function prototype changes. This solves that problem.

I’ve been getting into the habit of using Makefiles more and more in my projects.

It automates parameters like CFLAGS and LDFLAGS, which, in my experience, on most non-trivial programs, quickly balloon. Maybe it’s just me who likes to use a lot of fancy compiler options and tweeks. “-fno-zero-initialized-in-bss” anyone? I’m sure the embedded devs can relate to working around compiler magic.

Make and other build system tools allow for platform specific configuration that can be more painful to do in source code. Some people might argue about this and how to do it, but the options are there and you can pass pre-processors definitions to your source code based on the selected configuration.

Since your Makefiles describe the build dependency graph of your project you can easily parallelize the build. You just have to use the -j option. Keep in mind, however, it is easy to incorrectly specify these dependencies in your Makefile and break your build so I encourage you to test this whenever you change your Makefiles and write your Makefiles with build dependency orders in mind. Do not just write multiple tasks in a recipes and assume they will always execute in the same order.

Make will detect what has changed and only rebuild what is needed based on the dependency graph. This becomes more important when you have a large project that takes a long time to build and you want to test small changes to a specific subsystem. In the project that I am working on now, it is getting to the size where build times are becomes slower than I’d like for quickly rebuilding everything. This feature will allow me to build everything once and then just rebuild what I change as I modify source files.

Portability. I have been developing for Linux, Windows, and MacOS. MinGW contains a port of the make program for Windows. Put that in the path and run your Makefiles anywhere.

When I first started, I was writing build scripts too. One issue that I ran into is that build scripts do not, by default, echo your commands. This makes it harder to validate that it is running what you expect (such as the correct CFLAGS) and see what command caused what errors/warnings/output. Also, if a build command fails, you will probably want your script to stop execution. This means that you need to include ” || exit 1″ or check the exit code of all commands with if statements in bash. There are ways to set bash to echo commands and die on a command that returned a non-zero exit code. Eventually, however, it starts to feel like you are recreating make in a script.

For better or worse, make is a standard tool. Using it in your project will allow people familiar with the prevailing workflow to more easily download and build your software without having to read your manual or worse, try to to read through your custom build system to figure out how to use it to build for their own purposes. I don’t like to tell people how to do their stuff and ultimately it is your decision. There are plenty of things that I disagree with in the current *nix infrastructure. That being said, with such flexibility in your naming and build system, I would suggest that you don’t deviate too much from standard convention if not needed. I have been on the other side of trying to build software, maybe trying to do static builds for initramfs or something, and fighting with someone software that is using some custom build system that doesn’t accept the custom flags or doesn’t give me standard options. Following standard convention and tools will also allow people to more easily understand and contribute to your code.

To conclude, it depends on what works for you and your projects. Build scripts used to be the way to build software. Is all the stuff I mentioned so important or needed? Could it be implemented in a script? Probably not always and yes it could. I think once you learn how to write Makefiles and have a standard Makefile template that works well, reinventing that wheel in a build script becomes less appealing.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật