Search code examples
adagprbuild

Is it possible to have a file wildcard in gprbuild project files?


I have a project in which I often create a lot of new main entrypoint *.adb files in a certain directory. Is there any way to set up my project using gprbuild such that adding a new main program does not require editing the .gpr project file?

Currently, I have this, and need to modify the list of mains each time I add a new one:

project Adabots is

   for Source_Dirs use ("src", "src/examples");
   
   for Main use ("build_wall.adb", "remove_wall.adb", "get_stone.adb", "staircase_down.adb", "josephine.adb", "dig_cavern.adb", "build_maze.adb", "elevator.adb", "lovelace.adb", "dig_hallway.adb", "spiral_staircase.adb", "walk_up_stairs.adb");

But what I would have wanted to do is just say that every .adb file inside src/examples should be treated as a main.

The full project is here, in case that helps.


Solution

  • GPRBuild project files have very limited procedural capabilities. You can create and append to strings, and create and append to lists, and that's about it.

    However, you can do what you want by supplying the file names as scenario variable:

       Main_Names := external_as_list ("executables", ",");
       for Main use Main_Names;
    

    By using external_as_list, you can supply the names of all executables on the command line, separated by commas:

    gprbuild adabots.gpr -Xexecutables=build_wall.adb,remove_wall.adb,get_stone.adb
    

    Now you can use shell globbing to supply all *.adb files in src/examples (uses basename to strip the src/examples/ path; then tr to concatenate the names with commas):

    gprbuild adabots.gpr -Xexecutables=$(echo src/examples/*.adb | xargs -n 1 basename | tr '\n' ,)
    

    This can go in a Makefile as follows:

    MAIN_SOURCES=$(shell echo src/*.adb | xargs -n 1 basename | tr '\n' ,)
    
    all:
        gprbuild -Xexecutables=$(MAIN_SOURCES)
    
    %: src/%.adb
        gprbuild -Xexecutables=$^
    

    Note also that replacing gprbuild with alr build in the above also works, if your project is using alire.

    For building individual main programs, you can do e.g. make foo to build src/foo.adb.