繁体   English   中英

autotools:使用其他目录中的代码进行编译

[英]autotools: compiling with code from another directory

我有以下结构:

+Makefile.am
+-common
| +-common.c
| +-common.h
|
+-module1
| +module1.c
| +Makefile.am
|
+-module2
| +module2.c
| +Makefile.am

其中每个moduleX实际上由许多C和头文件组成,因此值得拥有自己的子目录。

我想用common.c代码编译每个moduleX。 我的意思是编译,而不仅仅是链接库,因为每个模块实际上定义了一些影响common.c编译的宏。 换句话说,每个模块的Makefile如下所示:

check_PROGRAMS = moduleX
moduleX_CFLAGS = -I$(top_srcdir)/common -DCOMMON_OPTION_X
moduleX_SOURCES = moduleX.c ../common/common.c

为什么我书面方式的原因../common/common.c而不是$(top_srcdir)/common/common.c这个bug ,(也显示在这里 )。

当然,顶级的Makefile.am声明每个模块都是子目录:

SUBDIRS = foo bar
TESTS = foo/foo bar/bar

./configure && ./make distcheck ,实际项目./configure && ./make distcheck失败并显示“找不到XXX.Po文件”。

我试图以更简单的规模重现问题( 下载此tar文件 ),并且在“common.h”上找不到它。

我想在两种情况下,问题是我没有成功告诉automake公共部分应该是每个模块的一部分(因此在构建树外时也会复制(VPATH))

实现这个目标的正确方法是什么?

欢迎您指出可以使用tar -xvf解压缩的示例所需的修改(请参阅内部的README以获取构建说明)

谢谢!

发生什么事:

要解决"common.h" not being found foobar.tar问题,我已经将EXTRA_DIST = common/common.h foo/foo.h bar/bar.h到顶部的Makefile.am中。 之后,命令./bootstrap && ./configure && make dist*.h文件包含到foobar-0.1.tar.gz中。

接下来,./ ./bootstrap && ./configure && make distcheck使用Makefile:204: ../common/.deps/foo-common.Po: No such file or directory失败Makefile:204: ../common/.deps/foo-common.Po: No such file or directory

这是日志:

Making distclean in bar
make[2]: Entering directory `/home/user/foobar-0.1/_build/bar'
...
rm -rf ../common/.deps ./.deps
...
make[2]: Leaving directory `/home/user/foobar-0.1/_build/bar'
Making distclean in foo
make[2]: Entering directory `/home/user/foobar-0.1/_build/foo'
Makefile:204: ../common/.deps/foo-common.Po: No such file or directory
make[2]: *** No rule to make target `../common/.deps/foo-common.Po'.  Stop.
make[2]: Leaving directory `/home/user/foobar-0.1/_build/foo'
make[1]: *** [distclean-recursive] Error 1
make[1]: Leaving directory `/home/user/foobar-0.1/_build'
make: *** [distcheck] Error 1

你可以看到, ../common/.deps被删除作为make distclean for bar的一部分。 这导致了foo失败的make distclean

为了避免这种自动行为,我们必须在foo/.depsbar/.deps目录中放置../common/.deps/foo-common.Po../common/.deps/bar-common.Po 要做到这一点,我们必须从common foobar目录中放置源代码。 这可以在Makefile构建时间内完成。

解决方案:这是基于umläute的想法的解决方案。 它基于构建期间的自动源文件生成

topdir Makefile.am:

SUBDIRS = foo bar
TESTS = foo/foo bar/bar
EXTRA_DIST = common/common.h common/common.c foo/foo.h bar/bar.h

富/ Makefile.am:

check_PROGRAMS = foo
foo_CFLAGS = -I$(top_srcdir)/common
foo_SOURCES = foo.c
nodist_foo_SOURCES = $(foo_common_SOURCES)

foo_common_SOURCES = common.c
CLEANFILES = $(foo_common_SOURCES)

$(foo_common_SOURCES):
    echo "#include \"$(top_builddir)/common/$@\"" >$@

酒吧/ Makefile.am

check_PROGRAMS = bar
bar_CFLAGS = -I$(top_srcdir)/common -DOPTION
bar_SOURCES = bar.c
nodist_bar_SOURCES = $(bar_common_SOURCES)

bar_common_SOURCES = common.c
CLEANFILES = $(bar_common_SOURCES)

$(bar_common_SOURCES):
    echo "#include \"$(top_builddir)/common/$@\"" >$@

在每个moduleX添加一个包装文件:

$ cat <<EOF >inc_common.c
#include "common.c"
EOF

并将该文件添加到moduleX_SOURCES而不是../common/common.c

顺便说一句, -I-D指令应该进入moduleX_CPPFLAGS (而不是moduleX_CFLAGS

我在几个大型,多个可执行文件项目中遇到了同样的问题。

我在Ubuntu / Linux上使用了以下内容

可以使用GCC中的相应参数创建依赖文件,但是,我将sed用于该部分作业。

这有一个makefile.top和makefile.bot都在顶级目录中(没有其他地方)

在顶级目录中有所有子目录使用的公共文件。

对于您的项目,您需要编辑makefile.top中的“alldirectories”宏以列出将包含每个可执行文件的源文件和头文件的子目录。

这是从顶级目录执行的,使用类似:make -f makefile.top

file:makefile.top

    SHELL = /bin/sh





    SRC := $(wildcard *.c)
    OBJ := $(SRC:.c=.o)
    DEP := $(SRC:.c=.d)
    INC := $(SRC:.c=.h)


    MAKE    :=  /usr/bin/make

    CC      :=  /usr/bin/gcc

    CP      :=  cp

    MV      :=  mv

    LDFLAGS :=  -L/usr/local/lib -L/usr/lib -L/lib

    DEBUG   :=  -ggdb3

    CCFLAGS :=  $(DEBUG) -Wall -W

    #CPPFLAGS += =MD

    LIBS    :=  -lssl -ldl -lrt -lz -lc -lm



    .PHONY: AllDirectories
    # the following statement needs to be edited as 
    # subdirectories are added/deleted/re-named
    #AllDirectories := \
    #    Command_Configuration \
    #    Communication \
    #    Main_Scheduler \
    #    Retrieve_CDS_Log \
    #    Retrieve_EventRecorder_Log \
    #    Retrieve_GPS \
    #    Retrieve_QES_Alarm_Log \
    #    Retrieve_QES_RealTime \
    #    Write_CDS_Log

    AllDirectories :=  \
        Main_Scheduler \
        Communication  \
        Retrieve_GPS   \
        Test_Communication_Dev 



    .PHONY: all
    #all: $(OBJ) $(AllDirectories)
    #   $(foreach d,$(AllDirectories), \
    #    ( cd $d && $(MAKE) -f makefile.top name=Tsk_$d all ); )

    all: $(OBJ) $(AllDirectories)
        $(foreach d,$(AllDirectories), \
        ( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )



    #
    # create dependancy files
    #
    %.d: %.c
        # 
        # ========= START $< TO $@ =========
        $(CC) -M $(CPPFLAGS) $< > $@.$$$$;                      \
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;     \
        rm -f $@.$$$$
        # ========= END $< TO $@ =========



    #
    # compile the .c file into .o files using the compiler flags
    #
    %.o: %.c %.d 
        # 
        # ========= START $< TO $@ =========
        $(CC) $(CCFLAGS) -c $< -o $@ -I. 
        # ========= END $< TO $@ =========
        # 



    .PHONY: clean
    #clean: $(AllDirectories)
    #   # ========== start clean activities ==========
    #   rm -f *.o
    #   rm -f $(name).map
    #   rm -f $(name)
    #   rm -f *.d
    #   $(foreach d,$(AllDirectories), \
    #    ( cd $d && $(MAKE) -f makefile.top clean ); )
    #   # ========== end clean activities ==========

    clean: $(AllDirectories)
        # ========== start clean activities ==========
        rm -f *.o
        rm -f $(name).map
        rm -f $(name)
        rm -f *.d
        rm -f ../bin/Tsk_*
        $(foreach d,$(AllDirectories), \
        ( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
        # ========== end clean activities ==========



    .PHONY: install
    #install: $(AllDirectories)
    #   # ========== start install activities ==========
    #   $(foreach d,$(AllDirectories), \
    #    ( cd $d && $(MAKE) -f makefile.mak clean ); )
    #   # ========== end install activities ==========

    install: $(AllDirectories)
        # ========== start install activities ==========
        $(foreach d,$(AllDirectories), \
        ( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
        # ========== end install activities ==========



    # include the contents of all the .d files
    # note: the .d files contain:
    # <filename>.o:<filename>.c plus all the dependancies for that file 
    # I.E. the #include'd header files
    # wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
    #
    ifneq "$(MAKECMDGOALS)" "clean"
    -include $(DEP)
    endif

file:makefile.bot

     SHELL = /bin/sh


    BINDIR  :=  /home/user/bin


    .PHONY: all
    all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot


    #
    # macro of all *.c files 
    # (NOTE:
    # (the following 'wildcard' will pick up ALL .c files
    # (like FileHeader.c and FunctionHeader.c 
    # (which should not be part of the build
    # (so be sure no unwanted .c files in directory
    # (or change the extension
    #
    SRC := $(wildcard *.c)
    OBJ := $(SRC:.c=.o)
    DEP := $(SRC:.c=.d)
    INC := $(SRC:.c=.h)


    COMMON_OBJ := $(wildcard ../*.o)
    #COMMON_SRC := $(wildcard ../*.c)
    #COMMON_OBJ := $(COMMON_SRC:.c=.o)
    #COMMON_DEP := $(COMMON_SRC:.c=.d)
    #COMMON_INC := $(COMMON_SRC:.c=.h)

    MAKE    :=  /usr/bin/make

    CC      :=  /usr/bin/gcc

    CP      :=  cp

    MV      := mv

    LDFLAGS :=  -L/usr/local/lib

    DEBUG   :=  -ggdb3

    CCFLAGS :=  $(DEBUG) -Wall -W

    #CPPFLAGS += =MD

    #LIBS    :=  -lidn -lssl -ldl -lrt -lz -lc -lm
    LIBS    :=   -lssl -ldl -lrt -lz -lc -lm



    #
    # link the .o files into the executable 
    # using the linker flags
    # -- explicit rule
    #
    $(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
        #
        # ======= $(name) Link Start =========
        $(CC) $(LDFLAGS) -o $@ $(OBJ) $(COMMON_OBJ) $(LIBS)
        # ======= $(name) Link Done ==========
        #



    # note:
    # using MV rather than CP results in all executables being re-made everytime
    $(BINDIR)/$(name): $(name)
        #
        # ======= $(name) Copy Start =========
        sudo $(CP) $(name) $(BINDIR)/.
        # ======= $(name) Copy Done ==========
        #



    #
    #create dependancy files -- inference rule
    # list makefile.mak as dependancy so changing makfile forces rebuild
    #
    %.d: %.c 
        # 
        # ========= START $< TO $@ =========
        $(CC) -M $(CPPFLAGS) $< > $@.$$$$;                      \
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;     \
        rm -f $@.$$$$
        # ========= END $< TO $@ =========



    # 
    # compile the .c file into .o files using the compiler flags
    # -- inference rule
    #
    %.o: %.c %.d 
        # 
        # ========= START $< TO $@ =========
        $(CC) $(CCFLAGS) -c $< -o $@ -I. 
        # ========= END $< TO $@ =========
        # 



    .PHONY: clean
    clean: 
        # ========== CLEANING UP ==========
        rm -f *.o
        rm -f $(name).map
        rm -f $(name)
        rm -f *.d
        # ========== DONE ==========



    .PHONY: install
    install: all

    # include the contents of all the .d files
    # note: the .d files contain:
    # <filename>.o:<filename>.c plus all the dependancies for that .c file 
    # I.E. the #include'd header files
    # wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
    #
    ifneq "$(MAKECMDGOALS)" "clean"
    -include $(DEP)
    endif

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM