如何编译一个程序?
如何编译一个程序?
// hello.c
#include <stdio.h>
int main()
{
printf("hello word!\n");
return 0;
}
// hello.cpp
#include <iostream>
using namespace std;
int main()
{
cout<<"hello world!"<<endl;
return 0;
}
gcc -o hello hello.c
gcc -o hello hello.cpp -lstdc++
g++ -o hello hello.cpp
gcc -I <头文件目录> -o main main.c sub.c add.c
编译流程
什么是Makefile?
Makefile 是一个程序构建工具,可在 Unix、Linux 及其版本上运行。它有助于简化可能需要各种模块的构建程序可执行文>件。
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,也可以执行操作系统的命令。
基本语法
目录:依赖
命令 # 以tab进行缩进
hello:hello.c
gcc -o hello hello.c
伪目标
.PHONY: clean
clean:
rm -f *.o
变量
变量名 = 值
CC = gcc
TARGET = hello
OBJ = hello.o
:= 立即解析变量
= 使用时解析变量
?= 重复定义时不被覆盖
+= 追加字符串
自动变量
$ 取值
$@ 目标文件名
$< 第一条件名称
$^ 所有条件名称
通配符和隐式规则
* 通配符
编译c/c++程序时自动生成.o文件
函数
# 调用格式
$(<function> <arguments>)
#模式字符串替换 查找text中的内容是否满足old ,以new替换
$(patsubst <old>,<new>,<text>)
#字符串替换函数 将字符串text中的old替换为new
$(subst <old>,<new>,<text>)
# 去重空格 去掉字符串开头和结尾的空格,并将中间连续的空格替换为1个空格
$(strip <string>)
# 查找字符串 查找in中的find返回
$(findstring <find>,<in>)
#过滤 选择text中满足pattem的字符串
$(filter <pattem>,<text>)
# 反过滤
$(filter-out <pattern>,<text>)
# 排序 按照升序对list排序
$(sort <list>)
#取单词 取出text中第n个单词
$(word <n>,<text>)
使用范例
# version 1
[可执行文件名]:[1.cpp] [2.cpp] [3.cpp] [...]
gcc/g++ -o [可执行文件名] [1.cpp] [2.cpp] [3.cpp] [...]
#version 2
[变量例:CC] = g++/gcc
[变量例:TARGET] = [可执行文件名]
[变量例:OBJ]: [链接文件:1.o] [2.o] [...]
$(TARGET) : $(OBJ)
$(CC) -o $(TARGET) $(OBJ)
[1.o]: [1.cpp]
$(CC) -c [1.cpp]
[1.o]: [1.cpp]
$(CC) -c [1.cpp]
[...]
#version 3
[变量例:CC] = g++/gcc
[变量例:TARGET] = [可执行文件名]
[变量例:OBJ]: [链接文件:1.o] [2.o] [...]
[变量例:FLAGS] = [编译选项:-c -Wall] # -Wall 警告
$(TARGET) : $(OBJ)
$(CC) -o $@ $^
%.o:%.cpp
$(CC) $(FLAGS) $< -o $@
.PHONY clean #防止存在文件名为clean
clean:
rm -f *.o $(TARGET)
#version 4
[变量例:CC] = g++/gcc
[变量例:TARGET] = [可执行文件名]
[变量例:SRC] = $(wildcard *.cpp)
[变量例:OBJ] = $(patsubst %.cpp,%.o,$(SRC))
[变量例:FLAGS] = [编译选项:-c -Wall]
$(TARGET) : $(OBJ)
$(CC) -o $@ $^
%.o:%.cpp
$(CC) $(FLAGS) $< -o $@
.PHONY clean #防止存在文件名为clean
clean:
rm -f *.o $(TARGET)
CMake拓展
# CMakeLists.txt
PROJECT(<项目名>) # 定义 _BINARY_DIR和_SOURCE_DIR变量
SET(SRC_LIST <*.cpp>)
MESSAGE(SATUS "<test>") # 输出信息
# SEND_ERROR 产生错误
# SATUS 输出前缀为-的信息
# FATAL_ERROR 终止进程
ADD_EXECUTABLE(<目标> ${SRC_LIST})
<!--CMake创建文件-->
//CMakeLists.txt
<!--指定CMake版本-->
cmake_minimum_required(VERSION 3.5)
<!--指定目标文件-->
project(hello)
<!--编译目标文件-->
add_executable(hello hello.cpp main.cpp)
双层CMake
-build
-CMakeLists.txt
-COPYRIGHT
-doc
--hello.txt
-README
-runhello.sh
-src
--CMakeLists.txt
--main.cpp
# 外层
PROJECT(HELLO)
ADD_SUBDIRECTORY(<路径:src> <输出:bin>)
# 内层——src目录下
ADD_EXECUTABLE(hello main.cpp)
安装
PROJECT(<HELLO>)
ADD_SUBDIRECTORY(<src> <bin>)
INSTALL(FILES <COPYRIGHT> README <安装路径:share/doc/cmake/>)
INSTALL(PROGRAMS <runhello.sh> DESTINATION <bin>)
INSTALL(DIRECTORY <doc/> DESTINATION <share/doc/cmake>)
静态库和动态库
静态库 “.a” ".lib" 编译时直接整合到代码中,程序可单独运行
动态库 “.so” ".dll" 编译时不会放到链接的目标程序中,程序无法单独运行
# 内层
SET(<LIBHELLO_SRC> <hello.cpp>)
ADD_LIBRARY(<HELLO> <SHARED|STATIC> $(<LIBHELLO_SRC>))
# 同时生成动态库和静态库
SET(<LIBHELLO_SRC> <hello.cpp>)
ADD_LIBRARY(<hello> STATIC $(<LIBHELLO_SRC>))
SET_TARGET_PRORERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
#清除
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
ADD_LIBRARY(hello SHARED $(<LIBHELLO_SRC>))
SET_TARGET_PRORERTIES(hello PROPERTIES OUTPUT_NAME "hello")
#清除
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
#指定动态库版本为 1.2 api 1
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION <1.2> SOVERSION <1>)
# 安装
INSTALL(FILES hello.h DESTINATION include/hello)
INSTALL(TARGETS hello hello_static LIBRATY DESTINATION <lib> ARCHIVE DESTINATION <lib>)
# 头文件搜索
INCLUDE_DIRECTORIES{<路径:/usr/include/hello>}


浙公网安备 33010602011771号