天天看點

對VC++工程編譯過程的梳理對VC++工程編譯過程的梳理

對VC++工程編譯過程的梳理

VC++的項目和解決方案檔案解讀,無非就是利用這些資訊進行一個軟體的編譯,這些檔案裡面是存放的項目的配置和工程的組織,類似于makefile檔案. 但是隻有VC++6.0的時候可以導出makefile檔案,VC6的project>Export MakeFile,往後的版本都取消了。 是以隻能從各個檔案中去擷取相關資訊,最後才編譯。

編譯器MSBuild (VCBuild) 調用配置檔案:

文章參閱MSDN上的MSBuild (Visual C++)

  • .vcxproj

    :工程配置檔案
  • .props

    :使用項目屬性表可以為生成工具(如編譯器或連結器)指定開關并建立使用者定義的宏。
  • .vcxproj.user

    :使用者檔案,存儲特定于使用者的屬性,例如調試和部署設定。vcxproj.user 檔案應用于特定使用者的所有項目。
  • .vcxproj.filters

    :當使用解決方案資料總管向項目中添加檔案時,篩選器檔案 (.vcxproj.filters) 會基于該檔案的檔案擴充名定義在解決方案資料總管樹視圖的哪個位置添加該檔案。

擷取配置

當編譯程式時,會把上面幾個檔案中所有資訊輸入到編譯器中,結合目前編譯器的全局參數

include files

lib files

source files

等等,從配置檔案中确定标準庫和頭檔案的位置,使所有參與編譯的依賴關系都找清楚。

編譯預處理階段

讀取源程式,對其中的僞指令(

以#開頭的指令

)和特殊符号進行處理;

  • 将所有的“#define”指令删除,并且将宏定義展開;
  • 處理所有的條件編譯指令;
  • 處理#include預編譯指令,将被包含的頭檔案插入到預編譯指令的位置。這可能是一個遞歸操作,如果被包含的頭檔案中又包含其他頭檔案;
  • 删除所有的注釋;
  • 添加行号和檔案辨別;
  • 保留所有的#program編譯器指令,後續的編譯步驟中要用到該指令。
  • 經過預編譯的處理以後,頭檔案被合并到源檔案中,并且所有的宏定義都被展開。

編譯階段

編譯階段将源程式(

*.c 或者*.cpp

)轉換成為目标代碼

*.obj

;

  • 以預編譯的輸出為輸入,将C++源代碼翻譯成計算機系統應将能夠識别的二進制機器指令,并将編譯的輸出結果存儲在COFF格式的目标檔案中。在編譯的中間過程中,還可以通過cl指令選擇性地輸出彙編語言格式的中間檔案。
  • 在執行編譯的時候,編譯器以“.cpp”檔案為機關,對于每一個“.cpp”檔案,編譯器都會輸出一個目标檔案。

連結階段

連接配接階段是把源程式轉換成的目标代碼(obj檔案)與你程式裡面調用的庫函數對應的代碼連接配接起來形成對應的可執行檔案(exe檔案)就可以了;

總結:

見簡簡單單的回顧了編譯的過程,重點想說的是在前面的擷取配置階段,使用者自定義的路徑,參數等都會讀入編譯器,解析出來.

應用:

mySerialPortTools.vcxproj.user 中定義了QTDIR

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <QTDIR>D:\Qt\Qt5.7.0\5.7\msvc2015_64</QTDIR>
    <LocalDebuggerEnvironment>PATH=$(QTDIR)\bin%3b$(PATH)</LocalDebuggerEnvironment>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <QTDIR>D:\Qt\Qt5.7.0\5.7\msvc2015_64</QTDIR>
    <LocalDebuggerEnvironment>PATH=$(QTDIR)\bin%3b$(PATH)</LocalDebuggerEnvironment>
  </PropertyGroup>
</Project>
           

mySerialPortTools.vcxproj檔案中會直接用這個參數QTDIR

<ClCompile>
      <AdditionalIncludeDirectories>.;$(QTDIR)\include;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtCore;temp\moc;$(QTDIR)\mkspecs\win32-msvc2015;.\GeneratedFiles;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalOptions>-Zc:strictStrings -Zc:throwingNew %(AdditionalOptions)</AdditionalOptions>
      <AssemblerListingLocation>temp\obj\</AssemblerListingLocation>
      <BrowseInformation>false</BrowseInformation>
      <DebugInformationFormat>None</DebugInformationFormat>
      <ExceptionHandling>Sync</ExceptionHandling>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <Optimization>MaxSpeed</Optimization>
      <PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_WIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessToFile>false</PreprocessToFile>
      <ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <RuntimeTypeInfo>true</RuntimeTypeInfo>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
      <WarningLevel>TurnOffAllWarnings</WarningLevel>
    </ClCompile>