0

I have a project with the following structure

Top Level Project Dir
        ->Other Source Code Folders
        ->Experiment Binaries
                  ->Experiment 1
                          -srcs.cpp
                          -main.cpp
                          -Makefile
                  ->Experiment 2
                          -srcs.cpp
                          -main.cpp
                          -Makefile

This project is made up of multiple experiments which compile into their own binaries. These experiment are built of of sources from the Top level directory as well as a few specific sources located in the experiments folder. The experiment name is unique and maps to the folders name. Currently In order to make a specific experiment binary I cd into the expeirment directory and run "Make". This structure I am using is becoming unmanageable as I make more and more experiment as all the Makefiles are basically the same and if i end up changing some dependencies in shared common code then i need update all the Makefiles. I want to unify the makefiles into a single one located at the ExperimentBinaries folder level. running "Make" would make all the Experiments placing the objects in the respective folder. and running "Make Experiment1" would make that specific experiment. I am not sure how to get a Makefile to ourput multiple binaries in this fashion.

lufthansa747
  • 1,923
  • 3
  • 26
  • 39
  • 2
    I'm not sure if you intend these directory names literally but note it's virtually impossible to use pathnames containing whitespace in makefiles. – MadScientist Jan 30 '20 at 16:31

2 Answers2

1

You could keep your Experiments Makefiles and create one at the root Experiment Binaries wich would call every sub Makefiles using the C flag.

make -C Experiment1
make -C Experiment2

This would run the make command with a given path.

Or if you want to get rid of your sub Makefiles, you can create one at the root with multiple rules. Each rules will compile every files in a given experiment folder (you could use wildcard) and then create all the binaries.

Lucas Gras
  • 961
  • 1
  • 7
  • 22
0

As a practical matter: - This is a lot easier to do if subdir names can be assumed to NOT contain a space. - The key to a robust solution is to use a file for wildcard targets, not directory.

# Get list of identically structured subdirectories
SUBDIRS:=$(ls)

# Directories have timestamps that subvert the behavior of make.
# So define a new "PHONY" name using a -make suffix.
MAKE_TARGETS=$(addsuffix -make,$(SUBDIRS))

# Top level default target.
all: $(MAKE_TARGETS)

# Each subdirectory target, assume an output "foo/a.out" for timestamp.
$(MAKE_TARGETS):  %-make:   %/a.out;
.PHONY: $(MAKE_TARGETS)

# Your actual rules, could also use wildcards.
$(addsuffix /a.out,$(SUBDIRS)): %/a.out
    #rule for building a.out from cpp files in $* subdirectory

# Other target suffixes can also be defined, like a "clean" target.
CLEAN_TARGETS=$(addsuffix -clean,$(SUBDIRS))
clean: $(CLEAN_TARGETS);
$(CLEAN_TARGETS): %-clean
    rm -rf $*/a.out $*/*.o       # customize, as needed
.PHONY: $(CLEAN_TARGETS)

help:
    echo "The following subdirectories build experiments: $(SUBDIR)"
    echo ""
    echo "The default target invokes corresponding make targets in each dir"
    echo "   'make'           #will build the targets in each subdir"
    echo "Or for a given folder, use the -make suffix for each folder. For example:"
    echo "   'make foo-make'  #will build the target for the 'foo' subdirectory"
    echo "Likewise: there is a clean target and clean suffix for each subdirectory"
    echo "   'make clean'     #for all subdirectories"
    echo "   'make foo-clean' #for just the 'foo' subdirectory"
geipel
  • 395
  • 1
  • 3
  • 9