解决我们的版本控制和构建问题

时间:2022-05-13 14:09:18

Where I work we need to rethink the way we develop software and keep track of each released version. Do you have any suggestions to solve our problems?

在我工作的地方,我们需要重新思考我们开发软件的方式并跟踪每个发布的版本。您有什么建议可以解决我们的问题吗?

  1. We develop on Windows in C++ using VS 2005 (and C++ Builder for some interface stuff)

    我们使用VS 2005在C ++上开发Windows(以及用于某些界面的C ++ Builder)

  2. We use GIT but in the worse possible way imaginable. We are somewhat open to move to another source control.

    我们使用GIT但是可以想象的更糟糕的方式。我们有点愿意转向另一个源代码控制。

  3. We have 40+ in-house developed DLL. Many of those can be updated frequently.

    我们有40多个内部开发的DLL。其中许多可以经常更新。

  4. We have a few dramatically different projects that depend on those DLL.

    我们有一些显着不同的项目依赖于这些DLL。

  5. We deliver 100+ systems a year, each of those requires custom configuration. The majority also requires custom patches. We try as much as we can to bring those patches back into the main trunk but forks are inevitable.

    我们每年提供100多个系统,每个系统都需要自定义配置。大多数还需要自定义补丁。我们尽可能地尝试将这些补丁带回主干,但叉子是不可避免的。

  6. If a few years down the road we have to update a client's system, we should be able to get back the code used for that release and all the environment parameters. We need a way to validate that this code match the binaries on the client's system. Getting back the code should be as trivial as possible and maybe with the exception of the compiler we should have everything needed to compile by doing a few simple operations.

    如果几年后我们必须更新客户端的系统,我们应该能够找回用于该版本的代码和所有环境参数。我们需要一种方法来验证此代码是否与客户端系统上的二进制文件匹配。获取代码应该尽可能简单,除了编译器之外,我们应该通过执行一些简单的操作来完成编译所需的一切。

  7. A programmer should be able to release an update for a client's system without depending on any other programmer no matter in what project (DLL) the patch is. He should be able to do it rapidly (less than 30 minutes). That make the concept of a single official release almost impossible.

    程序员应该能够在不依赖任何其他程序员的情况下发布客户端系统的更新,无论补丁是什么项目(DLL)。他应该能够快速完成(不到30分钟)。这使得单一官方发布的概念几乎不可能。

  8. Exchanging code between developer working on the same project should be easy and fast.

    在同一个项目上工作的开发人员之间交换代码应该简单快捷。

  9. Considering our huge code base we want to limit how much a developer has to recompile when he gets a patch (sharing the binaries is a must).

    考虑到我们庞大的代码库,我们希望限制开发人员在获得补丁时重新编译的程度(共享二进制文件是必须的)。

  10. A developer should be able to switch from one client's system release or branch to another easily (it's common to have to work on more than one release at the same time).

    开发人员应该能够轻松地从一个客户端的系统版本或分支切换到另一个客户端(通常需要同时处理多个版本)。

Edit: -We don't use makefile so far but that's something we are willing to consider. Everything is built using VS solutions.

编辑: - 到目前为止我们不使用makefile,但这是我们愿意考虑的事情。一切都是使用VS解决方案构建的。

1 个解决方案

#1


Git in itself is perfectly suited for having a multitude of branches of source code. However, the maintenance of those branches will always reside at the user and lies outside the scope of a given version control system.

Git本身非常适合拥有大量源代码分支。但是,这些分支的维护将始终驻留在用户处,并且位于给定版本控制系统的范围之外。

The only problem with Git is that it does not scale well for tracking compiled binary data over time. Binary data is mostly use-once and the diff/patch aspect which is important for source code is not important for compiled binary data. Instead, just create a .zip file for each source code version in Git containing a pre-compiled version of each DLL and put those .zip files on a network share.

Git唯一的问题是它随着时间的推移无法很好地跟踪编译的二进制数据。二进制数据主要是一次性使用,而对源代码很重要的diff / patch方面对于编译的二进制数据并不重要。相反,只需为Git中的每个源代码版本创建一个.zip文件,其中包含每个DLL的预编译版本,并将这些.zip文件放在网络共享上。

If you've done that, it sounds like you should invest time into your build system to be efficient. The version system can help here, but you're probably running into build problems anyways:

如果你已经这样做了,听起来你应该花时间在你的构建系统中以提高效率。版本系统可以在这里提供帮助,但您可能会遇到构建问题:

  • Your Build System should only compile DLLs when the source has changed or the DLLs on which it depends has its interface changed. How tricky this is depends on the language used: C# DLLs have quite a strict interface which make this quite easy, while C has not an interface to speak of (just add one #define to a source file, and everything might have to be compiled)
  • 您的构建系统应该只在源已更改或其所依赖的DLL更改其接口时编译DLL。这有多难取决于使用的语言:C#DLL具有相当严格的接口,这使得这很容易,而C没有可以说的接口(只需将一个#define添加到源文件,所有内容都可能必须编译)

  • Your Build System should reuse pre-compiled DLLs which should be stored somewhere. Preferably not in the same way as the source code since Git is not optimized for this.
  • 您的构建系统应该重用应该存储在某处的预编译DLL。优选地不以与源代码相同的方式,因为Git没有针对此进行优化。

  • Your Build System should cope branch changed OK. For example, Visual Studio leaves some files behind and does not always detect properly when a full rebuild has to be done.
  • 你的构建系统应该应对分支改变好了。例如,Visual Studio会留下一些文件,并且在完成必须完成重建时并不总能正确检测到。

  • Your Build System might have to use a compiler from a fixed location instead of the compiler-of-the-day installed on your developpers PC. You might want to put it under version control also, or at least make this dependency explicit.
  • 您的构建系统可能必须使用固定位置的编译器,而不是您在开发人员PC上安装的每日编译器。您可能还希望将其置于版本控制之下,或者至少使此依赖项显式化。

In the end we rolled our own build system which was limited in speed by the time to do a stat() of all the files involved when nothing was changed. However, this took some time to build. Things to consider when building a system your own:

最后,我们推出了我们自己的构建系统,该系统在没有任何更改时所做的所有文件的stat()时间速度有限。但是,这需要一些时间来构建。构建自己的系统时需要考虑的事项:

  • First construct a dependency graph: DLLs depends on its source files and other DLLs.
  • 首先构造一个依赖图:DLL依赖于它的源文件和其他DLL。

  • Use the modification times (mtime) of the files as a kind of 'version' of a file. Keep a cache of those mtimes, and consider a change in mtime a reason to update your cache.
  • 使用文件的修改时间(mtime)作为文件的“版本”。保留这些mtimes的缓存,并考虑更改mtime是更新缓存的原因。

  • When one mtime of a file has changed, you have to rebuild the DLL it belongs to. After a rebuld of the DLL, check whether the interface has changed. If the interface has changed, rebuild all the DLLs which depend on this one. This takes a graph traversal to only process DLLs once.
  • 当文件的一个mtime发生更改时,您必须重建它所属的DLL。在重新生成DLL之后,检查接口是否已更改。如果接口已更改,请重建所有依赖于此接口的DLL。这需要图遍历才能只处理一次DLL。

  • Bonus for making the compile run in parallel. Since you know your dependency graph, you also know which DLLs can be build in parallel.
  • 使编译并行运行的好处。由于您了解了依赖关系图,因此您也知道可以并行构建哪些DLL。

And the good thing is that this is all version control system independent, so it's not wasted time. It might even be that a simple approximation is enough to be able to do it <30 minutes. It depends.

好的是,这是所有版本控制系统独立的,所以不浪费时间。甚至可能是一个简单的近似就足以能够做到<30分钟。这取决于。

#1


Git in itself is perfectly suited for having a multitude of branches of source code. However, the maintenance of those branches will always reside at the user and lies outside the scope of a given version control system.

Git本身非常适合拥有大量源代码分支。但是,这些分支的维护将始终驻留在用户处,并且位于给定版本控制系统的范围之外。

The only problem with Git is that it does not scale well for tracking compiled binary data over time. Binary data is mostly use-once and the diff/patch aspect which is important for source code is not important for compiled binary data. Instead, just create a .zip file for each source code version in Git containing a pre-compiled version of each DLL and put those .zip files on a network share.

Git唯一的问题是它随着时间的推移无法很好地跟踪编译的二进制数据。二进制数据主要是一次性使用,而对源代码很重要的diff / patch方面对于编译的二进制数据并不重要。相反,只需为Git中的每个源代码版本创建一个.zip文件,其中包含每个DLL的预编译版本,并将这些.zip文件放在网络共享上。

If you've done that, it sounds like you should invest time into your build system to be efficient. The version system can help here, but you're probably running into build problems anyways:

如果你已经这样做了,听起来你应该花时间在你的构建系统中以提高效率。版本系统可以在这里提供帮助,但您可能会遇到构建问题:

  • Your Build System should only compile DLLs when the source has changed or the DLLs on which it depends has its interface changed. How tricky this is depends on the language used: C# DLLs have quite a strict interface which make this quite easy, while C has not an interface to speak of (just add one #define to a source file, and everything might have to be compiled)
  • 您的构建系统应该只在源已更改或其所依赖的DLL更改其接口时编译DLL。这有多难取决于使用的语言:C#DLL具有相当严格的接口,这使得这很容易,而C没有可以说的接口(只需将一个#define添加到源文件,所有内容都可能必须编译)

  • Your Build System should reuse pre-compiled DLLs which should be stored somewhere. Preferably not in the same way as the source code since Git is not optimized for this.
  • 您的构建系统应该重用应该存储在某处的预编译DLL。优选地不以与源代码相同的方式,因为Git没有针对此进行优化。

  • Your Build System should cope branch changed OK. For example, Visual Studio leaves some files behind and does not always detect properly when a full rebuild has to be done.
  • 你的构建系统应该应对分支改变好了。例如,Visual Studio会留下一些文件,并且在完成必须完成重建时并不总能正确检测到。

  • Your Build System might have to use a compiler from a fixed location instead of the compiler-of-the-day installed on your developpers PC. You might want to put it under version control also, or at least make this dependency explicit.
  • 您的构建系统可能必须使用固定位置的编译器,而不是您在开发人员PC上安装的每日编译器。您可能还希望将其置于版本控制之下,或者至少使此依赖项显式化。

In the end we rolled our own build system which was limited in speed by the time to do a stat() of all the files involved when nothing was changed. However, this took some time to build. Things to consider when building a system your own:

最后,我们推出了我们自己的构建系统,该系统在没有任何更改时所做的所有文件的stat()时间速度有限。但是,这需要一些时间来构建。构建自己的系统时需要考虑的事项:

  • First construct a dependency graph: DLLs depends on its source files and other DLLs.
  • 首先构造一个依赖图:DLL依赖于它的源文件和其他DLL。

  • Use the modification times (mtime) of the files as a kind of 'version' of a file. Keep a cache of those mtimes, and consider a change in mtime a reason to update your cache.
  • 使用文件的修改时间(mtime)作为文件的“版本”。保留这些mtimes的缓存,并考虑更改mtime是更新缓存的原因。

  • When one mtime of a file has changed, you have to rebuild the DLL it belongs to. After a rebuld of the DLL, check whether the interface has changed. If the interface has changed, rebuild all the DLLs which depend on this one. This takes a graph traversal to only process DLLs once.
  • 当文件的一个mtime发生更改时,您必须重建它所属的DLL。在重新生成DLL之后,检查接口是否已更改。如果接口已更改,请重建所有依赖于此接口的DLL。这需要图遍历才能只处理一次DLL。

  • Bonus for making the compile run in parallel. Since you know your dependency graph, you also know which DLLs can be build in parallel.
  • 使编译并行运行的好处。由于您了解了依赖关系图,因此您也知道可以并行构建哪些DLL。

And the good thing is that this is all version control system independent, so it's not wasted time. It might even be that a simple approximation is enough to be able to do it <30 minutes. It depends.

好的是,这是所有版本控制系统独立的,所以不浪费时间。甚至可能是一个简单的近似就足以能够做到<30分钟。这取决于。