Loading

如何编译一个程序?

如何编译一个程序?

// 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

编译流程

bylc

什么是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>}
posted @ 2025-05-31 20:43  Noxryn  阅读(9)  评论(0)    收藏  举报