Как добавить целевой файл в зависимости от вызываемого тега в make-файле

Я использую этот Makefile в основном для всех своих проектов, адаптируя его для разных типов библиотек или исполняемых файлов, которые мне нужно сгенерировать.
В этот раз мне нужно скомпилировать разные цели, которые имеют несколько общих файлов и один файл, который зависит от разных целей.

Я пытаюсь что-то подобное

# Add inputs and outputs from these tool invocations to the build variables

# All Target

RM := rm -rf
CXX:= g++
LD := g++
CC := gcc

TARGET = ../../Libs/libdemo.so

# definition of additional libraries for linking
LIBS := -L/data/somelib_lib/ -lsomelib1 -lsomelib2
# definition of include directories
# for each you need to add -I
INCLUDE :=  -I../../include

#compiler definition

CFLAGS= -std=c++11 -Wall -Wextra -c -fmessage-length=0 -fPIC -MMD -MP   -D __GXX_EXPERIMENTAL_CXX0X__ -D_GLIBCXX_USE_NANOSLEEP# All of the sources participating in the build are defined here

# Add inputs and outputs from these tool invocations to the build variablesLINKER_FLAG= -shared

target1: CPP_SRCS += \
src/main1.cpp

target1: CPP_DEPS += \
src/main1.d

target1: CFLAGS += -O0 -g3
target1: LINKER_FLAG += -g
target1: $(TARGET)
@echo "main1 called"
target2: CPP_SRCS += \
src/main2.cpp

target2: CPP_DEPS += \
src/main2.d

target2: CFLAGS += -O0 -g3
target2: LINKER_FLAG += -g
target2: $(TARGET)
@echo "main2 called"

profile: CFLAGS += -pg
profile: $(TARGET)
@echo "profile called"
valgrind: CFLAGS += -g -O1
valgrind: LINKER_FLAG += -g
valgrind: $(TARGET)

all: CFLAGS += -O3
all: $(TARGET)
@echo "all called"
CPP_SRCS += \
../src/file1.cpp \
../src/file2.cpp \
../src/LoadParams.cpp \
../src/file3.cpp  \CPP_DEPS += \
./src/file1.d \
./src/file2.d \
./src/LoadParams.d \
./src/file3.d  \

OBJECTDIR = ./
OBJECTS=$(CPP_SRCS:%.cpp=$(OBJECTDIR)%.o)# Tool invocations
$(TARGET): $(OBJECTS)
@echo 'Building target: $@'
@echo 'Invoking: GCC C++ Linker'
$(LD) $(LIBS) $(LINKER_FLAG) -o "$@" $(OBJECTS)
$(RM) $(OBJECTS)
$(RM) $(CPP_DEPS)
@echo 'Finished building target: $@'
@echo ' '

clean:
@echo "clean called"$(RM) $(TARGET)
$(RM) $(OBJECTS)
$(RM) $(CPP_DEPS)

#echo "$@ and $^"
$(OBJECTDIR)/%.o: %.cpp
@echo 'Building file: $<'
@echo 'Invoking: GCC C++ Compiler'
$(CXX) $(CFLAGS) $(INCLUDE) -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"@echo 'Finished building: $<'
@echo ' '

Теперь проблема в том, что если я вызываю make target1, компилятор компилирует только 4 файла, не включая файл main1.cpp, в то время как во время компоновки команда включает 5 файлов .o и, конечно, файл main1.o отсутствует.
Это означает, что $ (OBJECTS) генерируется правильно, но после переменной CPP_SRC не содержится файл main1.cpp.
Может кто-нибудь объяснить это странное поведение и дать мне несколько советов о том, как правильно решить проблемы (или предложить лучший способ выполнить ту же задачу)?
заранее спасибо

0

Решение

Беда здесь:

target1: CPP_SRCS += src/main1.cpp

Это присвоение целевой переменной, так что доступно в тело правила (и правил предварительных условий), но не в список предварительных условий правила (или предпосылок). Итак, это:

OBJECTS=$(CPP_SRCS:%.cpp=$(OBJECTDIR)%.o)

$(TARGET): $(OBJECTS)
...

не будет ставить main1.o в списке предварительных условий. Если это не ясно, попробуйте это:

$(TARGET): $(OBJECTS)
@echo the variable OBJECTS contains $(OBJECTS)
@echo but the prerequisite list is $^

Есть несколько способов подойти к решению, но имейте в виду, что с target1 а также target2 оба строят libdemo.so, не будет идеального решения.

Один из способов — дать библиотекам разные имена:

libdemo1.so: main1.o

libdemo2.so: main2.o

libdemo1.so libdemo2.so: $(OBJECTS)
@echo Building target: $@ from objects: $^
$(LD) $(LIBS) $(LINKER_FLAG) -o $@ $^

Другое — использовать рекурсию:

target1: main1.o
@$(MAKE) $(TARGET) CFLAGS=$(CFLAGS) LINKER_FLAG=$(LINKER_FLAG)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]