Makefile for building multiple applications linking a previous built library - c

I think to organize my project as follows:
my_project
|--src
|--include
|--test
The core files reside in the directories src and include, whereas the different test applications of the core are within test directory (multiple *.c containing each a main() function). The core should be build as static library which will be linked to all applications).
How to write a basic Makefile to match these requirements? I already googled and found the following website providing a Makefile template for building an executable 1 . How can this Makefile be extended for my needs?
If you think my project organization is bad or you have a better idea, let me know!
Any help is appreciated!
Thanks, Jonas

You haven't said where you want the library to go, so I'll assume it should go into src/ where the objects already go.
src/libcore.a: $(OBJECTS)
$(AR) -cvq $# $^
It looks as if the makefile you have will build test/testfoo.o from test/testfoo.c so I'll assume that that works. And you haven't said where you want the executable tests (e.g. testfoo) to go, so I'll put them in test/.
test/%: test/%.o src/libcore.a
$(CC) -o $# $< -Lsrc -lcore
EDIT:
If you want Make to build all of the tests by default, then you should have this before any other rule in the makefile:
TESTS := $(patsubst %.c,%,$(wildcard test/*.c))
all: $(TESTS)

There is a small project called dotmk which turns the creation of a Makefile very easy.
Here is the link:
https://github.com/swrh/dotmk
You just have to run the install script and create the Makefile like the examples

my Makefile now looks as follows:
SHELL = /bin/sh
CC = gcc
AR = ar
CFLAGS = -std=gnu99 -Iinclude -pedantic -Wall -Wextra -march=native -ggdb3
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
PROFILEFLAGS = -pg
ARFLAGS = -cvq
# core and test common includes
COMMON_INC = include/definitions.h include/debug.h
# core stuff
CORE_LIB = lib/libcore.a
CORE_SRC = $(shell echo src/*.c)
CORE_INC = $(shell echo include/*.h)
CORE_OBJ = $(CORE_SRC:.c=.o)
CORE_PUB_INC =
# test stuff
TEST_SERVER = test/server/server
TEST_SERVER_SRC = $(shell echo test/server/*.c)
TEST_SERVER_INC = $(shell echo test/server/*.h)
TEST_SERVER_OBJ = $(TEST_SERVER_SRC:.c=.o)
TEST_CLIENT = test/client/client
TEST_CLIENT_SRC = $(shell echo test/client/*.c)
TEST_CLIENT_INC = $(shell echo test/client/*.h)
TEST_CLIENT_OBJ = $(TEST_CLIENT_SRC:.c=.o)
all: $(CORE_LIB) $(TEST_SERVER) $(TEST_CLIENT)
core: $(CORE_LIB)
server: core $(TEST_SERVER)
client: core $(TEST_CLIENT)
$(CORE_LIB): $(CORE_OBJ)
$(AR) -cvq $# $^
$(TEST_SERVER): $(TEST_SERVER_OBJ)
$(CC) $(CFLAGS) -o $# $< -Llib -lcore
$(TEST_CLIENT): $(TEST_CLIENT_OBJ)
$(CC) $(CFLAGS) -o $# $< -Llib -lcore
debug: CFLAGS += $(DEBUGFLAGS)
debug: all
profile: CFLAGS += $(PROFILEFLAGS)
profile: all
release: CFLAGS += $(RELEASEFLAGS)
release: all
.PHONY : clean depend
clean:
-rm -f $(CORE_LIB) $(CORE_OBJ)
-rm -f $(TEST_SERVER) $(TEST_SERVER_OBJ)
-rm -f $(TEST_CLIENT) $(TEST_CLIENT_OBJ)
-rm -f gmon.out
depend:
#makedepend -- $(CFLAGS) -- $(CORE_SRC) $(TEST_SERVER_SRC) $(TEST_CLIENT_SRC)
I still have some problems:
- make creates the lib, the server and client test app. If I know modify one of the source files of the core (lib), make builds the lib newly, but not the server and client apps. Do I have a dependency problem?
- make or make all should build by default as DEBUG, whereas release and profile build a release, or profile version respectively.
I wonder, what is wrong in my makefile.
Thanks again!

Related

cross-compile library recipe in yocto

I have a library with few source code files (.c) and header files and the output is shared library (.so).
Currently, i am using Makefile for generating .so
C = gcc
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = libesys.so
SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
OBJECTS = $(SOURCES:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(LDFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
clean:
rm *.o libesys.so
I want to create a recipe in my meta layer to perform the above operation and generate .so when I do bitbake core-image-minimal. Can you please provide an example recipe which does similar operation.
First, have a look at simple recipe for a single source file from the dev-manual and try to first get a simple recipe building. You are correct in placing this recipe in your own meta layer.
Also have a look at this section that covers recipes with a Makefile.
Here is something to get you started
DESCRIPTION = "My test recipe"
LICENSE = "CLOSED"
PR = "r1"
S = "${WORKDIR}
FILES_${PN} = "libesys.so"
# Better to use a git repo for large projects
SRC_URI="file://xxxxxx \
file://yyyyyy \
"
do_install(){
oe_runmake install DESTDIR=${D} INCLUDEDIR=${includedir}
install -d ${D}${libdir}
install -m 0644 libesys.so ${D}${libdir}
}
BBCLASSEXTEND = "native"
You will also need to modify the core-image-minimal recipe to add a depends to your recipe so that it pulls in your lib.
DEPENDS+="your_recipe_name_here"
You can add this directly into the recipe itself, or add it via a .bbappends file that can reside in your layer.

Makefiles - ar: *.a: No such file or directory.... but there is... it's right there

Trying to compile a friend's code - but he has included no Makefile, I build my own and am perplexed by an issue I've run into.
I think it's best I post the full contents of the Makefile below... I tried to keep it short!
CFLAGS = -Wall -pedantic
LFLAGS =
CC = gcc
RM = /bin/rm -rf
AR = ar rc
RANLIB = ranlib
LIBRARY = const.a read.a descr.a
LIB_SRC = read.c futex.c testy.c
LIB_OBJ = $(patsubst %.c,%.o,$(LIB_SRC))
# pattern rule for object files
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
all: $(LIBRARY)
$(LIBRARY): $(LIB_OBJ)
$(AR) $(LIBRARY) $(LIB_OBJ)
$(RANLIB) $(LIBRARY)
clean:
$(RM) $(LIBRARY) $(LIB_OBJ)
.PHONY: depend
depend:
$(CFLAGS) -- $(LIB_SRC) 2>/dev/null
All of the files, const.h, read.h, and descr.h are in the directory in which I call make. Likewise for read.c, futex.c, and testy.c.
The files are entangled in various ways - if I need to show exactly the nature of these entanglements, I will do so.
I 'make' and the compiler alledges:
ar: read.a: No such file or directory
Is it not the case that read.a is supposed to be being produced? Of course it isn't there yet.
I've stared a while now and I feel like this must be something simple I am missing.
This command:
$(AR) $(LIBRARY) $(LIB_OBJ)
expands to this:
ar rc const.a read.a descr.a read.o futex.o testy.o
So when Make tries to build const.a, it tells ar to combine several files into const.a, starting with read.a, and ar complains that there's no such file. (Whether ar could do anything useful with read.a if it did exist is immaterial.)
It's not clear how you want Make to build those libraries, but this might be a step in the right direction:
$(LIBRARY): $(LIB_OBJ)
$(AR) $# $(LIB_OBJ)
$(RANLIB) $#
The automatic variable $# expands to the name of the target. You can use another one for the list of prerequisites ($(LIB_OBJ)), but let's try one new thing at a time.

I need some assistance with Makefile in my project

I'm trying to make a Makefile but I'm having some problems
first I have
2 source files: ~/main.c ~/lib/library.c
1 header file: ~/include/library.h
main.c and library.c both share the same header file library.h
# Compiler options
CC = gcc
INC = -I../include
CFLAGS = -Wall -g -c $(INC)
LIB = -L../lib
LFLAGS = -Wall -g $(LIB)
# Dependencies
LIBS = -libmylib
OBJS = main.o
SRCS = $(OBJS:.o=.c)
EXEC = a.out
# Other rules
RM = rm -rf
TAGS = tags
BAK = Makefile.bak
all: $(EXEC)
#echo ------------------------ Compile Complete ----------------------------
.PHONY: clean depend
$(EXEC): $(OBJS)
$(CC) $(LFLAGS) -o $# $^ $(LIBS)
.c.o:
$(CC) $(INC) -M $^
$(CC) $(CFLAGS) -o $# $<
clean:
$(RM) *.o *~ $(EXEC) $(TAGS) $(BAK)
depend: $(SRCS)
makedepend $(INC) $^
it keeps saying that I it can't make a rule out of library.o
plus I have another question
I acknowledge the fact that when Makefile comes in to action after calling 'make',
and subsequently go to the line .c.o or %c: %o(in GNU enhanced version) and make
.o files. but why doesn't it also call clean and depend automatically?
I've edited some things from the previous version of Makefile
this time, (well pretty similar to the previous problem) even though I
clarified the library path(-I../lib),
the Makefile cannot find the archive file (which I created as libmylib.a in ../lib dir)
now it's driving me crazy
but why doesn't it also call clean and depend automatically?
Because make only builds the target you tell it. If you don't specify one, the first target is built, which in many cases, such as yours, is the 'all' target.

Using a Makefile with C

So I have three files:
jarvismarch.c (includes "jarvismarchtools.h")
jarvismarchtools.c
jarvismarchtools.h
I would like to use a makefile to compile the aforementioned files. How would I go about this?
The typical minimal makefile looks like this:
OBJ = jarvismarch.o jarvismarchtools.o
all: $(OBJ)
$(CC) -o jarvismarch $(OBJ)
Taking the comment of asveikau into account and adding a clean target it becomes:
OBJ = jarvismarch.o jarvismarchtools.o
BIN = jarvismarch
CFLAGS = -Wall -pedantic -ansi
all: $(BIN)
$(BIN): $(OBJ)
$(CC) -o # $(OBJ)
clean:
rm -f $(OBJ) $(BIN)
(Windows users need to use .obj instead of .o)
I strongly recommend against using make. It might be simple at first, but once your project grows I highly recommend a more complete build tool like SCons, CMake or Boost.Build.
Assuming that you are trying to build jarvismarch.exe:
jarvismarch.exe : jarvismarch.o jarvismarchtools.o
$(CC) -o $# $^
The leading whitespace on the second line needs to be a TAB character.

How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories?

A few months ago, I came up with the following generic Makefile for school assignments:
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon#gmail.com
# Date : 2010-11-05
#
# Changelog :
# 0.01 - first version
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): obj
#$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
#$(CC) $(CFLAGS) $(SOURCES)
#echo "Compilation complete!"
clean:
#$(rm) $(TARGET) $(OBJECTS)
#echo "Cleanup complete!"
This will basically compile every .c and .h file to generate .o files and the executable projectname all in the same folder.
Now, I'd like to push this a little. How can I write a Makefile to compile a C project with the following directory structure?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
In other words, I'd like to have a Makefile that compiles C sources from ./src/ into ./obj/ and then link everything to create the executable in ./bin/.
I've tried to read different Makefiles, but I simply can't make them work for the project structure above; instead, the project fails to compile with all sorts of errors. Sure, I could use full blown IDE (Monodevelop, Anjuta, etc.), but I honestly prefer to stick with gEdit and the good ol' terminal.
Is there a guru who can give me a working solution, or clear information about how this can be done? Thank you!
** UPDATE (v4) **
The final solution :
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon#gmail.com
# Date : 2011-08-10
#
# Changelog :
# 2010-11-05 - first version
# 2011-08-10 - added structure : sources, objects, binaries
# thanks to http://stackoverflow.com/users/128940/beta
# 2017-04-24 - changed order of linker params
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
.PHONY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
.PHONY: remove
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"
First, your $(OBJECTS) rule is problematic, because:
it's kind of indiscriminate, making all sources prerequisites of every object,
it often uses the wrong source (as you discovered with file1.o and file2.o)
it tries to build executables instead of stopping at objects, and
the name of the target (foo.o) is not what the rule will actually produce (obj/foo.o).
I suggest the following:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
The $(TARGET) rule has the same problem that the target name does not actually describe what the rule builds. For that reason, if you type make several times, Make will rebuild the target each time, even though there is no reason to. A small change fixes that:
$(BINDIR)/$(TARGET): $(OBJECTS)
$(LINKER) $# $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
Once that's all in order, you might consider more sophisticated dependency handling; if you modify one of the header files, this makefile will not know which objects/executables must be rebuilt. But that can wait for another day.
EDIT:
Sorry, I omitted part of the $(OBJECTS) rule above; I've corrected it. (I wish I could use "strike" inside a code sample.)
You can add the -I flag to the compiler flags (CFLAGS) to indicate where the compiler should look for source files , and the -o flag to indicate where the binary should be left:
CFLAGS = -Wall -I./src
TARGETPATH = ./bin
$(TARGET): obj
#$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
In order to drop the object files into the obj directory, use the -o option when compiling. Also, look at the $# and $< automatic variables.
For example, consider this simple Makefile
CFLAGS= -g -Wall -O3
OBJDIR= ./obj
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o )
all:$(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$#
Update>
By looking at your makefile, I realize you are using the -o flag. Good. Continue using it, but add a target directory variable to indicate where the output file should be written.
I have stopped writing makefiles these days, if your intention is to learn go ahead, else you have good makefile generator that comes with eclipse CDT. If you want some maintainability / multiple project support with in your build tree, have a look at the following -
https://github.com/dmoulding/boilermake I found this pretty good..!

Resources