Какова СУХАЯ версия следующих целей Makefile? - PullRequest
2 голосов
/ 04 апреля 2010

Я не знаю, как выполнить команду, хранящуюся как переменную, или как использовать ifeq внутри цели, поэтому у меня есть очень избыточный Makefile на данный момент!

В идеале я хотел бы иметь только одну цель (all), которая будет запускать сохраненную команду на Mac и запускать ее дважды в Linux, один раз с -m32 и один раз с -m64.

all:
    echo PLEASE SELECT OS, e.g. make linux
    exit 1

mac:
     gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME) $(SOURCE) $(LIBRARIES)

linux:
    gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME64) $(SOURCE) $(LIBRARIES64) -m64
    gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME) $(SOURCE) $(LIBRARIES) -m32

ОБНОВЛЕНИЕ: Это то, чем я закончил, прочитав различные предложения. (Да, я знаю, что должен использовать autoconf ...). Спасибо всем за вашу помощь!

ifeq($(PLATFORM), Linux)
    COMMON = -pthread -fPIC
    PLATFORM_CFLAGS = $(COMMON) -m32
    PLATFORM_CFLAGS64 = $(COMMON) -m64
endif

ifeq ($(PLATFORM), Darwin)
    PLATFORM_CFLAGS = -arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk
endif

all: $(PLATFORM)_all

Darwin_all:
     mkdir -p ../../../../tmp
     gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS) -o $(BUILD_DIR)$(BUILD_NAME) $(SOURCE) $(LIBRARIES)

Linux_all: Darwin_all
     gcc $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS64) -o $(BUILD_DIR)$(BUILD_NAME64) $(SOURCE) $(LIBRARIES64)

Ответы [ 3 ]

2 голосов
/ 04 апреля 2010

Вы заставляете макросы выполнять большую часть работы, отмечая, что вы должны использовать $ (CC), а не gcc.

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64

# We could do some fancy stuff here...
# Except that we will remove the commands momentarily
all:
    echo PLEASE SELECT OS, e.g. make linux
    exit 1

# Note that without a qualifier
# - MacOS X 10.5.x will build 32-bit
# - MacOS X 10.6.x will build 64-bit
# But why not build both anyway?
mac:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

linux:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

О, и посмотрите, команды теперь одинаковы для Linux и MacOS X ... так что мы можем сделать:

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64

all:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

Черт возьми, это тяжелая работа - писать $ (XXX) вместо $ {XXX}, как я обычно делаю в своих make-файлах.

По сути, мы применяем СУХОЙ (не повторяю себя), делая имена скучно систематическими. Makefiles не должен быть увлекательным.

Если вы все еще хотите иметь разницу между вашими платформами, то вы можете сделать что-то в соответствии с рекомендациями Ивана Андруса. GNU Make позволяет вам оценивать команды оболочки, поэтому:

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64

all:  $(shell uname)

Linux:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

Darwin:
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32)

Если вы чувствуете, что не можете положиться на GNU Make, тогда:

BUILD_COMMAND = $(CC) $(SHARED_OPT) $(GENERAL_CFLAGS) $(PLATFORM_CFLAGS)
BUILD_NAME32  = $(BUILD_NAME)
TARGET_32     = $(BUILD_DIR)$(BUILD_NAME32)
TARGET_64     = $(BUILD_DIR)$(BUILD_NAME64)
LIBS_32       = $(LIBRARIES)
LIBS_64       = $(LIBRARIES64)
OPTS_32       = -m32
OPTS_64       = -m64
BUILD_32      = use_32_bit
BUILD_64      = use_64_bit
BUILD_TYPE    = $(BUILD_32) $(BUILD_64)

.PHONEY: $(BUILD_32) $(BUILD_64)

all:  $(BUILD_TYPE)

use_64_bit:
    $(BUILD_COMMAND) -o $(TARGET_64) $(SOURCE) $(LIBS_64) $(OPTS_64)

use_32_bit:
    $(BUILD_COMMAND) -o $(TARGET_32) $(SOURCE) $(LIBS_32) $(OPTS_32)

По умолчанию это скомпилирует 32-битную и 64-битную версии. Если вы хотите использовать только 32-разрядную или только 64-разрядную версию, запустите соответствующий из этих двух:

make BUILD_TYPE=use_32_bit
make BUILD_TYPE=use_64_bit
2 голосов
/ 04 апреля 2010

Это довольно просто, но вы должны иметь возможность адаптировать его к более сложным вещам, изменив команду оболочки, которую вы запускаете.

PLATFORM := $(shell uname)

all:$(PLATFORM)

Darwin:
    echo Darwin

Linux:
    echo Linux
1 голос
/ 04 апреля 2010

У вас есть несколько полезных советов (исследуйте платформу, используйте переменные), но вы также должны знать, что вы работаете очень близко к точке, где лучше перестать думать с точки зрения поддержки платформ, а не с точки зрения описание функций, которые требуются для вашего программного обеспечения, и использование autoconf (и семейства) для обнаружения того, что на самом деле присутствует.

Имейте в виду, что если это приложение с графическим интерфейсом, у вас, вероятно, будет так много различий между кодом OSX и кодом Linux / X11, что обнаружение на платформе является разумным. Просто редко нужно делать это для всего, что ориентировано на командную строку, так как тогда OSX очень похож на обычный старый Unix.

...