参考资料:
CMake & Make
GCC(GNU Compiler Collection)是由 GNU 开发的编程语言编译器,可以在 Windows 和 Linux 等各种系统上编译代码。Windows 上的 Visual Studio 是个不错的编程工具,但是它有不少烦人的限制(比如不能内联汇编),而且它的 .sln
和 .vcxproj
不能在 Linux 上使用。
-
我们结合两者优点,先使用 VS 的
CMake 项目
来编程,然后用gcc
编译得到在各个平台通用的代码。但是gcc
编译时,需要对各个文件进行排序,否则容易链接失败。 -
可以使用
make
工具,根据Makefile
文件指定编译配置。不过,编写MakeFile
也是一件体力活。 -
进一步,我们使用
CMake
工具,根据CMakeLists.txt
文件来生成MakeFile
文件。 -
注意,我们的编译是在 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命令设置编译参数
add_compile_options(
-w -O3 -maes -mavx2
-Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls -Wshadow -Wpointer-arith
-L/usr/local/include #在这里添加头文件目录
)
#为后续的所有gcc命令设置链接参数(似乎没用,还是用 link_libraries 吧)
add_link_options(
-L/usr/local/lib #在这里添加库目录
-lm -lssl -lcrypto #要链接的库
)
#将源文件分组(头文件不需要,已经被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库(注意,没有"-l")
#编译各个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
编译步骤:
- 打开
WSL
进入工作目录 - 执行
cmake ./
生成MakeFile
文件 - 执行
make
编译工程代码 - 测试
/bin
内的.exe
文件是否正确 - 库文件在
/lib
内
Windows 下的缺点
在 Windows 下使用 gcc, make, cmake
也可以,但是本人的工程代码(简单逻辑的代码没问题)出现了
internal error: aborting at ../../ld/ldlang.c:527 in compare_section
的错误,查了好多资料,还是搞不懂哪儿出错了(弱小又无助)
另外,Windows 下的 openssl
一直找不到 PATH
里写明了的 include
以及 lib
的位置,还要手动复制到工作目录下,烦死了 (╬ ̄皿 ̄)