C++学习笔记(37)
302、makefile
在实际开发中,项目的源代码文件比较多,按类型、功能、模块分别存放在不同的目录和文件中,哪
些文件需要先编译,那些文件后编译,那些文件需要重新编译,还有更多更复杂的操作。
make 是一个强大的实用工具,用于管理项目的编译和链接。make 需要一个编译规则文件 makefile,
可实现自动化编译。 一、app/demo01.cpp
#include "public.h" // 包含通用函数和类的头文件。
#include "myapi.h" // 包含另一个通用函数和类的头文件。
using namespace std;
int main()
{
func(); // 调用通用的函数。
func1(); // 调用另一个通用的函数。
AA a; // 用通用类声明对象。
a.show(); // 调用对象的方法。
BB b; // 用另一个通用类声明对象。
b.show(); // 调用对象的方法。
}
二、app/makefile
INCLUDEDIR=-I/home/wucz/tools -I/home/wucz/api
LIBDIR=-L/home/wucz/tools -L/home/wucz/api
all:demo01 demo02 demo03
demo01:demo01.cpp
g++ -o demo01 demo01.cpp $(INCLUDEDIR) $(LIBDIR) -lpublic -lmyapi
cp demo01 /tmp/. demo02:demo02.cpp
g++ -o demo02 demo02.cpp $(INCLUDEDIR) $(LIBDIR) -lpublic -lmyapi
demo03:demo03.cpp
g++ -o demo03 demo03.cpp $(INCLUDEDIR) $(LIBDIR) -lpublic -lmyapi
clean:
rm -f demo01 demo02 demo03
三、tools/public.h
// 通用函数和类的头文件。
#include <iostream>
// 声明一个通用的函数。
void func();
// 声明一个通用的类。
class AA
{
public:
void show();
};
四、tools/public.cpp
// 通用函数和类的代码实现文件。
#include "public.h" using namespace std;
// 通用函数的代码实现。
void func()
{
cout << "升级了调用了 func()函数。\n";
}
// 通用类的代码实现。
void AA::show()
{
cout << "升级了我是一只傻傻鸟。\n";
}
五、tools/makefile
# 指定编译的目标文件是 libpublic.a 和 libpublic.so
all:libpublic.a \
libpublic.so
# 编译 libpublic.a 需要依赖 public.h 和 public.cpp
# 如果被依赖文件内容发生了变化,将重新编译 libpublic.a
libpublic.a:public.h public.cpp
g++ -c -o libpublic.a public.cpp
libpublic.so:public.h public.cpp
g++ -fPIC -shared -o libpublic.so public.cpp
# clean 用于清理编译目标文件,仅在 make clean 才会执行。
clean:
rm -f libpublic.a libpublic.so
六、api/myapi.h
// 另一个通用函数和类的头文件。
#include <iostream>
// 声明一个通用的函数。
void func1();
// 声明一个通用的类。
class BB
{
public:
void show();
};
七、api/myapi.cpp
// 另一个通用函数和类的代码实现文件。
#include "myapi.h" using namespace std;
// 通用函数的代码实现。
void func1()
{
cout << "调用了 func1()函数。\n";
}
// 通用类的代码实现。
void BB::show()
{
cout << "你是一只傻傻鸟。\n";
}
八、api/makefile
# 指定编译的目标文件是 libmyapi.a 和 libmyapi.so
all:libmyapi.a libmyapi.so
# 编译 libmyapi.a 需要依赖 myapi.h 和 myapi.cpp
# 如果被依赖文件内容发生了变化,将重新编译 libmyapi.a
libmyapi.a:myapi.h myapi.cpp
g++ -c -o libmyapi.a myapi.cpp
libmyapi.so:myapi.h myapi.cpp
g++ -fPIC -shared -o libmyapi.so myapi.cpp
# clean 用于清理编译目标文件,仅在 make clean 才会执行。
clean:
rm -f libmyapi.a libmyapi.so
303、main 函数的参数
一、main 函数的参数
main 函数有三个参数,argc、argv 和 envp,它的标准写法如下:
int main(int argc,char *argv[],char *envp[])
{
return 0;
}
argc 存放了程序参数的个数,包括程序本身。
argv 字符串的数组,存放了每个参数的值,包括程序本身。
envp 字符串的数组,存放了环境变量,数组的最后一个元素是空。
在程序中,如果不关心 main()函数的参数,可以省略不写。 二、操作环境变量
1)设置环境变量
int setenv(const char *name, const char *value, int overwrite);
name 环境变量名。
value 环境变量的值。
overwrite 0-如果环境不存在,增加新的环境变量,如果环境变量已存在,不替换其值;非 0-如果
环境不存在,增加新的环境变量,如果环境变量已存在,替换其值。
返回值:0-成功;-1-失败(失败的情况极少见)。
注意:此函数设置的环境变量只对本进程有效,不会影响 shell 的环境变量。如果在运行程序时执行
了 setenv()函数,进程终止后再次运行该程序,上次的设置是无效的。
2)获取环境变量的值
char *getenv(const char *name);
三、示例
#include <iostream>
using namespace std;
int main(int argc,char *argv[],char *envp[])
{
if (argc!=4)
{
cout << "表白神器程序的使用方法:./demo 追求者姓名 被追求者姓名 表白内容\n";
return -1;
}
cout << argv[1] << "开始向" << argv[2] << "表白。\n";
cout << argv[3] << endl;
cout << argv[1] << "表白完成。\n";
return 0;
cout << "一共有" << argc << "个参数。\n";
// 显示全部的参数。
for (int ii=0;ii<argc;ii++)
{
cout << "第" << ii << "个参数:" << argv[ii] << endl;
}
// 显示全部的环境变量。
for (int ii=0;envp[ii]!=0;ii++) // 环境变量数组最后一个元素是 0。
{
cout << envp[ii] << endl;
}
// 设置环境变量 AA。
setenv("AA","aaaa",0);
// 显示环境变量 AA 的值。
cout << "AA=" << getenv("AA") << endl;
return 0;
}