Как получить файлы cpp из разных каталогов, скомпилированные в одну папку?

У меня есть несколько файлов C++, распределенных по нескольким папкам.

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

Они гарантированно будут иметь уникальное имя. Я хочу скомпилировать все эти файлы С++ для разделения объектных файлов в каталоге obj/.

У меня есть список всех исходных файлов с относительным путем и их соответствующими именами назначения.

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

Как сделать правило, которое будет преобразовывать файл С++ из первого списка в объектный файл из второго?

Эти попытки не работают:

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

%.obj: %.cpp
    # ...

.cpp.obj:
    # ...

Я бы не хотел писать такие правила:

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

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

person Niklas R    schedule 26.07.2012    source источник


Ответы (5)


Попробуйте установить VPATH:

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

И добавить полный список файлов (я бы рекомендовал вам явно перечислить файлы, не использовать функцию $(wildcard ...)) и привязку приложения:

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 $@ $+

$(wildcard) имеет раздражающую тенденцию подбирать что-либо в каталогах, например, одноразовые тестовые файлы или временные файлы (если они имеют подходящее имя: ~file.cpp).

person fork0    schedule 26.07.2012

Я могу придумать одно решение: просто создайте их на месте с помощью простого правила, а затем сделайте «этап сбора», перемещая файлы «.o» в одну папку.

Создайте цель "collect_objs", которая зависит от вашего $(OBJS), а затем ваша "основная" цель должна зависеть от "collect_objs".

Обход можно сделать с помощью оболочки

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

Конечно, это подразумевает использование пакета UnxUtils (с «find» и «mv») или Cygwin, поскольку вы работаете в Windows.

Другой вариант — явно сгенерировать цели для каждого вашего файла .c/.cpp с помощью какого-либо инструмента. Возьмите python, просмотрите исходные каталоги и для каждого файла .c/.cpp напишите

obj/file_name.o:
       gcc -c path/fo/file_name.c -o obj/file_name.o
person Viktor Latypov    schedule 26.07.2012

Используйте cmake, чтобы настроить конфигурацию сборки.

Некоторое время назад я создал простой пример проекта на github.

person moooeeeep    schedule 26.07.2012

Стандартный способ - иметь Makefile в каждой папке и рекурсивно вызывать с помощью include

Это были мои первые два попадания на 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

person steffen    schedule 26.07.2012

Не имеет строгого отношения к этому вопросу, поскольку он не имеет отношения к Make, хотя я хотел бы показать, как я компилирую свои проекты сейчас, спустя 3 года. Craftr – это система метасборки на основе Python, которая поощряет непрямые сборки вне дерева (например, build в рабочем дереве). Создание объектных файлов и создание статической библиотеки так же просто, как

# 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],
)

Запуск craftr -eb приведет к следующей структуре продуктов сборки

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
person Niklas R    schedule 25.12.2015