如何用 GCC, CMake 和 Make 编译C/C++代码

参考资料:

  1. Makefile和CMakeLists的区别

  2. Cmake编写CmakeList.txt 语法备忘

CMake & Make

GCC(GNU Compiler Collection)是由 GNU 开发的编程语言编译器,可以在 Windows 和 Linux 等各种系统上编译代码。Windows 上的 Visual Studio 是个不错的编程工具,但是它有不少烦人的限制(比如不能内联汇编),而且它的 .sln.vcxproj 不能在 Linux 上使用。

  1. 我们结合两者优点,先使用 VS 的 CMake 项目 来编程,然后用 gcc 编译得到在各个平台通用的代码。但是 gcc 编译时,需要对各个文件进行排序,否则容易链接失败。

  2. 可以使用 make 工具,根据 Makefile 文件指定编译配置。不过,编写 MakeFile 也是一件体力活。

  3. 进一步,我们使用 CMake 工具,根据 CMakeLists.txt 文件来生成 MakeFile 文件。

  4. 注意,我们的编译是在 Linux 上进行的,在 Windows 上可以使用 WSL 直接对本地文件进行处理。

这样,就可以比较方便地用 gcc 编译大型工程了 ヾ(๑╹◡╹)ノ"

CMakeLists 语法

这里只介绍一些基本的语法,足够日常的使用了。

我不再详细地一一介绍,就写个简单的注释,备忘:

cmake_minimum_required(VERSION 3.10)	#指定最小版本

project(MyProject C ASM)	#指定工程名称以及类型

set(CMAKE_C_STANDARD 11)	#指定C11
set(CMAKE_CXX_STANDARD 11)	#指定C++11
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_Cxx_STANDARD_REQUIRED ON)

enable_language(ASM)	#启用汇编
SET(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS asm)	#设置后缀

set(CMAKE_BUILD_TYPE Release)	#设置Debug还是Release

include_directories(SYSTEM) #设置include目录
link_directories(SYSTEM)    #设置static/dll目录

#也可以设置为工作目录下的一些文件夹
include_directories(${PROJECT_SOURCE_DIR}/openssl) 
link_directories(${PROJECT_SOURCE_DIR}/openssl/lib ${PROJECT_SOURCE_DIR}/lib/)

SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)  #设置exe文件目录,放置后续的add_executable结果
SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/)    #设置static/dll库目录,放置后续的add_library结果

#nasm或yasm不支持-mavx2,-maes等指令,所以须前置
#但编译出的TIMER.a似乎链接不上?一直找不到func。其他的由C代码编译出的库可以正常链接
add_library(TIMER cputimer.asm)	#编译asm文件为静态库
add_library(TIMER SHARED cputimer.asm)	#编译asm文件为动态库

#为后续的所有gcc命令设置编译参数
#这里的-lm,-lcrypto似乎没用?
add_compile_options(
    -w -O3 -lm -lssl -lcrypto -maes -mavx2
    -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls -Wshadow -Wpointer-arith
)

#将源文件分组(头文件不需要,已经被include写入源文件)
set(A_SRCS a1.c a2.c a3.c)
set(B_SRCS b1.c b2.c b3.c b4.c)
set(C_SRCS c1.c c2.c)
set(D_SRCS d1.c)

#将测试文件分组
set(TEST_B_SRCS test_b.c)
set(TEST_C_SRCS test_c.c)
set(TEST_D_SRCS test_d.c)

#递归执行src子目录下的CMakeLists.txt(如果有的话)
add_subdirectory(src)

add_library(B ${A_SRCS} ${B_SRCS})			#编译出静态库
add_library(C SHARED ${A_SRCS} ${C_SRCS})	#编译出动态库
target_link_libraries(B PUBLIC m)  			#添加math库
target_link_libraries(C INTERFACE crypto)  	#添加openssl库

#对于同样的代码,设置不同的宏
add_library(D128 ${D_SRCS})
add_library(D256 ${D_SRCS})
target_compile_definitions(D128 PUBLIC SAFETY=128)	#新建一个宏,取值128
target_compile_definitions(D256 PUBLIC SAFETY=256)	#新建一个宏,取值256

link_libraries(m)	#后续的所有gcc指令都链接math库

#编译各个main文件得到exe文件,并链接对应的库
add_executable(test_b ${B_SRCS})
add_executable(test_c ${C_SRCS})
add_executable(test_d128 ${D_SRCS})
add_executable(test_d256 ${D_SRCS})
target_link_libraries(test_b B)
target_link_libraries(test_c C)
target_link_libraries(test_d128 D128)
target_link_libraries(test_d256 D256)

为了让上述的 target_compile_definitions 起作用,需要这么写 .h 文件:

#ifndef SAFETY
	#define SAFETY  128		// 设置安全强度
#endif

编译步骤:

  1. 打开 WSL 进入工作目录
  2. 执行 cmake ./ 生成 MakeFile 文件
  3. 执行 make 编译工程代码
  4. 测试 /bin 内的 .exe 文件是否正确
  5. 库文件在 /lib

Windows 下的缺点

在 Windows 下使用 gcc, make, cmake 也可以,但是本人的工程代码(简单逻辑的代码没问题)出现了

internal error: aborting at ../../ld/ldlang.c:527 in compare_section

的错误,查了好多资料,还是搞不懂哪儿出错了(弱小又无助)

另外,Windows 下的 openssl 一直找不到 PATH 里写明了的 include 以及 lib 的位置,还要手动复制到工作目录下,烦死了 (╬ ̄皿 ̄)

猜你喜欢

转载自blog.csdn.net/weixin_44885334/article/details/129432917