文章

CMake添加敏感参数

在程序开发中难免会需要使用一些敏感参数,又不能同步到Github,在开发B站视频推荐程序时我也遇到了这样的问题,并尝试了使用CMake添加,尽管最后放弃了这种做法,但是仍在此做一个记录

CMake添加敏感参数

在我花好几个小时搜索和研究之后,我发现没有办法实现跨平台的在编译时设置临时环境变量(主要是VS和CLion),如果为了保证数据安全性(防止本文的方法在预处理后的二进制文件出现数据泄露,见使用宏定义),就不得不放弃跨平台的适用性,在IDE中设置临时环境变量,毕竟CMake只是提供编译的跨平台性,调试时设置临时环境变量是IDE的事情,没有办法做到全平台通用的设置方法,而我最终采取的方法就是简单地在CLion中配置临时环境变量,见最终解决办法

今天在继续研究我的B站爬虫时,有一个需求,我需要向程序中传入我B站登录的Cookie信息,但是众所周知,Cookie这东西属于敏感信息,我的代码还要上传到Github的,肯定不能明码写出。再加上Cookie会因为我退出登录再重新登录而刷新,而且我的代码还需要在Github Action中运行,明码写出也是不能接受的。

宏定义

因故我首先学习了如何在CMake构建时在被排除在Git的文件里,将我的Cookie设置为一个临时的环境变量(这主要是为了配合Github Secret),然后再将这个环境变量转换为代码级别的宏定义,从而在我的代码中使用CMake定义的项目级别的宏来获取我的Cookie,下面是我操作步骤的总结

引入外部文件

第一步当然是引入一个外部文件,这个文件不会同步到Github,之后的Cookie就可以安全地定义在这里,在本地时我只需要让CMake执行里面的设置指令即可,而Github Action中则跳过这一步,直接使用定义的Secret即可。

我导入文件的代码如下:

1
2
3
4
5
set(config "${CMAKE_CURRENT_SOURCE_DIR}/excluded/CMakeUserVars.cmake")

if(EXISTS ${config})
    include(${config})
endif()

"${CMAKE_CURRENT_SOURCE_DIR}/excluded/CMakeUserVars.cmake"是我的文件的导入路径,其中${CMAKE_CURRENT_SOURCE_DIR}表示当前的CMake文件的路径,剩下的部分指向我用来存储Cookie的CMakeUserVars.cmake配置文件。

为了方便,我使用set()函数定义了一个变量config来代表文件路径,后面则使用${config}来获取变量对应的值。在配置文件中我也是使用的这个函数来定义COOKIE环境变量的,只不过有一点差异,在配置文件中我是这样写的:

1
set(ENV{COOKIE} "...")

ENV{COOKIE}代表的是定义一个临时的环境变量,其变量名叫COOKIE

ifendif块则是检测文件是否存在(适配Github Action中的情况),若存在再执行里面的代码。

检查参数

毕竟只是在本地才有配置文件,在远端时我也就必须检测用户有没有设置COOKIE这个环境变量,若没有就需要报一个错误,阻止编译继续进行下去,而我的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## Check
set(check ON)
set(message OFF)
set(wrong OFF)
if(check)
    if(DEFINED ENV{COOKIE})
        if (message)
            message(STATUS "Now Cookie: $ENV{COOKIE}")
        endif ()
    else ()
        message(SEND_ERROR "Cookie is needed !")
        set(wrong ON)
    endif ()
endif ()
if (wrong)
    message(FATAL_ERROR "Environment Variables not all have been set ! Please check Log and set !")
endif ()

if(DEFINED ENV{COOKIE})这一行是检测COOKIE这个环境变量有没有被定义,而不是检测其对应的值,如果是要读取环境变量对应的值应当在前面加上$$ENV{COOKIE},然后根据情况输出错误信息。考虑到我可能以后还要添加一些需要设置的参数,我使用wrong来记录是否有错误出现,并在所有检查全部完成以后再统一终止构建,以便用户一次就知道所有没有设置的参数。

生成宏

接下来就是构建的最后一步,为我的代码生成预先定义好的宏,这部分我的代码如下:

1
2
3
add_compile_definitions(
        COOKIE="$ENV{COOKIE}"
)

使用add_compile_definitions函数,我就可以设置CMake预先定义的宏,然后在代码中使用。以这里为例,定义的宏就是COOKIE$ENV{COOKIE}将环境变量COOKIE的值读取并传输给宏COOKIE

其他

显示构建信息

默认情况下CMake不会显示构建过程中的细节信息的,也就是说我的报错相信不会在终端中看到,如果要显示它们,需要在构建CMake时设置参数-CMAKE_VERBOSE_MAKEFILEON为ON(在cmd窗口构建时,或者参考Libcurl将参数设置到CLion中)。不过我选择的是在CMake中添加set(CMAKE_VERBOSE_MAKEFILEON ON),效果是一样的,而且运行的时候方便开关。

使用宏定义

可能读者有困惑,直接使用环境变量不好吗,为什么要定义成宏,而且宏在预处理之后就又显示出COOKIE来了。

我最初也是这样想的,但是操作之后我发现CMake临时定义的环境变量在代码编译时就没用了,也就是说配置文件中设置的变量不会传递到编译好的程序里,只能使用宏定义才可以,至于预处理后又显示出COOKIE了属于没有办法的事情。

问题

按照上述过程配置之后,最初我的代码可以正常运行,可是后来出现无法得到我的宏下数据的问题,且迟迟无法解决,最终我采用了其他方法(文章开篇),这个问题也没有解决。

最终解决办法

在折腾一圈,浪费数个小时之后,最终我还是采取了前面警告的办法,放弃跨平台通用性(我也不知道为什么我要跨平台通用性,诶,就是想😋),决定在CLion中设置临时运行环境变量。

参考Clion官方文档,我开始尝试设置调试时的临时环境变量。

起初我是想通过脚本添加环境变量的,可是尝试之后出现很多问题,包括但不限于

  1. 每次运行都会启动我的默认.sh文件打开软件
  2. 添加总是失败,我怀疑是脚本运行完成之后设置的值就自动销毁了,或者我的程序就是错误的,无法运行(最可能,但是没有语法错误呀)
  3. 脚本失败导致我直接添加的值也报废了

在改为直接添加之后就没什么问题了,添加方法官网也说得很详细了,在此不再赘述。

经过几个小时的折腾,最终设置完成之后我的cookie就很好地隐藏起来了,程序通过getenv("COOKIE")获取COOKIE值,并在代码中使用,我的程序也很好地将数据爬取下来了,然后我又可以正常进行开发工作了🎉🍻。

本文由作者按照 CC BY 4.0 进行授权