[1] CMake On Linux - 编译链接可执行程序

本帖子适用于初学者,StepByStep的入门CMake,CMake也是一门编程语言,只不过是针对编译和链接这种程序构建的过程的语言,学习基本语法就可以初步入门,后面需要什么复杂的功能,进阶掌握需要自己去查找官方文档,后续会给出查阅的一些方式

软件平台

  • Win 7
  • VMware Workstation 12 Pro
  • Ubuntu 15.10
  • CMake 3.2.2

case 1

目录结构

+
| 
+--- main.cpp
+--- CMakeLists.txt
|
/--+ build/
   |
   +--- hi

文件内容

//main.cpp
#include <iostream>

using namespace std;

int main()
{
   cout<<"Hello CMake!"<<endl;
    return 0;
}
//CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(HELLO)
ADD_EXECUTABLE(hi main.cpp)
  1. mkdir t1
  2. mkdir build
  3. vim CMakeLists.txt
  4. vim main.cpp
  5. cd build
  6. cmake ..
  7. make
    即可在build目录下编译出hello可执行文件

语法解释

cmake不区分大小写,建议命令使用大写!

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
设置所写的txt文件,至少需要的cmake版本

PROJECT(HELLO)
为本次构建起一个名字,这不是最后exe的名字

ADD_EXECUTABLE(hi main.cpp)
添加可执行文件,第一个参数是可执行文件的名字,第二个参数是源文件(暂时只考虑少量源文件,这样可以依次写在后面,后面有命令来批量加入源文件)

cmake ..
该命令中..,意味着CMakeLists.txt在上一层目录,这样构建保证了所有构建的文件全部在build文件夹中,方便使用版本控制软件如git进行版本控制,只需要忽略build就可以了

case 2

目录结构

同case1

文件内容

//CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is BINARY dir:" ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir:" ${PROJECT_SOURCE_DIR})
ADD_EXECUTABLE(hi ${SRC_LIST})
#SET_TARGET_PROPERTIES(hi PROPERTIES LINKER_LANGUAGE CXX)

语法解释

SET(VAR_NAME t1.cpp t2.cpp t3.cpp …)
set命令用于设置一个变量SRC_LIST,用来表示后面的所有给出的文件
使用变量需要用如下形式 :${SVAR_NAME},但是如果在IF中使用,则不需要${},直接IF(VAR_NAME)

PROJECT_BINARY_DIRPROJECT_SOURCE_DIR变量是在PROJECT(HELLO)语句之后cmake默认定义和初始化
其中PROJECT_BINARY_DIR,是输入cmake命令的目录,本例就是build目录
其中PROJECT_SOURCE_DIR,是输入cmake命令后面紧跟着的目录,本例就是..目录,
注:PROJECT_SOURCE_DIR目录里要有CMakeLists.txt

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)
message命令用于在cmake..时,向命令行输出信息
SEND_ERROR,产生错误信息,跳过生成信息
STATUS,输出前缀为-的信息
FATAL_ERROR,立即终止所有cmake过程

SET_TARGET_PROPERTIES(hi PROPERTIES LINKER_LANGUAGE CXX)
SET_TARGET_PROPERTIES设置一些标志,下面的命令设置连接器为C++连接器
注意到,#是cmake的注释符

case 3

目录结构

+
| 
+--- CMakeLists.txt
+--- Copyright.txt
+--- ReadME.txt
/--+ src/
   |
   +--- CMakeLists.txt
   /--+ hello/
      |
      +--- CMakeLists.txt  
      /--+ src/
         |
         +--- main.cpp 
|
/--+ build/
   |
   /--+ bin/
      |
      +--- mycmake
/--+ doc/
   |
   +--- Userguide.rst

本次依旧使用case2的例子,但是更像一个工程,doc目录存在文档,src目录存放源文件(当然实际工程src目录下可能还有很多子目录,还有一些依赖的外部库等等,这些会后面详细说明),我们控制最后编译链接出的mycmake可执行程序在build的bin目录下

文件内容

//   /CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(HELLO)
MESSAGE(STATUS "This is BINARY dir" ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir" ${PROJECT_SOURCE_DIR})
ADD_SUBDIRECTORY(src)
//  /src/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
ADD_SUBDIRECTORY(hello)
//  /src/hello/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin")
AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/hello/src HELLO_src)
ADD_EXECUTABLE(mycmake ${HELLO_src})
SET_TARGET_PROPERTIES(mycmake PROPERTIES LINKER_LANGUAGE CXX)

语法解释

ADD_SUBDIRECTORY(src)
添加子目录,子目录要有CMakeLists.txt

SET(EXECUTABLE_OUTPUT_PATH “${PROJECT_BINARY_DIR}/bin”)
EXECUTABLE_OUTPUT_PATH是cmake默认变量,修改它可以把可执行文件的路径修改,下面修改为build/bin

AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src/hello/src HELLO_src)
AUX_SOURCE_DIRECTORY,自动识别目标目录下的所有源文件,赋值给第二个参数变量,可以直接用于ADD_EXECUTABLE语句

<think>嗯,用户问的是将CMake命令中的Freetype库从.so动态库换成.a静态库是否可行。首先,我需要确认静态库和动态库在链接时的区别。静态库在编译时会被整合到可执行文件中,而动态库则在运行时加载。因此,理论上只要库的ABI兼容,替换成静态库应该是可行的。 接下来,我需要检查用户提供的路径是否正确。路径是/usr/lib/arm-linux-gnueabihf/libfreetype.a,确认该路径下确实存在这个.a文件。如果不存在,用户需要安装静态库包,比如在Debian系系统上可能是libfreetype6-dev或者libfreetype-dev的静态库部分。 然后,考虑CMake的配置。用户通过-D选项指定了FREETYPE_LIBRARY变量,这通常用于覆盖CMake自动查找的结果。但有些CMake的Find模块可能不仅需要库路径,还需要指定静态链接的标志。例如,可能需要设置FREETYPE_LIBRARY_STATIC或者额外的链接器参数。 另外,链接静态库可能会影响依赖关系。如果Freetype本身依赖其他库,比如zlib或png,这些也需要静态链接,否则会导致运行时错误。用户需要确保所有依赖项都正确链接,或者使用静态编译的依赖库。 还需要注意许可证问题。某些库的静态链接可能有不同的许可要求,用户需要确认是否符合项目需求,特别是如果项目需要分发的话。 最后,测试是关键。用户应该在替换后重新运行CMake编译,观察是否有链接错误或运行时问题。如果有错误,可能需要调整CMakeLists.txt,明确指定使用静态链接,或者添加必要的依赖库。 总结一下,替换成静态库是可行的,但需要检查路径、依赖项、链接选项,并进行充分测试。</think>### 分步解析: --- #### 1. **基本可行性判断** - **可以替换**:将 `.so` 动态库路径改为 `.a` 静态库路径在语法上是允许的,只要: ```bash cmake .. -DFREETYPE_LIBRARY=/usr/lib/arm-linux-gnueabihf/libfreetype.a ``` ✅ 文件存在 ✅ 静态库与动态库 ABI 兼容 ✅ 项目支持静态链接 --- #### 2. **关键验证步骤** - **检查文件存在性**: ```bash ls /usr/lib/arm-linux-gnueabihf/libfreetype.a ``` - 若不存在:需安装静态库(例如 `apt install libfreetype6-dev`) - **验证 CMake 配置输出**: ```bash grep "Freetype" CMakeCache.txt # 检查是否成功识别静态库路径 ``` --- #### 3. **依赖关系处理** - **静态链接的级联依赖**: - 若 Freetype 依赖 `zlib`/`libpng` 等其他库,需确保这些依赖也静态链接: ```cmake find_package(ZLIB REQUIRED) # 需提前配置 target_link_libraries(your_target PRIVATE ${ZLIB_LIBRARIES}) ``` --- #### 4. **CMake 高级配置** - **强制静态链接标志**(必要时): ```cmake set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") ``` - **显式指定静态库模式**: ```cmake set(FREETYPE_USE_STATIC_LIBS ON) # 部分 FindFreetype.cmake 模块支持此选项 ``` --- #### 5. **常见问题与解决** - **错误示例**: ```text undefined reference to `FT_Init_FreeType' ``` - **原因**:静态库链接顺序错误或依赖缺失 - **解决方案**: ```cmake target_link_libraries(your_target PRIVATE freetype.a -lpng -lz) ``` --- #### 6. **替代方案推荐** - **使用 CMake 自动查找**(推荐): ```cmake find_package(Freetype REQUIRED) target_link_libraries(your_target PRIVATE Freetype::Freetype) ``` - 若需强制静态链接: ```bash cmake .. -D Freetype_USE_STATIC_LIBS=ON ``` --- ### 总结 | 情况 | 是否可行 | 注意事项 | |----------------------------|----------|---------------------------------| | 直接替换 `.so` → `.a` | ✅ 可以 | 需验证文件存在性、依赖完整性 | | 通过 CMake 自动查找静态库 | ✅ 更推荐 | 需模块支持 `Freetype_USE_STATIC_LIBS` | | 存在复杂依赖链 | ⚠️ 谨慎 | 需手动链接所有依赖的静态库 | 建议优先使用 `find_package` + `Freetype_USE_STATIC_LIBS` 的标准化方式,可避免硬编码路径带来的跨平台问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值