c++跨平臺技術學習(二)--使用跨平臺的Make系統

make主要用在代碼移植性上。跨平臺管理編譯工作有好幾種方法,每種的核心都是一個叫make的程序,這是一個跨平臺的工具。

Make

假如你有一個程序叫做bar,它由bar.cpp和main.cpp兩個C++源文件以及一個bar.h頭文件組成

main.cpp

#include "bar.h"
int main(int argc, char *argv[]) {
    Bar bar;
    bar.SetBar(17);
    bar.PutBar();

}

bar.h

#pragma once
#ifndef  _BAR_00__
#define  _BAR_00__
class Bar {
public:
    void SetBar(int bar);
    void PutBar();
private:
    int m_bar;

};
#endif // ! _BAR_00__

bar.cpp

#include<stdlib.h>
#include<stdio.h>
#include "bar.h"
void Bar::SetBar(int bar) {
    m_bar = bar;
}
void Bar::PutBar() {
    char buf[16];
    snprintf(buf, sizeof(buf) - 1, "% d", m_bar);
    setenv("BAR", buf, 1);
}

bar對象維護了一個整數m_bar.m_bar的值由SetBar()決定,而PutBar()函數則把m_bar的值存到環境變量BAR裏。

從創建一個簡單腳本build.sh開始,把它編譯鏈接爲一個bar應用程序

#! /bin/sh
g++ -g -o bar bar.cpp main.cpp

隨後執行

sh build.sh

make工具按照一定的依賴規則來執行一組命令,以獲得需要的目標或結果。上面例子中,目標就是可執行文件bar,它依賴於源文件bar.cpp和main.cpp,而用來生成可執行文件的命令是

g++ -o bar bar.cpp main.cpp

make要求在一個文件裏指定目標,依賴關係和命令,通常這個文件的名字是Makefile,下面這個makefile同樣可以編譯我們的例子

bar:bar.cpp main.cpp
g++ -g -o bar bar.cpp main.cpp

有了Makefile之後,只需要鍵入下列命令

make

然後make就會爲我們生成bar程序

make如何處理shell腳本帶來的問題:

  • make沒徹底消除可移植性,在windows上,make並不像linux活mac上那樣是原生應用程序.
  • makefile並沒有解決指定不同編譯器編譯項目的問題。
  • 命令行參數依然是硬編碼
  • make只會在源碼的修改時間比可執行文件的修改時間萬,才重新編譯bar

    如何改進呢,重寫makefile如下

bar:bar.o main.o
   g++ -g -o bar main.o bar.o
bar.o:bar.cpp bar.h
  g++ -g -c bar.cpp
main.o:main.cpp bar.h
  g++ -g -c main.cpp

上面的makefile通過引入兩個新目標bar.o和main.o解決了依賴性的問題。現在依賴關係有了明確的目標,例如當bar.cpp和bar.h發生修改時,bar.o應該重新編譯。bar自己的依賴關係也發生了變化,它不在依賴於源文件,而是依賴於目標文件。所以touch文件main.cpp後再執行make時,會得到以下結果

touch main.cpp
make
g++ -g -c main.cpp
g++ -g -o bar bar.o main.o

注意到make只重新編譯了目標main.o和bar,但是編譯器和命令行參數仍舊是硬編碼。這兩個問題都可以用macro來解決

OBJS=bar.o  main.o
CXXFLAGS=-g
barL $(OBJS)
         $(CXX) $(CXXFLAGS) -o $@ $(OBJS)
bar.o:bar.cpp bar.h
         $(CXX) $(CXXFLAGS) -c bar.cpp
main.o:main.cpp bar.h
         $(CXX) $(CXXFLAGS) -c main.cpp)

如果你注意到所有的.o文件其實都只依賴於對應的.cpp文件和bar.h的話,我們可以進一步改進Makefile,通過額外的make機制如模式規則(pattern rules),Makefile可以簡化爲:

OBJS=bar.o main.o
CXXFLAGS= -g
bar:$(OBJS)
      $(CXX) $(CXXFLAGS) -o $@(OBJS)
% o:%.cpp
      $(CXX) $(CXXFLAGS) -c $ <
$(OBJS):bar.h

問題依然存在,把-g 提取出來放到CXXFLAGS裏確實是一大進步,但是依然是Makefile裏的硬編碼,what’s more terrible,它和編譯器脫離開來了,如果CXX不是使用g++,那麼-g可能會在別的編譯器上有完全不同的意思

未完待續……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章