未分類

如何從源代碼安裝軟件...然後刪除它

簡介:本詳細指南介紹瞭如何從Linux中的源代碼安裝程序以及如何從源代碼中刪除安裝的軟件。

Linux發行版的最大優勢之一是它的包管理器和相關的軟件庫。 有了它們,您就擁有了以完全自動化的方式在計算機上下載和安裝新軟件所需的所有工具和資源。

但是儘管他們付出了很多努力,但軟件包維護者無法處理每一個用例。 他們也無法打包所有可用的軟件。 因此,有些情況下您必須自己編譯和安裝新軟件。 至於我自己,最常見的原因,到目前為止,我必須編譯一些軟件,當我需要運行一個非常具體的版本。 或者因為我想修改源代碼或使用一些花哨的編譯選項。

如果您的需求屬於後一類,您可能已經知道自己在做什麼。 但對於絕大多數Linux用戶來說,首次從源代碼編譯和安裝軟件可能看起來像一個啟動儀式:有點可怕; 但有希望進入一個新的可能世界,並成為特權社區的一部分,如果你克服了這一點。

建議閱讀如何在Ubuntu中安裝和刪除軟件[完整指南]

A.從Linux中的源代碼安裝軟件

而這正是我們將在這裡做的。 就該文章而言,假設我需要安裝 的NodeJS 8.1.1在我的系統上。 那個版本確切。 Debian存儲庫中沒有的版本:

sh$ apt-cache madison nodejs | grep amd64
    nodejs | 6.11.1~dfsg-1 | http://deb.debian.org/debian experimental/main amd64 Packages
    nodejs | 4.8.2~dfsg-1 | http://ftp.fr.debian.org/debian stretch/main amd64 Packages
    nodejs | 4.8.2~dfsg-1~bpo8+1 | http://ftp.fr.debian.org/debian jessie-backports/main amd64 Packages
    nodejs | 0.10.29~dfsg-2 | http://ftp.fr.debian.org/debian jessie/main amd64 Packages
    nodejs | 0.10.29~dfsg-1~bpo70+1 | http://ftp.fr.debian.org/debian wheezy-backports/main amd64 Packages

步驟1:從GitHub獲取源代碼

像許多開源項目一樣,NodeJS的源代碼可以在GitHub上找到: https://github.com/nodejs/node

所以,讓我們直接去那裡。

如果你不熟悉 GitHub上, 混帳 或任何其他 版本控制系統 值得一提的是,該存儲庫包含該軟件的當前來源,以及多年來對該軟件所做的所有修改的歷史記錄。 最終到為該項目編寫的第一行。 對於開發人員來說,保持歷史有很多優點。 對於我們今天,主要的是我們將能夠在任何給定的時間點獲得項目的來源。 更準確地說,我將能夠獲得我想要的8.1.1版本發佈時的源代碼。 即使從那以後有很多修改。

在GitHub上,您可以使用“分支”按鈕在不同版本的軟件之間導航。 “分支”和“標籤”在Git中是一些相關的概念。 基本上,開發人員創建“分支”和“標記”以跟踪項目歷史中的重要事件,例如他們開始處理新功能或發布版本時。 我不會在這裡詳細介紹,您需要知道的是我正在尋找版本 標記 “v8.1.1”

在“v8.1.1”標籤上選擇後,頁面會刷新,最明顯的變化是標籤現在顯示為URL的一部分。 此外,您會注意到文件更改日期也不同。 您現在看到的源樹是在創建v8.1.1標記時存在的源樹。 從某種意義上說,您可以將git等版本控制工具視為時間旅行機器,讓您可以來回瀏覽項目歷史記錄。

此時,我們可以下載NodeJS 8.1.1的源代碼。 你不能錯過建議下載項目的ZIP存檔的藍色大按鈕。 至於我自己,為了解釋起見,我將從命令行下載並解壓縮ZIP。 但如果你喜歡使用 GUI 工具,請不要猶豫,改為:

wget https://github.com/nodejs/node/archive/v8.1.1.zip
unzip v8.1.1.zip
cd node-8.1.1/

下載ZIP存檔非常有用。 但如果你想“像專業人士”這樣做,我建議直接使用 git 工具下載源。 它並不復雜 - 它將是您經常遇到的工具的第一次接觸:

# first ensure git is installed on your system
sh$ sudo apt-get install git
# Make a shallow clone the NodeJS repository at v8.1.1
sh$ git clone --depth 1 
              --branch v8.1.1 
              https://github.com/nodejs/node
sh$ cd node/

順便說一句,如果您有任何問題,請將本文的第一部分作為一般性介紹。 稍後我會對基於Debian和ReadHat的發行版進行更詳細的解釋,以幫助您解決常見問題。

無論如何,無論何時使用下載源代碼 git 或者作為ZIP存檔,您現在應該在當前目錄中具有完全相同的源文件:

sh$ ls
android-configure  BUILDING.md            common.gypi      doc            Makefile   src
AUTHORS            CHANGELOG.md           configure        GOVERNANCE.md  node.gyp   test
benchmark          CODE_OF_CONDUCT.md     CONTRIBUTING.md  lib            node.gypi  tools
BSDmakefile        COLLABORATOR_GUIDE.md  deps             LICENSE        README.md  vcbuild.bat

步驟2:了解程序的構建系統

我們通常談論“編譯源代碼”,但編譯只是從源代碼生成工作軟件所需的階段之一。 構建系統是一組工具和實踐,用於自動化和表達這些不同的任務,以便通過發出少量命令來完全構建軟件。

如果概念很簡單,那麼現實就更複雜了。 因為不同的項目或編程語言可能有不同的要求。 或者因為程序員的口味。 或支持的平台。 或者出於歷史原因。 或者......或者......有幾乎無窮無盡的理由選擇或創建另一個構建系統。 所有這些都說有很多不同的解決方案。

NodeJS使用了 GNU風格的構建系統。 這是開源社區的熱門選擇。 再一次,開始您的旅程的好方法。

編寫和調優構建系統是一項非常複雜的任務。 但對於“最終用戶”,GNU風格的構建系統使用兩個工具恢復自身: configuremake.

configure file是一個特定於項目的腳本,它將檢查目標系統配置和可用功能,以確保可以構建項目,最終處理當前平台的特性。

典型的重要組成部分 configure 工作是建立 Makefile。 這是包含有效構建項目所需指令的文件。

make 工具另一方面,是任何類Unix系統上都可以使用的POSIX工具。 它將讀取特定於項目的內容 Makefile 並執行構建和安裝程序所需的操作。

但是,與Linux世界一樣,您仍然需要一些延遲來根據您的特定需求自定義構建。

./configure --help

configure -help 命令將顯示所有可用的配置選項。 再次,這是特定於項目的。 說實話,有時需要深入了解項目,然後才能完全理解每個配置選項的含義。

但是至少有一個標準的GNU Autotools選項你必須知道: --prefix 選項。 這與文件系統層次結構和軟件安裝位置有關。

推薦的read8 Vim提示和技巧將使您成為專業用戶

步驟3:FHS

典型分佈上的Linux文件系統層次結構大多符合 文件系統層次標準(FHS)

該標準解釋了系統各種目錄的用途: /usr, /tmp, /var 等等。

使用GNU Autotools和大多數其他構建系統時,新軟件的默認安裝位置將是 /usr/local。 根據FSH,這是一個不錯的選擇 “/ usr / local層次結構供系統管理員在本地安裝軟件時使用? 系統軟件更新時,需要保護它不被覆蓋。 它可以用於可在一組主機之間共享但在/ usr中找不到的程序和數據。“

/usr/local 層次結構以某種方式複制根目錄,您將在那裡找到 /usr/local/bin 對於可執行程序, /usr/local/lib 對於圖書館, /usr/local/share 用於體系結構獨立文件等。

使用時唯一的問題 /usr/local 用於自定義軟件安裝的樹是用於將所有軟件混合在一起的文件。 特別是,在安裝了幾個軟件之後,很難跟踪到哪個文件 /usr/local/bin/usr/local/lib 屬於哪個軟件。 但這不會給系統帶來任何問題。 畢竟, /usr/bin 幾乎是一團糟。 但是,當您想要刪除手動安裝的軟件時,這將成為一個問題。

為了解決這個問題,我通常更喜歡在中安裝自定義軟件 /opt 而是子樹。 再一次,引用FHS:

_“/ opt保留用於安裝附加應用程序軟件包。

要安裝在/ opt中的軟件包,必須在單獨的/ opt /中找到其靜態文件。 或/ opt / 目錄樹,其中是描述軟件包的名稱,並且是提供商的LANANA註冊名稱。” _

所以我們將創建一個子目錄 /opt 專門用於我們的自定義NodeJS安裝。 如果有一天我想刪除該軟件,我只需刪除該目錄:

sh$ sudo mkdir /opt/node-v8.1.1
sh$ sudo ln -sT node-v8.1.1 /opt/node
# What is the purpose of the symbolic link above?
# Read the article till the end--then try to answer that
# question in the comment section!

sh$ ./configure --prefix=/opt/node-v8.1.1
sh$ make -j9 && echo ok
# -j9 means run up to 9 parallel tasks to build the software.
# As a rule of thumb, use -j(N+1) where N is the number of cores
# of your system. That will maximize the CPU usage (one task per
# CPU thread/core + a provision of one extra task when a process
# is blocked by an I/O operation.

除了“ok”之後的任何東西 make 命令已完成意味著在構建過程中出現錯誤。 因為我們運行並行構建 -j 選項,在構建系統產生大量輸出的情況下檢索錯誤消息並不總是容易的。

在問題的情況下,只需重新啟動 make,但沒有 -j 選擇這次。 並且錯誤應該出現在輸出的末尾附近:

sh$ make

最後,一旦編譯結束,您可以通過運行以下命令將軟件安裝到其位置:

sh$ sudo make install

並測試它:

sh$ /opt/node/bin/node --version
v8.1.1

B.如果從源代碼安裝時出現問題怎麼辦?

我上面解釋的主要是你在一個記錄良好的項目的“構建指令”頁面上看到的內容。 但鑑於本文的目標是讓您從源代碼編譯您的第一個軟件,可能值得花時間調查一些常見問題。 所以,我將再次完成整個過程,但這次是從一個全新的極小的Debian 9.0和CentOS 7.0系統。 所以你可以看到我遇到的錯誤以及我是如何解決它們的。

來自Debian 9.0“Stretch”

[email protected]:~$ git clone --depth 1 
                             --branch v8.1.1 
                             https://github.com/nodejs/node
-bash: git: command not found

這個問題很容易診斷和解決。 只需安裝 git 包裝:

[email protected]:~$ sudo apt-get install git
[email protected]:~$ git clone --depth 1 
                             --branch v8.1.1 
                             https://github.com/nodejs/node && echo ok
[...]
ok
[email protected]:~/node$ sudo mkdir /opt/node-v8.1.1
[email protected]:~/node$ sudo ln -sT node-v8.1.1 /opt/node

這裡沒問題。

[email protected]:~/node$ ./configure --prefix=/opt/node-v8.1.1/
WARNING: failed to autodetect C++ compiler version (CXX=g++)
WARNING: failed to autodetect C compiler version (CC=gcc)
Node.js configure error: No acceptable C compiler found!
        Please make sure you have a C compiler installed on your system and/or
        consider adjusting the CC environment variable if you installed
        it in a non-standard prefix.

顯然,要編譯項目,您需要一個編譯器。 NodeJS正在使用 C ++語言,我們需要一個C ++ 編譯器。 在這裡,我將為此安裝`g ++`,GNU C ++編譯器:

[email protected]:~/node$ sudo apt-get install g++
[email protected]:~/node$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
[email protected]:~/node$ make -j9 && echo ok
-bash: make: command not found

另一個缺少的工具。 同樣的症狀。 相同解決方案

[email protected]:~/node$ sudo apt-get install make
[email protected]:~/node$ make -j9 && echo ok
[...]
ok
[email protected]:~/node$ sudo make install
[...]
[email protected]:~/node$ /opt/node/bin/node --version
v8.1.1

成功了!

請注意:我已經逐一安裝了各種工具,以展示如何診斷編譯問題並向您展示解決這些問題的典型解決方案。 但是,如果您更多地搜索該主題或閱讀其他教程,您會發現大多數發行版都有“元軟件包”作為安裝一些或所有用於編譯軟件的典型工具的保護傘。 在基於Debian的系統上,您可能會遇到 建立必需品 為此目的包。 在基於Red Hat的發行版中,這將是 “開發工具” 組。

來自CentOS 7.0

[[email protected] ~]$ git clone --depth 1 
                               --branch v8.1.1 
                               https://github.com/nodejs/node
-bash: git: command not found

沒有找到指令? 只需使用安裝即可 yum 包經理:

[[email protected] ~]$ sudo yum install git
[[email protected] ~]$ git clone --depth 1 
                               --branch v8.1.1 
                               https://github.com/nodejs/node && echo ok
[...]
ok
[[email protected] ~]$ sudo mkdir /opt/node-v8.1.1
[[email protected] ~]$ sudo ln -sT node-v8.1.1 /opt/node
[[email protected] ~]$ cd node
[[email protected] node]$ ./configure --prefix=/opt/node-v8.1.1/
WARNING: failed to autodetect C++ compiler version (CXX=g++)
WARNING: failed to autodetect C compiler version (CC=gcc)
Node.js configure error: No acceptable C compiler found!

        Please make sure you have a C compiler installed on your system and/or
        consider adjusting the CC environment variable if you installed
        it in a non-standard prefix.

你猜它:NodeJS是用C ++語言編寫的,但我的系統缺少相應的編譯器。 百勝來救援。 由於我不是常規的CentOS用戶,我實際上必須在Internet上搜索包含g ++編譯器的軟件包的確切名稱。 引導我到那個頁面: https://superuser.com/questions/590808/yum-install-gcc-g-doesnt-work-anymore-in-centos-6-4

[[email protected] node]$ sudo yum install gcc-c++
[[email protected] node]$ ./configure --prefix=/opt/node-v8.1.1/ && echo ok
[...]
ok
[[email protected] node]$ make -j9 && echo ok
[...]
ok
[[email protected] node]$ sudo make install && echo ok
[...]
ok
[[email protected] node]$ /opt/node/bin/node --version
v8.1.1

成功。 再次。

C.對源代碼中安裝的軟件進行更改

您可以從源安裝軟件,因為您需要在分發存儲庫中沒有的特定版本。 或者因為你想要 修改 那個節目。 要么修復錯誤,要么添加功能。 畢竟,開源就是這樣。 因此,我將利用這個機會讓您體驗一下您現在能夠編譯自己的軟件所擁有的強大功能。

在這裡,我們將對NodeJS的來源進行微小的改動。 我們將看看我們的更改是否會合併到軟件的編譯版本中:

打開文件 node/src/node.cc 在你最喜歡的 文本編輯器 (vim,nano,gedit,...)。 並嘗試找到該代碼片段:

   if (debug_options.ParseOption(argv[0], arg)) {
      // Done, consumed by DebugOptions::ParseOption().
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
      printf("%sn", NODE_VERSION);
      exit(0);
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
      PrintHelp();
      exit(0);
    }

它在附近 行3830的文件。 然後修改包含的行 printf 改為匹配那個:

      printf("%s (compiled by myself)n", NODE_VERSION);

然後回到你的終端。 在進一步研究之前 - 為了讓您更深入地了解git背後的力量 - 您可以檢查是否修改了正確的文件:

diff --git a/src/node.cc b/src/node.cc
index bbce1022..a5618b57 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -3828,7 +3828,7 @@ static void ParseArgs(int* argc,
     if (debug_options.ParseOption(argv[0], arg)) {
       // Done, consumed by DebugOptions::ParseOption().
     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
-      printf("%sn", NODE_VERSION);
+      printf("%s (compiled by myself)n", NODE_VERSION);
       exit(0);
     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
       PrintHelp();

您應該在更改之前看到行之前的“ - ”(減號)。 更改後的行前面有一個“+”(加號)。

現在是重新編譯和重新安裝軟件的時候了:

make -j9 && sudo make install && echo ok
[...]
ok

這一次,它可能失敗的唯一原因是你在更改代碼時犯了錯字。 如果是這種情況,請重新打開 node/src/node.cc 文件編輯器中的文件並修復錯誤。

一旦您設法編譯並安裝了新修改的NodeJS版本,您就可以檢查您的修改是否實際包含在軟件中:

[email protected]:~/node$ /opt/node/bin/node --version
v8.1.1 (compiled by myself)

恭喜! 您已經對開源程序進行了第一次更改!

D.讓shell找到我們的自定義構建軟件

你可能已經註意到,直到現在,我總是通過指定二進製文件的絕對路徑來啟動我新編譯的NodeJS軟件。

/opt/node/bin/node

有用。 但至少可以說這很煩人。 實際上有兩種常見的方法可以解決這個問題。 但要了解它們,您必須首先知道您的shell通過查找可執行文件來查找可執行文件 PATH 環境變量.

[email protected]:~/node$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

在這個Debian系統上,如果你沒有明確指定任何目錄作為命令名的一部分,shell將首先查找可執行程序 /usr/local/bin,如果沒有找到 /usr/bin,如果沒有找到 /bin 然後,如果沒有找到 /usr/local/games 然後,如果沒有找到 /usr/games,如果沒有找到...... shell將報告錯誤 “沒有找到指令”.

鑑於此,我們有兩種方法可以使shell可以訪問命令:將其添加到已配置的命令之一 PATH 目錄。 或者通過添加包含我們的可執行文件的目錄 PATH.

添加/ usr / local / bin中的鏈接

只是 仿形 節點二進制可執行文件 /opt/node/bin/usr/local/bin 這將是一個壞主意,因為通過這樣做,可執行程序將無法再找到屬於其他所需組件 /opt/node/ (軟件相對於自己的位置定位資源文件是一種常見做法)。

因此,傳統的方法是使用符號鏈接:

[email protected]:~/node$ sudo ln -sT /opt/node/bin/node /usr/local/bin/node
[email protected]:~/node$ which -a node || echo not found
/usr/local/bin/node
[email protected]:~/node$ node --version
v8.1.1 (compiled by myself)

這是一個簡單而有效的解決方案,特別是如果軟件包僅由幾個眾所周知的可執行程序組成 - 因為您必須為每個用戶可調用命令創建符號鏈接。 例如,如果您熟悉NodeJS,那麼您就知道了 npm 伴侶應用程序我應該從符號鏈接 /usr/local/bin 太。 但是我把它作為一種練習給你。

修改PATH

首先,如果您嘗試了上述解決方案,請刪除先前創建的節點符號鏈接以從清除狀態開始:

its[email protected]:~/node$ sudo rm /usr/local/bin/node
[email protected]:~/node$ which -a node || echo not found
not found

而現在,這是改變你的神奇命令 PATH:

[email protected]:~/node$ export PATH="/opt/node/bin:${PATH}"
[email protected]:~/node$ echo $PATH
/opt/node/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

簡單地說,我更換了內容 PATH 環境變量按其先前的內容,但前綴為 /opt/node/bin。 所以,正如你現在可以想像的那樣,shell將首先進入 /opt/node/bin 可執行程序的目錄。 我們可以確認使用了 which 命令:

[email protected]:~/node$ which -a node || echo not found
/opt/node/bin/node
[email protected]:~/node$ node --version
v8.1.1 (compiled by myself)

只要您創建了符號鏈接,“鏈接”解決方案就是永久性的 /usr/local/bin中, PATH 更改僅對當前shell有效。 我讓你自己做一些研究,知道如何改變 PATH 永久。 作為提示,它與您的“個人資料”有關。 如果您找到解決方案,請使用下面的評論部分與其他讀者分享!

E.如何從源代碼中刪除新安裝的軟件

由於我們的自定義編譯NodeJS軟件完全位於 /opt/node-v8.1.1 目錄,刪除該軟件並不比使用該軟件更多的工作 rm 命令刪除該目錄:

sudo rm -rf /opt/node-v8.1.1

謹防: sudorm -rf 是一個危險的雞尾酒! 在按“enter”鍵之前,請務必檢查您的命令兩次。 如果刪除錯誤的目錄,您將不會收到任何確認消息並且不會取消刪除...

然後,如果你修改了你的 PATH,你將不得不恢復這些變化。 這根本不復雜。

如果你已經創建了鏈接 /usr/local/bin 你將不得不將它們全部刪除:

[email protected]:~/node$ sudo find /usr/local/bin 
                                 -type l 
                                 -ilname "/opt/node/*" 
                                 -print -delete
/usr/local/bin/node

等待? 依賴地獄在哪裡?

作為最後的評論,如果您閱讀有關編譯自己的自定義軟件的內容,您可能已經聽說過 依賴地獄。 這是一個令人討厭的情況的暱稱,在能夠成功編譯軟件之前,您必須首先編譯一個必備庫,這反過來需要另一個庫,而這個庫本身可能與您已經使用的其他軟件不兼容安裝。

您的發行版的軟件包維護者的部分工作是實際解決該依賴性地獄,並確保您的系統的各種軟件使用兼容的庫並按正確的順序安裝。

在那篇文章中,我故意選擇安裝NodeJS,因為它實際上沒有依賴關係。 我說“虛擬”,因為事實上,它 依賴。 但是這些依賴項的源代碼存在於項目的源代碼庫中(在 node/deps 子目錄),所以你不必手動下載和安裝它們。

但如果您有興趣了解有關該問題的更多信息並學習如何處理它,請告訴我使用下面的評論部分:這對於更高級的文章來說將是一個很棒的主題!

資源