VS2017也推出很久了,在单位的时候写linux的服务端程序只能用vim,这让用惯了IDE的我很难受。
加上想自己撸一套linux上的轮子,决定用VS开工远程编写调试linux程序。
在windows下编写静态库并在另一个项目中引用很简单
新建项目的时候选择静态库,进去把代码撸好,即可编译出静态库*.lib
随后在希望使用该静态库的项目中设置一下链接器“附加库目录”为"../Debug"(和你的输出路径有关),然后添加"附加依赖项"静态库名.lib",然后就可以顺利的编译静态库了。
但是在linux下这件事却让我头疼了几天,我一开始也准备按照windows下的套路来解决,解决在新建项目的时候压根没看到静态库这一选项……
不过还好在常规里面找到了“配置类型”选项,设置成“静态库(.a)”就可以了。
在准备使用静态库的时候,真正的麻烦来了,一开始我按照windwos下的思路,当前项目链接时的工作目录就是解决方案的路径,所以按照编译出来的文件结构写下了“附加库目录”(../common/bin/x64/Debug),然后去填写“附加依赖项”(“libcommon.a”),编译的时候就华丽丽的出错了,提示没有这个文件……
后来尝试过吧“libcommon.a”改成““common””、“附加库目录”直接指定成linux上的绝对地址等方案,但是很可惜没有任何一个方案可以。
在linux下自己写参数指定绝对地址能够顺利将静态库链接成功,但是用vs的环境却总是失败,这个时候有点让我怀疑人生了。
甚至一度想用VS写好代码然后去linux下写MAKEFILE,手动编译。但是转念一想,这岂不是回到远古时代了?不行,我得干掉这个问题。
后来突发奇想,写了一个小程序myhelp,放进了usr/bin/中
int main(int argc,char **argv) { char buf[80]; getcwd(buf, sizeof(buf)); std::ofstream f; f.open("/home/reskai/work.txt"); if (f) { f << buf; f << "\r\n"; while (argc-- > 0) { f << *argv++ << "\r\n"; } f.close(); } return 0; }
myhelp用来获取当前的工作目录,以及将调用的参数全部输出到文件当中。
随后更改项目的链接器,用myhelp替换掉g++来当链接器,得到了一些有意思的信息
/home/reskai myhelp -o /home/reskai/projects/projectK/bin/x64/Debug/projectK.out -Wl,--no-undefined -Wl,-L../common/bin/x64/Debug -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack /home/reskai/projects/projectK/obj/x64/Debug/main.o libcommon.a
在远程调用linux的时候,当前的工作目录不是项目路径而是~/……恩……就是这个我想当然的原因导致我一直没能够成功编译
然后我就去改了“附加库目录”,设置到了正确的位置,随后重新链接……我再次怀疑人生,仍然无法找到文件。(其实这个时候应该想到的,之前我设置附加库目录为绝对地址仍然无法链接说明了这个选项还是有bug的)
最后没有办法的情况下,我试着将“附加库目录”给删除了,然后在"附加依赖项"中直接填入完整的静态库路径“./projects/common/bin/x64/Debug/libcommon.a”,这次终于通过链接了。
虽然终于成功用vs在linux下静态链接了自己写的库,但是这个解决方法吧,有点不伦不类的。不知道到底是vs2017的BUG还是我对linux的编译链接体系不太清楚。
用此文记录下我遇到的这个问题与思考方法以及最终的解决方案。
题外话,就是因为这个问题让我之前一天到凌晨4点才睡着,第二天上了一天班,晚上又想这个问题到现在这个点才解决。