簡體   English   中英

Makefile - 如何組織和構建多個庫版本

[英]Makefile - How to organize and build multiple library versions

我正在嘗試創建一個構建系統,但我應該使用的結構不清楚。 我有各種庫文件及其相關的包含。 這些庫文件(或模塊)可能有不同的版本。 因此,module1 可能只有 1 個版本,而 ModuleN 可能有 50 個版本。 現在我的問題是我不確定如何組織我的樹,以便我可以為給定版本構建我的 Library.a 包。

我的第一個想法是按以下方式組織我的文件:

           Libraries                      Includes
               ¦                              ¦
    ----------------------          ----------------------
    ¦          ¦          ¦         ¦          ¦          ¦
   V1.0      V1.1       V1.2       V1.0      V1.1       V1.2
    ¦          ¦          ¦         ¦          ¦          ¦         
 Lib1.c     Lib3.c     Lib2.c     Lib1.h     Lib3.h     Lib2.h   
 Lib2.c                Lib3.c     Lib2.h                Lib3.h
 Lib3.c                           Lib3.h
 Lib4.c                           Lib4.h 

現在,我將如何構建我的包 V1.2,考慮到它還需要在整個樹中合並最新庫的聯盟(即 V1.2 包 = V1.0 U V1.1 U V1.2)。 在這種情況下,手動定義規則不會太困難,但很快就會變得無法管理 100 個文件。

也許在通常的實踐中將未更改的文件從一個版本復制到下一個版本,但隨后就很難知道哪里是什么。

有沒有解決這個問題的典型方法?

處理這個問題的正確方法是使用像 Git 這樣的版本控制系統。 它旨在准確處理您所描述的內容。

評論中有幾條關於使用 Git 完成您想要的操作的建議。 但是,您似乎對庫中文件的存儲方式存在誤解。

你在評論中說:

我想一次性從最新的存儲庫中構建任何版本的庫(如果你願意,可以從 Git 中提取),而不必從 Git 中進行可能的 100 次拉取

和:

但是如果你了解分支,你就會知道通過切換你會丟失之前的快照。 因此,如果您從構建一個分支(獲得 V1.0)開始,然后切換到第二個分支構建 V1.1,您將失去 V1.0。

查看這些注釋和您的示例文件結構,這表明您認為 V1.0 分支將包含Lib1.cLib2.cLib3.cLib4.c而 V1.1 分支將僅包含Lib3.c並且 V1.2 分支將只包含Lib2.cLib3.c 不是Git 的工作方式。

以下是如何在 Git 中存儲這些文件的示例:

首先將 V1.0 文件放入目錄結構中:

[dbush@db-centos7 mylib]$ ls -lR
.:
total 0
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:19 inc
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:17 src

./inc:
total 16
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib1.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib2.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib3.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib4.h

./src:
total 16
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:16 Lib1.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib2.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib3.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib4.c

然后創建一個新的 git repo,添加文件並提交它們:

[dbush@db-centos7 mylib]$ git init
Initialized empty Git repository in /home/dbush/mylib/.git/
[dbush@db-centos7 mylib]$ git add *
[dbush@db-centos7 mylib]$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   inc/Lib1.h
#   new file:   inc/Lib2.h
#   new file:   inc/Lib3.h
#   new file:   inc/Lib4.h
#   new file:   src/Lib1.c
#   new file:   src/Lib2.c
#   new file:   src/Lib3.c
#   new file:   src/Lib4.c
#
[dbush@db-centos7 mylib]$ git commit

現在你已經提交了 1.0 版本的文件,接下來我們根據當前版本創建一個標簽:

[dbush@db-centos7 mylib]$ git tag -a -m "version 1.0" V1.0
[dbush@db-centos7 mylib]$ git tag  -l
V1.0

現在,Lib3.c 看起來像這樣:

#include <stdio.h>

void lib3()
{
    printf("lib3 1.0\n");
}

現在讓我們對 1.1 版本進行更改:

#include <stdio.h>

void lib3()
{
    printf("lib3 1.1\n");
}

我們可以看到工作副本和簽入版本之間存在差異:

[dbush@db-centos7 mylib]$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   src/Lib3.c
#
no changes added to commit (use "git add" and/or "git commit -a")
[dbush@db-centos7 mylib]$ git diff
diff --git a/src/Lib3.c b/src/Lib3.c
index 3593018..12542d9 100644
--- a/src/Lib3.c
+++ b/src/Lib3.c
@@ -2,5 +2,5 @@

 void lib3()
 {
-    printf("lib3 1.0\n");
+    printf("lib3 1.1\n");
 }

然后我們提交更改:

[dbush@db-centos7 mylib]$ git add src/Lib3.c
[dbush@db-centos7 mylib]$ git commit -m "updated Lib3.c for version 1.1"

並將其標記為 1.1 版:

[dbush@db-centos7 mylib]$ git tag  -a -m "version 1.1" V1.1

現在讓我們假設我們想要構建 1.0 代碼。 我們簽出標簽:

[dbush@db-centos7 mylib]$ git checkout V1.0
Note: checking out 'V1.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at a1ee8c1... initial commit
[dbush@db-centos7 mylib]$ ls -lR
.:
total 0
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:19 inc
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:33 src

./inc:
total 16
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib1.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib2.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib3.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib4.h

./src:
total 16
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:16 Lib1.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib2.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:33 Lib3.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib4.c
[dbush@db-centos7 mylib]$ cat src/Lib3.c
#include <stdio.h>

void lib3()
{
    printf("lib3 1.0\n");
}
[dbush@db-centos7 mylib]$ cat src/Lib2.c
#include <stdio.h>

void lib2()
{
    printf("lib2 1.0\n");
}

您可以看到完整的源代碼樹可用,並且 Lib3.c 是 1.0 版本,Lib2.c 也是如此。 現在我們要構建 1.1,所以讓我們獲取 1.1 標簽:

[dbush@db-centos7 mylib]$ git checkout V1.1
Previous HEAD position was a1ee8c1... initial commit
HEAD is now at 95a429c... updated Lib3.c for version 1.1
[dbush@db-centos7 mylib]$ ls -lR
.:
total 0
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:19 inc
drwxrwxr-x. 2 dbush dbush 62 Jan 20 10:35 src

./inc:
total 16
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib1.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib2.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:18 Lib3.h
-rw-rw-r--. 1 dbush dbush 13 Jan 20 10:19 Lib4.h

./src:
total 16
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:16 Lib1.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib2.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:35 Lib3.c
-rw-rw-r--. 1 dbush dbush 62 Jan 20 10:17 Lib4.c
[dbush@db-centos7 mylib]$ cat src/Lib3.c
#include <stdio.h>

void lib3()
{
    printf("lib3 1.1\n");
}
[dbush@db-centos7 mylib]$ cat src/Lib2.c
#include <stdio.h>

void lib2()
{
    printf("lib2 1.0\n");
}

從這里您可以看到,不僅存在 Lib3.c 的 1.1 副本,而且還存在所有其他包含 V1.0 內容的文件。 您不需要進行多次簽出,也不會丟失任何在最新提交中未更新的文件。

你可以按照上面的例子來設置你的倉庫。 所以你會:

  • 將 1.0 文件放在所需的目錄結構中
  • 創建一個新的 git repo 並提交文件
  • 標簽版本 1.0
  • 復制 1.1 版的文件更改
  • 提交更改的文件,然后標記版本 1.1
  • 復制 1.2 版的文件更改
  • 提交更改的文件,然后標記版本 1.2
  • 等等...

如果您在使用新版本時需要刪除文件,這也適用。 例如,如果在 1.3 版中刪除了 Lib4.c,那么在檢出標簽 1.0、1.1 和 1.2 時會看到該文件,但在檢出標簽 1.3 時則不會。

因此,一旦您設置了 Git 存儲庫,您所需要做的就是檢出單個標簽一次,您就擁有了所需的一切。

編輯:

當需要將這些文件用於多個(可能是並發的)構建時,Git 仍然非常適合這一點。 如果您要保留建議的文件夾結構,則需要了解文件的完整歷史記錄才能獲得每個文件的正確版本,並且您仍希望將每個相關源文件的副本復制到“活動”構建目錄中以便由一個構建創建的目標文件不會被另一個覆蓋。 Git 將完全為您管理所有這些。

Git 允許克隆本地存儲庫,並執行特定分支或標簽的最小克隆,這樣您只需復制您需要的內容,而不是在進程中獲取整個 git 歷史記錄,因此擁有多個副本不是問題。 您可以按如下方式執行此操作:

[dbush@db-centos7 mylib]$ git status
# On branch master
nothing to commit, working directory clean
[dbush@db-centos7 mylib]$ cd ..
[dbush@db-centos7 ~]$ git clone --single-branch --branch V1.0 ./mylib mylib-v1.0
Cloning into 'mylib-v1.0'...
done.
Note: checking out 'a1ee8c1bfdbb20f3e0716212582338371b60d9bc'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

[dbush@db-centos7 ~]$ cd mylib-v1.0
[dbush@db-centos7 mylib-v1.0]$ git status
# Not currently on any branch.
nothing to commit, working directory clean
[dbush@db-centos7 mylib-v1.0]$ git branch -l
* (no branch)
[dbush@db-centos7 mylib-v1.0]$ 

--branch選項表示克隆特定的分支或標簽,而--single-branch選項創建一個僅包含給定標簽的淺層克隆,這樣克隆的.git目錄就不會很大並且可以快速創建。

我知道 OP 說他不想使用 Git,所以這個答案更適合閱讀這個問題的其他人。

從存儲庫構建任意版本的一種非常常見的做法是使用標簽。 標記是一種突出特定提交的方式。 Git 支持兩種類型的標簽:輕量級標簽和帶注釋標簽。

輕量級標簽就像一個分支。 它只是一個指向提交的指針。 與分支的不同之處在於這個指針不會隨着新的提交而改變。 不建議將這些標簽用於您的目的。 它們在開發過程中更多地供開發人員使用。 要創建輕量級標簽,請使用此命令

git tag <name>

另一種標簽類型是帶注釋的標簽。 它們包含更多信息並進行校驗和。 這些是您要用於發布的那些。 與提交一樣,您為帶注釋的標簽指定標簽消息。 要創建帶注釋的標簽,請使用以下命令:

git tag -a <name>

這將打開一個編輯器,您可以在其中編寫標簽消息。 您也可以使用-m "<message>"在命令行上指定消息

要查看所有標簽,只需使用:

git tag

您可以像結帳分支一樣結帳標簽:

git checkout <tag>

在此處閱讀有關標記的更多信息: https : //git-scm.com/book/en/v2/Git-Basics-Tagging

因此,您要做的是為對應於發布的每個提交創建一個(最好是帶注釋的)標簽。 然后,假設您可以通過調用make來構建項目,您可以使用以下兩個命令構建任何版本:

git checkout <tag>
make

注意:在上面的評論中,我說的是分支。 那是我暫時的困惑。 可以為此目的使用分支,但標記是正確的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM