Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make for compiling — all *.c files in folders & subfolders in project

Tags:

linux

makefile

To compile two files i have created a makefile where i use to mention the object name or i can use the pattern rule using patsubst.

# ----------------------------------------------------------------------------
# Makefile for building tapp
#
# Copyright 2010 FriendlyARM (http://www.arm9.net/)
#

ifndef DESTDIR
DESTDIR            ?= /opt/FriendlyARM/tiny6410/linux/rootfs_qtopia_qt4
endif

#CFLAGS              = -c -Wall -O2  # wall is for warning show and 02 is optiminisation level 2
CFLAGS              = -c -O2  # wall is for warning show and 02 is optiminisation level 2
#CC                    = arm-linux-gcc   # compiler name
CC                    = gcc   # compiler name
LD                    = ld

INSTALL             = install         # 

TARGET              = led_player_project

#OBJ = led-player_backup.o led-player.o
OBJ := $(patsubst %.c,%.o,$(wildcard *.c */*.c))

#OBJ = $(shell find . -name '*.c')

all: $(TARGET) 
#all: $(OBJ)

led_player_project : $(OBJ)
    $(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
#       $(LD) $(LDFLAGS) -o $@ $< $(LIBS)

%.o : %.c
    $(CC) $(CFLAGS) $< -o $@

#$< -o $@


install: $(TARGET)
    $(INSTALL) $^ $(DESTDIR)/usr/bin

clean :
    rm -rf *.o $(TARGET) $(OBJ)


# ----------------------------------------------------------------------------

.PHONY: $(PHONY) install clean

# End of file
# vim: syntax=make

#EOF

Now if my project contains folder contains subfolders & they contains further files. Then can i write pattern rule to compile every file & create an common executable?

1> Do i will have to create makefile in every-subfolder so that i can invoke that makefile from main makefile, like integrating static driver to linux kernel each driver have respective makefile ?
2> Or common makefile for full project ?
3> can i use patsubst to compile every file without mentioning there name.
4> How can i combine every *.o to create on executable called main.

enter image description here

Edit :---
@Jan Hudec I have modified my makefile as per your comment (i have posted it above). Now i am just trying with two folders inside my main folder. I am getting following error Folder structure :--

main Folder  ----> one Folder 
             ----> two Folder 

Folder Main contains :--

main.c 
main.h
Makefile

Folder one contains :--

one.c
one.h

Folder two contains :--

two.c
two.h

main.c content :--

#include <stdio.h>
#include <stdlib.h>

#include "main.h"

int main()
{
  char *p;

  printf("\n\n main \n");

  one();
  two();

  return 0;
}

main.h content :---

#include "one/one.h"
#include "two/two.h"

one.c content :---

    #include <stdio.h>
    #include <stdlib.h>

#include "one.h"

    void one()
    {

      printf("\n one \n");

    }

one.h content :---

void one();

two.c content :---

#include <stdio.h>
#include <stdlib.h>

#include "two.h"

void two()
{

  printf("\n two \n");

}

two.h content :---

void two();

Error i got at make time :----

ignite@ignite:~/testing/main$ make
gcc    -c -O2   main.c -o main.o
gcc    -c -O2   one/one.c -o one/one.o
gcc    -c -O2   two/two.c -o two/two.o
ld  -o led_player_project main.o one/one.o two/two.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080
main.o: In function `main':
main.c:(.text.startup+0x11): undefined reference to `puts'
one/one.o: In function `one':
one.c:(.text+0xb): undefined reference to `puts'
two/two.o: In function `two':
two.c:(.text+0xb): undefined reference to `puts'
make: *** [led_player_project] Error 1
ignite@ignite:~/testing/main$ 
like image 511
Katoch Avatar asked Dec 19 '22 22:12

Katoch


1 Answers

Ad 1 and 2: The filenames can safely include directories and % matches / as necessary. So you can easily have:

$(wildcard subdir/*.c) $(wildcard anotherdir/*.c)

or even

$(wildcard */*.c)

... or as suggested by keltar in comment

$(shell find . -name '*.c')

which is recursive.

Ad 3: You are doing it.

Ad 4: Create a target with $(OBJ) as dependencies and use the automatic variable just as you do for compilation:

main : $(OBJ)
        $(LD) $(LDFLAGS) -o $@ $< $(LIBS)
like image 69
Jan Hudec Avatar answered May 18 '23 12:05

Jan Hudec