The benefit of an IDE like Eclipse is: it makes working with projects very easy, as generates make files and it takes and automatically manages the make file(s). But sometimes this might not be what I want because I need greater flexibility and control, or I want to use the same make files for my continues integration and automated testing system. In that case a hand crafted make file is the way to go.
One thing does not exclude the other: This article explains how to use make files with Eclipse with similar comfort as the managed build system in Eclipse, but with the unlimited power of make files:
Outline
Eclipse comes with a built-in build system (managed make): I can configure the compiler linker settings, and Eclipse takes care about the rest. In this tutorial I’ll explain how I can create and use hand crafted make files with Eclipse. The proposed make file and template makes it easy to control the build system with make. The proposed approach requires that every new source file added to the project requires a extension of the make file, but the make file with auto-generate dependency files for all the included header files.
The benefit of using make files are:
- Easier to store and track in a version control system than the Eclipse .cproject files and settings
- Complete control of the build and make process
- Rather trivial to extend with other steps like working with a version control system or an automated test system as part of the build process
- Can use the same build (make) both inside the IDE and outside (e.g. on an automated build system)
- and writing make files is fun too 🙂
The make file approach requires understanding the build process, and for this it is helpful to understand what is used with the managed make, so I can use it as a base or inspiration.
Preconditions
To use make files in Eclipse, I need the following:
- Eclipse IDE. I’m using the NXP MCUXpresso IDE v10.0.2 (Neon based), but any other Eclipse distribution would do it too.
- Installed GNU toolchain with make utility. Usually this comes with a bundled Eclipse IDE or you can use a DIY toolchain.
- Compiler and linker settings for your target device. Use the options from an existing example project.
- Startup and linker files. Here again you can borrow from an existing example project.
- Application source files. I recommend to start with an ’empty’ main first.
A good way to get the necessary files and options is to look at an existing example project which usually is using ‘manged make’.
💡 I have put the sources of this project on GitHub. Check the link to the GitHub project in the Links section at the end of this article.
Coming from Eclipse Managed Make
With the managed make system, Eclipse detects the files present in the project (e.g. *.c) and generates the make files automatically:
This generates make files:
With a build tool integration, I have a GUI where I can set the options for the tools:
All this information gets added to the make files, and if I do a build, it calls the make utility (or builder) to build it with all the necessary command lines. I can can see what it does with checking the console view output:
With this, I should have everything to make a make file project.
Creating Make File Project
I’m creating a new make file project in Eclipse with the menu File > New Project:
As with many things in Eclipse, there are multiple ways to do things.
If I have existing code I want to add, I can use the ‘Makefile Project with Existing Code’. Then I can give a name and an existing code location (folder). It will then create the project inside that code location folder and add all the source files to the project:
The generic way is to generate a C or C++ project:
Then give the project a name and select an empty make file project with the supported toolchain:
Then press ‘Next’ and go through the remaining dialogs depending on the selected toolchain. This creates an empty project like this:
Application File
To have something to compile, add a new source file:
Name it main.c or whatever you like:
Then add a main() routine with some code, e.g.
static int i; void main(void) { for(;;) { i++; } /* do not leave main() */ }Makefile
Next, use the context menu New > File on the project folder:
Create a file named ‘makefile’ in the project:
This adds an empty make file.
CMSIS, System Files and Startup
The next step heavily depends on the device used. I’m using in this example the NXP FRDM-KL25Z board. To structure things, I have created directories for the sources. The special ‘debug‘ folder will be used to place the object and executable files.
Make File Syntax
The next step is to implement the make file content. A generic make file looks like this:
all: hello.axf clean: rm main.o hello.axf hello.axf: main.o gcc -g -o hello main.o main.o: gcc -c -g main.cEach entry in the make file has the following syntax:
<target>: <list of dependencies> <tab>Commands to execute💡 Note that there needs to be a <TAB> character in front of each command!
There are two special targets named all an clean. ‘clean’ is used to delete all temporary files, and ‘all’ is used to build the application.
Makefile Content
In the makefile I define variables for deleting files, the compiler and the linker:
############################ # Command for removing files RM := rm -rf ############################ # Compiler CC := arm-none-eabi-gcc ############################ # Linker LL := arm-none-eabi-gccThen I define a macro for the final executable I want to make:
############################ # Binary/exectable to build EXE := \ ./debug/MyMakeProject.axfNext a list of all object files. Because the object files will be placed in the ‘debug’ folder, this is part of the name:
############################ # List of object files OBJS := \ ./debug/main.o \ ./debug/startup_MKL25Z4.o \ ./debug/system_MKL25Z4.oThe next thing is something really cool. If main.c includes the header file main.h, I would have to write a rule like
main.o: main.c main.h $(CC) -c main.c -o main.oBut this is very painful: I have to write the rule for each file and need to keep track of the header files. Instead, I let the compiler create dependency files later below with extension .d (for dependency). The dependency file main.d looks like this:
debug/main.o debug/main.d: source/main.c source/main.h source/main.h:I’m including the files as additional rule files if it is not the ‘clean’ target:
############################ # Include generated dependcy files (only if not clean target) ifneq ($(MAKECMDGOALS),clean) ifneq ($(strip $(C_DEPS)),) -include $(C_DEPS) endif endifThe following is the set of compiler options which I can use later:
############################ # Compiler options CC_OPTIONS := -c -std=gnu99 -O0 -g -ffunction-sections -fdata-sections -fno-builtin -mcpu=cortex-m0plus -mthumb -DCPU_MKL25Z128VLK4 -D__USE_CMSIS -I"CMSIS" -I"source"Similar, the options for the linker:
############################ # Linker Options LL_OPTIONS := -nostdlib -Xlinker -Map="debug/MyMakeProject.map" -Xlinker --gc-sections -Xlinker -print-memory-usage -mcpu=cortex-m0plus -mthumb -T linkerfile.ld -o $(EXE)Next the target to build the application:
############################ # Main (all) target all: $(EXE) @echo "*** finished building ***"Followed by the target to do a ‘clean’:
############################ # Clean target clean: -$(RM) $(EXECUTABLES) $(OBJS) $(EXE) -$(RM) ./debug/*.map -@echo ' 'Below is the rule to link the application with all the object files:
############################ # Rule to link the executable $(EXE): $(OBJS) $(USER_OBJS) linkerfile.ld @echo 'Building target: $@' @echo 'Invoking: Linker' arm-none-eabi-gcc $(LL_OPTIONS) $(OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' 'Next, I specify rules to build the object files. I have to specify a rule for each subfolder I’m going to use:
############################ # Rule to build the files in the source folder ./debug/%.o: ./source/%.c @echo 'Building file:lt;' $(CC) $(CC_OPTIONS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -MT"$(@:%.o=%.d)" -o "$@" "lt;" @echo 'Finished building:lt;' @echo ' ' ############################ # Rule to build the files in the CMSIS folder ./debug/%.o: ./CMSIS/%.c @echo 'Building file:lt;' $(CC) $(CC_OPTIONS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -MT"$(@:%.o=%.d)" -o "$@" "lt;" @echo 'Finished building:lt;' @echo ' '💡 The option -MMD -MP -MF”$(@:%.o=%.d)” -MT”$(@:%.o=%.o)” is generating the dependency .d file for each source file compiled.
Make Build Targets
To build the project, the usual ‘make/build’ and ‘clean’ menu/commands in Eclipse can be used. But there is another cool way: Build targets!
For this, open the Build Targets view (menu Windows > Show Views > Other):
In that view, select the project and click the ‘New Build Target’ button:
Create a target for ‘clean’:
This adds a ‘Build Targets’ group to the project. Use the context menu to add a new target for ‘all’:
With this, I can double-click or use the context menu to execute a target in the makefile :-).
Summary
Managed make and build in Eclipse is a great feature: it is simple and easy to use, and probably the right thing for 98% of the use cases with an IDE like Eclipse. But if I want to use normal make files with Eclipse, this is not hard. With the proposed make file template I have to extend the list of files if new sources get added to the project. Otherwise everything is taken care of. Writing make files requires a learning phase, but this can be a well invested effort.
Happy Making 🙂
Links
- Project and files of this article on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/FRDM-KL25Z/MyMakeProject
- Make file tutorial: https://mcuoneclipse.com/2012/02/13/make-my-make-with-eclipse-and-mcu10/
- GNU Make: https://www.gnu.org/software/make/
- http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
- http://wanderinghorse.net/computing/make/
Thanks Erich. I just need this tutorial. 🙂
LikeLike
you are welcome 🙂
LikeLike
Hi Erich: I have followed this tutorial as closely as I could, but I cannot generate the MK files that are shown in your third diagram. I have the “makefile” to start with, but I need to generate an MK tree to be useable in Wiced Studio. Can you help? How do I convert Unix Makefile system into Wiced-Eclipse MK build system? I have been searching for a solution for a couple of weeks now, and your example is the first one that has given me hope that it may be possible. Thanks, Garry.
LikeLike
Nice tutorial. I love using makefiles for build automation, I don’t know if its the same in Windows, but I usually do the build based on the project directories, just fetch all .c files in there and .s files and automatically build all of them. make provides some useful features for this sort of thing. You can also specify the source directories directly as variables, and fetch all the files inside those directories with something like C_SRCS := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c)) where SRC_DIRS is a list of directories with source files. That way you could even automate populating the SRC_DIRS list based on the project root directory if need be. For the list of object files: C_OBJS := $(patsubst %.c,$(OBJ_FOLDER)%.o,$(notdir $(C_SRCS))) where OBJ_FOLDER is some sort of build directory if you don’t want to make your source folder dirty. Cleaning the project is usually reduced down to deleting that build directory. You can have a look at my makefile here: https://github.com/Muriukidavid/twr-k60n512_2017/blob/master/Makefile .
It might a little too much for a beginner, but I have learned that a great makefile is generic enough to be reused across projects with minimal changes. And yes, when it comes to version control, and of course sharing your code to the world on the Internet, makefiles are much better than IDE files like, .cproject files. Anything parametric rocks!! Thats why I love me some OpenSCAD for 3D modeling as well. Git and share the .scad files, let everyone change the code and render the models on their computers. How I wish every model on thingiverse.com was a .scad file…
LikeLike
Great input! I have tried OpenSCAD and I love it, but simply had not enough time to deal with it, that’s why I’m still doing my 3D models with Autodesk 123Design :-(.
LikeLike
Thanks again for all you do, Erich!
LikeLike
Pingback: Building Eclipse and MCUXpresso IDE Projects from the Command Line | MCU on Eclipse
Pingback: Tutorial: Porting BLE+NRF Kinetis Design Studio Project to MCUXpresso IDE | MCU on Eclipse
Pingback: Managing Project and Library Dependencies with Eclipse CDT | MCU on Eclipse
Hi Eric,
Do you know if it’s possible to have the makefile in another folder than where the project is saved/created and the makefile to use relative paths?
The folder structure looks something like this (it’s a bit more complex, actually):
root/
/sources
/projects/my_project_1/.cproject
/lvl1/lvl2/lvl3/makefile
So technically, what I would like to achieve is to be able to both do a “make” in the shell and compile the Eclipse project.
So far I’ve found out that the Build command (in the Builder Settings) does not manage well the relative paths used by the makefile, and I couldn’t pass this point.
Best regards!
LikeLike
I have not used such a structure. But I think you face a problem with the ‘current directory’ if using relative paths. Using Eclipse with the GNU MCU Eclipse plugins, the current directory for the compiler/make/etc is the ‘output’ folder which is usually named ‘Debug’ or ‘Release’, so this is the base for your relative path settings. If using make outside of Eclipse, you need to make sure that the current path is the same, otherwise your relative paths won’t point to the correct location?
LikeLike
Great tutorial(s)! However, one thing that has been bothering me on several occasions, is integrating Eclipse with embedded makefile projects and version control. If you have any pointers on this that would be very much appreciated. For example:
– I want to clone a project from git (or other vcs, or simply unzip a project tree), and -quickly- start working on it from Eclipse, with -all- settings (external build, launchers, indexer settings, etc.) readily available.
– Similar when cloning the project a second time to a different directory (e.g. working on a different branch in parallel) -> new Eclipse instance to work on that, in different virtual desktop for example.
I have never been able to figure this out properly; which files to check in to version control (.project, .cproject, but this doesn’t seem to be enough) to have -all- project settings shared and available.
Setting it up once works fine (long list of indexer include paths), but I don’t like doing this multiple times. It’s still not clear to me if Eclipse properly supports this or not. Project settings should (all) be part of the checked-in project in my opinion.
LikeLike
Great suggestion, and writing something about this has been on my plate for a longer time. I see how soon I can do this, but right now I’m swamped with getting the new university semester started.
LikeLike
To follow up: I have published a tutorial on this subject here: https://mcuoneclipse.com/2018/09/30/tutorial-git-with-eclipse/
I hope this helps,
Erich
LikeLike
Hello Erich,
what if i have more than 100 .cpp files in my project? should i add every .cpp to the Makefile and build .o files?
Best regards,
Hani
LikeLike
Hi Hani,
if you write your make file by hand: yes.
Or you can consider something as https://github.com/Melinysh/PyMake
I hope this helps,
Erich
LikeLike
Pingback: Building and Flashing ESP32 Applications with Eclipse | MCU on Eclipse
Since an Eclipse-Managed Make generates the make files automatically, is it possible to call “make” from a command line to build a project with a managed make? If not, why not?
LikeLike
sure, that works:
make -f makefile all
for example.
LikeLike
Hi Erich: I have followed this tutorial as closely as I could, but I cannot generate the MK files that are shown in your third diagram. Thus, I am stuck. I have the Unix “makefile” tree to start with, but I need to generate an MK tree to be usable in Wiced Studio (Eclipse shell that uses MK tree). Can you help? How do I convert Unix Makefile system into Wiced-Eclipse MK build system? I have been searching for a solution for a couple of weeks now, and your example is the first one that has given me hope that it may be possible. Thanks, Garry.
Your article: https://mcuoneclipse.com/2017/07/22/tutorial-makefile-projects-with-eclipse/comment-page-1/?unapproved=213016&moderation-hash=34ff6b30aeab7937e5e030049af887f4#comment-213016
LikeLike
Hi Garry,
the makes files in the third image (https://mcuoneclipse.files.wordpress.com/2017/07/generated-make-files.jpg) are generated by Eclipse for an ‘automake’ project.
So this should be generated by default for new projects in WICED if you create a new project. Converting a Unix make file system works as long as you stay on the same host system (switching between Windows and Unix is a challenge because of the paths and drive letters on Windows).
If you have an existing and working make file system, you should be able to just build it from the command line.
Then basically point to the make file from the eclipse project as in this article here. So make sure you can build things from the command line first to find any issues (e.g. path or tool settings).
I hope this helps,
Erich
LikeLike
Hi Erich:
Thank you for your reply.
I will try this again, but I think something is not right.
I start with a cmake project that works fine with VS2017 driven by CMakeFiles.txt
Then, I generate Unix Makefiles with -G “Eclipse CDT4 – Unix Makefiles”, and I get “makefile” in correct locations where the CMakeFiles.txt are located.
Then, I create New “Makefile Project from Existing Code” and I get the new project created.
Then, I select project properties, but the makefile generation box is grey (disabled).
So, I cannot generate MK file system from new project that has makefiles.
What am I missing?
Thanks, Garry.
LikeLike
If you create in Eclipse a project with “Makefile Project from Existing Code”, then it means that you have to supply the make file, it will not be an automake project (make files generated).
So you have either a ‘automakefile project’ where Eclipse is doing all the work for you, or if you create a makefile project then you are responsible for the make files.
In any case it is a make file project, but the difference is who is maintaining it (you or Eclipse).
I hope this makes it clear?
LikeLike
Hi Erich:
Thank you for that explanation.
What is the difference between a generated Unix Makefile, and an “MK” file as used by Wiced?
Can I simply rename all the “makefile” to “makefile.MK” and expect it to work?
There are dozens of these makefiles in many sub-directories, so renaming is a lot of work, but I will do it if you think it might work.
For example, in file “scan.mk” (from a Wiced project) there are two effective lines:
NAME := App_Scan
$(NAME)_SOURCES := scan.c
I understand these two lines in MK, but nowhere in the Unix Makefile can I find any direct reference to the C source files to be compiled. The conditionals with .o and .s are there, but no .c
To me it looks like two different systems. Also, I cannot find the := assignment in the Unix Makefiles.
What I think I need is some way to have the cmake -G “Eclipse CDT4 – Unix Makefiles” generator create MK format directly, so I tried the different generators for MinGW, Ninja, NMake, but none of them creates the same style as the Wiced-Eclipse MK file format. Is there such a thing?
Any comments would be much appreciated.
Thanks, Garry.
LikeLike
Hi Garry,
I admit I have not used WICED recently (would need to re-install it, my notebook disk was running out of space).
Simply renaming make files is not a guarantee that it will work. It might work, but it all depends.
First there are different versions of make files (depending on the version of make utility), but the general basic syntax should always work.
Not sure what you mean with ‘Unix make files’: the difference would be how files are used/referenced (drive letters, forward vs. backward slashes, etc).
I doubt about an approach to ‘create Wiced-Ecliopse MK file format’: simply use ‘normal’ make files and treat it as such: you won’t be able to mimik the auto-generated make files in an easy way, unless you write your own generator?
LikeLike
Hi Erich:
Thanks for your reply. I am okay working with Wiced so you don’t need to install that program. I just need to get Eclipse to create an MK file.
I am now starting from scratch, creating a new project with only two files “main.c” and “stub.c”
I have used the following steps in Eclipse:
File – New – Project – C Project
Next
Makefile project – Empty Project – MinGW GCC – Project Name – Location (not default)
Next
create two new C files in “src” folder
Of course I could not compile these files because there is no makefile or MK file.
Now, please suggest how to create MK file as shown in your sample.
I think I made a “wrong turn” somewhere in this new project creation.
Thank you for your help.
Garry.
LikeLike
Hi Garry,
see https://mcuoneclipse.com/2012/02/13/make-my-make-with-eclipse-and-mcu10/ for a tutorial about creating a make file.
Erich
LikeLike
Hi Erich:
Thank you for the link to the makefile tutorial. I am working through that now.
BUT, in the third image that we are discussing, who created the “sources.mk”, “objects.mk”, and “subdir.mk” files. Also, who created the “makefile”?
Did you create all of these “MK” files by yourself, did Eclipse generate some of them? Was the “makefile” used by Eclipse to generate the “MK” files?
I presume you started with the “makefile” then Eclipse created the three MK files, which I what I am trying to do, but I am getting very confused at the moment.
Thanks for you help.
Garry.
LikeLike
Hi Garry,
the extension of the files (.mk, .mak, .MK) really does not matter. You are free to name the files the way you like, but usually the top make file is named ‘makefile’.
The make files in https://mcuoneclipse.files.wordpress.com/2017/07/generated-make-files.jpg are all generated by Eclipse.
The make file in https://mcuoneclipse.files.wordpress.com/2017/07/extended-project-structure.png is one generated by hand.
You are free to organize the make files and the names as you want, but as a starter just have one file and name it makefile.
LikeLike
Hi Erich:
Can you help me find these so-called “global variables”, as created by cmake Generator to get from CMakeLists.txt to Unix makefile. Here is my situation:
I have reached an impasse with the cmake Generator related to the manner in which the cmake Generator handles a couple of include directories from the original CMakeLists.txt. There are two lines involved that are not directly created in the generated makefile:
From the source file CMakeLists.txt we have:
259 include_directories(${MACRO_UTILS_INC_FOLDER})
260 include_directories(${UMOCK_C_INC_FOLDER})
It seems like the cmake Generator does not directly create corresponding include directory statements in the generated makefile, but instead, puts a statement in a generated readme.md file as follows:
The project will export a *global variable* MACRO_UTILS_INC_FOLDER that points to the folder needed to be included so that `#include “azure_macro_utils/macro_utils.h”` resolves properly.
The same applies to the UMOCK_C_INC_FOLDER, and thus is creating build errors.
Unfortunately, there are no clues given as to where these exported *global variables* are hidden. They are not in Windows Environment Variables, which I thought would make sense for command-line operation, so the mystery is to find these hidden global variables then include them (somehow) during the *make* makefile command-line operation.
At this point, I am stuck in my work.
I would appreciate any suggestions Thank you, Garry Anderson.
Attached files for your reference: CMakeLists.txt (source), readme.md (generated), makefile (generated)
LikeLike
Hi Garry,
I have mixed feelings about such generators. I believe you have to devfine these variables on the command line passed to cmake.
Another thought is: maybe it would be easier for you if you write the make file instead using a generator/converter?
Erich
PS: there were no files attached
LikeLike
Hi Erich: I previously attached two files, but they did not get through. Perhaps we could continue with regular email that delivers attachments correctly. Please let me know your email address. I do not use Twitter, Facebook, or any other social media. I only use regular email. Thank you, Garry.
LikeLike
Hi Gary,
you find my contact details on https://mcuoneclipse.com/about/
LikeLike
Hi Erich: I think I have reduced my question to one simple question: “What statement/syntax/command do I put in a makefile to make it include a folder, which is searched for finding other H files during make?” There must be some way to tell “make” which folders to search during the build process. “Cmake” has it, so “make” should also have it. Download attachments from here: https://files.secureserver.net/0sARqmkldheM4B
Thanks, Garry Anderson.
LikeLike
Standard make does not support this to my knowledge.
LikeLike