visual studio 编译之源文件时间戳问题

  最近在开发项目中遇到一个很奇怪的问题:在源文件没有任何修改的情况下,每次使用visual studio(2020预览版)启动程序调试前,项目都会被重新编译一遍。这一度让我怀疑是最新版本预览版IDE的隐藏的问题,但是仔细思考又不太可能,于是基于一个没有出现这个问题的commit创建新的测试分支,对比验证没有出现类似问题,排除IDE的问题。最终对比commit提交历史,发现端倪,定位问题根本原因是引入的新库文件时间戳出现问题。(旧版本nuget-4.1.0打包工具在最新的visual studio 2019和2022下解包库相关文件时间戳出现问题,使用最新的nuget-5.1.0版本无此问题)

一、Build Solution & Rebuild Solution  & Clean Solution之间的区别

       Build Solution : 执行增量型构建。如果编译器认为代码文件未改变,就不会重写编译;否则需要进行编译。

       Clean Solution : 删除所有之前编译的文件。

       Rebuild Solution :  删除所有之前编译的文件,即:Clean;然后重写编译,不管代码文件是否由更改。

  1.1.两种编译过程流程图

  1.2.Build Solution执行过程:

  

  1.3.Rebuild Solution执行过程:

  

二、文件时间戳带来的编译问题

  2.1.编译器如何检测代码文件改变呢?——文件时间戳

    新建一个源代码文件*.h;*.cpp并添加代码:

     

    Build后的*.obj文件时间戳如下:

    

     修改后编译的源码文件:

    

     构建生存的对象文件:

    

     文件不做任何修改,进行Build:

    

          

    Clean:

    clean前:

     

     

    clean后:

    

    

     *.exe和*.obj文件被删除。

  2.2.手动修改时间戳

    2.2.1.源码不变,时间戳改为过去

    前:

    

    后:

    

    

    未进行重写编译。

    2.2.2.源码不变,时间戳改为将来

    前:

    

     后:

    

     第一次Build:

    

     第二次Build:

    

    只有代码文件修改时间戳在当前系统时间戳前,不管是否修改源文件,都会认为文件被修改,重写编译。

    2.2.3.源码修改,时间戳改为过去

    前:

    

     后:

    

     

    不会被重写编译。

  在正常编译代码中,修改文件的时间戳是系统自动计算的,一般编译过一次,不修改后,再次编译一般不会再重写编译;但是不保证一些包管理器由于版本问题,导致解析过程中出现时间戳超前(如最开始导读部分的问题),会导致每次都会重写编译,严重影响到项目开发进度。

三、给编码带来的一些启示

  • 尽量减少公共头文件,因为稍稍修改下这类头文件内容,那些包含头文件的其他源文件都会被重写编译;可以将一些特属于某个类或命名空间的的常量,枚举单独定义在头文件或定义在*.cpp(*.cc)文件中的。
  • 编译防火墙:定义接口类,使用指针组合对应的实现类,实现类单独定义和实现。这样,修改实现类的源文件,只会重写编译修改的文件,其他包含接口类的文件不必重写编译。

参考:

  • https://stackoverflow.com/questions/3095901/difference-between-build-solution-rebuild-solution-and-clean-solution-in-visua
  • https://bitwizards.com/thought-leadership/blog/2014/august-2014/visual-studio-why-clean-build-rebuild
  • https://www.cppstories.com/2018/01/pimpl/
posted @ 2021-08-22 20:35  blackstar666  阅读(732)  评论(0编辑  收藏  举报