Test programs with fpm that require an input file

I am trying to set up a small project with a small number of modules (one implements a simple progress bar - a weekend fun project) that can be built with fpm, but I have run into a slight problem: several of my test programs require an input file. These files are part of the “test” directory, but of course they are not copied to the location of the test executables. Is there a way to instruct fpm to copy these files into the proper location or is there another way to achieve this?

2 Likes

This is not a direct answer to your question.

In neural-fortran I do this from the test program rather than at the fpm level. For example, see test_cnn_from_keras. In a nutshell:

  • The library provides string constants with URLs to the test files
  • The test calls a subroutine that downloads the file from the URL if not present in the current directory (in my case using curl but it could be anything you want)

Thanks to @rouson for the suggestion to take this approach.

I’m curious to learn if there’s a way to do this with fpm.

1 Like

There was a discussion about this previously:

The advice from @everythingfunctional was:

I would suggest that hard-coding filenames and paths is generally bad practice in almost any scenario. The most common solution (and IMHO preferable) is to pass filenames/paths as command line arguments.

The opinion of @certik and @urbanjost was that fpm run should assume you are running from the root directory (and you could thereby use relative paths). However @awvwgk remarked this type of behavior is not compatible with expectations from other build systems including CMake and Meson.

Hence, providing the input files to the program is left as an exercise to the user.

1 Like

One possible simple (relatively) change to the --directory or -C option would be to actually run from the specified directory and to execute the program using a full pathname or setting the PATH variable to include the root directory appended with the build directory and then executing the command. The -C option is not explained in the built-in help but is equivalent to (cd $DIRECTORY;fpm $OPTIONS) when you enter “fpm -C $DIRECTORY $OPTIONS”.

What I find easiest, however, is to create a directory like $HOME/tryout and put it at the beginning of my $PATH when developing a program; and then doing a fpm(1) install into that directory and then running the program(s) like any command in my path from any directory.

Someone started putting messages on stdout instead of stderr, so now command options like --runner are partially broken, but until recently you could do things in a bash shell like

    $(fpm run --runner realpath)  

which would execute the program by its full pathname so you could run it from anywhere but now you have to grep out the messages and stuff to get the intended output.
If the “Entering DIRNAME” messages were writing to stderr (and probably not even being written unless verbose mode were selected) that could be done cleanly again.

1 Like

Thanks for your answers - not sure how to proceed yet, but in the worst case, I can simply print a note to point out how to use the test programs :slight_smile:

After some meditation I found a very simple solution to the problem. Because the test input files are very small (10 lines or less), it was easy enough to have the test programs write out the contents, if there is no file by that name, before proceeding. This may not be the solution in all cases, but it is for me :slight_smile: Now I need to create a repository and check the documentation.

As a user, similarly to @Arjen, when I do fpm run --example some_ex -C ./data I would expect fpm to remain in that directory. I think I don’t get the point of the -C option. When/why would it be useful?. The help docs (now v0.10.0) state the following which is not very helpful IMO.

 -C, --directory PATH
             Change working directory to PATH before running any command

In my case I am not allowed to modify the example sources, and hence paths to files, since the fpm repo is a metapackage and all the sources are external, so I had to write an ugly Shell script.