对于一个常见的c++脚本想要将其编译成可执行文件还是动/静态库,主要存在两种情况,一主要还是看该脚本具体操作和实现,是否具备函数主入口(main函数),如果有则将其编译成可执行文件,否则只能将其编译成动/静态库,提供一个接口供别人去使用。二是将接口函数前面添加extern "C"等关键字来进行库的编译选择,这种情况可以参考这篇笔记python与c++混合编码-CSDN博客,下面是一个简单的示例
(1)编译成可执行文件
主要的脚本内容如下,
///test.cpp
#include<iostream>
void fun(const char * p)
{
std::cout<<p<<std::endl;
}
int main() {
// 调用函数
fun("additional info");
return 0;
}
对应的CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(MyProgram)
add_executable(my_program test.cpp)
然后编译完成后得到my_program可执行文件
(2)编译动/静态库
还是上面的示例脚本,只不过需要去掉main函数,为了方便后面的调用,拆分成一个头文件和具体的函数实现。一般对外提供sdk会采用这种方式,具体如下:
首先,将 fun
函数放入一个源文件中,例如 fun.cpp
。然后,创建一个头文件 fun.h
,声明 fun
函数:
// fun.h
#ifndef FUN_H
#define FUN_H
void fun(const char* p);
#endif // FUN_H
接下来,将 fun
函数的定义放入 fun.cpp
:
// fun.cpp
#include "fun.h"
#include <iostream>
void fun(const char* p) {
std::cout << p << std::endl;
}
》静态库
创建 CMakeLists.txt
文件来定义静态库:
cmake_minimum_required(VERSION 3.0)
project(MyStaticLib)
add_library(mylib STATIC fun.cpp)
编译
mkdir build && cd build
cmake ..
make
》动态库
创建 CMakeLists.txt
文件来定义动态库:
cmake_minimum_required(VERSION 3.0)
project(MySharedLib)
add_library(mylib SHARED fun.cpp)
一样操作对其进行编译。
》调用库
这里先构建接口函数,
// main.cpp
#include "fun.h"
int main() {
fun("additional info");
return 0;
}
然后修改cmakelists.txt
cmake_minimum_required(VERSION 3.0)
project(MyStaticLib)
#add_library(mylib STATIC fun.cpp)
#add_library(mylib SHARED fun.cpp)
#link_directories(${CMAKE_SOURCE_DIR}/build_static) ##指定静态库,可以用 find_library 结合 target_link_libraries 来替换
link_directories(${CMAKE_SOURCE_DIR}/build_dynamic) ##指定动态库
add_executable(my_program main.cpp)
# 链接库
target_link_libraries(my_program mylib)
最后编译项目完成调用,看一下完成上面操作后整个项目目录结构。
(3)本地依赖编译
如果是本地自己调用,不需要封装成头文件+库文件的方式,这样我们可以修改CMakeLists.txt本地进行编译
cmake_minimum_required(VERSION 3.0)
project(MyStaticLib)
add_executable(my_program main.cpp fun.cpp)
但是如果项目变复杂一些,将所有头文件都放到include文件夹下,想要正确编译则需要在CMakeLists.txt中加入头文件路径
cmake_minimum_required(VERSION 3.0)
project(MyStaticLib)
include_directories(include)
add_executable(my_program main.cpp fun.cpp)
如果同时将其他脚本都放入src文件夹则只需
cmake_minimum_required(VERSION 3.0)
project(MyStaticLib)
include_directories(include)
add_executable(my_program main.cpp src/fun.cpp)
补:计算一段时间复杂度和空间复杂度时,需要系统地分析代码的各个部分。以下是总结的步骤和方法:
时间复杂度计算方法
-
识别基本操作:基本操作(如算术运算、比较、赋值等)通常视为 O(1)。
-
分析循环:
- 单层循环:遍历长度为 n 的循环,其时间复杂度是 O(n)。
- 嵌套循环:如果有两个嵌套循环,每个循环的长度为 n,那么时间复杂度是 O(n^2)。但需要具体分析内部操作是否会导致每次迭代都进行完整的内部循环,有时候每个元素只访问两次,时间复杂度依然为o(n).
-
分析条件语句:条件语句的时间复杂度取决于最坏情况下的执行路径。
-
函数调用:考虑被调用函数的时间复杂度。例如,如果函数 A 调用了时间复杂度为 O(n) 的函数 B,那么函数 A 的时间复杂度至少是 O(n)。
-
递归:使用递归树或主定理来求解递归的时间复杂度。例如,递归深度为 d,每层递归处理 n 个元素,则总复杂度为 O(n * d)。
-
组合所有部分:将所有部分的时间复杂度组合起来,取其中最大的一部分作为整个算法的时间复杂度。
空间复杂度计算方法
-
基本数据类型:基本数据类型(如 int, float, char)占用固定的空间,通常视为 O(1)。
-
数组和容器:数组和容器的空间复杂度通常是 O(n),其中 n 是元素的数量。例如,长度为 n 的数组的空间复杂度是 O(n)。
-
递归:递归的空间复杂度包括递归调用的栈空间。对于递归深度为 d 的递归,其栈空间复杂度为 O(d)。
-
动态分配的内存:任何动态分配的内存(如通过 new 或 malloc 分配的内存)需要计入空间复杂度。
(4)封装成sdk
创建一个完整的C++ SDK示例涉及多个组件和步骤。下面是一个简化的示例,展示如何将一个C++库封装为SDK,并提供基本的构建、使用和分发指南。
》步骤 1: 定义API
假设我们有一个简单的数学库,提供基本的数学操作。
头文件math_lib.h
#ifndef MATH_LIB_H
#define MATH_LIB_H
class MathLib {
public:
static int Add(int a, int b);
static int Subtract(int a, int b);
};
#endif // MATH_LIB_H
函数实现math_lib.cpp
#include "math_lib.h"
int MathLib::Add(int a, int b) {
return a + b;
}
int MathLib::Subtract(int a, int b) {
return a - b;
}
》步骤 2: 使用CMake构建系统
编写CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MathLibSDK)
add_library(MathLib STATIC math_lib.cpp)
target_include_directories(MathLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
》步骤 3: 编写示例代码example.cpp
#include "math_lib.h"
int main() {
int sum = MathLib::Add(5, 3);
int difference = MathLib::Subtract(5, 3);
return 0;
}
以及对应的用于示例CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MathLibExample)
add_executable(MathLibExample example.cpp)
target_link_libraries(MathLibExample MathLib)
》步骤 4: 打包SDK
接下来创建一个脚本来打包SDK。对应的比如package_sdk.sh
#!/bin/bash
SDK_VERSION="1.0.0"
SDK_NAME="math_lib_sdk"
rm -rf ${SDK_NAME}_${SDK_VERSION}
mkdir -p ${SDK_NAME}_${SDK_VERSION}/lib/include/bin
# 复制库文件和头文件
cp libMathLib.a ${SDK_NAME}_${SDK_VERSION}/lib/
cp math_lib.h ${SDK_NAME}_${SDK_VERSION}/include/
# 复制示例代码
cp example.cpp ${SDK_NAME}_${SDK_VERSION}/bin/
# 创建压缩包
tar -czvf ${SDK_NAME}_${SDK_VERSION}.tar.gz ${SDK_NAME}_${SDK_VERSION}
echo "SDK packaged: ${SDK_NAME}_${SDK_VERSION}.tar.gz"
然后编写README.md以提供如何使用SDK的说明。
# MathLib SDK
MathLib 是一个简单的C++ SDK,提供基本的数学操作。
## 安装
1. 下载SDK压缩包。
2. 解压到合适的目录。
## 使用
将 `lib` 目录添加到库路径,将 `include` 目录添加到包含路径。
示例代码 `example.cpp` 展示了如何使用 MathLib 进行加法和减法操作。
## 构建示例
```sh
mkdir build
cd build
cmake ..
make
```
## 许可证
...
》步骤 5: 分发SDK
1. 在Linux环境中,运行 `package_sdk.sh` 脚本创建SDK压缩包。
2. 将生成的 `.tar.gz` 文件分发给用户。
用户需要从分发渠道下载SDK压缩包,解压,并根据README中的说明将库和头文件添加到他们的项目路径中。请注意,该示例非常简化,实际的SDK开发可能涉及更多的细节,如错误处理、多平台支持、版本控制、安全性考虑,以及是采用动态库还是静态库等。此外,根据目标平台和用户需求,可能需要提供不同的构建配置和安装说明。