c - Makefile - 如何组织和构建多个库版本

标签 c makefile build msbuild

我正在尝试创建一个构建系统,但我应该使用的结构不清楚。
我有各种库文件及其相关的包含。
这些库文件(或模块)可能有不同的版本。因此,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,考虑到它还需要在整个树中合并最新库的 union (即 V1.2 包 = V1.0 U V1.1 U V1.2)。在这种情况下,手动定义规则不会太难,但如果有 100 多个文件,它很快就会变得难以管理。

在通常的实践中,也许将未更改的文件从一个版本复制到下一个版本,但是很难知道在哪里是什么。

有没有解决这个问题的典型方法?

最佳答案

处理这个问题的正确方法是使用像 Git 这样的版本控制系统。它旨在处理 正是 你所描述的。

评论中有几个关于使用 Git 来完成你想要的东西的建议。但是,您似乎对库中文件的存储方式存在误解。

你在评论中说:

I would like to build any version of the library out of the latest repository (pulled freshly from Git if you like), in one go, without having to do potentially 100's of pulls from Git



和:

But if you understood branches, you would know that by switching you will loose your previous snapshot. So if you start by building a branch (get V1.0), then switch to second branch to build V1.1, you will have lost V1.0.



查看这些注释和您的示例文件结构,这表明您认为 V1.0 分支将包含 Lib1.c , Lib2.c , Lib3.c , 和 Lib4.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");
}

我们可以看到工作副本和 checkin 版本之间存在差异:

[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 内容。您不需要进行多次 checkout ,也不会丢失任何未在最新提交中更新的文件。

你可以按照上面的例子来设置你的 repo。所以你会:
  • 将 1.0 文件一起放在所需的目录结构中
  • 创建一个新的 git repo 并提交文件
  • 标签版本 1.0
  • 复制 1.1 版的文件更改
  • 提交更改的文件,然后标记版本 1.1
  • 复制 1.2 版的文件更改
  • 提交更改的文件,然后标记版本 1.2
  • 等等...

  • 如果您在进入新版本时需要删除文件,这也适用。例如,如果您在 1.3 版中删除了 Lib4.c,那么当您 checkout 标签 1.0、1.1 和 1.2 时,您会看到该文件,但在 checkout 标签 1.3 时不会看到该文件。

    因此,一旦您设置了 Git 存储库,您所需要做的就是 checkout 一个标签,然后您就拥有了所需的一切。

    编辑:

    当需要将这些文件用于多个(可能是并发的)构建时,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克隆的目录不大,可以快速创建。

    关于c - Makefile - 如何组织和构建多个库版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47469774/

    相关文章:

    c - GCC错误;下标值既不是数组也不是指针也不是 vector

    c - 目标中调用的 Makefile

    c# - Hololens 构建失败 - 命令 AssemblyConverter.exe 已退出,代码为 1

    java - 在 autoconf 或 makefile 中禁用版本后缀/扩展

    android - 使用 ant debug 命令构建 android 项目时,我的 apk 名称中附加了 debug 一词。我如何改变它?

    Android - zipalign 在 apksigner 之前失败

    c - 程序没有输出(预计 3 行),没有编译或运行时错误

    c - 错误 : stray '\302' in program

    c - 不安全的转换

    makefile - 子生成文件和向上传递变量