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.cppPerformMovesType1.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:
- Input these entries in this config file
(gives config file name, options to put for each config file entry)… - 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.
I can think of a couple of similar build systems:
libgcc.a). It wants to ensure that only the necessary functions link into your program. Since the unit of linker granularity is a single.oit builds one.cfile dozens of times with different-D_enable_xxxoptions to turn on each function individually. Then it usesarto build the resulting.ointo a.awhich you can link against to get only what you need.xororandororbits 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_xoroptions to produce dozens of.oeach 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.atechnique is not important.It sounds like you could use a mix of those to produce a library of
.owhere each one is pre-compiled with your specific options and then rebuild justmain.cover and over calling different functions and linking against your libaray.Based on your comments below, here are a few other ideas:
mkdir obj-mytarget; cd obj-mytarget; ../path/to/gcc/configure --options...; makeTheconfigurescript createsconfig.hand aMakefilespecific to the options (and, of course, the system capabilities). One big advantage of this setup is that all of the build products (from.oto executables) for that set of options are self-contained and do not interfere with builds using other options.GENERICwhich produces the default kernel orLINTwhich turns on everything for static analysis purposes) and then invokingconfig CONFNAME.configparses the simple config file and creates a directory tree named after the file. The directory tree contains aMakefileand various.hfiles to control the build. Same basic advantages as the method above.