**Linux 知识补充 -- 程序的静态与动态编译** 1652270 **冯舜** 额外加分作业 ============================= 具体思路: - 编译的机器需要有 `mariadb-devel` 包, 可直接在 CentOS ISO 用 `yum` 获得 - 从 http://rpm.pbone.net/index.php3/stat/3/srodzaj/2/search/mariadb-5.5.56-2.el7.src.rpm 下载 mariadb 的源码 `mariadb-5.5.56-2.el7.src.rpm`, 解压得到 `.tar.gz` 文件, 再次解压它, 得到一个 CMake 工程 - 切换到工程文件夹, 将 CMake 工程进行构建: `cmake . -DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock`. 参数 `-DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock` 必须添加, 否则生成出来的库文件指定的 socket 默认路径 `/tmp/mysql.sock` 会与 CentOS 环境中的 MySQL socket 文件位置 (`/var/lib/mysql/mysql.sock`) 不同. - 构建后直接在当前目录得到一个 Makefile 工程, 再用 `make` 构建它. - 构建后得到 `./libmysql/libmysqlclient.a`, 是 MySQL 客户端库的静态库文件. 放在 `mysql_demo.cpp` 同目录中. - 再从 `libstdc++-static`、`zlib-static` 包中提取出 `libz.a`、`libstdc++.a` 等静态库文件, 放在 `mysql_demo.cpp` 同目录中. - 使用 `g++ -static -nostartfiles -nostdlib ```mysql_config --cflags``` -o mysql_demo "/usr/lib64/"crt1.o "/usr/lib64/"crti.o "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/"crtbeginT.o mysql_demo.cpp ./libmysqlclient.a ./libstdc++.a "/usr/lib/x86_64-redhat-linux6E/lib64/"libpthread.a "/usr/lib/x86_64-redhat-linux6E/lib64/"libdl.a "/usr/lib/x86_64-redhat-linux6E/lib64/"librt.a "/usr/lib/x86_64-redhat-linux6E/lib64/"libm.a ./libz.a "/usr/lib/x86_64-redhat-linux6E/lib64/"libc.a "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/"libgcc_eh.a "/usr/lib/x86_64-redhat-linux6E/lib64/"libc.a "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/"crtend.o "/usr/lib64/"crtn.o` 完成编译. 可用 `makefile` 做一些变量替换, 详见下面的 `makefile` 文件源码. - 该命令的思路为: 用 `-nostdlib` 取消 gcc 默认加上的系统库, 而转为自行模拟 gcc 添加系统库和 C 运行时目标文件 (`crt*.o`) 的行为, 将所有涉及到 `libc` 等底层库的库文件替换为 `.a` 静态库. ~~~~~~~~~~~~~~~~~~~~~~~~Makefile all : mysql_demo MYLIBDIR = "/usr/lib/x86_64-redhat-linux6E/lib64/" MYLIBDIR2 = "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/" MYLIBDIR3 = "/usr/lib64/" mysql_demo : mysql_demo.cpp $(CXX) -static -nostartfiles -nostdlib `mysql_config --cflags` -o $@ $(MYLIBDIR3)crt1.o $(MYLIBDIR3)crti.o $(MYLIBDIR2)crtbeginT.o $^ ./libmysqlclient.a ./libstdc++.a $(MYLIBDIR)libpthread.a $(MYLIBDIR)libdl.a $(MYLIBDIR)librt.a $(MYLIBDIR)libm.a ./libz.a $(MYLIBDIR)libc.a $(MYLIBDIR2)libgcc_eh.a $(MYLIBDIR)libc.a $(MYLIBDIR2)crtend.o $(MYLIBDIR3)crtn.o .PHONY : clean clean : $(RM) mysql_demo mysql_demo.o ~~~~~~~~~~~~~~~~~~~~~~~~ 将整个工程目录复制到另一台虚拟机上 (该虚拟机应有一个正确配置的 MySQL 服务器, 密码为 `root123`), 执行 `make` 并运行生成的可执行文件, 发现一切正常. ![Figure [bonus1]: 构建运行正常](pic3/bonus1.png width=100%)