Gnu Makefile - Handling dependencies

2020-06-03 03:15发布

What approach do C++ programmers on Unix platform use to create and manage Makefiles?

I was using hand made Makefiles for my projects but they don't handle header file changes and other dependencies. I googled around and found a good solution here.

But I ran into a problem here in the sed command -

    sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
        -e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \

The problem is with the 3rd expression "-e 's/ *\$$//'. It doesn't work. Its supposed to remove trailing backslashes. I understand that there has to be double dollar there since this is part of a Makefile. Can someone tell me what wrong here?

Here's the complete Makefile -

CC=g++
CFLAGS=-g -Wall
LIBS=-lpthread

OBJS=file1.o file2.o
TARGET=testProg

$(TARGET) : $(OBJS)
        $(CC) -o $@ $^ $(CFLAGS) $(LIBS)

%.o : %.cpp
        $(CC) -MMD -c -o $@ $< $(CFLAGS)
        @cp $*.d $*.P; \
            sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
                -e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
            rm -f $*.d

-include $(OBJS:%.o=%.P)

clean :
        rm -f $(TARGET) $(OBJS)

all : $(TARGET)

Apart from the solution to this problem, I would also like some tips/pointers to my 1st question.

12条回答
虎瘦雄心在
2楼-- · 2020-06-03 03:55

I must be missing something. Why doesn't generating dependency files work for you?

查看更多
够拽才男人
3楼-- · 2020-06-03 04:02

Instead of the sed scripts, use gcc's -MT option to modify the target of the generated dependency rules. This blog post has more info.

查看更多
别忘想泡老子
4楼-- · 2020-06-03 04:03

I prefer to use CMake, even though it's not strictly the solution to your problem.

It's a project description language that'll generate your Makefiles, Visual Studio Project, Eclipse Project, KDevelop, etc for you. All the dependencies are done for you:

CMakeLists.txt

add_executable(my_exe file1.c file2.c)
target_link_libraries(my_exe my_library)
add_subdirectory(lib)

In lib/CMakeLists.txt

add_library(my_library file3.c file4.c)

This creates a my_exe from file1.c file2.c linked against my_library. I find this much simpler. It also has things like package discovery:

find_package(Qt4)
查看更多
Viruses.
5楼-- · 2020-06-03 04:03

With a more modern version of GCC, you can add the -MP flag to have GCC generate empty rules for the headers itself.

查看更多
干净又极端
6楼-- · 2020-06-03 04:04

In a make file anything you list on the dependency line is a dependency header files or other files included.

BSD tutorial on make Note: you can auto generate header dependency info with the -MM switch of GCC.

查看更多
一夜七次
7楼-- · 2020-06-03 04:09
  1. I use that approach too and can't praise it highly enough. And I write my makefiles by hand and reuse them a lot on new projects.
  2. .The expression "s/ *\\$//" will work outside the context of Make. Within a makefile it doesn't work because Make tries to interpret "$/" before handing the result to the shell. So you must use "s/ *\\$$//" (note the extra $) within the makefile, but this won't work outside the context of Make (so testing it is a slight pain).



EDIT:

I've tried your makefile, and that sed statement seems to remove trailing backslashes just fine. Try something simpler, like this:

backslash:
    @echo " \\" > $@

test: backslash
    @echo without sed:
    @cat backslash
    @echo with sed:
    @sed -e 's/ *\\$$//' < backslash



EDIT: All right, now I'm hooked. Could you try these experiments and tell us the results?

Change the last character to 'z'      :  s/.$/z/
Change a trailing backslash to 'z'    :  s/\\$/z/
Change a trailing backslash to 'z'    :  sm\\$mzm
Delete a trailing backslash           :  s/\\$//
Delete spaces and a trailing backslash:  s/ *\\$//
Try all of these inside and outside of Make, with '$' and '$$'.
查看更多
登录 后发表回答