Его необязательно писать каждый раз заново.
Есть мнение, что сначала надо все-таки мануал прочитать.
Вопрос зависимостей для C/С++ там как правило разбирают.
Вопрос зависимостей для C/С++ там как правило разбирают.
Ну вот я не очень понимаю use case - я добавляю новый .h файл, от которого зависят несколько других .h и .c, это мне его в зависимости для всех нужных .o руками прописывать или где?
Блин, какие мейк файлы? 1970й год на дворе! :) Набивать на перфокартах!!
Правильно его гененировать. Например с помощью cmake
Если совсем-совсем правильно, то это будет autotools.
А по простецки dependencies можно gcc попросить сделать: gcc -MM file.c
А по простецки dependencies можно gcc попросить сделать: gcc -MM file.c
ааа11111 не надо! Старое говно старых мамонтов же.
Понятно.
Ключики gcc посмотрите, -E что ли генерит зависимости.
Ключики gcc посмотрите, -E что ли генерит зависимости.
man gcc блин. И загуглить и прочитать gnu make manual
Ну вот смотрю я на оный язык и вижу то же самое :)
А, точно.
Я один раз -M указывал, он добавлял все стандартные хидеры, а с двумя ок.
Я один раз -M указывал, он добавлял все стандартные хидеры, а с двумя ок.
autotools - это совсем-совсем неправильно. Это ядерная бомба замедленного действия.
Хотя у хозяина журнала, вероятно, рванет быстро - у него же вроде кросс-сборка имеется...
Хотя у хозяина журнала, вероятно, рванет быстро - у него же вроде кросс-сборка имеется...
О, ребе. Ви таки просто обязаны заценить mk-configure :) Ну не зря же про него на каждом LVEE рассказывают :)
Про -MM уже сказали. Подробно и аккуратно, если это линукс и, соответственно, GNU make, разобрано в его мануале. В целом - решение далеко от идеала, но лучше средствами make не делается, вылезает проблема курицы и яйца. У bsd make (pmake в линуксах) средства иные. Сделать makefile так, чтобы жрали оба - задача сложная, и автоподхват зависимостей будет делаться только в два прохода (make depend && make).
Да, в случае генерируемых включаемых файлов gcc -MM тоже порой обламывается.
Кстати, вообще рекомендую посмотреть на "старую добрую" идею двухпроходного подхода. Она тоже по-своему корява, но зато мейкфайл будет читаем.
Да, в случае генерируемых включаемых файлов gcc -MM тоже порой обламывается.
Кстати, вообще рекомендую посмотреть на "старую добрую" идею двухпроходного подхода. Она тоже по-своему корява, но зато мейкфайл будет читаем.
Как раз с кросс-сборкой у автокрапа все хорошо
вот первый попавшийся.
Компиляция под х86 сломана, но леххко чинится по аналогии (делаем эльф)
Компиляция под х86 сломана, но леххко чинится по аналогии (делаем эльф)
TARGET = atmega328 CC = avr-g++ LD = avr-gcc RM = rm AR = ar MKDIR = mkdir OPTIMIZE = -Os PORT = /dev/ttyUSB0 CFLAGS = -g -Wall -W $(OPTIMIZE) -mmcu=$(TARGET) -Iinclude -Iinc CFLAGS += -DF_CPU=16000000UL -D__AVR_ATmega328__ -c LDFLAGS = -g -Wl,-Map,$(OUT)$(BINNAME).map -mmcu=$(TARGET) -lm OBJCOPY = avr-objcopy OBJDUMP = avr-objdump #DUDE = avrdude.exe -B 2.0 -p m8 -c avrispv2 -P com1 DUDE = avrdude -patmega328p -carduino -P$(PORT) -b57600 -D x86_CC = g++ x86_LD = g++ x86_CFLAGS = -g -Wall -W $(OPTIMIZE) -Iinclude -c LIBS = OUT = out/ SRC = src/ SRC2 = src-lib/ O = .o O86 = .obj E = .elf HEX = .hex BIN = .bin SREC = .srec x86 = .exe BINNAME = test vpath %.cpp $(SRC) vpath %.c $(SRC) vpath %.cpp $(SRC2) vpath %.c $(SRC2) vpath %.$(E) $(OUT) OBJS = $(subst $(SRC),$(OUT), $(subst .C,$(O), $(subst .c,$(O), $(subst .cpp,$(O), $(wildcard $(SRC)*.cpp $(SRC)*.c $(SRC)*.C))))) OBJS += $(subst $(SRC2),$(OUT), $(subst .C,$(O), $(subst .c,$(O), $(subst .cpp,$(O), $(wildcard $(SRC2)*.cpp $(SRC2)*.c $(SRC2)*.C))))) OBJS_x86 = $(subst $(SRC),$(OUT), $(subst .C,$(O86), $(subst .c,$(O86), $(subst .cpp,$(O86), $(wildcard $(SRC)*.cpp $(SRC)*.c $(SRC)*.C))))) ########################## all: $(OUT) $(OUT)$(BINNAME)$(E) $(OUT)$(BINNAME)$(HEX) $(OUT)$(BINNAME)$(BIN) all: $(OUT)$(BINNAME)$(SREC) $(OUT)$(BINNAME).S debug: $(OUT) $(OUT)$(BINNAME)$(x86) clean: -rm -rf $(OUT) prog: all $(DUDE) -U flash:w:"$(OUT)$(BINNAME)$(HEX)" ########################## $(OUT)%$(O): %.cpp @echo "[ CC ]" $< @$(CC) $(CFLAGS) -o$@ $< $(OUT)%$(O): %.c @echo "[ CC ]" $< @$(CC) $(CFLAGS) -o$@ $< $(OUT)%$(HEX): $(OUT)%.elf @echo "[ OBJCOPY ]" $@ @$(OBJCOPY) -j .text -j .data -O ihex $< $@ $(OUT)%_eeprom$(HEX): $(OUT)%.elf @echo "[ OBJCOPY ]" $@ @$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ $(OUT)%_eeprom$(SREC): $(OUT)%.elf @echo "[ OBJCOPY ]" $@ @$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ $(OUT)%_eeprom$(BIN): $(OUT)%.elf @echo "[ OBJCOPY ]" $@ @$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ $(OUT)%$(SREC): $(OUT)%.elf @echo "[ OBJCOPY ]" $@ @$(OBJCOPY) -j .text -j .data -O srec $< $@ $(OUT)%$(BIN): $(OUT)%.elf @echo "[ OBJCOPY ]" $@ @$(OBJCOPY) -j .text -j .data -O binary $< $@ $(OUT)%.S: $(OUT)%.elf @echo "[ OBJDUMP ]" $@ @$(OBJDUMP) -S $< > $@ @echo "[ OBJDUMP ]" $@.d @$(OBJDUMP) -d $< > $@.d $(OUT)%$(O86): %.cpp @echo "[ x86_CC ]" $< @$(x86_CC) $(x86_CFLAGS) -o$@ $< $(OUT)%$(O86): %.c @echo "[ x86_CC ]" $< @$(x86_CC) $(x86_CFLAGS) -o$@ $< $(OUT)$(BINNAME)$(E): $(OBJS) @echo "[ LD ]" $@ @$(LD) $(LDFLAGS) -o $@ $^ $(OUT)$(BINNAME)$(x86): $(OBJS_x86) @echo "[ x86_LD ]" $@ $(x86_LD) $(x86_LDFLAGS) -o $@ $^ $(OUT): @echo "[ MKDIR ]" $@ @-$(MKDIR) $@
gcc -что-то-там, дает некую шнягу, которую делаем для всех цэшников по make dep. потом эту шнягу тупо инклюдаем в мэйкфайл.
автотулз это лишний уровень неуправляемости.
если делать 'как придется' то периодически будет лезть говно, а если аккуратно - то это ни разу не проще аккуратного ручного мэйкфайла.
если делать 'как придется' то периодически будет лезть говно, а если аккуратно - то это ни разу не проще аккуратного ручного мэйкфайла.
Лично я руками пишу. У меня уже три Makefile в проекте, общей сложностью (wc -l) 6641 строки :) правда, из них не меньше трети пробелов и комментариев. Много ли у вас там зависимостей? Тем более, один раз вы их пропишете, и все, потом только добавляй.
Читал, кстати, как-то раз совет насчет сделать один .h файл типа такого:
Потом каждый .c файл его включает, но объявляет, что именно он использует:
Для меня это неактуально, но вообще такой файл выглядит довольно удобной идеей.
Читал, кстати, как-то раз совет насчет сделать один .h файл типа такого:
#ifdef USE_THIS ... код для this ... #endif #ifdef USE_THAT ... код для that ... #endifM
Потом каждый .c файл его включает, но объявляет, что именно он использует:
#define USE_THIS #include "myheader.h"
Для меня это неактуально, но вообще такой файл выглядит довольно удобной идеей.
Нинада никакх make dep. При первой сборке объектников генерируются правила с зависимостями. Всё прозрачно.
Собственно, что это я: конкретно в вашем use case можно, скажем, сгруппировать цели по зависимостям:
Но это может быть не очень удобно, потому что зависимости идут в неочевидном порядке (хотя, по-моему, они будут в том же порядке, что и в файле), и несколько трудно писать стандартные рецепты с использованием символов вроде
foo.o bar.o: baz.h foo.o: foo.c foo.h рецепт
Но это может быть не очень удобно, потому что зависимости идут в неочевидном порядке (хотя, по-моему, они будут в том же порядке, что и в файле), и несколько трудно писать стандартные рецепты с использованием символов вроде
$<
.Потыкай ещё этих мягких IDE'шных кнопок да запусти дебагер!
Page 1 of 4