Makefile的嵌套目录示例

             最近遇到需要将vs2010的c++项目移植到linux下面的问题,由于项目中分了很多个子目录,如何写Makefile是一个很头疼的问题,不过还好,经过一番折腾,还是实现了初步的要求,下面给出一个嵌套目录的Makefile示例:

  先说一些必要的知识点:

1.在linux下编译c++项目,我目前知道的有下面几种方法:

 1.1 在命令行运行类似 g++ -c main.cpp -o mian.o 命令,100个cpp文件,运行100条对应的命令。(好累o(︶︿︶)o

 1.2 将上面的100条命令,全部保存到一个shell脚本中,然后运行 sh run.sh

 1.3 利用Makefile文件,来编译上面100个cpp文件(此文采用这种方法来编译

 1.4 利用libtool来编译

2.编写Makefile有很多规则,网上有很多介绍这方面的资料。

3.linux的强大之处在于正则表达式和通配符,在Makefile里面,

 src_files = $(wildcard *.cpp) 变量src_files表示所有.cpp文件

 objects = $(patsubst %.cpp, %.o, $(src_files))变量objects表示所有.o文件

4.每个目录都应该有一个Makefile文件,可以在Makefile里面嵌入shell的for循环命令,来调用嵌套目录的Makefile

--------------------------------------------------

本示例的目录结构为:

[root@localhost test]$ tree
.
├── dir1
│   ├── dir11
│   │   ├── func11.cpp
│   │   ├── func11.h
│   │   └── Makefile
│   ├── dir12
│   │   ├── func12.cpp
│   │   ├── func12.h
│   │   └── Makefile
│   ├── func1.cpp
│   ├── func1.h
│   └── Makefile
├── main.cpp
└── Makefile

有4个目录,所以有4个Makefile,其中和mian.cpp在同一目录的Makefile,负责调用剩下的Makefile。

// ./main.cpp
#include <stdio.h>
#include "dir1/func1.h"
#include "dir1/dir11/func11.h"
#include "dir1/dir12/func12.h"

int main(int argc, char * argv[])
{
        func1();

        func11();
        func12();

        return 0;
}
// ./dir1/func1.h
void func1();
// ./dir1/func1.cpp
#include <stdio.h>
#include "func1.h"

void func1()
{
        printf("[%s:%s] Hello World!\n", __FILE__, __FUNCTION__);
}
// ./dir1/dir11/func11.h
void func11();
// ./dir1/dir11/func11.cpp
#include <stdio.h>
#include "func11.h"

void func11()
{
        printf("[%s:%s] Hello World!\n", __FILE__, __FUNCTION__);
}
// ./dir1/dir12/func12.h
void func12();
// ./dir1/dir12/func12.cpp
#include <stdio.h>
#include "func12.h"

void func12()
{
        printf("[%s:%s] Hello World!\n", __FILE__, __FUNCTION__);
}

--------------各个目录对应的Makefile如下-------------------------

注意:由于CSDN显示的原因,"$ $target " 实际为 "$$target","$ $subdir"也是一样

// ./Makefile
GCC = gcc
CC = g++

is_debug = 0
DEBUG =
prefix = ./build_linux/x64/Release

ifeq ($(is_debug), 1)
        DEBUG = -g
        prefix = ./build_linux/x64/Debug
else
        DEBUG = -O3
        prefix = ./build_linux/x64/Release
endif

#----------------------------------
CFLAGS = -c -Wall $(DEBUG) -I. -I/usr/include
LIBS = -L/usr/lib64 -ldl -lpthread

#----------------------------------
out_exe = main
objects = main.o

libs_a = \
        dir1/libfunc1.a \
        dir1/dir11/libfunc11.a \
        dir1/dir12/libfunc12.a

SUBDIRS = \
        dir1 \
        .

#----------------------------------
all:
        $(MAKE) $(AM_MAKEFLAGS) all-recursive

#----------------------------------
all-am: Makefile $(out_exe)

$(out_exe): $(objects) $(libs_a)
        rm -f $(out_exe)
        $(CC) -o $(out_exe) $(objects) $(libs_a) $(LIBS)

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

#----------------------------------
recursive_targets = all-recursive clean-recursive

$(recursive_targets):
        dot_seen=no; \
        target=`echo $@ | sed s/-recursive//`; \
        list='$(SUBDIRS)'; \
        for subdir in $$list; do \
                echo "Making $ $target in $ $subdir"; \
                if test "$$subdir" = "."; then \
                        dot_seen=yes; \
                        local_target="$$target-am"; \
                else \
                        local_target="$$target"; \
                fi; \
                (cd $ $subdir && $(MAKE) $(AM_MAKEFLAGS) $ $local_target is_debug=$(is_debug)); \
        done;

#----------------------------------
clean: clean-recursive

clean-am:
        rm -f *.o $(out_exe)

#----------------------------------
.PHONY: all $(recursive_targets) clean


// ./dir1/Makefile
GCC = gcc
CC = g++
AR = ar
ARFLAGS = crs

is_debug = 0
DEBUG =

ifeq ($(is_debug), 1)
        DEBUG = -g
else
        DEBUG = -O3
endif

CFLAGS = -c -Wall $(DEBUG) -I. -I/usr/include

#----------------------------------
libs_a = \
        dir11/libfunc11.a \
        dir12/libfunc12.a

SUBDIRS = \
        dir11 \
        dir12 \
        .

lib_a = libfunc1.a

src_files = $(wildcard *.cpp)

objects = $(patsubst %.cpp, %.o, $(src_files))

#----------------------------------
all:
        $(MAKE) $(AM_MAKEFLAGS) all-recursive

#----------------------------------
all-am: Makefile $(lib_a)

#----------------------------------
$(lib_a): $(objects)
        -rm -f $(lib_a)
        $(AR) $(ARFLAGS) $(lib_a) $(objects)

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

#----------------------------------
recursive_targets = all-recursive clean-recursive

$(recursive_targets):
        dot_seen=no; \
        target=`echo $@ | sed s/-recursive//`; \
        list='$(SUBDIRS)'; \
        for subdir in $$list; do \
                echo "Making $ $target in $ $subdir"; \
                if test "$$subdir" = "."; then \
                        dot_seen=yes; \
                        local_target="$$target-am"; \
                else \
                        local_target="$$target"; \
                fi; \
                (cd $ $subdir && $(MAKE) $(AM_MAKEFLAGS) $ $local_target is_debug=$(is_debug)); \
        done;

#----------------------------------
clean: clean-recursive

clean-am:
        rm -f *.o $(lib_a)

#----------------------------------
.PHONY: all $(recursive_targets) clean


// ./dir1/dir11/Makefile
GCC = gcc
CC = g++
AR = ar
ARFLAGS = crs

is_debug = 0
DEBUG =

ifeq ($(is_debug), 1)
        DEBUG = -g
else
        DEBUG = -O3
endif

CFLAGS = -c -Wall $(DEBUG) -I. -I/usr/include

#----------------------------------
lib_a = libfunc11.a

src_files = $(wildcard *.cpp)

objects = $(patsubst %.cpp, %.o, $(src_files))

#----------------------------------
all: $(lib_a)

$(lib_a): $(objects)
        -rm -f $(lib_a)
        $(AR) $(ARFLAGS) $(lib_a) $(objects)

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

#----------------------------------
clean:
        rm -f *.o $(lib_a)

#----------------------------------
.PHONY: all clean

// ./dir1/dir12/Makefile
GCC = gcc
CC = g++
AR = ar
ARFLAGS = crs

is_debug = 0
DEBUG =

ifeq ($(is_debug), 1)
        DEBUG = -g
else
        DEBUG = -O3
endif

CFLAGS = -c -Wall $(DEBUG) -I. -I/usr/include

#----------------------------------
lib_a = libfunc12.a

src_files = $(wildcard *.cpp)

objects = $(patsubst %.cpp, %.o, $(src_files))

#----------------------------------
all: $(lib_a)

$(lib_a): $(objects)
        -rm -f $(lib_a)
        $(AR) $(ARFLAGS) $(lib_a) $(objects)

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

#----------------------------------
clean:
        rm -f *.o $(lib_a)

#----------------------------------
.PHONY: all clean


----------------1.编译Release版本--------------------------
运行 make 或 make is_debug=0

[fujin@localhost test3]$ make
make  all-recursive
make[1]: Entering directory `/home/fujin/work/test/make_file/test3'
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
list='dir1 .'; \
for subdir in $list; do \
        echo "Making $target in $subdir"; \
        if test "$subdir" = "."; then \
                dot_seen=yes; \
                local_target="$target-am"; \
        else \
                local_target="$target"; \
        fi; \
        (cd $subdir && make  $local_target is_debug=0); \
done;
Making all in dir1
make[2]: Entering directory `/home/fujin/work/test/make_file/test3/dir1'
make  all-recursive
make[3]: Entering directory `/home/fujin/work/test/make_file/test3/dir1'
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
list='dir11 dir12 .'; \
for subdir in $list; do \
        echo "Making $target in $subdir"; \
        if test "$subdir" = "."; then \
                dot_seen=yes; \
                local_target="$target-am"; \
        else \
                local_target="$target"; \
        fi; \
        (cd $subdir && make  $local_target is_debug=0); \
done;
Making all in dir11
make[4]: Entering directory `/home/fujin/work/test/make_file/test3/dir1/dir11'
g++ -c -Wall -O3 -I. -I/usr/include func11.cpp -o func11.o
rm -f libfunc11.a
ar crs libfunc11.a  func11.o
make[4]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1/dir11'
Making all in dir12
make[4]: Entering directory `/home/fujin/work/test/make_file/test3/dir1/dir12'
g++ -c -Wall -O3 -I. -I/usr/include func12.cpp -o func12.o
rm -f libfunc12.a
ar crs libfunc12.a  func12.o
make[4]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1/dir12'
Making all in .
make[4]: Entering directory `/home/fujin/work/test/make_file/test3/dir1'
g++ -c -Wall -O3 -I. -I/usr/include func1.cpp -o func1.o
rm -f libfunc1.a
ar crs libfunc1.a  func1.o
make[4]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1'
make[3]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1'
make[2]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1'
Making all in .
make[2]: Entering directory `/home/fujin/work/test/make_file/test3'
g++ -c -Wall -O3 -I. -I/usr/include main.cpp -o main.o
rm -f main
g++ -o main main.o dir1/libfunc1.a dir1/dir11/libfunc11.a dir1/dir12/libfunc12.a -L/usr/lib64 -ldl -lpthread
make[2]: Leaving directory `/home/fujin/work/test/make_file/test3'
make[1]: Leaving directory `/home/fujin/work/test/make_file/test3'


----------------2.编译Debug版本--------------------------

运行 make is_debug=1

[fujin@localhost test3]$ make is_debug=1
make  all-recursive
make[1]: Entering directory `/home/fujin/work/test/make_file/test3'
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
list='dir1 .'; \
for subdir in $list; do \
        echo "Making $target in $subdir"; \
        if test "$subdir" = "."; then \
                dot_seen=yes; \
                local_target="$target-am"; \
        else \
                local_target="$target"; \
        fi; \
        (cd $subdir && make  $local_target is_debug=1); \
done;
Making all in dir1
make[2]: Entering directory `/home/fujin/work/test/make_file/test3/dir1'
make  all-recursive
make[3]: Entering directory `/home/fujin/work/test/make_file/test3/dir1'
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
list='dir11 dir12 .'; \
for subdir in $list; do \
        echo "Making $target in $subdir"; \
        if test "$subdir" = "."; then \
                dot_seen=yes; \
                local_target="$target-am"; \
        else \
                local_target="$target"; \
        fi; \
        (cd $subdir && make  $local_target is_debug=1); \
done;
Making all in dir11
make[4]: Entering directory `/home/fujin/work/test/make_file/test3/dir1/dir11'
g++ -c -Wall -g -I. -I/usr/include func11.cpp -o func11.o
rm -f libfunc11.a
ar crs libfunc11.a  func11.o
make[4]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1/dir11'
Making all in dir12
make[4]: Entering directory `/home/fujin/work/test/make_file/test3/dir1/dir12'
g++ -c -Wall -g -I. -I/usr/include func12.cpp -o func12.o
rm -f libfunc12.a
ar crs libfunc12.a  func12.o
make[4]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1/dir12'
Making all in .
make[4]: Entering directory `/home/fujin/work/test/make_file/test3/dir1'
g++ -c -Wall -g -I. -I/usr/include func1.cpp -o func1.o
rm -f libfunc1.a
ar crs libfunc1.a  func1.o
make[4]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1'
make[3]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1'
make[2]: Leaving directory `/home/fujin/work/test/make_file/test3/dir1'
Making all in .
make[2]: Entering directory `/home/fujin/work/test/make_file/test3'
g++ -c -Wall -g -I. -I/usr/include main.cpp -o main.o
rm -f main
g++ -o main main.o dir1/libfunc1.a dir1/dir11/libfunc11.a dir1/dir12/libfunc12.a -L/usr/lib64 -ldl -lpthread
make[2]: Leaving directory `/home/fujin/work/test/make_file/test3'
make[1]: Leaving directory `/home/fujin/work/test/make_file/test3'

--------------3.运行结果-----------------------
[fujin@localhost test3]$ tree
.
├── dir1
│   ├── dir11
│   │   ├── func11.cpp
│   │   ├── func11.h
│   │   ├── func11.o
│   │   ├── libfunc11.a
│   │   └── Makefile
│   ├── dir12
│   │   ├── func12.cpp
│   │   ├── func12.h
│   │   ├── func12.o
│   │   ├── libfunc12.a
│   │   └── Makefile
│   ├── func1.cpp
│   ├── func1.h
│   ├── func1.o
│   ├── libfunc1.a
│   └── Makefile
├── main
├── main.cpp
├── main.o
└── Makefile

3 directories, 19 files
[fujin@localhost test3]$ ./main
[func1.cpp:func1] Hello World!
[func11.cpp:func11] Hello World!
[func12.cpp:func12] Hello World!









  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值