如何使我的高度模块化项目易于最终用户编译?

发布于 2024-10-20 06:33:09 字数 1486 浏览 5 评论 0原文

我正在开发一组相对较大的串行代码 C 代码库,然后我的合作者将在 CUDA 中对其进行并行化。

对于这个项目,我的代码基本上可以归结为

#include "Initialize.cpp"
#include "PerformMoves.cpp"
#include "CollectResults.cpp"

main() 
{
   //DECLARE General Vars

   Initialize();

   for (unsigned int step=0; step < maxStep; step++)
   {
      PerformMoves();
   }

   CollectResults();
}

现在,我在 Initialize 和 PerformMoves 中执行的步骤将非常不同,具体取决于我正在构建的模拟类型。速度是最高的性能,因为我的代码是蒙特卡罗模拟,将执行数百万次移动,每个移动可能涉及数千次计算。因此我想避免任何不必要的条件。

因此我本质上想要不同的“即插即用”C 模块,例如

InitializeSimType1.cpp 初始化SimType2.cpp 初始化SimType3.cpp

PerformMovesType1.cpp PerformMovesType2.cpp PerformMovesType3.cpp

...

每个都针对某种类型的模拟程序进行了优化,没有大条件的“绒毛”来处理各种情况。

目前我有两种不同类型的模拟,只需将它们放在两个不同的文件夹中并按如下方式编译:

g++ Main.cc 初始化.cpp PerformMoves.cpp CollectResults.cpp -o MC_Prog

我想转向某种条件编译方案,其中我有某种配置文件,我在其中指定选项,它会获取正确的 cpp 文件并编译它们。

我认为 makefile+config 文件是我最好的选择,但除了基本目标和非常线性的编译之外,我对复杂 makefile 的世界还很陌生。

有哪些好的方法可以创建列表驱动的编译系统,使具有非常基本的 C 知识的用户能够轻松地使用他们想要的模块构建目标。我的最终用户不会有大量的 makefile 知识(或一般的编程知识),因此他们端的复杂系统是不可能的。我希望他们基本上拥有一个透明的配置文件驱动系统,允许他们选择一个 Initialize 模块、一个 PerformMoves 模块和一个 CollectResults 模块。一旦他们用自己的选择修改了这个配置文件,我希望他们能够进行单命令编译。

换句话说,我希望能够创建一个指导用户的自述文件:

  1. 在此配置文件中输入这些条目 (给出配置文件名,为每个配置文件条目放置的选项)...
  2. 使用此命令进行编译(给出单个命令)

我知道这是一个相当抽象和复杂的问题,但我知道那里有一些 Makefile/c 专家谁可以给我一些好的指导。

I am working on a relatively large set of serial code C-code libraries, which will then be parallelized in CUDA by my collaborators.

For this project my code essentially boils down to

#include "Initialize.cpp"
#include "PerformMoves.cpp"
#include "CollectResults.cpp"

main() 
{
   //DECLARE General Vars

   Initialize();

   for (unsigned int step=0; step < maxStep; step++)
   {
      PerformMoves();
   }

   CollectResults();
}

Now the steps I perform inside Initialize and PerformMoves will be very different depending on what kind of simulation I'm building. Speed is of the utmost performance as my code is a Monte Carlo simulation that will be performing millions of moves, each of which involves potentially thousands of calculations. Thus I want to avoid any unnecessary conditionals.

Thus I essentially want different "plug and play" C modules, e.g.

InitializeSimType1.cpp
InitializeSimType2.cpp
InitializeSimType3.cpp

PerformMovesType1.cpp
PerformMovesType2.cpp
PerformMovesType3.cpp

....

Each optimized for a certain type of simulation procedure, without the "fluff" of large conditionals to handle a variety of cases.

Currently I have two different types of simulations, and just have these in two different folders and compile as follows:

g++ Main.cc Initialize.cpp
PerformMoves.cpp CollectResults.cpp -o
MC_Prog

I would like to move to some sort of conditional compilation scheme, where I have some sort config file where I specify options and it grabs the correct cpp files and compiles them.

I would assume that a makefile+config files is my best bet, but beyond basic targets and very linear compilation I'm pretty novice to the world of complex makefiles.

What are some good ways that I could create a list-driven compilation system, that would allow users with very basic C knowledge to easily build a target with the modules they want. My end users won't have a great deal of makefile knowledge (or programming knowledge in general), so a complex system on their end is out of the question. I want them basically to have a transparent configuration-file driven system that will allow them to pick one Initialize module, one PerformMoves module, and one CollectResults module. Once they've modified this configuration file with their picks, I want them to be able to do a single-command compilation.

In other words I want to be able to create a README that directs users:

  1. Input these entries in this config file
    (gives config file name, options to put for each config file entry)...
  2. Compile using this command (gives single command)

I know this is a rather abstract and complex question, but I know there are some Makefile/c experts out there who could offer me some good guidance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒绊 2024-10-27 06:33:09

我可以想到几个类似的构建系统:

  1. 当您构建 GCC 时,它会使用辅助例程构建库(例如 libgcc.a)。它希望确保只有必要的功能链接到您的程序中。由于链接器粒度的单位是单个 .o,因此它会使用不同的 -D_enable_xxx 选项多次构建一个 .c 文件,以打开每个文件单独发挥作用。然后,它使用 ar 将生成的 .o 构建为 .a,您可以链接该文件以仅获取您需要的内容。
  2. X 窗口服务器有几个函数执行基本相同的操作,只是最内层循环中的数学不同。例如,它可能会xorandor位在一起。它也不希望在其内部循环中使用条件,因此它使用不同的 -D_math_xor 选项一遍又一遍地构建相同的文件,以生成数十个 .o,每个文件都有一个函数执行循环函数中包含的特定数学运算。它使用了所有的.o(因为该操作实际上是由X客户端选择的,而不是在编译时),因此.a技术并不重要。

听起来您可以混合使用这些内容来生成 .o 库,其中每个库都使用您的特定选项进行预编译,然后仅重建 main.c 。以及调用不同的函数并链接到您的 libaray。

根据您下面的评论,这里有一些其他想法:

  1. 当您构建 binutils、GCC、glibc 等时,您将解压缩源代码分发版,但您不在源代码树内构建。相反,你 mkdir obj-mytarget; cd obj-mytarget; ../path/to/gcc/configure --选项...; make configure 脚本创建 config.h 和一个特定于选项(当然还有系统功能)的 Makefile 。此设置的一大优点是该组选项的所有构建产品(从 .o 到可执行文件)都是独立的,不会干扰使用其他选项的构建。
  2. 经典的 BSD 内核配置是通过编辑文件来完成的(通常给出全大写名称,如 GENERIC,它生成默认内核或 LINT,它打开所有内容以进行静态分析)然后调用config CONFNAMEconfig 解析简单的配置文件并创建一个以该文件命名的目录树。目录树包含一个 Makefile 和各种 .h 文件来控制构建。基本优点与上述方法相同。
  3. avr-libc(Atmel AVR 微控制器的 libc)通过自动为数十个微控制器(内存大小、外设可用性等存在差异)创建目标目录并构建所有的变体,自动执行上述方法单次通过。结果是产生了许多库,提供了能够针对任何 AVR 的交叉构建环境。您可以使用类似的想法来自动构建程序的每个排列。

I can think of a couple of similar build systems:

  1. When you build GCC it builds libraries with helper routines (eg libgcc.a). It wants to ensure that only the necessary functions link into your program. Since the unit of linker granularity is a single .o it builds one .c file dozens of times with different -D_enable_xxx options to turn on each function individually. Then it uses ar to build the resulting .o into a .a which you can link against to get only what you need.
  2. The X window server has several functions which perform largely identical operations except that the math in the very innermost loop is different. For example, it might xor or and or or bits together. It doesn't want a conditional in its inner loop either so it builds the same file over and over with different -D_math_xor options to produce dozens of .o each with one function that performs the specific math operation wrapped in the looping function. It uses all of the .o (because the operation is actually selected by the X client, not at compile time) so the .a technique is not important.

It sounds like you could use a mix of those to produce a library of .o where each one is pre-compiled with your specific options and then rebuild just main.c over and over calling different functions and linking against your libaray.

Based on your comments below, here are a few other ideas:

  1. When you build binutils, GCC, glibc, etc you unpack the source distribution but you don't build inside the source tree. Instead you mkdir obj-mytarget; cd obj-mytarget; ../path/to/gcc/configure --options...; make The configure script creates config.h and a Makefile specific to the options (and, of course, the system capabilities). One big advantage of this setup is that all of the build products (from .o to executables) for that set of options are self-contained and do not interfere with builds using other options.
  2. The classic BSD kernel configuration is done by editing a file (idiomatically given an all caps name like GENERIC which produces the default kernel or LINT which turns on everything for static analysis purposes) and then invoking config CONFNAME. config parses the simple config file and creates a directory tree named after the file. The directory tree contains a Makefile and various .h files to control the build. Same basic advantages as the method above.
  3. avr-libc (a libc for Atmel AVR microcontrollers) automates the above approaches by automatically creating target directories for dozens of microcontrollers (with variations in memory size, peripheral availability, etc) and building all of the variations in a single pass. The result is many libraries, providing a cross build environment capable of targeting any AVR. You could use a similar idea to automatically build every permutation of your program.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文