應用程序編譯後 只能在兼容該編譯器的平台上運行 , 為什麼 windows/linux 程序可以在多個系統版本間運行?
比如xp平台的程序可以在win7等版本系統運行
ubuntu 系統下通過apt-get install 安裝的程序 也都可以在不同ubuntu 版本間運行
先說「是不是」目標為x86平台的ubuntu編譯的程序,在arm, powerpc版的ubuntu上都不能運行。再談題目
「兼容該編譯器」這話說得很模糊。。。我在x86的ubuntu上搭一個交叉編譯環境(比如目標平台MIPS),這叫不叫x86 ubuntu「兼容」MIPS編譯器?
關鍵是,程序編譯完成後,和編譯器就沒什麼關係了(運行時庫不算,VM語言不考慮),全成機器碼了。指令不一致就跪了,所以以x86為目標編譯的程序不能放到ARM上跑。理論上只要硬體指令兼容,都可以跑,但實際上,程序可能有各種依賴(用了操作系統API,外部庫之類),不同系統的可執行文件的格式也不一致,所以Windows編譯的程序放到Linux上不能運行。但是同種操作系統、同平台提供的庫,格式等等基本相同,就是所謂「兼容」,所以基本上可以在多個版本上運行。還有一點ubuntu 系統下通過apt-get install 安裝的程序 也都可以在不同ubuntu 版本間運行
apt-get install安裝程序,會根據你的系統平台,選擇相應的編譯版本下載,所以同樣的命令,在x86/x64/ARM/PowerPC等不同平台上裝的東西是不一樣的。
即使排除API的兼容問題,用靜態編譯出的可執行文件(不依賴動態鏈接庫),還是會有執行文件格式的問題,比如win下可執行文件的格式的PE,linux下是ELF。就算是同樣的可執行文件格式,比如都是ELF,ABI不兼容(比如大小端不同,棧的調用方法不同)也還是不能跑。
windows是花費了巨大的人力物力,才能達到依賴了win95的bug的程序在98修了這個bug之後還能自如的運行在98上的。linux嘛……
不談源碼兼容性,也不談 java .net 等基於虛擬機的,只談二進位兼容,有這麼幾個層次
1. 指令集和體系結構
x86 arm misc 互不兼容
x64 可以跑x86, arm64也可以跑 arm32 還有相同架構不同晶元的小差異,比如 intel 和 amd 不同的擴展指令集,這個編譯器會處理掉2. 封裝格式
linux 支持 aout 和 elf window 支持 pe , dos 下的com和exe 不是pe,在windows下是用模擬層跑的3. 運行時庫,大部分的兼容性問題應該出在這裡
鏈接 libc++3 的程序,系統里只有 libc++4 就不能跑 linux 的運行時庫兼容性做的不太好,而且系統不鼓勵軟體自帶庫 windows 在這方面是下苦工的,如 vczh 所說,而且軟體有自帶庫的習慣,有了WinSxS之後,不同版本庫共用要好的多了以前win下軟體自帶庫是直接和exe放一起的,對於ms自己的庫,現在是鼓勵用 Redistributable Package,以便不同軟體共用庫
4. 雜七雜八的兼容性問題
某個版本windows有bug,做了個fix,反而新版本windows修復bug後不能跑了。 linux是不管這種問題的,只有ms花了大量資源去搞這個。某新版windows引入的新特性,但在老版本上還要跑,那麼在源碼里做個運行時版本判斷。不判斷直接用新特性,老系統就跑不了。
還有硬編碼 c:windowssystem32 c:documents and settings 這種只能呵呵的。其實windows在這個地方做了不少工作,但如果windows裝D盤呢。
=========開始回答問題的分割線=========
arm misc 及其他嵌入式系統,不會考慮二進位兼容性,換個系統就必須重編譯android 在 java 層面abi是相同的,高版本系統自帶或者模擬低版本庫來保證兼容性。
在非java的so庫上,封裝格式必然是elf,android軟體會自帶多體系架構的so庫,armv5 armv7 x86linux 上,arm 的 怎麼也跑不了 x86 的程序吧。
最近幾年 gcc 的lib穩定了不少, libcpp3 libcpp4 那時才叫痛苦。apt-get install 安裝的就是各個編譯的特定系統兼容的軟體。windows x86 系統還是跑不了 x64 程序x64 系統基本都能跑 x86 程序軟體有自帶庫的習慣WinSxS 保證系統庫不會衝突鼓勵用 Redistributable Package,庫可共用windows 解決兼容性問題是做的最好的。這分明是一個關於裝載和執行的問題。一個應用程序對操作系統來說就是一個數據文件,只要它符合系統對「應用程序」這種文件的格式要求,它就能運行。「應用程序編譯後 只能在兼容該編譯器的平台上運行」, 這是一種不科學的模糊說法。
有種東西叫指令集和體系結構,有種東西叫運行時庫,你們體會一下。
兼容啊,高版本一般兼容低版本。出於商業需求
但是跨平台是不兼容的,比如windows的二進位和linux的不能互相使用。因為操作系統載入和處理可執行文件的方式與操作系統相關。推薦閱讀:
※gcc局部變數不用初始化么?
※對於同樣的 C 語言代碼,為什麼 Mac OS X 上用 gcc 編譯運行的結果和其他系統不同?
※GCC的參數-march=native是如何獲取cpu類型和指令集的?