Makefile编写----实例展示
2018-02-03 13:42
176 查看
本文档内容:
1,验证在makefile文件中是否一定需要指定.h文件(头文件)?
2,遍历子目录,并且在子目录执行make命令。
3,执行make clean时,遍历子目录执行make clean命令。
4,使用makefile生成动态库和静态库。
测试用例:
twohellos.c 文件中有main函数,main 函数调用hellofirst.c和hellosecond.c中的函数hellofirst() 和 hellosecond();
其中hellofirst.h和hellosecond.h是其对应的头文件。
下面是文件源码:
/* ------hellofirst.c------------*/
#include <stdio.h>
void hellofirst()
{
printf("The first hello\n");
}
/* ------hellofirst.h------------*/
#ifndef HELLOFIRST_H
#define HELLOFIRST_H
extern void hellofirst(void);
#endif
/* ------hellosecond.c------------*/
#include <stdio.h>
void hellosecond()
{
printf("The second hello\n");
}
/* ------hellosecond.h------------*/
#ifndef HELLOSECOND_H
#define HELLOSECOND_H
extern void hellosecond(void);
#endif
/* ------twohellos.c------------*/
int main(int argc, char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
通过makefile实现生成可执行文件twohellos,
为了突出主题,gcc中有关的参数(比如:-g ,-Wall 等)就不写了。
内容如下:
---------------------------------------------------------------
twohellos : twohellos.o hellofirst.o hellosecond.o
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
twohellos.o : twohellos.c hellofirst.h hellosecond.h
gcc -c twohellos.c
hellofirst.o : hellofirst.c hellofirst.h
gcc -c hellofirst.c
hellosecond.o : hellosecond.c hellosecond.h
gcc -c hellosecond.c
.PHONY : clean
clean :
-rm -f *.o
-rm -f twohellos
---------------------------------------------------------------
操作过程如下:
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 74 Feb 13 14:12 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 98 Feb 14 10:13 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 76 Feb 13 14:12 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 102 Feb 14 10:14 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 385 Feb 14 10:25 Makefile
-rw-rw-r--. 1 dingqs dingqs 82 Feb 14 10:14 twohellos.c
[dingqs@localhost home]$ make
gcc -c twohellos.c
gcc -c hellofirst.c
gcc -c hellosecond.c
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
[dingqs@localhost test]$ ll
total 44
-rw-rw-r--. 1 dingqs dingqs 74 Feb 13 14:12 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 98 Feb 14 10:13 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 10:53 hellofirst.o
-rw-rw-r--. 1 dingqs dingqs 76 Feb 13 14:12 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 102 Feb 14 10:14 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 10:53 hellosecond.o
-rw-rw-r--. 1 dingqs dingqs 385 Feb 14 10:25 Makefile
-rwxrwxr-x. 1 dingqs dingqs 6719 Feb 14 10:53 twohellos
-rw-rw-r--. 1 dingqs dingqs 82 Feb 14 10:14 twohellos.c
-rw-rw-r--. 1 dingqs dingqs 1464 Feb 14 10:53 twohellos.o
[dingqs@localhost test]$ ./twohellos
The first hello
The second hello
[dingqs@localhost test]$ make clean
rm -f *.o
rm -f twohellos
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 74 Feb 13 14:12 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 98 Feb 14 10:13 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 76 Feb 13 14:12 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 102 Feb 14 10:14 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 385 Feb 14 10:25 Makefile
-rw-rw-r--. 1 dingqs dingqs 82 Feb 14 10:14 twohellos.c
[dingqs@localhost home]$
在真实的项目中.c文件中提供的对外接口一般放在同名的.h文件中,然后在.c文件中include即可。
同时,在包含main()函数的.c文件的头部都会include main函数使用其他.c文件对应的.h文件。
比较接近真实项目的代码如下(主要添加箭头指的那四行):
/* ------hellofirst.c------------*/
#include <stdio.h>
#include "hellofirst.h" <--------------------------
void hellofirst()
{
printf("The first hello\n");
}
/* ------hellofirst.h------------*/
#ifndef HELLOFIRST_H
#define HELLOFIRST_H
extern void hellofirst(void);
#endif
/* ------hellosecond.c------------*/
#include <stdio.h>
#include "hellosecond.h" <--------------------------
void hellosecond()
{
printf("The second hello\n");
}
/* ------hellosecond.h------------*/
#ifndef HELLOSECOND_H
#define HELLOSECOND_H
extern void hellosecond(void);
#endif
/* ------twohellos.c------------*/
#include "hellofirst.h" <--------------------------
#include "hellosecond.h" <--------------------------
int main(int argc,char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
上面对应的makefile文件就可以不再考虑那么多的.h文件了。这样看就舒服多了:
更新后的makefile如下:
---------------------------------------------------------------
twohellos : twohellos.o hellofirst.o hellosecond.o
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
twohellos.o : twohellos.c
gcc -c twohellos.c
hellofirst.o : hellofirst.c
gcc -c hellofirst.c
hellosecond.o : hellosecond.c
gcc -c hellosecond.c
.PHONY : clean
clean :
-rm -f *.o
-rm -f twohellos
---------------------------------------------------------------
下面是操作过程:
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 11:16 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 11:19 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 11:16 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 11:19 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 314 Feb 14 11:17 Makefile
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 11:17 twohellos.c
[dingqs@localhost test]$ make
gcc -c twohellos.c
gcc -c hellofirst.c
gcc -c hellosecond.c
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
[dingqs@localhost test]$ ll
total 44
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 11:16 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 11:19 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 11:20 hellofirst.o
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 11:16 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 11:19 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 11:20 hellosecond.o
-rw-rw-r--. 1 dingqs dingqs 314 Feb 14 11:17 Makefile
-rwxrwxr-x. 1 dingqs dingqs 6719 Feb 14 11:20 twohellos
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 11:17 twohellos.c
-rw-rw-r--. 1 dingqs dingqs 1448 Feb 14 11:20 twohellos.o
[dingqs@localhost test]$ ./twohellos
The first hello
The second hello
[dingqs@localhost test]$ make clean
rm -f *.o
rm -f twohellos
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 11:16 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 11:19 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 11:16 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 11:19 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 314 Feb 14 11:17 Makefile
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 11:17 twohellos.c
[dingqs@localhost test]$$
在真实的项目中很少把所有的文件放在一个文件夹中,
往往是每个模块放在一个文件夹中,各个模块共同编译出最终的可执行文件。
为了说明这个情况,下面把上面的代码结构修改一下:
当前文件夹下有Makefile,twohellos.c两个文件,和hellofirt,hellosecond两个文件夹;
其中hellofirst.c和hellofirst.h放在hellofirst文件夹中,
hellosecond.c和hellosecond.h放在hellosecond文件夹中。
为了模拟更多情况,在当前文件下再创建lib和include两个文件夹。
其中lib文件夹存放hellofirst和hellosecond文件夹中执行make命令产生的静态库libhellofirst.a和动态库libhellosecond.so;
其中include文件夹存放hellofirst和hellosecond文件夹中产生的静态库和动态库对应的头文件:hellofirst.h和hellosecond.h。
结构如下:
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ └── Makefile
├── include
├── lib
├── Makefile
└── twohellos.c
4 directories, 8 files
[dingqs@ADB200 test_multproj]$
在外层执行make命令时,会进入hellofirst和hellosecond文件夹中执行make命令。
所以hellofirst和hellosecond文件夹中都需要有相应的makefile文件。
注意:所有的.c和.h文件中的内容都没有任何变化,和上面的例子一样,
不过为了方便,不至于翻到上面查看代码,所以在此处会原样的copy过来。
所以重点还是关注每个Makefile文件的内容。
首先看hellofirst文件夹中的内容:
/* ------hellofirst.c------------*/
#include <stdio.h>
#include "hellofirst.h" <--------------------------
void hellofirst()
{
printf("The first hello\n");
}
/* ------hellofirst.h------------*/
#ifndef HELLOFIRST_H
#define HELLOFIRST_H
extern void hellofirst(void);
#endif
在hellofirst文件夹中的makefile需要完成编译hellofirst.c和hellofirst.h成静态库libhellofirst.a;
同时把这个静态库copy到lib中,把hellofirst.h头文件copy到include中。
下面是makfile源码:
----------------------------------------
LIB_TOP_DIR = ../lib
INC_TOP_DIR = ../include
CC = gcc
CFLAGES := -Wall -ggdb -O0
OBJS = hellofirst.o
LIB = libhellofirst.a
INC = hellofirst.h
all : $(LIB)
# get .a file
$(LIB) : $(OBJS)
rm -f $@
ar cr $@ $^
cp $(LIB) $(LIB_TOP_DIR)
cp *.h $(INC_TOP_DIR)
# get .o file
%.o : %.c
$(CC) -c $(CFLAGES) $< -o $@
.PHONY : clean
clean :
rm -f $(OBJS) $(LIB)
cd $(LIB_TOP_DIR); rm -f $(LIB)
cd $(INC_TOP_DIR); rm -f $(INC)
----------------------------------------
验证一下结果:
[dingqs@ADB200 test_multproj]$ cd hellofirst/
[dingqs@ADB200 hellofirst]$ ll
total 12
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 12:07 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 12:07 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 458 Feb 14 15:57 Makefile
[dingqs@ADB200 hellofirst]$ make
gcc -c -Wall -ggdb -O0 hellofirst.c -o hellofirst.o
rm -f libhellofirst.a
ar cr libhellofirst.a hellofirst.o
cp libhellofirst.a ../lib
cp *.h ../include
[dingqs@ADB200 hellofirst]$ cd ../
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ └── Makefile
├── include
│ └── hellofirst.h
├── lib
│ └── libhellofirst.a
├── Makefile
└── twohellos.c
4 directories, 12 files
[dingqs@ADB200 test_multproj]$
由上面的结果可知这个makefile文件实现了想要的功能。
下面进入hellosecond文件夹,如何实现makefile,生成动态库。
hellosecond.c和hellosecond.h文件内容如下:
/* ------hellosecond.c------------*/
#include <stdio.h>
#include "hellosecond.h" <--------------------------
void hellosecond()
{
printf("The second hello\n");
}
/* ------hellosecond.h------------*/
#ifndef HELLOSECOND_H
#define HELLOSECOND_H
extern void hellosecond(void);
#endif
在 hellosecond 文件夹中的makefile需要完成编译hellosecond.c和hellosecond.h成动态库libhellosecond.so;
同时把这个动态库copy到lib中,把hellosecond.h头文件copy到include中。
下面是makfile源码:
----------------------------------------
LIB_TOP_DIR = ../lib
INC_TOP_DIR = ../include
CC = gcc
CFLAGES := -Wall -ggdb -O0
OBJS = hellosecond.o
LIB = libhellosecond.so
INC = hellosecond.h
all : $(LIB)
# get .so file
$(LIB) : $(OBJS)
rm -f $@
$(CC) -shared $^ -o $@
cp $(LIB) $(LIB_TOP_DIR)
cp *.h $(INC_TOP_DIR)
# get .o file
%.o : %.c
$(CC) -c $(CFLAGES) -fpic $< -o $@
.PHONY : clean
clean :
rm -f $(OBJS) $(LIB)
cd $(LIB_TOP_DIR); rm -f $(LIB)
cd $(INC_TOP_DIR); rm -f $(INC)
----------------------------------------
验证下结果:
[dingqs@ADB200 test_multproj]$ cd hellosecond/
[dingqs@ADB200 hellosecond]$ ll
total 12
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 12:07 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 12:07 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 480 Feb 14 15:57 Makefile
[dingqs@ADB200 hellosecond]$ make
gcc -c -Wall -ggdb -O0 -fpic hellosecond.c -o hellosecond.o
rm -f libhellosecond.so
gcc -shared hellosecond.o -o libhellosecond.so
cp libhellosecond.so ../lib
cp *.h ../include
[dingqs@ADB200 hellosecond]$ cd ../
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ ├── hellosecond.o
│ ├── libhellosecond.so
│ └── Makefile
├── include
│ ├── hellofirst.h
│ └── hellosecond.h
├── lib
│ ├── libhellofirst.a
│ └── libhellosecond.so
├── Makefile
└── twohellos.c
4 directories, 16 files
[dingqs@ADB200 test_multproj]$
下面看看外层文件夹中的makefile文件如何写:
需要完成的功能包括:
1,分别到hellofirst和hellosecond文件夹中执行make命令;
2,使用lib和include中的库文件和头文件编译可执行文件twohellos;
3,实现make clean命令,功能包括分别到hellofirst和hellosecond中执行make clean和在当前目录下删除中间文件和可执行文件。
先看twohellos.c文件:
/* ------twohellos.c------------*/
#include "hellofirst.h" <--------------------------
#include "hellosecond.h" <--------------------------
int main(int argc,char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
再看Makefile 如何编写:
----------------------------------------
CC = gcc
CFLAGES = -Wall -ggdb -O0
SUBDIRS = hellofirst hellosecond
OBJS = twohellos.o
BIN = twohellos
LIB_PATH = ./lib
INCLUDE_PATH = ./include
LIB_PATH = ./lib
INCLUDE_PATH = ./include
all : subdirs mybin
subdirs :
for dir in $(SUBDIRS); \
do \
make -C $$dir; \
done
mybin : $(BIN)
$(BIN) : $(OBJS)
$(CC) $< -L$(LIB_PATH) -I$(INCLUDE_PATH) -lhellofirst -lhellosecond -o $@
%.o : %.c
$(CC) -c $(CFLAGES) $< -L$(LIB_PATH) -I$(INCLUDE_PATH) -lhellofirst -lhellosecond -o $@
.PHONY : clean
clean :
rm -f $(OBJS) $(BIN)
cd $(LIB_PATH); rm -f *
cd $(INCLUDE_PATH); rm -f *
for dir in $(SUBDIRS);\
do \
# make -C $$dir $@; \
cd $$dir; make -w $@; cd ../ ; \
done
----------------------------------------
验证功能:
[dingqs@ADB200 test_multproj]$ ll
total 24
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:26 hellofirst
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:33 hellosecond
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:33 include
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:33 lib
-rw-rw-r--. 1 dingqs dingqs 766 Feb 14 17:53 Makefile
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 12:08 twohellos.c
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ ├── hellosecond.o
│ ├── libhellosecond.so
│ └── Makefile
├── include
│ ├── hellofirst.h
│ └── hellosecond.h
├── lib
│ ├── libhellofirst.a
│ └── libhellosecond.so
├── Makefile
└── twohellos.c
4 directories, 16 files
[dingqs@ADB200 test_multproj]$ make
for dir in hellofirst hellosecond; \
do \
make -C $dir; \
done
make[1]: Entering directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellofirst'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellofirst'
make[1]: Entering directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellosecond'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellosecond'
gcc -c -Wall -ggdb -O0 twohellos.c -L./lib -I./include -lhellofirst -lhellosecond -o twohellos.o
gcc twohellos.o -L./lib -I./include -lhellofirst -lhellosecond -o twohellos
export LD_LIBRARY_PATH=/home/dingqs/gcc_test2/hello_1/test_multproj/lib:D_LIBRARY_PATH
[dingqs@ADB200 test_multproj]$
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ ├── hellosecond.o
│ ├── libhellosecond.so
│ └── Makefile
├── include
│ ├── hellofirst.h
│ └── hellosecond.h
├── lib
│ ├── libhellofirst.a
│ └── libhellosecond.so
├── Makefile
├── twohellos
├── twohellos.c
└── twohellos.o
4 directories, 18 files
[dingqs@ADB200 test_multproj]$ ./twohellos
./twohellos: error while loading shared libraries: libhellosecond.so: cannot open shared object file: No such file or directory
[dingqs@ADB200 test_multproj]$ export LD_LIBRARY_PATH=/home/dingqs/gcc_test2/hello_1/test_multproj/lib:D_LIBRARY_PATH
[dingqs@ADB200 test_multproj]$ ./twohellos
The first hello
The second hello
[dingqs@ADB200 test_multproj]$
在执行可执行文件时发现报错:
error while loading shared libraries: libhellosecond.so: cannot open shared object file: No such file or directory
这时由于可执行文件加载动态库时找不到libhellosecond.so文件。
如何解决:
1.就是按照上面的解决方法:
在shell下执行下面命令即可:
export LD_LIBRARY_PATH=/home/dingqs/gcc_test2/hello_1/test_multproj/lib:D_LIBRARY_PATH
有个缺点就是退出shell后,就无效了。
比如:执行上面export命令后,查看如下:
[dingqs@ADB200 test_multproj]$ ldd twohellos
linux-vdso.so.1 => (0x00007ffd25de8000)
libhellosecond.so => /home/dingqs/gcc_test2/hello_1/test_multproj/lib/libhellosecond.so (0x00007f2f827ce000)
libc.so.6 => /lib64/libc.so.6 (0x0000003724200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003723a00000)
ctrl+d后,即退出当前shell,然后重新连接后查看:
[dingqs@ADB200 test_multproj]$ ldd twohellos
linux-vdso.so.1 => (0x00007fff7697f000)
libhellosecond.so => not found
libc.so.6 => /lib64/libc.so.6 (0x0000003724200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003723a00000)
[dingqs@ADB200 test_multproj]$
[dingqs@ADB200 test_multproj]$
2,就是在makefile文件中使用"-Wl,R"参数;
说到这里,进一步说说LDFLAGS指定-L虽然能让链接器找到库进行链接,
但是运行时链接器却找不到这个库,如果要让软件运行时库文件的路径也得到扩展,
那么我们需要增加这两个库给"-Wl,R"
LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib
如 果在执行./configure以前设置环境变量
export LDFLAGS="-L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib" ,
注意设置环境变量等号两边不可以有空格,而且要加上引号哦(shell的用法)。
那么执行configure以后,Makefile将会设置这个选项, 链接时会有这个参数,
编译出来的可执行程序的库文件搜索路径就得到扩展了。
本文档内容:
1,验证在makefile文件中是否一定需要指定.h文件(头文件)?
2,遍历子目录,并且在子目录执行make命令。
3,执行make clean时,遍历子目录执行make clean命令。
4,使用makefile生成动态库和静态库。
测试用例:
twohellos.c 文件中有main函数,main 函数调用hellofirst.c和hellosecond.c中的函数hellofirst() 和 hellosecond();
其中hellofirst.h和hellosecond.h是其对应的头文件。
下面是文件源码:
/* ------hellofirst.c------------*/
#include <stdio.h>
void hellofirst()
{
printf("The first hello\n");
}
/* ------hellofirst.h------------*/
#ifndef HELLOFIRST_H
#define HELLOFIRST_H
extern void hellofirst(void);
#endif
/* ------hellosecond.c------------*/
#include <stdio.h>
void hellosecond()
{
printf("The second hello\n");
}
/* ------hellosecond.h------------*/
#ifndef HELLOSECOND_H
#define HELLOSECOND_H
extern void hellosecond(void);
#endif
/* ------twohellos.c------------*/
int main(int argc, char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
通过makefile实现生成可执行文件twohellos,
为了突出主题,gcc中有关的参数(比如:-g ,-Wall 等)就不写了。
内容如下:
---------------------------------------------------------------
twohellos : twohellos.o hellofirst.o hellosecond.o
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
twohellos.o : twohellos.c hellofirst.h hellosecond.h
gcc -c twohellos.c
hellofirst.o : hellofirst.c hellofirst.h
gcc -c hellofirst.c
hellosecond.o : hellosecond.c hellosecond.h
gcc -c hellosecond.c
.PHONY : clean
clean :
-rm -f *.o
-rm -f twohellos
---------------------------------------------------------------
操作过程如下:
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 74 Feb 13 14:12 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 98 Feb 14 10:13 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 76 Feb 13 14:12 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 102 Feb 14 10:14 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 385 Feb 14 10:25 Makefile
-rw-rw-r--. 1 dingqs dingqs 82 Feb 14 10:14 twohellos.c
[dingqs@localhost home]$ make
gcc -c twohellos.c
gcc -c hellofirst.c
gcc -c hellosecond.c
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
[dingqs@localhost test]$ ll
total 44
-rw-rw-r--. 1 dingqs dingqs 74 Feb 13 14:12 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 98 Feb 14 10:13 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 10:53 hellofirst.o
-rw-rw-r--. 1 dingqs dingqs 76 Feb 13 14:12 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 102 Feb 14 10:14 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 10:53 hellosecond.o
-rw-rw-r--. 1 dingqs dingqs 385 Feb 14 10:25 Makefile
-rwxrwxr-x. 1 dingqs dingqs 6719 Feb 14 10:53 twohellos
-rw-rw-r--. 1 dingqs dingqs 82 Feb 14 10:14 twohellos.c
-rw-rw-r--. 1 dingqs dingqs 1464 Feb 14 10:53 twohellos.o
[dingqs@localhost test]$ ./twohellos
The first hello
The second hello
[dingqs@localhost test]$ make clean
rm -f *.o
rm -f twohellos
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 74 Feb 13 14:12 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 98 Feb 14 10:13 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 76 Feb 13 14:12 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 102 Feb 14 10:14 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 385 Feb 14 10:25 Makefile
-rw-rw-r--. 1 dingqs dingqs 82 Feb 14 10:14 twohellos.c
[dingqs@localhost home]$
在真实的项目中.c文件中提供的对外接口一般放在同名的.h文件中,然后在.c文件中include即可。
同时,在包含main()函数的.c文件的头部都会include main函数使用其他.c文件对应的.h文件。
比较接近真实项目的代码如下(主要添加箭头指的那四行):
/* ------hellofirst.c------------*/
#include <stdio.h>
#include "hellofirst.h" <--------------------------
void hellofirst()
{
printf("The first hello\n");
}
/* ------hellofirst.h------------*/
#ifndef HELLOFIRST_H
#define HELLOFIRST_H
extern void hellofirst(void);
#endif
/* ------hellosecond.c------------*/
#include <stdio.h>
#include "hellosecond.h" <--------------------------
void hellosecond()
{
printf("The second hello\n");
}
/* ------hellosecond.h------------*/
#ifndef HELLOSECOND_H
#define HELLOSECOND_H
extern void hellosecond(void);
#endif
/* ------twohellos.c------------*/
#include "hellofirst.h" <--------------------------
#include "hellosecond.h" <--------------------------
int main(int argc,char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
上面对应的makefile文件就可以不再考虑那么多的.h文件了。这样看就舒服多了:
更新后的makefile如下:
---------------------------------------------------------------
twohellos : twohellos.o hellofirst.o hellosecond.o
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
twohellos.o : twohellos.c
gcc -c twohellos.c
hellofirst.o : hellofirst.c
gcc -c hellofirst.c
hellosecond.o : hellosecond.c
gcc -c hellosecond.c
.PHONY : clean
clean :
-rm -f *.o
-rm -f twohellos
---------------------------------------------------------------
下面是操作过程:
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 11:16 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 11:19 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 11:16 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 11:19 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 314 Feb 14 11:17 Makefile
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 11:17 twohellos.c
[dingqs@localhost test]$ make
gcc -c twohellos.c
gcc -c hellofirst.c
gcc -c hellosecond.c
gcc twohellos.o hellofirst.o hellosecond.o -o twohellos
[dingqs@localhost test]$ ll
total 44
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 11:16 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 11:19 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 11:20 hellofirst.o
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 11:16 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 11:19 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 1504 Feb 14 11:20 hellosecond.o
-rw-rw-r--. 1 dingqs dingqs 314 Feb 14 11:17 Makefile
-rwxrwxr-x. 1 dingqs dingqs 6719 Feb 14 11:20 twohellos
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 11:17 twohellos.c
-rw-rw-r--. 1 dingqs dingqs 1448 Feb 14 11:20 twohellos.o
[dingqs@localhost test]$ ./twohellos
The first hello
The second hello
[dingqs@localhost test]$ make clean
rm -f *.o
rm -f twohellos
[dingqs@localhost test]$ ll
total 24
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 11:16 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 11:19 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 11:16 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 11:19 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 314 Feb 14 11:17 Makefile
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 11:17 twohellos.c
[dingqs@localhost test]$$
在真实的项目中很少把所有的文件放在一个文件夹中,
往往是每个模块放在一个文件夹中,各个模块共同编译出最终的可执行文件。
为了说明这个情况,下面把上面的代码结构修改一下:
当前文件夹下有Makefile,twohellos.c两个文件,和hellofirt,hellosecond两个文件夹;
其中hellofirst.c和hellofirst.h放在hellofirst文件夹中,
hellosecond.c和hellosecond.h放在hellosecond文件夹中。
为了模拟更多情况,在当前文件下再创建lib和include两个文件夹。
其中lib文件夹存放hellofirst和hellosecond文件夹中执行make命令产生的静态库libhellofirst.a和动态库libhellosecond.so;
其中include文件夹存放hellofirst和hellosecond文件夹中产生的静态库和动态库对应的头文件:hellofirst.h和hellosecond.h。
结构如下:
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ └── Makefile
├── include
├── lib
├── Makefile
└── twohellos.c
4 directories, 8 files
[dingqs@ADB200 test_multproj]$
在外层执行make命令时,会进入hellofirst和hellosecond文件夹中执行make命令。
所以hellofirst和hellosecond文件夹中都需要有相应的makefile文件。
注意:所有的.c和.h文件中的内容都没有任何变化,和上面的例子一样,
不过为了方便,不至于翻到上面查看代码,所以在此处会原样的copy过来。
所以重点还是关注每个Makefile文件的内容。
首先看hellofirst文件夹中的内容:
/* ------hellofirst.c------------*/
#include <stdio.h>
#include "hellofirst.h" <--------------------------
void hellofirst()
{
printf("The first hello\n");
}
/* ------hellofirst.h------------*/
#ifndef HELLOFIRST_H
#define HELLOFIRST_H
extern void hellofirst(void);
#endif
在hellofirst文件夹中的makefile需要完成编译hellofirst.c和hellofirst.h成静态库libhellofirst.a;
同时把这个静态库copy到lib中,把hellofirst.h头文件copy到include中。
下面是makfile源码:
----------------------------------------
LIB_TOP_DIR = ../lib
INC_TOP_DIR = ../include
CC = gcc
CFLAGES := -Wall -ggdb -O0
OBJS = hellofirst.o
LIB = libhellofirst.a
INC = hellofirst.h
all : $(LIB)
# get .a file
$(LIB) : $(OBJS)
rm -f $@
ar cr $@ $^
cp $(LIB) $(LIB_TOP_DIR)
cp *.h $(INC_TOP_DIR)
# get .o file
%.o : %.c
$(CC) -c $(CFLAGES) $< -o $@
.PHONY : clean
clean :
rm -f $(OBJS) $(LIB)
cd $(LIB_TOP_DIR); rm -f $(LIB)
cd $(INC_TOP_DIR); rm -f $(INC)
----------------------------------------
验证一下结果:
[dingqs@ADB200 test_multproj]$ cd hellofirst/
[dingqs@ADB200 hellofirst]$ ll
total 12
-rw-rw-r--. 1 dingqs dingqs 94 Feb 14 12:07 hellofirst.c
-rw-rw-r--. 1 dingqs dingqs 95 Feb 14 12:07 hellofirst.h
-rw-rw-r--. 1 dingqs dingqs 458 Feb 14 15:57 Makefile
[dingqs@ADB200 hellofirst]$ make
gcc -c -Wall -ggdb -O0 hellofirst.c -o hellofirst.o
rm -f libhellofirst.a
ar cr libhellofirst.a hellofirst.o
cp libhellofirst.a ../lib
cp *.h ../include
[dingqs@ADB200 hellofirst]$ cd ../
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ └── Makefile
├── include
│ └── hellofirst.h
├── lib
│ └── libhellofirst.a
├── Makefile
└── twohellos.c
4 directories, 12 files
[dingqs@ADB200 test_multproj]$
由上面的结果可知这个makefile文件实现了想要的功能。
下面进入hellosecond文件夹,如何实现makefile,生成动态库。
hellosecond.c和hellosecond.h文件内容如下:
/* ------hellosecond.c------------*/
#include <stdio.h>
#include "hellosecond.h" <--------------------------
void hellosecond()
{
printf("The second hello\n");
}
/* ------hellosecond.h------------*/
#ifndef HELLOSECOND_H
#define HELLOSECOND_H
extern void hellosecond(void);
#endif
在 hellosecond 文件夹中的makefile需要完成编译hellosecond.c和hellosecond.h成动态库libhellosecond.so;
同时把这个动态库copy到lib中,把hellosecond.h头文件copy到include中。
下面是makfile源码:
----------------------------------------
LIB_TOP_DIR = ../lib
INC_TOP_DIR = ../include
CC = gcc
CFLAGES := -Wall -ggdb -O0
OBJS = hellosecond.o
LIB = libhellosecond.so
INC = hellosecond.h
all : $(LIB)
# get .so file
$(LIB) : $(OBJS)
rm -f $@
$(CC) -shared $^ -o $@
cp $(LIB) $(LIB_TOP_DIR)
cp *.h $(INC_TOP_DIR)
# get .o file
%.o : %.c
$(CC) -c $(CFLAGES) -fpic $< -o $@
.PHONY : clean
clean :
rm -f $(OBJS) $(LIB)
cd $(LIB_TOP_DIR); rm -f $(LIB)
cd $(INC_TOP_DIR); rm -f $(INC)
----------------------------------------
验证下结果:
[dingqs@ADB200 test_multproj]$ cd hellosecond/
[dingqs@ADB200 hellosecond]$ ll
total 12
-rw-rw-r--. 1 dingqs dingqs 97 Feb 14 12:07 hellosecond.c
-rw-rw-r--. 1 dingqs dingqs 99 Feb 14 12:07 hellosecond.h
-rw-rw-r--. 1 dingqs dingqs 480 Feb 14 15:57 Makefile
[dingqs@ADB200 hellosecond]$ make
gcc -c -Wall -ggdb -O0 -fpic hellosecond.c -o hellosecond.o
rm -f libhellosecond.so
gcc -shared hellosecond.o -o libhellosecond.so
cp libhellosecond.so ../lib
cp *.h ../include
[dingqs@ADB200 hellosecond]$ cd ../
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ ├── hellosecond.o
│ ├── libhellosecond.so
│ └── Makefile
├── include
│ ├── hellofirst.h
│ └── hellosecond.h
├── lib
│ ├── libhellofirst.a
│ └── libhellosecond.so
├── Makefile
└── twohellos.c
4 directories, 16 files
[dingqs@ADB200 test_multproj]$
下面看看外层文件夹中的makefile文件如何写:
需要完成的功能包括:
1,分别到hellofirst和hellosecond文件夹中执行make命令;
2,使用lib和include中的库文件和头文件编译可执行文件twohellos;
3,实现make clean命令,功能包括分别到hellofirst和hellosecond中执行make clean和在当前目录下删除中间文件和可执行文件。
先看twohellos.c文件:
/* ------twohellos.c------------*/
#include "hellofirst.h" <--------------------------
#include "hellosecond.h" <--------------------------
int main(int argc,char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
再看Makefile 如何编写:
----------------------------------------
CC = gcc
CFLAGES = -Wall -ggdb -O0
SUBDIRS = hellofirst hellosecond
OBJS = twohellos.o
BIN = twohellos
LIB_PATH = ./lib
INCLUDE_PATH = ./include
LIB_PATH = ./lib
INCLUDE_PATH = ./include
all : subdirs mybin
subdirs :
for dir in $(SUBDIRS); \
do \
make -C $$dir; \
done
mybin : $(BIN)
$(BIN) : $(OBJS)
$(CC) $< -L$(LIB_PATH) -I$(INCLUDE_PATH) -lhellofirst -lhellosecond -o $@
%.o : %.c
$(CC) -c $(CFLAGES) $< -L$(LIB_PATH) -I$(INCLUDE_PATH) -lhellofirst -lhellosecond -o $@
.PHONY : clean
clean :
rm -f $(OBJS) $(BIN)
cd $(LIB_PATH); rm -f *
cd $(INCLUDE_PATH); rm -f *
for dir in $(SUBDIRS);\
do \
# make -C $$dir $@; \
cd $$dir; make -w $@; cd ../ ; \
done
----------------------------------------
验证功能:
[dingqs@ADB200 test_multproj]$ ll
total 24
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:26 hellofirst
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:33 hellosecond
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:33 include
drwxrwxr-x. 2 dingqs dingqs 4096 Feb 15 11:33 lib
-rw-rw-r--. 1 dingqs dingqs 766 Feb 14 17:53 Makefile
-rw-rw-r--. 1 dingqs dingqs 126 Feb 14 12:08 twohellos.c
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ ├── hellosecond.o
│ ├── libhellosecond.so
│ └── Makefile
├── include
│ ├── hellofirst.h
│ └── hellosecond.h
├── lib
│ ├── libhellofirst.a
│ └── libhellosecond.so
├── Makefile
└── twohellos.c
4 directories, 16 files
[dingqs@ADB200 test_multproj]$ make
for dir in hellofirst hellosecond; \
do \
make -C $dir; \
done
make[1]: Entering directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellofirst'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellofirst'
make[1]: Entering directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellosecond'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/dingqs/gcc_test2/hello_1/test_multproj/hellosecond'
gcc -c -Wall -ggdb -O0 twohellos.c -L./lib -I./include -lhellofirst -lhellosecond -o twohellos.o
gcc twohellos.o -L./lib -I./include -lhellofirst -lhellosecond -o twohellos
export LD_LIBRARY_PATH=/home/dingqs/gcc_test2/hello_1/test_multproj/lib:D_LIBRARY_PATH
[dingqs@ADB200 test_multproj]$
[dingqs@ADB200 test_multproj]$ tree
.
├── hellofirst
│ ├── hellofirst.c
│ ├── hellofirst.h
│ ├── hellofirst.o
│ ├── libhellofirst.a
│ └── Makefile
├── hellosecond
│ ├── hellosecond.c
│ ├── hellosecond.h
│ ├── hellosecond.o
│ ├── libhellosecond.so
│ └── Makefile
├── include
│ ├── hellofirst.h
│ └── hellosecond.h
├── lib
│ ├── libhellofirst.a
│ └── libhellosecond.so
├── Makefile
├── twohellos
├── twohellos.c
└── twohellos.o
4 directories, 18 files
[dingqs@ADB200 test_multproj]$ ./twohellos
./twohellos: error while loading shared libraries: libhellosecond.so: cannot open shared object file: No such file or directory
[dingqs@ADB200 test_multproj]$ export LD_LIBRARY_PATH=/home/dingqs/gcc_test2/hello_1/test_multproj/lib:D_LIBRARY_PATH
[dingqs@ADB200 test_multproj]$ ./twohellos
The first hello
The second hello
[dingqs@ADB200 test_multproj]$
在执行可执行文件时发现报错:
error while loading shared libraries: libhellosecond.so: cannot open shared object file: No such file or directory
这时由于可执行文件加载动态库时找不到libhellosecond.so文件。
如何解决:
1.就是按照上面的解决方法:
在shell下执行下面命令即可:
export LD_LIBRARY_PATH=/home/dingqs/gcc_test2/hello_1/test_multproj/lib:D_LIBRARY_PATH
有个缺点就是退出shell后,就无效了。
比如:执行上面export命令后,查看如下:
[dingqs@ADB200 test_multproj]$ ldd twohellos
linux-vdso.so.1 => (0x00007ffd25de8000)
libhellosecond.so => /home/dingqs/gcc_test2/hello_1/test_multproj/lib/libhellosecond.so (0x00007f2f827ce000)
libc.so.6 => /lib64/libc.so.6 (0x0000003724200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003723a00000)
ctrl+d后,即退出当前shell,然后重新连接后查看:
[dingqs@ADB200 test_multproj]$ ldd twohellos
linux-vdso.so.1 => (0x00007fff7697f000)
libhellosecond.so => not found
libc.so.6 => /lib64/libc.so.6 (0x0000003724200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003723a00000)
[dingqs@ADB200 test_multproj]$
[dingqs@ADB200 test_multproj]$
2,就是在makefile文件中使用"-Wl,R"参数;
说到这里,进一步说说LDFLAGS指定-L虽然能让链接器找到库进行链接,
但是运行时链接器却找不到这个库,如果要让软件运行时库文件的路径也得到扩展,
那么我们需要增加这两个库给"-Wl,R"
LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib
如 果在执行./configure以前设置环境变量
export LDFLAGS="-L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib" ,
注意设置环境变量等号两边不可以有空格,而且要加上引号哦(shell的用法)。
那么执行configure以后,Makefile将会设置这个选项, 链接时会有这个参数,
编译出来的可执行程序的库文件搜索路径就得到扩展了。
相关文章推荐
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile编写----实例展示
- Makefile 编写实例
- Makefile编写实例(生成so文件)
- Makefile编写------------实例演示
- Linux/Unix下makefile文件编写实例
- Makefile自动编写工具实例