linux的make和makefile学习
- 准备工作
- 使用GNU链接库
- 链接到math库
- 编写复利程序
- 创建自己的库
- 链接到主目录
- 不同的C标准
准备工作
安装GCC和Make工具
安装中文输入法
参考:http://t.csdn.cn/eH0Ow
sudo apt-get update
sudo apt-get install ibus
sudo apt-get install ibus-pinyin
sudo apt-get install fcitx
sudo apt-get install fcitx-pinyin
完成后重启
重启进入设置:
使用GNU链接库
链接到math库
编写复利程序
命名为interest.c
#include <studio.h>
#include <math.h>
int main(void)
{
int years=15; /*要存多少年 */
int savings=99000; /*存多少钱*/
float interest=1.5; /*年利率为1.5%*/
printf("The total savings after %d years is %.2f\n", years, savings * pow(1+(interest/100),years));
return 0;
}
编译链接程序:
编译链接库:-lz -lrt -lm -lc都是什么库
-lz 压缩库(Z)
-lrt 实时库(real time):shm_open系列
-lm 数学库(math)
-lc 标准C库(C lib)
-dl ,是显式加载动态库的动态函数库
gcc interest.c -o interest -lm
./interest #运行程序
-o指定编译汇编输出程序名
创建自己的库
1、创建头文件:prime.h
2、创建库文件:prime.c
int isprime(long int number)
{
long int j; /*长整型*/
int prime=1;
/*测试是否这个数能被整除,从2开始*/
for(j=2;j<number;j++)
{
/*用取余操作测试这个数能否被整除*/
if(number%j==0)
{
prime=0; //不是素数
}
}
if(prime==1)
{
return 1;//素数
}
else{
return 0;//非素数
}
}
3、编译成目标文件
gcc -Wall -Wextra -pedantic -fPIC -c prime.c
-Wall:开启所有警告(可以理解为warinig all),使用它能够使GCC产生尽可能多的警告信息。(非常推荐使用该选项)GCC给出的警告信息虽然从严格意义上说不能算作错误,但却很可能成为错误的栖身之所。
-Wextra是关于打开警告的,这些警告可能比其他选项更有用或更麻烦(因为它们可能警告程序员可以接受的代码)。
-pedantic 是 GCC 编译器的一个编译选项。这个选项会让编译器严格遵守 C++ 标准,并输出标准要求的诊断信息,对于一些可能不符合 C++ 标准的语法或者行为会给出警告或者错误提示。
-fpic 该选项用于生成位置无关代码(PIC),尤其被用于共享库的创建(如果目标机器架构支持的话)。使用该选项编译出的代码在访问所有常量地址时,会通过全局偏移表(GOT)进行计算得到。
-c参数是用来编译源代码文件,生成目标文件(object file)的选项(.o)。
4、将目标文件打包成库
gcc -shared -Wl,-soname,libprime.so -o libprime.so prime.o
使用 -shared 选项生成共享库时,最好还是带上 -fpic 或 -fPIC 等选项。
-Wl后面的东西是作为参数传递给链接器ld的
-soname则指定了动态库的soname(简单共享名,Short for shared object name)
这样做的目的主要是允许系统中多个版本的库文件共存,习惯上在命名库文件的时候通常与soname相同
libxxxx.so.major.minor
其中,xxxx是库的名字,major是主版本号,minor 是次版本号
-o指定输出文件名libprime.so
被包含在共享库中的目标文件prime.o
链接到主目录
1、写程序is-it-a-prime.c,调用共享库libprime.so
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "prime.h"
int main(int argc, char *argv[])
{
long int num;
/*只接收一个参数*/
if (argc!=2)
{
fprintf(stderr, "Usage: %s number\n", argv[0]);//stderr -- 标准错误输出设备
return 1;
}
/*只接收数字0-9*/
if (strspn(argv[1],"0123456789")!=strlen(argv[1]))
//strspn返回字符串s开头连续包含字符串accept内的字符数目。 若strspn()返回的数值为n,则代表字符串s 开头连续有n 个字符都是属于字符串accept内的字符。
// strlen函数:当计算长度时,只有遇到'\0'才会停止计算,同时计算的长度不包含'\0'。
{
fprintf(stderr, "Only numeric values are accepted\n");
return 1;
}
num=atol(argv[1]); //atol() C 标准库 - <stdlib.h> 描述 C 库函数 long int atol(const char *str) 把参数 str 所指向的字符串转换为一个长整数(类型为 long int 型)。
if(isprime(num)) //是否素数
{
printf("%ld is a prime\n", num);
}
else
{
printf("%ld is not a prime\n", num);
}
return 0;
}
2、链接
gcc -L${PWD} is-it-a-prime.c -o is-it-a-prime -lprime #指定共享库路径
export LD_LIBRARY_PATH=${PWD}:${LD_LIBRARY_PATH} #设置环境变量为共享库目录(当前目录)
-L用来告诉gcc去哪里找库文件。 通常来讲, gcc默认会在程序当前目录、/lib、/usr/lib和/usr/local/lib下找对应的库。
-L /home/hello/lib,表示将/home/hello/lib目录作为第一个寻找库文件的目录, 寻找的顺序是:/home/hello/lib–>/lib–>/usr/lib–>/usr/local/lib
LD_LIBRARY_PATH 这个环境变量是大家最为熟悉的,它告诉loader:在哪些目录中可以找到共享库。可以设置多个搜索目录,这些目录之间用冒号分隔开。
假如现在需要在已有的环境变量上添加新的路径名,则采用如下方式: LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH.(newdirs是新的路径串)
不同的C标准
C89是1989年发布的,兼容性最好,使用最广泛,实现最完整
C99更新一些
写两个进程,分别用C89和C99编译
1、写c文件no-return.c
在这里插入代码片
2、用C89编译程序