Mam plik makefile, który buduje, a następnie wywołuje inny plik makefile. Ponieważ ten plik makefile wywołuje więcej plików makefile, które wykonują pracę, której tak naprawdę nie zmienia. Dlatego ciągle myśli, że projekt jest zbudowany i aktualny.
dnetdev11 ~ # make
make: `release' is up to date.
Jak zmusić plik makefile do odbudowania celu?
clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean
build = svn up ~/xxx \
$(clean) \
~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace \
$(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1) \
release:
$(build )
debug:
$(build DEBUG=1)
clean:
$(clean)
install:
cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib
Uwaga: Nazwy zostały usunięte, aby chronić niewinnych
Edycja: Wersja ostateczna naprawiona:
clean = $(MAKE) -f xxx_compile.workspace.mak clean;
build = svn up; \
$(clean) \
./cbp2mak/cbp2mak -C . xxx_compile.workspace; \
$(MAKE) -f xxx_compile.workspace.mak $(1); \
.PHONY: release debug clean install
release:
$(call build,)
debug:
$(call build,DEBUG=1)
clean:
$(clean)
install:
cp ./source/xxx_utillity/release/xxx_util /usr/bin
cp ./dlls/Release/xxxcore.so /usr/lib
.PHONY
nie był to twój jedyny problem, a tak naprawdę nie powinieneś edytować rozwiązania pytania, a przynajmniej już nie.)Odpowiedzi:
Możesz zadeklarować, że jeden lub więcej celów jest fałszywych .
źródło
:
, a nie tylko wyniku końcowego, który chcesz utworzyć (np. Pliku binarnego). W pytaniurelease
,debug
,clean
, iinstall
są celem wykonania, niexxx_util
lubxxxcore.so
czy cokolwiek innego.-B
Przełącznik do marki, którego forma jest długa--always-make
, mówimake
do znaczników czasu lekceważenie i wprowadzić określone cele. Może to pokonać cel użycia make, ale może być tym, czego potrzebujesz.źródło
Jedną sztuczką, która kiedyś była udokumentowana w podręczniku firmy Sun,
make
jest użycie (nieistniejącego) celu „.FORCE”. Możesz to zrobić, tworząc plik force.mk, który zawiera:Następnie, zakładając, że Twój makefile zostanie wywołany
makefile
, możesz uruchomić:Ponieważ
.FORCE
nie istnieje, wszystko, co od niego zależy, będzie nieaktualne i odbudowane.Wszystko to będzie działać z dowolną wersją
make
; w Linuksie masz GNU Make i dlatego możesz używać celu .PHONY, jak omówiono.Warto również zastanowić się, dlaczego
make
uważa wydanie za aktualne. Może to być spowodowane tym, żetouch release
wśród poleceń wykonano polecenie; może tak być, ponieważ istnieje plik lub katalog o nazwie „release”, który istnieje i nie ma żadnych zależności, a więc jest aktualny. Jest faktyczny powód ...źródło
Ktoś inny zasugerował .PHONY, co jest zdecydowanie poprawne. .PHONY należy stosować dla każdej reguły, dla której porównanie daty między danymi wejściowymi i wyjściowymi jest nieprawidłowe. Ponieważ nie masz żadnych celów formularza
output: input
, powinieneś użyć .PHONY dla WSZYSTKICH z nich!To powiedziawszy, prawdopodobnie powinieneś zdefiniować niektóre zmienne u góry pliku makefile dla różnych nazw plików i zdefiniować reguły rzeczywistej marki, które mają sekcje wejściową i wyjściową, abyś mógł korzystać z zalet make, a mianowicie, że będziesz kompilować tylko rzeczy, które są niezbędne do skopiowania!
Edycja: dodano przykład. Niesprawdzone, ale tak właśnie robisz .PHONY
źródło
.PHONY
celu nie ma znaczenia. Może być w dowolnym miejscu wMakefile
.Jeśli dobrze pamiętam, „make” używa znaczników czasu (czas modyfikacji pliku), aby ustalić, czy cel jest aktualny. Częstym sposobem wymuszenia przebudowy jest aktualizacja znacznika czasu za pomocą polecenia „touch”. Możesz spróbować wywołać „dotyk” w swoim pliku makefile, aby zaktualizować znacznik czasu jednego z celów (być może jednego z tych plików pod-makefile), co może zmusić Make do wykonania tego polecenia.
źródło
Ta prosta technika pozwoli normalnie funkcjonować plikowi makefile, gdy wymuszanie nie jest pożądane. Utwórz nowy cel o nazwie force na końcu swojego makefile . Siła cel dotknie plik domyślny cel zależy. W poniższym przykładzie dodałem touch myprogram.cpp . Dodałem również rekurencyjne połączenie do wykonania . Spowoduje to, że domyślny cel zostanie wykonany za każdym razem, gdy wpiszesz make force .
źródło
make
wewnątrz pliku Makefile. Użyj$(MAKE)
zamiast tego.Próbowałem tego i zadziałało to dla mnie
dodaj te linie do Makefile
zapisz i teraz zadzwoń
i wszystko ponownie skompiluje
Co się stało?
1) „nowe” połączenia czyste. „clean” do „rm”, który usuwa wszystkie pliki obiektowe, które mają rozszerzenie „.o”.
2) „nowe” połączenia „wykonaj”. „spraw, aby” zobaczył, że nie ma plików „.o”, więc ponownie utworzy wszystkie „.o”. następnie linker łączy wszystkie pliki .o w jednym pliku wykonywalnym
Powodzenia
źródło
new
lepsze wykorzystanie$(MAKE)
niżmake
Zgodnie z Recursive Millera Uważaj za szkodliwe , powinieneś unikać dzwonienia
$(MAKE)
! W przypadku, gdy pokazujesz, jest to nieszkodliwe, ponieważ tak naprawdę nie jest to plik makefile, a jedynie skrypt opakowania, który równie dobrze mógłby zostać napisany w Shell. Ale mówisz, że kontynuujesz to na głębszych poziomach rekurencji, więc prawdopodobnie napotkałeś problemy pokazane w tym eseju otwierającym oczy.Oczywiście dzięki GNU unikanie tego jest kłopotliwe. I chociaż zdają sobie sprawę z tego problemu, jest to ich udokumentowany sposób działania.
OTOH, makepp został stworzony jako rozwiązanie tego problemu. Możesz napisać swoje pliki makefile na poziomie katalogu, ale wszystkie zostaną połączone w pełny widok twojego projektu.
Ale starsze pliki makefile są zapisywane rekurencyjnie. Jest więc obejście, w którym
$(MAKE)
nic nie kieruje, ale kieruje żądania z powrotem do głównego procesu makepp. Tylko jeśli robisz zbędne lub, co gorsza, sprzeczne rzeczy między swoimi zgłoszeniami, musisz poprosić--traditional-recursive-make
(co oczywiście łamie tę zaletę makepp). Nie znam twoich innych plików makefile, ale jeśli są one napisane czysto, przy pomocy makepp niezbędne przebudowy powinny nastąpić automatycznie, bez potrzeby sugerowania tutaj innych hacków.źródło
:
), zawsze będzie się odbudowywać w razie potrzeby.Jeśli nie musisz zachowywać żadnych wyników, które udało się skompilować
odbudowuje wszystko
źródło
To zależy od celu. Jeśli jest to fałszywy cel (tj. Cel NIE jest powiązany z plikiem), powinieneś zadeklarować go jako .PHONY.
Jeśli jednak cel nie jest fałszywym celem, ale z jakiegoś powodu chcesz go odbudować (na przykład, gdy używasz makra wstępnego przetwarzania __TIME__), powinieneś użyć schematu FORCE opisanego w odpowiedziach tutaj.
źródło
http://www.gnu.org/software/make/manual/html_node/Force-Targets.html#Force-Targets
źródło
Zostało już wspomniane, ale pomyślałem, że mogę dodać do korzystania
touch
Jeśli
touch
wszystkie pliki źródłowe, które mają zostać skompilowane,touch
polecenie zmieni znaczniki czasu pliku na czas systemowy, w którymtouch
polecenie zostało wykonane.Sygnatura czasowa pliku źródłowego jest
make
używana do „poznania” pliku, który się zmienił i należy go ponownie skompilowaćNa przykład: Jeśli projekt był projektem c ++, to zrób to
touch *.cpp
, a następnie uruchommake
ponownie, a make powinno skompilować cały projekt.źródło
Jak wskazał abernier, istnieje zalecane rozwiązanie w podręczniku GNU make manual, który wykorzystuje „fałszywy” cel do wymuszenia odbudowania celu:
Będzie działać czysto, niezależnie od innych zależności.
Dodałem średnik do roztworu z instrukcji, w przeciwnym razie wymagana jest pusta linia.
źródło
W moim systemie Linux (Centos 6.2) istnieje znacząca różnica między deklarowaniem celu .PHONY a tworzeniem fałszywej zależności od FORCE, kiedy reguła faktycznie tworzy plik pasujący do celu. Gdy plik musi być generowany za każdym razem, wymagał zarówno Fałszywej zależności FORCE na pliku, jak i .PHONY dla fałszywej zależności.
źle:
dobrze:
źródło
make clean
usuwa wszystkie już skompilowane pliki obiektowe.źródło