【问题标题】:How to add target file depending of called tag in makefile如何根据makefile中的调用标签添加目标文件
【发布时间】:2018-02-16 02:46:22
【问题描述】:

我基本上将这些 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 variables 



LINKER_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 文件之后。 有人可以解释这种奇怪的行为并给我一些关于如何正确解决问题的提示(或提出更好的方法来执行相同的任务)吗? 提前致谢

【问题讨论】:

  • 您(至少)有两个目标,target1target2,它们构建了具有不同内容的文件 libdemo.so。你确定要这样吗?
  • 是的,我很确定。该示例保持简单以显示有问题的行为,真正的示例更加清晰,编译标志也发生了变化,但这不是重点。最后的范围是如果我们想要使用代码的某些部分的不同实现,即实时/非实时行为。

标签: c++ makefile


【解决方案1】:

麻烦就在这里:

target1: CPP_SRCS += src/main1.cpp

这是一个target-specific variable assignment,因此它在规则的正文(以及先决条件的规则)中可用,但不在先决条件列表中规则(或先决条件)。所以这个:

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

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

不会将main1.o 放在先决条件列表中。如果不清楚,试试这个:

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

有几种方法可以解决问题,但请注意,由于target1target2 都构建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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多