[C++] 如何使用Sharpmake集成SDK

一、初识Sharpmake

1.简介

Sharpmake是一款由Ubisoft开发的以C#为脚本语言的开源Make工具,适用于各种C/C++,C#应用程序的开发管理过程,保证团队项目拥有一个统一化规则的项目配置管理与构建工具,其支持的功能有:

  • 项目生成与配置管理

    • 支持C++项目(.vcxproj),C#(.csproj)项目的生成,并且支持将Sharpmake脚本转换为makefile以便在cmake等其他make工具中进行项目生成。
    • 根据项目文件目录层级与包含规则,管理大量的项目源码文件,并生成对应的项目配置文件(.proj).
    • 可灵活管理项目配置文件(.proj)的内容,无需频繁的手动修改。
    • 管理生成项目间的依赖关系,实现增量构建、并行构建。
  • 解决方案生成与构建配置管理

    • 定义目标平台类型(win,linux,mac,game console...)与优化级别(debug,release...)
    • 动态配置包含项目

Github: https://github.com/ubisoft/Sharpmake

 

2.基本使用方式

2.1 Sharpmake常用特性

https://github.com/ubisoft/Sharpmake/blob/main/Sharpmake/Attributes.cs
[Sharpmake.Generate]: 标记需要被生成的解决方案和项目类。被此属性修饰的类会被Sharpmake编译器处理和生成对应的Visual Studio解决方案或项目文件。
[Sharpmake.Export]: 标记需要被导出以供其他Sharpmake脚本使用的类型。是一种"逻辑项目",不会实际生成项目文件。
[Configure]: 用于标记项目或解决方案的配置方法。这些方法会在生成过程中被调用,用于设置编译选项、依赖关系、项目预编译宏等构建配置。
[Fragment]: 用于定义项目配置的特性标记。通过Fragment可以为项目指定不同的构建变体,并通过AddFragmentMask控制项目间的依赖关系。

 

2.2 Sharpmake常用函数

2.2.1 AddTargets

可以在Project或Solution的CTOR中调用,以声明解决方案或项目所支持的开发环境与目标平台等,但是这里有一些需要注意的点,以明白"缺失败xxx构建目标"错误的由来:

  • Solution构造函数中的AddTargets是在解决方案层面定义构建目标,它的主要作用是:

    • 确定整个解决方案支持的平台和配置组合
    • 为解决方案中的所有项目提供一个统一的构建环境
    • 控制构建方案级别的构建选项
  • Project构造函数中的AddTargets的作用基本与Solution差不多,但是仅针对单个项目自身的目标配置

  • 关于Solution与Project在AddTargets调用方面的关系:

    • 如果Project没有显式定义自己的Targets,则会使用包含它的Solution中定义的Targets会作为默认值(额外注意,Project的显式Targets定义可以继承自父类的构造函数中的定义)
    • Project最终显式定义的所有Targets必须等价于Solution Targets,如果Project中定义了Solution中的不存在的Target,这些额外的Target最终会被过滤掉。
  • 关于Project间依赖在AddTargets调用方面的关系:

    //ProjectA.sharpmake.cs
    [Configure]
    public void Configure(Configuration conf, Target target)
    {
    conf.AddPrivateDependency<ProjectB>(target);
    }

    此时ProjectB的Targets也需要等价于当前ProjectA的Targets,否则将在依赖解析过程发生报错,即使ProjectA添加了一个Solution中不存在,且最终会被忽略的Target。

 

2.2.2 AddFragment

可以在Project或Solution的CTOR中调用,用于标记和过滤项目配置的机制,为项目定义特定的构建特征或属性,这些特征会影响项目在依赖关系中的行为。
当项目 A 依赖项目 B 时,AddFragmentMask 决定了项目 A 在不同 Target 配置下应该链接项目 B 的哪些配置版本。这种机制通过以下方式工作:

public class CoreLibrary : Project
{
    public CoreLibrary()
    {
        AddTargets(new Target(
            Optimization.Debug | Optimization.Release
        ));

        [Configure]
        public void ConfigureAll(Configuration conf, Target target)
        {
            if(target.HaveFragment<Optimization>())
            {
                var fragment = target.GetFragment<Optimization>();
                System.Console.WriteLine($"{fragment} fragment be setted.");
            }
        }
    }
}

public class GameProject : Project
{
    public GameProject()
    {
        AddTargets(new Target(
            Optimization.Debug | Optimization.Release | Optimization.Retail
        ));

        // 指定在Game只使用CoreLibrary的Debug和Release版本,此时将不会产生依赖解析报错
        AddFragmentMask(Optimization.Debug | Optimization.Release);
    }

    [Configure]
    public void ConfigureAll(Configuration conf, Target target)
    {
        conf.AddPrivateDependency<CoreLibrary>(ReferencePrivate);
    }

}

Output:

Debug fragment be setted.
Release fragment be setted.

当依赖者添加了具体的FragmentMask,则被依赖者的Targets就必须含有对应的定义,否则将会产生缺少配置项错误。

 

2.2.3 AddPublicDependency/AddPrivateDependency

在有[Configure]特性修饰的成员函数中调用,用于管理项目间依赖关系。

[Sharpmake.Generate]
public class MathLibInvoker : Project
{
    public MathLibInvoker()
    {
        Name = "MathLibInvoker";
        SourceRootPath = @"[project.sourcePath]\MathLibInvoker";
    }

    public override void Config(Configuration conf, Target target)
    {
        // ... 其他代码
        conf.AddPublicDependency<Mathematics.MathLibraryDLL>(target);
    }
}

 

2.2.4 AddDefine/AddExportDefine

在有[Configure]特性修饰的成员函数中调用,用于为生成的项目添加预编译宏,其中:

  • AddDefine仅作用于生成的项目自身
  • AddExportDefine将会把宏定义传播到其他依赖它的项目中,假设有一个单条依赖链:
    • 若为私有依赖,则传播终止于依赖者。
    • 若为公有依赖,则传播将根据依赖链继续向外传递,直到遇到某一个私有依赖为止。

 

二、SDK集成

1.前期准备

1.1 前往SDK官网下载目标版本的SDK包,并解压到本地

  • 参考SDK官方提供的SDK文档,检查SDK中的文件是否存在缺失或配置不正确的情况。

 

1.2 将SDK文件拷贝到项目目录中

  • 参考SDK文档,将必要的头文件与源文件拷贝到项目对应的SDK管理目录下。

 

2.开始集成

2.1 一般SDK的常见形式与对应的基本接入流程

general-SDK-code-structure-Integration-Method

 

2.2 编写Sharpmake脚本

  • 根据SDK内容,确定SDK对应的sharpmake项目结构,并编写xxx.sharpmake.cs脚本。

 

2.3 运行Sharpmake.Application

可以通过cmd直接运行sharpmake.application.exe

  • 示例: sharpmake.application /souces('${project.main.sharpmake.cs}')

 

2.4 编写SDK的调试代码

打开生成/更新后的解决方案,并根据团队的代码规范,参考SDK官方文档编写SDK的测试代码(可以是SDK初始化/接口调用等简单代码),并在API调用的关键步骤打印 入参、结果等日志以验证SDK的运行情况。

 

2.5 构建目标平台

对于本地测试,如果你集成了一个客户端的SDK,那么可以编译客户端的target,相应的,如果是服务端SDK,那么编译服务端target。
对于提交测试,请注意条件编译,因为你的测试代码可能没有同时兼顾这些情况。

 

2.6运行以测试调试代码

  • 运行目标平台构建出的可执行文件,收集日志文件,结束运行。
  • 根据输出的日志结果判断调试代码是否存在错误调用,并视情况修改调试代码。

当调试代码运行结果均符合期望,则基本完成了SDK的接入工作。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇