Jak mogę napisać plik makefile, aby automatycznie wykryć i zrównać kompilację z GNU Make?

Nie jestem pewien, czy jest to możliwe tylko w jednym pliku Makefile, ale miałem nadzieję napisać plik Makefile w taki sposób, że próba zbudowania dowolnego celu w pliku automatycznie magicznie wykrywa liczbę procesorów w bieżącym systemie i buduje cel równolegle dla liczby procesorów.

Coś w stylu poniższych przykładów "pseudokodów", ale dużo czystsze?

all:
    @make -j$(NUM_PROCESSORS) all

Lub:

all: .inparallel
    ... build all here ...

.inparallel:
    @make -j$(NUM_PROCESSORS) $(ORIGINAL_TARGET)

W obu przypadkach wystarczy wpisać:

% make all

Miejmy nadzieję, że to sprawia, że sens.

UPDATE: wciąż mam nadzieję na przykładowy plik Makefile dla powyższego. Nie interesuje mnie znalezienie liczby procesów, ale interesuje mnie jak napisać plik makefile do zbudowania równolegle bez opcji linii poleceń-J.

Author: dlamotte, 2010-03-27

7 answers

Część detekcji będzie zależna od systemu operacyjnego. Oto fragment, który będzie działał na Linuksie i Mac OS X:

NPROCS:=1
OS:=$(shell uname -s)

ifeq($(OS),Linux)
  NPROCS:=$(shell grep -c ^processor /proc/cpuinfo)
endif
ifeq($(OS),Darwin) # Assume Mac OS X
  NPROCS:=$(shell system_profiler | awk '/Number Of CPUs/{print $4}{next;}')
endif

Aby go uruchomić, prawdopodobnie będziesz musiał ponownie wywołać make. Więc Twoim problemem jest zapobieganie nieskończonej rekurencji. Możesz zarządzać tym, mając dwa pliki Makefile(pierwszy tylko resetuje wartość -j), ale prawdopodobnie jest to możliwe do finezji.

 21
Author: dmckee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-29 11:30:23

Po grzebaniu w rozdziale 2 ldd3 i przeczytaniu odpowiedzi dmckee ' ego, wymyśliłem niezbyt dobrą odpowiedź na użycie dwóch plików Makefile (wolałbym tylko jeden).

$ cat Makefile
MAKEFLAGS += -rR --no-print-directory

NPROCS := 1
OS := $(shell uname)
export NPROCS

ifeq ($J,)

ifeq ($(OS),Linux)
  NPROCS := $(shell grep -c ^processor /proc/cpuinfo)
else ifeq ($(OS),Darwin)
  NPROCS := $(shell system_profiler | awk '/Number of CPUs/ {print $$4}{next;}')
endif # $(OS)

else
  NPROCS := $J
endif # $J

all:
    @echo "running $(NPROCS) jobs..."
    @$(MAKE) -j$(NPROCS) -f Makefile.goals $@

%:
    @echo "building in $(NPROCS) jobs..."
    @$(MAKE) -j$(NPROCS) -f Makefile.goals $@
$ cat Makefile.goals
MAKEFLAGS += -rR --no-print-directory
NPROCS ?= 1

all: subgoal
    @echo "$(MAKELEVEL) nprocs = $(NPROCS)"

subgoal:
    @echo "$(MAKELEVEL) subgoal"

Co sądzisz o tym rozwiązaniu?

Korzyści widzę, że ludzie nadal typować make budować. Więc nie ma jakiegoś skryptu "sterownika", który wykonuje NPROCS i make -j$(NPROCS) pracę, o której ludzie będą musieli wiedzieć zamiast pisać make.

Minusem jest to, że będziesz musiał wyraźnie użyć make -f Makefile.goals, Aby zrób seryjną kompilację. I nie jestem pewien, jak rozwiązać ten problem...

Aktualizacja: Dodano $J do powyższego segmentu kodu. Wygląda na to, że praca działa całkiem dobrze. Mimo że jego dwa pliki Makefile zamiast jednego, nadal jest całkiem bezproblemowy i przydatny.

 6
Author: dlamotte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-29 15:41:10

Oto co zrobiłem:

ifeq ($(OS),Linux)
        NUMPROC := $(shell grep -c ^processor /proc/cpuinfo)
else ifeq ($(OS),Darwin)
        NUMPROC := $(shell sysctl hw.ncpu | awk '{print $$2}')
endif

# Only take half as many processors as available
NUMPROC := $(shell echo "$(NUMPROC)/2"|bc)

ifeq ($(NUMPROC),0)
        NUMPROC = 1
endif 
 6
Author: amos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-12 19:36:30

Właśnie dodałem to do mojego pliku Makefile. Pozwala tworzyć dowolną liczbę zadań, ale stara się utrzymać średnie obciążenie poniżej liczby rdzeni procesora.

MAKEFLAGS+="-j -l $(shell grep -c ^processor /proc/cpuinfo) "

Uwaga Jest to specyficzne dla Linuksa.

 6
Author: TedKotz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 07:21:23

Pominę detekcję $(NPROCS), ale oto jak możesz to zrobić w jednym Makefile (to jest prawdopodobnie GNU Make specific, ale wygląda na wariant, który używasz):

ifeq ($(NPROCS),)
# Code to set NPROCS...
%:
    $(MAKE) -j$(NPROCS) NPROCS=$(NPROCS)
else
# All of your targets...
endif

Zobacz Definiowanie domyślnych regułi nadpisywanie części innego pliku Makefilew GNU Make Manual.

 5
Author: Jack Kelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-03 23:31:17

Jeśli chcesz, aby była automatyczna, możesz nadpisać typowe polecenie make jako alias do siebie w .bashrc w katalogu domowym.

Przykład:

alias make="make -j"

Albo możesz zrobić coś takiego:

alias jmake="make -j"

W przypadku, gdy nie chcesz go nadpisać, ale chcesz szybkiego i łatwego (i niezapomnianego) sposobu na równoległe uruchamianie make.

 2
Author: bean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-25 06:40:16

Jeśli dobrze przeczytam pytanie, celem jest jak największe zrównoleglenie procesu budowania. Strona podręcznika make zawiera następujące dane

Jeśli opcja-j jest podana bez argumentu, make nie ograniczy liczby zadań, które mogą być uruchomione jednocześnie.

Czy nie jest to w zasadzie rozwiązanie, które chcesz? Jeśli Twój plik Makefile ma wystarczającą ilość równoległych celów, użyjesz wszystkich swoich procesorów, a jeśli cele nie są równoległe, ta opcja -j nie pomoże anywas.

 1
Author: grundprinzip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-18 18:19:06