Niklas R
Niklas R

Reputation: 16860

How to get cpp files from different directories compiled into one folder?

I have a number of C++ files distributed in several folders.

a_library/
    file1.cpp
    file2.cpp
    category1/
        file3.cpp
        file4.cpp

They are guaruanteed to be uniquely named. I want to compile all those C++ files to seperate Object-files in the obj/ directory.

I have a list of all source-files with relative path, and their corresponding destination-names.

a_library/file1.cpp
a_library/file2.cpp
a_library/category1/file3.cpp
a_library/category1/file4.cpp

obj/file1.obj
obj/file2.obj
obj/file3.obj
obj/file4.obj

How can I make a rule that will convert a C++ file from the first list to a object-file from the second one?

These attempts do not work:

obj/%.obj: %:cpp
    # ...

%.obj: %.cpp
    # ...

.cpp.obj:
    # ...

I would like to not write rules like this:

obj/%.obj: a_library/%.cpp
    # ...

obj/%.obj: a_library/category1/%.cpp
    # ...

Upvotes: 6

Views: 3007

Answers (5)

Niklas R
Niklas R

Reputation: 16860

Not strictly related to this question as it doesn't have to do with Make, though I'd like to show how I compile my projects now, 3 years later. Craftr is a Python based meta build system that encourages indirect out-of-tree builds (eg. a build in the working tree). Building object files and cresting a static library is as easy as

# craftr_module(my_project)
from craftr import *
from craftr.ext.platform import cxx, ar
objects = cxx.compile(
  sources = path.platform('**/*.cpp'),
)
lib = ar.staticlib(
  output = 'myproj',
  inputs = [objects],
)

Running craftr -eb will result with the following structure of build products

Craftfile
file1.c
file2.c
category1/
  file3.c
  file4.c
build/
  my_project/
    obj/
      file1.o
      file2.o
      category1/
        file3.o
        file4.o
    libmyproj.a

Upvotes: 0

steffen
steffen

Reputation: 8958

The standard way is to have a Makefile in each folder and call recursively with include

This was my first two hits on 10^100:

http://owen.sj.ca.us/~rk/howto/slides/make/slides/makerecurs.html

http://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/Recursion.html

Upvotes: 0

fork0
fork0

Reputation: 3461

Try setting VPATH:

VPATH = a_library:a_library/category1
obj/%.o: %.cpp
    $(CXX) -c $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) -o $@ $<

And to add complete file list (I would recommend you explicitely list the files, do not use $(wildcard ...) function) and linking of the application:

files := main.cpp $(wildcard a_library/*.cpp) a_library/category1/file.cpp

obj/application: $(patsubst %.cpp,obj/%.o,$(notdir $(files)))
    $(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $+

The $(wildcard) has an annoying tendency to pick up anything in the directories, like one-off test files or temporaries (if they happen to have a fitting name: ~file.cpp).

Upvotes: 6

Viktor Latypov
Viktor Latypov

Reputation: 14467

One solution I can think of: just build them inplace with a simple rule and then make a "collection phase" moving the ".o" files to a single folder.

Make a "collect_objs" target which depends on your $(OBJS) and then your "main" target must depend on "collect_objs".

The traversal can be done using shell

dirs := $(shell find ./ -type d)
collect_objs: $(dirs)
      for d in $+; do \
          mv *.o YourDestDir/*.o
      done

Of course, this implies using UnxUtils package (with 'find' and 'mv') or Cygwin since you are on Windows.

The other option is to generate the targets for each of your .c/.cpp file explicitly, using some tool. Grab python, traverse source directories and for each .c/.cpp file write

obj/file_name.o:
       gcc -c path/fo/file_name.c -o obj/file_name.o

Upvotes: 1

moooeeeep
moooeeeep

Reputation: 32502

Use cmake to make the build configuration for you.

Some time ago I set up a simple example project on github.

Upvotes: 0

Related Questions