g++编译单文件
1、为了统一管理,我们在/home/carl下创建一个c++的文件夹
命令:mkdir -p /home/carl/c++ (加上-p防止上一级路径不存在)
2、新建一个main.cpp源代码文件,文件内容使用c++打印出自己的学号
提示:编辑文档可使用vim或者gedit
3、使用g++编译并链接main.cpp文件
只编译
g++ -o main.o -c main.cpp
(-o:指定生成可执行文件的名称 -c:只编译不链接,只生成目标文件。)
链接
g++ -o myid main.o
运行
./myid
g++编译多个文件
1、新建两
个文件,分别命名为func.cpp和func.h,分别写入如下内容
#include "func.h"
void print_func1(void)
{
cout<<"using func1—lin"<<endl;
}
#ifndef _FUNC_H
#define _FUNC_H
#include<iostream>
using namespace std;
void print_func1(void);
#endif
2、修改main.cpp文件,内容如下
#include "func.h"
int main(int argc,char** argv)
{
print_func1();
return 0;
}
3、使用g++编译并链接多个cpp和h文件
编译
g++ -o main.o -c main.cpp
g++ -o func.o -c func.cpp
链接
g++ -o myid main.o func.o
运行
./myid
练习:请在上面的基础上增加一对cpp和h文件,在这对文件里,实现函数打印
using func2—学号,完成后在主函数调用,并编译链接形成可执行文件
Makefile编译普通工程
Linux下的软件编译,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
(回想编译nginx中 make -j8这个命令,其实用到的就是makefile这个编译命令文件)
makefile文件结构如下
target: prerequisites
command
target也就是一个目标文件,可以是Object File,也可以是执行文件,还可以是一个标签。prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(Shell命令)
接下来以编译前面ppt的多文件编译的makefile为例来说明
1、前面编译用的命令如下
编译
g++ -o main.o -c main.cpp
g++ -o func.o -c func.cpp
链接
g++ -o myid main.o func.o
将这三句用makefile来表示,形式如下
编译
目标 依赖
main.o:main.cpp
g++ -c main.cpp
shell命令
func.o:func.cpp
g++ -c func.cpp
链接
myid:func.o main.o
g++ -o myid func.o main.o
2、将上述命令写入名为Makefile的文件
3、请实验在终端中打入
(1)
make
rm -f main.o
(2)
make main.o
rm -f main.o
(3)
make func.o
rm -f func.o
(4)
make myid
观察(1)和(2)对应的输出结果,可以知道make和make main.o的效果是一致
4、那么为了执行make就完成编译链接,就应该把最后一个目标拿到第一个,结果如下
5、请完成上一个练习(3个cpp文件)的工程的makefile的书写
6、经常在编译完成后我们经常需要清理中间文件,或者有时希望清理掉所有编译链接生成的文件,因此可以添加clean这个规则
Makefile编译带动态库工程
1、接下来介绍需要链接外部动态库工程的makefile的书写
当有些函数经常需要使用时,比如日志系统函数,我们可以把它封装成动态库或者静态库(这边可自行查找下动态库和静态库的区别)。
在例子中,我们将func.cpp和func.h这个功能函数封装成libfunc.so动态库
2、首先复制一份c++文件夹及目录下的文件,接着切换到c++so中将func.cpp编译成动态库
cp -r /home/carl/c++ /home/carl/c++so
cd /home/carl/c++so
g++ func.cpp -fPIC -shared -o libfunc.so
3、如图,运行完后,会出现一个libfunc.so文件,即我们需要的动态库
4、接着以自己学号创建一个文件夹,将func.h和libfunc.so放入该文件夹下,此时完全可以将func.cpp这个文件删掉
5、接下来修改main.cpp文件,内容如下
#include "func.h"
int main(int argc,char** argv)
{
print_func1();
return 0;
}
5、重要的步骤来了,我们需要修改makefile,在makefile修改中需要在编译的时候指向头文件,在链接的时候指向动态库,同时为了方便可采用shell中变量赋值的方式进行修改,最终的makefile如下(特别需要注意inc和libs这个路径到底要指向哪里)
6、至此结束
利用cmake生成Makefile
makefile的写法还是有点麻烦,那有没有更好的自动生成makefile的工具呢?答案是有,而且很多,回想一下配置nginx第一步运行./configure其实这一步就是在生成对应的makefile
这里给大家介绍cmake的用法,因为比如很多代码opencv(图像处理)、pix-autopilot(飞控)都是用cmake来完成makefile的生成。
1、创建一个cmake的文件夹用来放置实验要用的文件,然后在cmake中将如下代码放入main.cpp文件中
#include<iostream>
using namespace std;
int main(int argc,char** argv)
{
cout<<"MDA19115"<<endl;
return 0;
}
2、创建CMakeLists.txt文件,并在文件内填入如下内容
PROJECT(myid)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
add_executable(myid main.cpp)
1、利用cmake生成多文件工程的makefile
仿照makefile编译多文件工程的方式建立main.cpp func.cpp func.h三个文件
2、编辑CMakeLists.txt,主要要指定源代码的位置在哪即可,
PROJECT(myid)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
AUX_SOURCE_DIRECTORY(/home/carl/cmake/ DIR_SRCS)
ADD_EXECUTABLE(myid ${DIR_SRCS})
3、配置并编译,可以看到先编译func.o再编译main.cpp.o
接下来完成带有动态链接库的工程的cmake配置
1、将前面makefile编译带动态库的动态库和头文件所在的lin文件夹拷贝到当前目录下,并删除func.cpp
2、编译带有动态库需要指定头文件目录,因此需要加下以下语句
include_directories(/home/carl/cmake/MDA19115)
3、链接带有动态库需要指定链接库,虚词需要添加以下语句,这样g++才能链接到动态库
target_link_libraries(myid /home/carl/cmake/MDA19115/libfunc.so)
4、最终的cmakelist.txt内容如下
5、生成makefile并编译
最后,可以利用cmake配置makefile将我们所写的程序或者动态库打包成deb包
1、只要在cmakelist.txt中添加如下信息:
#设置安装目录
set(CMAKE_INSTALL_PREFIX "/home/carl/cmake/install")
#拷贝依赖库头文件
set_target_properties(myid PROPERTIES PUBLIC_HEADER "/home/carl/cmake/lin/func.h")
install(TARGETS myid
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
#拷贝依赖库到lib目录下
install(FILES /home/carl/cmake/lin/libfunc.so DESTINATION lib)
2、请将以下信息改成自己的,需要出现学号信息,作为最后截图用
#设置deb包信息
set(CPACK_SET_DESTDIR ON)
set(CPACK_PACKAGE_NAME "myid")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "myid")
set(CPACK_PACKAGE_VENDOR "myid")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_CONTACT "lin")
set(CPACK_PACKAGE_VERSION_MAJOR "1")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_RPM_PACKAGE_GROUP "myid")
set(CPACK_RPM_PACKAGE_URL "xujc lin")
set(CPACK_RPM_PACKAGE_DESCRIPTION "myid")
set(CPACK_PACKAGE_RELEASE 1)
set(CPACK_RPM_PACKAGE_LICENSE "myid")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "func")
# 设置默认生成器
set(CPACK_GENERATOR "DEB")
include(CPack)
3、配置并生成deb包
cmake .
make package
可以看到生成了deb包
4、通过三个命令查看deb包的信息
dpkg-deb -W 包名 #查看信息
dpkg-deb -c 包名 #安装这个包会提供哪些文件
dpkg-deb -I 包名 #包具体信息