New project: Should I use fpm? Meson? stdlib? etc

Scientists like myself are famously bad at software engineering. I have a code I need to use with a horrible custom build system written in Perl. :grimacing:

I want to start a new project. I come here seeking advice on some of the initial decisions to try to start the project on the right foot. Iā€™m going to write an OpenACC + MPI code that compiles to CPU or GPU, and I want to make it easy to build / use / maintain.

(1) As a build system, should I use fpm (ā€œFortran Package Managerā€) or Meson? Or something else? I have experience with neither. Whatā€™s easy?

(2) There will be optional modules. Whatā€™s a good way to turn modules on or off? My baseline plan is to recompile the code and use the cpp preprocessor that most compilers have to decide which modules get included. Does that sound like a good option?

(3) Iā€™m going to need FFT, Linear Algebra, random numbers, etc. I could use CUDA libs when I compile to GPU and stdlib when I compile to CPU.

  • Does that sound like a good idea?
  • How mature is stdlib? Should I use it?
  • What is the best way to switch between CUDA and stdlib? Should I use preprocessor macros and conditional compilation?

Iā€™m also thinking about how these choices intersect. For example, stdlib doesnā€™t work with nvfortran. Ok. No problem; nvfortran can be just for GPU when I use CUDA. Butā€¦ one of the features of fpm is that you can mark dependencies. If I say that stdlib is a dependency, will that prevent me from compiling with nvfortran CUDA?

Oh, and would fpm limit my ability to change the compilation options? Like with the optional modules I mentioned in (2)?

(4) Iā€™m going to need config files. Iā€™m thinking of using TOML (Tomā€™s Obvious Minimal Language). There is a Fortran library for TOML. I see options to ā€œbuild with fpmā€ or ā€œintegrate TOML Fortran in your meson projectā€. Let me know if you have any thoughts about that.

Thanks for the help. Feel free to give any advice that you have in mind, or rant about the horrible code youā€™re forced to maintain so I can avoid making the same mistakes.

Thanks!

5 Likes

For what purposes do you intend to use stdlib. While I am neither an expert in stdlib (a collection of of modules complementing the Fortran standard) nor CUDA (a way to offload computations to the GPU) I see rather little overlap.

For things like linear algebra and FFT several libraries sre available.
The most used package for Linear Albebra is LAPACK for which there exists a reference inplementation from netlib.org, but also more optimized implementations like OpenBLAS or Intel MKL that take the CPU architecture you are using into account.

Note that CUDA is only suported by Nvidia cards (Although I think there is some semi-automatic program that converts CUDA code into code that utilizes AMD cards, but I have no idea how well this works).

1 Like

Itā€™s a matter of personal taste, I guess. In my opinion, GNU Makefiles is a must, because they work everywhere with minimal or no changes at all, even on Haiku OS (or even onā€¦ that other popular ā€œoperating systemā€, so to speak.)
Anything else is optional. As a packager for two GNU/Linux distributions I learned one thing, there is no perfect building system, and every time I see an application/library using a weird new one Iā€™m thinking ā€œoh no, not againā€. Given the language, fpm is an obvious choice, but other than that, I wouldnā€™t consider anything else but Makefiles. I had to deal with other build systems, including of course the much used CMakeā€¦ Iā€™m sorry, but I was not impressed by any of them.

ā€¦ but again, itā€™s a matter of personal taste. The best build system is the one you know the most. Even the Perl-based you mentioned could be the way to go. It sounds scary to me. and I would replace it with something -anything- else, without a second thought. But if you know it well, by all means use it. Donā€™t overthink the build system, as long it doesnā€™t stand on your way. The KISS principle exists for a reason. I canā€™t stress this fact enough.

It does, at least to me. Thatā€™s what I do. Never felt I needed something more fancy. Again, the KISS principleā€¦

stdlib is a quick way to get functionality you would have to implement yourself otherwise. Thatā€™s its purpose. Still - and again, thatā€™s just my opinion - the less dependencies, the better, and you seem to already have some you wonā€™t avoid easily, such as FFT. I would think twice adding another one. How much of stdlib will you need? If the answer is ā€œa lotā€, and you are not interested to do it yourself insteadā€¦ the answer is obvious.

Whatever libraries you end up using, make sure you know not only what they are doing but also how they do it. Of course, that doesnā€™t mean you need to know what every single line of their code does. But you need to have a good knowledge of the methods used. Do not use black boxes, even if they are the state-of-the-art.

Iā€™m not the right person to answer about switching between CUDA and stdlib. I would also argue hereā€¦ are you sure CUDA will accelerate execution? Because there are bottlenecks that may very well do the opposite. I would, at the very least, try with more conventional parallelization methods first. Unless of course, we are talking about a well-established GPU-based software - in that case just ignore the last part.

Call me old fashioned if you so wish, but what I do about that is to write a config file which is then processed by my first generic Makefile. I even use this to set flags I could very well just add in the make command. I donā€™t even use GNU Autoconf (I could, but itā€™s not very portable.) Why Iā€™m just using a config file I write myself? Because it is simple, and it works. Yes, it might sound crude, but it works. Every time. Oh, and in every platform, no questions asked. KISS principle again.

2 Likes

My experience parallels @Pap. I still prefer Makefiles over every other system Iā€™ve tried. For me it Just Works and does on every system I run on. I never have to worry about having the ā€œcorrectā€ (as defined by the developers) version of CMake installed on my system just to build a library that I might only use one function/subroutine from. I have a set of procedures built around Makefiles that Iā€™ve used for over 20 years and have applied to projects that are comprised of tens of thousands of lines of code spread out over dozens of subdirectories. I write my own Bash configure scripts that define what compiler I want to use along with other build options. Itā€™s really not that hard once you learn how to do it and again for me they Just Work. For me the biggest problem with Makefiles are the silly tab indentation rules which I guess is one of the main reasons people moved away from them.

I believe the driving force behind the various alternative build systems was the need to support Windows. Since most of the code Iā€™ve written over the last 30 years or so was targeted at large scale HPC systems which were Unix/Linux based I never felt the need for something like CMake for my own projects. Therefore, the decision as to what build system you use is as stated by others is really just a matter of personal preference and what the primary OS you are targeting is.

3 Likes

Can you elaborate what you mean by optional modules? Does this boil down to different mathematical models (say with additional terms), different choices of boundary conditions, different solvers (say conjugate gradients, GMRES, direct solvers), or different libraries (use FFTPACK or FFTW)? Or do you mean something else?

As @Jweber has already mentioned, stdlib doesnā€™t offer either FFT or Linear Algebra (BLAS, LAPACK), so I think there is no overlap there. Since youā€™ll be using OpenACC, the NVIDIA HPC SDK already includes OpenBLAS (which is a slight misnomer, because it provides both BLAS and LAPACK routines) for CPU, and cuBLAS and cuSOLVER for GPU.

For FFT you could use FFTW or FFTPACK on CPU. In case the FFT is supposed to be across multiple MPI ranks, a few specialized libraries exist such as 2DECOMP&FFT.

2 Likes

Probably yes, but the fact is Makefiles just work there, so there is no real need to look for something else.
I only use that ā€œoperating systemā€ to check if my libraries work there. And they do, with plain Makefiles. At least they do work with MinGW-w64, which is what I usually use. They also work with the older MinGW, or TDM-GCC. And of course they work with MSYS2 - but I never felt I needed to go that far.
A simple batch file sets up paths, opens Emacs, and Iā€™m ready to build (or do actual programming, if I wanted to.) Everything just works. Like @rwmsu said, you set it once, it works forever. Makefiles were never a problem. And even automatic module dependency resolution can be done in a very nice way, using plain Makefiles. I honestly fail to see why another build system is needed.

Sometime ago, I tried to move everything to Haiku OS, just out of curiosity. Itā€™s a very ā€œnicheā€ platform for ā€œnerdsā€. And guess what, Makefiles worked there as well. The only change I had to do is to add two lines in the generic first Makefile. Good luck finding another build system that will offer such portability with minimal, if any, changes.

When it comes to CMake at least, I believe the driving force was incompatibilities between different versions of Make:

Doing the same thing in GNU Make or using the POSIX Make subset can often be quite different. That said, Paul Smith (the GNU Make maintainer) says: ā€œDonā€™t hassle with writing portable ā€˜makefilesā€™, use a portable ā€˜makeā€™ instead.ā€

Anyways, the complexity of maintaining makefiles and scripts, along with the inherent complexity and workarounds needed to use a dozen of compilers on different hardware, is what led to autoconf, even before CMake.

But I agree with both of you to ā€œkeep things simpleā€ and try not to overthink it. If youā€™ve reached a point where you spend more time tinkering with the build system, than the application code, then you know youā€™ve got a problem.

4 Likes

Correct, but I have yet to find a platform not supporting GNU Make or at least POSIX nowadays. Itā€™s trivial even in that popular ā€œoperating systemā€, thanks to projects like MinGW (which is active for decades now). You can actually do the same even inā€¦ DOS / FreeDOS.
Of course, things were different back in the 80s - early 90s, but back then CMake or any of those ā€œmodernā€ build systems didnā€™t exist either.

Starting a new project - and a Fortran one, it would be a no-brainer for me to start simple and use fpm: works great on all platforms, covers as-is 90% of your external package needs (stdlib, fftpack, toml-f, mpi, cpp preprocessor).

As your project grows in complexity, you may down the road (wild guess - in 1, 2, 3 years?) stumble upon missing features, in which case you can decide whether you want to contribute to the project (maybe youā€™re going to be an fpm pro then), or switch to more broad-range build systems.

In other words, if it was me, I would not overthink any potential future development but would start with what gets me the most bang for the buck today.

3 Likes

Totally agree with @FedericoPerini, currently my main build tool is CMake, but learned to like a lot fpm. These build systems are not mutually exclusive, so you could start with fpm and if needed, add CMake or meson later on, once your project matures. You should in principle no need to touch your source code for that, add the files required for that specific build tool at the root of the project.

You can actually find several of the new Fortran projects having CMakeLists.txt files and fpm.toml files such that the user can pick his best choice.

3 Likes

Hard disagree with the advice to write gnu makefiles! Nobody should be doing that anymore, certainly not for Modern Fortran. (my opinion!! donā€™t come after me gnu folks!) FPM should be your first stop. If/when you hit the limits of what FPM can provide, please submit an issue since itā€™s a relatively new tool. Since almost no configuration is required itā€™s easy to get started and isnā€™t that much time lost if you end up deciding you need something more complicated (CMake, meson, or whatever).

14 Likes

There are many people who will totally disagree with that statement, myself included. Iā€™m very much a ā€œGNU folkā€, and all I have to say is juust because GNU Make is old it doesnā€™t mean it is obsolete. If it ainā€™t broken, donā€™t fix it. And GNU Make is not broken.
But donā€™t worry, I wonā€™t come after you, I even liked your comment. Like I said, the best build system is the one you are most familiar with.
By the way, whatā€™s your address and your number? Iā€™ll go dig up my war axe and my glock, then pay you a visit. :rofl:

P.S. Jokes aside, death threats ave very much a thing on the Internet, for stupid reasons like ā€œI disagree with this program you use, mine is betterā€. Itā€™s even worse between gamers, as far I can tell. People are just insaneā€¦

2 Likes

When people stop requiring a particular version of CMake, meson etc. to build their codes Iā€™ll consider using something other than Makefiles. I have better things to do than build CMake from scratch because the version of Linux I run doesnā€™t have a prebuilt deb package for the required version of CMake. I tried fpm but it did not correctly resolve module dependencies in my codes where I have the source spread out over about 25 subdirectories. Maybe the most recent versions will but Iā€™m not inclined to waste time trying to get something new and shiny to work when I already have something that has worked for about 20 years and will still work 20 years in the future.

1 Like

From a userā€™s perspective that might be true, but when deploying cross-platform software (multiple OS and architecture combinations) it can happen more often than you think. Packaging for Pythonā€™s pip C/C++ and Fortran codebases without the use of CMake and Meson is truly a nightmare.

In terms of the learning curve for users unfamiliar with all build systems, I think that fpm is quite easier to learn/use that GNU Makefiles, CMake, Menson, etc., so I would give that a shot first.

That being said, I whole hardheadedly agree with the sentiment of

1 Like

I think it is quite reasonable for actively developed build tools to be versioned and continuously deprecating features/adding new ones. That is also the case with GNU Makefiles, they add new features and break backwards compatibility all the time, see Changelog v4.4

As long as your solution works for you, then that is all that matters.

For the fpm case you mentioned above I am a bit curious if you could share some additional information to understand the problem (either here on a different thread or on GitHub). Moving from one build tool to another is no easy task but ideally we would want fpm to make this transition as easy as possible.

2 Likes

The goal is to write a program that can compile to CPU or GPU. Stdlib is for the CPU option. I need random numbers, linear algebra, FFT, etc. All things that are listed as goals for stdlib. CUDA is not only a way to offload to the GPU. It also comes with a math library with random numbers, linear algebra, FFT, etc.

After looking at stdlib more closely, it looks like they donā€™t support any of the things that I listed. Evidently that list I read was more like a set of goals than a set of actual features. So I guess the new plan is to use one of the other Fortran libraries, like the ones you listed.

Yeah. Not ideal.

Is the code public? Can you submit a bug report to FPM for this? Automatically resolving the module dependencies is one of the main features. Iā€™ve never seen it fail, but it looks like you have some kind of edge case that breaks it?

Iā€™m definitely targeting large scale HPC systems. The code will only ever run on some flavor of Linux (perhaps Unix). Anyway, thank you for your perspective. That was interesting.

Sure. The purpose of the code is to run hydrodynamic simulations gas in a protoplanetary disk. Modules include things like magnetic fields, sources of ionization, solid grains, etc. One person might want to run MHD simulations, while another may want to study purely hydrodynamic instabilities. So there would be a ā€œmagneticā€ module that you can turn on or off.

Yes to different boundary conditions. Very likely yes to different libraries.

Yeah. My mistake. I was going by the list on the GitHub page, but it looks like that is more like a list of goals.

Thanks! That sounds like a good strategy.

Oh! I didnā€™t know about 2DECOMP&FFT. Thanks for the link. I just realized I donā€™t know whether the code Iā€™m trying to replace does FFT across MPI ranks. I think it should. Otherwise the result would be wrong. Iā€™m going to go figure that out.

Thanks for the help!

Thanks!

Another vote for fpm. Thatā€™s very helpful. Btw, yeah, I noticed a couple of projects that had more than one option, including toml-f. I had never seen that before.

Somebody give me the ability to add 100 likes. I promise I will only use it in that very post only. :slight_smile:
In my main computer I am running a stable distribution, because I donā€™t want surprises every morning (I do use rolling distros as well, but I want something rock-solid stable as my ā€œdaily driverā€.) In such a stable distribution, there are strict rules none can ignore, especially distro packagers like me. The relevant rule here is: Nothing changes until the next version, unless it is a security update (with stuff like FireFox or samba being the usual suspects.) No other exceptions whatsoever.

Now, next stable version of the distribution may be next year or worse (and it will be in the beta stage and RC versions for some time.) Until then, it is mathematically sure a new ā€œshinyā€ version of CMake will show up (or whatever else, Iā€™m just using CMake as an example here.) Oh, and it may break compatibility with the previous version as well, because everybody knows new is better by definition. And itā€™s not new enough if it doesnā€™t break things with the previous version, right?
But even if the new version of the build system doesnā€™t break things, someone (letā€™s call him Eucild) will think ā€œah, a new version of CMake, letā€™s use it in my library just because, and while I am on it, letā€™s make the new version of CMake a requirement, so that my new version will look freshā€. This is packagerā€™s hell. I know it first hand because I am packaging stuff in a rolling distro as well.

And it is userā€™s hell as well. Letā€™s say I am just a user, and I need the new version of Eucildā€™s library, because he added something that will make my life easier. His new library is perfectly compatible with my some-months-old distro, except he opted to use the new shiny CMake as a requirement to build the library (trust me, this is not the exception, itā€™s what it usually happens.) So I canā€™t use his library right away because ofā€¦ the goddamn build system Eucild changed. As a user, Iā€™ll have to either rebuild Euclidā€™s library using another build system (thatā€™s easier told than done,) or build the new CMake myself, and place it in my own personal repository to use it instead of the distroā€™s one. All that just toā€¦ compile Euclidā€™s library. And then someone else will make the new version of Euclidā€™s library a dependency to his own stuff. Then Iā€™ll have to cope with that as well. My answer to all that is simple: No, thank you.

Even that is not objectively true. I am not going to deny GNU tools are a bit cryptic, so to speak. But I also found CMake to be unnecessarily complicated. Even simple things I could easily do with Makefiles, it took me hours or worse to figure out how to do the same in CMake - and even then it wasnā€™t as good as I wanted it to be. Essentially, I had to learn a new scripting language - and not a particularly well thought, I might add. All that created a big fat ā€œwhy am I even doing thisā€ in my head. Iā€™m pretty sure someone familiar with CMake would think the same while trying to learn GNU Make.

Now fpm is another story. It is a Fortran project and it deserves all my respects. After all, we need a package manager - not because it is desperately needed, but because every language has its own ā€œpipā€ nowadays. At some point Iā€™ll have to learn how to use it, even though, honetly, I donā€™t really need it.

1 Like