«Стандартная библиотека» для создания проектов C / C ++ с Make - PullRequest
1 голос
/ 20 апреля 2011

Иногда мне нужно, чтобы в моем проекте использовался простой make-файл, хотя это устаревшая технология сборки, которая не рекомендуется для любого использования, но поскольку make доступна практически везде, иногда это имеет смысл.

Однако я хочу, чтобы мой Makefile выглядел примерно как

Include "../buildexec.mk"

TARG = my_exec

CPPFILES = file1.cpp \
           file2.cpp \

и иметь весь общий (и ужасный) код отслеживания зависимостей, который находится в builddexec.mk.

Есть ли такая "Создать библиотеку"?

В Go есть стандартный Makefile, который вы можете включить, и ваш Makefile выглядит так же красиво, как this :

include $(GOROOT)/src/Make.inc

TARG=irc
GOFILES=irc.go irc_struct.go irc_callback.go

include $(GOROOT)/src/Make.pkg 

Что-нибудь похожее для C ++?

уточнение: Я знаю о tup, cmake и scons / я знаю о waf, bjam и т. Д. / Но я хочу, чтобы мои deps были такими маленькими / чтобы компиляция не была проблемой вообще. Я специально просил поддержку Make, а не альтернативу Make.

Ответы [ 5 ]

1 голос
/ 20 апреля 2011

Я бы предложил создать make-файл вместо automake . Cmake также генерирует make-файлы, а также может создавать файлы проекта для нескольких IDE.

Проблема в том, что нет ни одного make.Самый базовый синтаксис всегда один и тот же, но что-то более сложное (что вам нужно для таких целей) не совместимо даже между GNU make и BSD make (не пытаясь упомянуть NMAKE ).Однако Automake может работать с несколькими версиями make и предоставлять правила автоматической зависимости, где они доступны (их поддерживают только некоторые компиляторы).

0 голосов
/ 05 августа 2011

Нет моих знаний.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *] С действительно действительно много проблем с make, но это все еще самый доступный инструмент из всех, и как только вы запустите его правильно, вы должны просто сосредоточиться на разработке.напишите make-файлы.Но вместо того, чтобы искать «make library», действительно простое решение (если вы на самом деле были инициированы на языке Make), которое часто упускают из виду за очевидность, - это реализовать свой собственный .Создайте скрипт make, содержащий набор шаблонных правил и переменных по умолчанию для связи с make-файлом проекта, и просто включите этот скрипт в make-файл каждого проекта.Это не сложно, может быть, немного отнимает много времени, но часто окупается очень хорошо, особенно если у вас много небольших проектов для управления.

Я работаю с таким дизайном.У меня есть пара GNU make-скриптов, тщательно разработанных для того, чтобы предложить почти тривиальный механизм для создания довольно сложных систем сборки: автоматическое создание зависимостей, обработка разных языков, генерация синтаксических анализаторов языков, различные конфигурации сборки (отладка или выпуск), генерация журнала сборки,и так далее.И сценарий не громоздкий: текущая версия содержит всего около 250 строк кода make-файла, исключая комментарии.

Я оставлю вам образец более старой версии такой системы, которая обрабатывает только исходный код C, которыйсодержал несколько функций.Он должен обрабатывать компиляцию двоичных файлов и библиотек (как статических, так и динамических).Это также должно помочь вам отслеживать межпроектные зависимости через переменную DEPS.

Вызовите это $(ROOT)/project.mk:

# Remove the default suffix rules.
.SUFFIXES:

# Turn on the delete-on-error feature.
.DELETE_ON_ERROR:

# Set up additional command variables.
STRIP ?= strip

# Set up a global search path to locate prerequisites.
VPATH := $(VPATH) $(shell find -type d)

# Locate all source files from the default locations in the project tree.
SRC := $(SRC) $(shell find src -name '*.c')

# Set up the default dependency files.
DEP := $(DEP) $(addprefix dep/,$(addsuffix .d,$(basename $(notdir $(filter %.c,$(SRC))))))

# Set up the default object files.
OBJ := $(OBJ) $(addprefix obj/,$(addsuffix .o,$(basename $(notdir $(filter %.c,$(SRC))))))

# Set up a set of default flags for all commands used.
STRIPFLAGS ?= -p
CPPFLAGS ?= -DNDEBUG
CFLAGS ?= -Wall -Wextra -Werror -pedantic -O3 -march=native -fomit-frame-pointer -ffast-math
LDFLAGS ?= --as-needed -O1
ARFLAGS ?= -scr

# Set up the default include and library search paths.
override INCLUDES := \
    $(addprefix $(ROOT)/,$(addsuffix /include,$(DEPS))) \
    $(INCLUDES)
override LIBRARIES := \
    $(addprefix $(ROOT)/,$(addsuffix /lib,$(DEPS))) \
    $(LIBRARIES) lib

# The default rule to build every target in the project.
.PHONY: all
all: deps $(DEP) $(OBJ) $(BIN) $(LIB)

# Phony rule to recursively build the library dependencies.
.PHONY: deps
deps:
    @for dep in $(DEPS); do cd $(ROOT)/lib/$$dep && $(MAKE); done

# Secondary expansion is used to properly locate prerequisites.
.SECONDEXPANSION:

# Rule for dependency file generation.
%.d: $$(notdir $$*).c
    $(CC) -M $(CPPFLAGS) $(CFLAGS) -iquote include $(addprefix -I ,$(INCLUDES)) $< -MM -MG -MP -MT '$@ $(filter %/$(notdir $*).o,$(OBJ))' > $@

# Rule for compiling object files.
%.o: $$(notdir $$*).c
    $(CC) -c $(CPPFLAGS) $(CFLAGS) -iquote include $(addprefix -I ,$(INCLUDES)) $< -o $@

# Rule for linking binaries.
%: $$(notdir $$*).c
    $(CC) $(CPPFLAGS) $(CFLAGS) $(addprefix -Xlinker ,$(LDFLAGS)) -iquote include $(addprefix -I ,$(INCLUDES)) $(addprefix -L ,$(LIBRARIES)) $(filter-out $<,$^) -o $@ $(addprefix -l,$(LDLIBS))
    $(STRIP) $(STRIPFLAGS) $@

# Rule for linking shared libraries.
%.so: $$(notdir $$*).c
    $(CC) $(CPPFLAGS) $(CFLAGS) $(addprefix -Xlinker ,$(LDFLAGS)) -iquote include $(addprefix -I ,$(INCLUDES)) $(addprefix -L ,$(LIBRARIES)) $(filter-out $<,$^) -o $@ -fpic -shared -Wl,-h,$(notdir $@) $(addprefix -l,$(LDLIBS))
    $(STRIP) $(STRIPFLAGS) $@

# Rule for generating static libraries.
%.a:
    $(AR) $(ARFLAGS) $@ $?

# Include all dependency files and remake them if necessary.
ifneq ($(MAKECMDGOALS),clean)
    include $(DEP)
endif

# Phony rule to clean the entire build tree.
.PHONY: clean
clean:
    @for dep in $(DEPS); do cd $(ROOT)/lib/$$dep && $(MAKE) clean; done
    $(RM) $(DEP) $(OBJ) $(BIN) $(LIB) $(CLEAN)

ROOT содержит путь к каталогу ваших проектов (рабочая копия репозитория, например), обычно экспортируется как переменная окружения.Вам также понадобится пара каталогов (bin, dep, obj и src) в ваших проектах.

Примером Makefile с использованием этой системы может быть:

DEPS := mylib

BIN := bin/test
LIB := lib/libtest.a

include $(ROOT)/project.mk

bin/test: $(OBJ)
lib/libtest.a: obj/test1.o obj/test2.o

То есть вы просто пишете минимум, необходимый для вашего проекта, и пусть система сборки сделает все остальное.Вы всегда можете явно указать значение для данной переменной (SRC, например, или CFLAGS), но если вы этого не сделаете, то оно получит разумное значение по умолчанию.

Выше было адаптировано кмои потребности, но это должно быть просто, чтобы приспособиться к вашим, оставив при этом все так же просто, как примеры, которые вы упомянули.

0 голосов
/ 27 апреля 2011

Есть проект GoogleCode, делающий именно то, что я хотел:

http://code.google.com/p/nonrec-make/

0 голосов
/ 21 апреля 2011

Это сделает то, что вы просите (по крайней мере, в GNUMake).

makelib.mk:

$(TARG): $(CPPFILES:.cc=.o)
    $(CC) $^ -o $@

%.o : %.cc
    $(CC) -MD -o $@ $<                                               
    @cp $*.d $*.P; \                                                        
      sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \            
          -e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \                 
      rm -f $*.d                                                       

-include $(CPPFILES:.cc=.P)

Makefile:

CPPFILES = foo.cc bar.cc
TARG = someTarget
include makelib.mk      # Note lower-case "i"

CPPFILES = baz.cc quartz.cc quince.cc
TARG = anotherTarget
include makelib.mk

...

Но совет: не стоит так сильно ругать свои инструменты. Это энергия, которую вы могли бы использовать, чтобы научиться их использовать или переключаться на те, которые вам нравятся больше.

0 голосов
/ 20 апреля 2011

Возможно, вы захотите взглянуть на CMake или Premake .

. В больших проектах на C / C ++ вы, как правило, предъявляете дополнительные требования, такие как API для конкретной платформы или библиотекикоторые нуждаются в настройке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...