Visual C++ for Linux Tips (01): `Copy File` 失效的解决方案
Visual C++ for Linux Tips (01): Copy File
失效的解决方案
01.问题描述
通过 MSVC 的 Visual C++ for Linux 开发 Linux 应用程序非常方便,但是它总有一些小问题。我从 Visual C++ for Linux 推出第一个版本开始起就尝试着用它,见证了每一个新版本都解决了旧版本的一些问题,到现在已经变得越来越完善了,但还是有一些长期存在的问题有待解决。
借着手头写一个新的工具软件的机会,说一下Copy File
失效的问题。
开发 Windows 程序时,Copy File
的表现
为了说明Copy File
这个 feature 在 Visual C++ for Linux 上存在的问题,我们先对比一下,开发 Windows 程序时,Copy File
的正常表现。
比如说,如下图所示,我项目中引用了一个配置文件:TelemDecoder_logsconf_kvfile.conf
,我希望每次我的程序编译之后,配置文件被自动拷贝到编译输出目录的Resource/Configuration
子目录中,如果该子目录不存在,则创建该子目录再拷贝。
我们在TelemDecoder_logsconf_kvfile.conf
这一项上面单击鼠标右键,在 Context Menu (右键菜单)中设置它的属性:
Content 属性选择Yes
,表明这个文件是和程序编译过程有关的。Item Type 属性选择Copy File
,这时,左边的配置属性列表中就会多出来Copy File
这个类别。
如下图所示,在Copy File
这个属性类别中,我们可以在Destination Directories
属性中设置文件输出的路径。此处我们将该路径设置为:$(OutDir)/Resource/Configuration
这样,在程序编译完后,在编译结果输出目录中,可以看到,(1) Resource/Configuration
子目录被创建;(2) TelemDecoder_logsconf_kvfile.conf
文件被拷贝到了该子目录中。
开发 Linux 程序时,Copy File
的表现
然而,在用 Visual C++ for Linux 插件开发 Linux 程序时,我们也将TelemDecoder_logsconf_kvfile.conf
配置文件设置成:Content: Yes; Item Type: Copy File
,并按照我们之前的理解设置了Copy File
这个属性类中的Destination Directories
属性,结果,TelemDecoder_logsconf_kvfile.conf
并未被拷贝到我们期望的目录。岂止是这样,当我们查看都有哪些文件被上传到了 Remote Machine,结果发现TelemDecoder_logsconf_kvfile.conf
并没有像源代码文件那样被上传到 Remote Machine。
02.问题检索
要相信,如果我们遇到的这个问题不是特别冷门,在互联网上应该也有许多人遇到了同样的问题。看看他们都有哪些讨论。
经过搜索,发现果然有很多同行在讨论这个问题,但是迄今为止还没有什么特别好的解决办法。
检索结果一:Files not being copied remotely #369
在 Files not being copied remotely #369 这个链接中,我们看到,早在2019年3月,就有人在 https://github.com/Microsoft/VSLinux/ 这个开源项目中报告过这个 Bug。是的,这当然是一个显而易见的 Bug。不过这个 Bug 拖到了现在还没有解决,现在已经是2022年12月了,我的 Visual Studio 2022 的版本也已经升级到了最新的 17.4.2,该 Bug 依然可被复现。
检索结果二:丑陋的 Workaround
典型的讨论,见:Visual C++ for Linux: copy content files to build directory? 这是 Stackoverflow 上的讨论。通常来说, Stackoverflow 里面的回答者还是比较有耐心的。
目前从互联网上检索到的变通的解决办法( Workaround),无非是有 2 个:一个办法就是在 Post-Build Event 中进行文件拷贝;另一个办法就是在项目属性中的 Copy Sources 属性类中,配置Additional Sources To Copy
。
Visual C++ for Linux 的 Post-Build Event 一直都用得有点别扭,我曾经在这个地方折腾过很多次。不太指望在这里进行稍微复杂一点的设置。
Additional Sources To Copy
详见链接:Copy Sources Project Properties (Linux C++) 我实在是不想用这个办法,因为它要设置 fulllocalpath 和 fullremotepath,这令我非常抗拒。我本来就希望项目设置尽可能灵活适应不同的开发者/开发环境,一旦用上了 fullpath,每次都得告诉其他人将此处改成他们自己的开发环境所采用的路径。我希望这里能够采用相对路径,然后用上像$(OutDir)
这样的IDE变量,但是经过一圈折腾,发现相对路径行不通。
总之上面说的这两个解决办法都非常丑陋。
03.解决办法
首先,解决文件被上传到 Remote Machine 的问题首先,解决文件被上传到 Remote Machine 的问题
首先我希望TelemDecoder_logsconf_kvfile.conf
这个配置文件能够像源代码文件那样被自动上传到 Remote Machine 中去,这样的话,我哪怕是通过一些笨办法,也能实现自动部署到我期望的目录中去这个想法。
经过尝试,我发现比较理想的做法,是将该文件的属性设置为:Content: Yes; Item Type: Text
,如下图所示:
然后 Build,发现好歹TelemDecoder_logsconf_kvfile.conf
能够被部署到源代码文件中去了。这就有戏。
设置文件部署路径:重命名Remote File
在 Copy Sources 属性类中,可以通过Remote File
来设置文件部署的位置和名称。
看看我们能够借助的IDE环境变量有哪些:如下图所示,$(RemoteOutDir)
这个变量正合我意。
所以,我们把Remote File
设置为:$(RemoteOutDir)/Resource/Configuration/TelemDecoder_logsconf_kvfile.conf
,如下图所示:
Copy Sources 属性类的设置如下表所示:
Property | Value |
---|---|
Remote File | $(RemoteOutDir)/Resource/Configuration/TelemDecoder_logsconf_kvfile.conf |
Copy Remotely | Yes |
Copy To Output Directory | No |
然后执行 Build,结果正如我们预期的那样。问题解决。
(幸亏通过设置Remote File
属性解决了这个问题,否则我就只能通过 Shell 脚本来进行文件部署了。)