OS-variabele van regel instellen

Ik probeer een gedeelde bibliotheek met één set code te maken en alles werkt, behalve dit probleem met mijn Makefile. Hier is mijn (vereenvoudigde) Makefile tot nu toe:

OBJS = bar.o

libfoo.so:    OS = LINUX      # These don't seem to happen
libfoo.dll:   OS = WINDOWS

# Linux
ifeq ($(OS), LINUX)
CC = gcc
...

# Windows
else ifeq ($(OS), WINDOWS)
CC = i686-pc-mingw32-gcc
...
endif


all: libfoo.so libfoo.dll

libfoo.so: clean $(OBJS)
    ...

libfoo.dll: clean $(OBJS)
    ...


bar.o: bar_$(OS).c bar.h
    ...

Dus als u make libfoo.so invoert, verwacht ik dat dit eerst OS = LINUX instelt. Als het vervolgens bar.o bereikt (het is een afhankelijkheid van libfoo), moet het weten welke balk _ $ (OS) .c moet worden gebruikt. Ik krijg echter de foutmelding:

make: *** No rule to make target `bar_.c', needed by bar.o. Stop.

Wat me vertelt dat wanneer het bar.o probeert te maken, $ (OS) niet is ingesteld. Maar zou dat niet het eerste ding moeten zijn dat gebeurt wanneer ik libfoo.so probeer te maken, en die regel wordt geëvalueerd?

1

3 antwoord

Doelspecifieke variabelen zijn beschikbaar in de hoofdtekst van de regel, niet in de vereisten daarvoor. Maar zelfs als u dit zou kunnen laten werken, zou u om problemen vragen: als u de ene bibliotheek en vervolgens de andere bouwt, is er geen mogelijkheid voor Make om te weten dat de bar.o die werd gemaakt want de eerste is verkeerd voor de tweede en zou niet gebruikt moeten worden.

Er zijn verschillende manieren om het gewenste effect te krijgen, maar geen enkele is perfect. Ik zou voorstellen om twee verschillende bestandsnamen van objecten te gebruiken, zoals bar_unix.o en bar_windows.o .

2
toegevoegd
"Doelspecifieke variabele" was de zin waarnaar ik op zoek was, maar ik wist het niet. Dit is nu logisch. Uw afzonderlijk genoemde o bestandsoplossing is wat ik gebruikte om dit te laten werken, en ik denk dat ik dit zal blijven doen. Bedankt!
toegevoegd de auteur Jonathon Reinhart, de bron
Blijkt dat de manier om dit echt te doen, is door een recursieve call te maken (wat eleganter is in mijn situatie, aangezien ik veel variabelen moet instellen voor de toolchain).
toegevoegd de auteur Jonathon Reinhart, de bron

Misschien wilt u het besturingssysteem detecteren met behulp van uname en vervolgens voorwaardelijk compileren. This legt uit

1
toegevoegd
Dit helpt helemaal niet. Ik bouw de .so en .dll vanaf hetzelfde systeem, dus welk besturingssysteem mijn dev-box gebruikt, is niet relevant.
toegevoegd de auteur Jonathon Reinhart, de bron

Als u een doelspecifieke variabele wilt instellen en die variabele vervolgens buiten de hoofdtekst van die regel beschikbaar wilt stellen, kunt u de Makefile na het exporteren van de variabele recursief bellen:

OBJS ?= foo.o                    # Use ? so it isn't blown away on recursive call

libfoo.so: OS = LINUX
libfoo.so: OBJS += linux_only.o
libfoo.so:
    $(MAKE) -s build_libfoo_linux

build_libfoo_linux: $(OBJS)
    @echo "OS = $(OS)"           # Should print "OS = LINUX"

export OS                        # Can be anywhere

U moet onthouden dat u de variabelen die u wilt "behouden" wilt exporteren na het recursieve maakgesprek. En als u, zoals hierboven weergegeven, variabelen vóór het gesprek toevoegt, moet u hun eerste toewijzing met ? = maken, zodat ze niet de tweede keer worden ingesteld.

0
toegevoegd