简体   繁体   English

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

[英]autotools: compiling with code from another directory

I have the following structure: 我有以下结构:

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

where each moduleX is actually made of many C and header files, and therefore deserve their own subdirectory. 其中每个moduleX实际上由许多C和头文件组成,因此值得拥有自己的子目录。

I want to compile each moduleX with the common.c code. 我想用common.c代码编译每个moduleX。 I mean compile, not just link with a library because each module actually defines some macro that influence the compilation of common.c. 我的意思是编译,而不仅仅是链接库,因为每个模块实际上定义了一些影响common.c编译的宏。 In other words the Makefile of each module looks like: 换句话说,每个模块的Makefile如下所示:

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

The reason why I am writting ../common/common.c and not $(top_srcdir)/common/common.c is this bug , (also shown here ). 为什么我书面方式的原因../common/common.c而不是$(top_srcdir)/common/common.c这个bug ,(也显示在这里 )。

The top Makefile.am declares, of course, each module as subdir: 当然,顶级的Makefile.am声明每个模块都是子目录:

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

On the real project ./configure && ./make distcheck fails with a "XXX.Po file not found" when building for distcheck. ./configure && ./make distcheck ,实际项目./configure && ./make distcheck失败并显示“找不到XXX.Po文件”。

I have tried to reproduce the problem in a much simpler scale ( download this tar file ), and there, it fails on "common.h" not being found. 我试图以更简单的规模重现问题( 下载此tar文件 ),并且在“common.h”上找不到它。

I guess that in both cases, the problem is that I haven't succeeded to tell automake that the common part should be a part of each module (and therefore copied as well when building out of tree (VPATH)) 我想在两种情况下,问题是我没有成功告诉automake公共部分应该是每个模块的一部分(因此在构建树外时也会复制(VPATH))

What is the proper way to achieve this? 实现这个目标的正确方法是什么?

You are welcome to point out the modification needed to the tared example which you can untar with tar -xvf (see the README inside for build instructions) 欢迎您指出可以使用tar -xvf解压缩的示例所需的修改(请参阅内部的README以获取构建说明)

Thanks! 谢谢!

WHATS HAPPENS: 发生什么事:

To resolve "common.h" not being found issue for foobar.tar I've added EXTRA_DIST = common/common.h foo/foo.h bar/bar.h to the top Makefile.am. 要解决"common.h" not being found foobar.tar问题,我已经将EXTRA_DIST = common/common.h foo/foo.h bar/bar.h到顶部的Makefile.am中。 After that, the command ./bootstrap && ./configure && make dist will include *.h files into foobar-0.1.tar.gz. 之后,命令./bootstrap && ./configure && make dist*.h文件包含到foobar-0.1.tar.gz中。

Next, ./bootstrap && ./configure && make distcheck fails with Makefile:204: ../common/.deps/foo-common.Po: No such file or directory . 接下来,./ ./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

Here is log: 这是日志:

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

You can see, ../common/.deps is removed as part of make distclean for bar. 你可以看到, ../common/.deps被删除作为make distclean for bar的一部分。 That results in make distclean for foo failed. 这导致了foo失败的make distclean

In order to avoid such automake behavior we have to place ../common/.deps/foo-common.Po and ../common/.deps/bar-common.Po inside foo/.deps and bar/.deps directories. 为了避免这种自动行为,我们必须在foo/.depsbar/.deps目录中放置../common/.deps/foo-common.Po../common/.deps/bar-common.Po To do that we have to place sources from common inside foo and bar directories. 要做到这一点,我们必须从common foobar目录中放置源代码。 That's could be done during build time from Makefile . 这可以在Makefile构建时间内完成。

SOLUTION: Here is solution based on umläute's idea. 解决方案:这是基于umläute的想法的解决方案。 It's based on automatic source file generation during build. 它基于构建期间的自动源文件生成

topdir Makefile.am: 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

foo/Makefile.am: 富/ 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/$@\"" >$@

bar/Makefile.am 酒吧/ 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/$@\"" >$@

in each moduleX add a wrapper file: 在每个moduleX添加一个包装文件:

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

and add that file to the moduleX_SOURCES instead of ../common/common.c . 并将该文件添加到moduleX_SOURCES而不是../common/common.c

btw, the -I and -D directives should go into moduleX_CPPFLAGS (rather than moduleX_CFLAGS ) 顺便说一句, -I-D指令应该进入moduleX_CPPFLAGS (而不是moduleX_CFLAGS

I have had the same problem on several large, multiple executables projects. 我在几个大型,多个可执行文件项目中遇到了同样的问题。

I used the following on Ubuntu/Linux 我在Ubuntu / Linux上使用了以下内容

The dependancy files can be created using the appropriate parameters with GCC, however, I used sed for that part of the job. 可以使用GCC中的相应参数创建依赖文件,但是,我将sed用于该部分作业。

This has a makefile.top and makefile.bot are both in the top level directory (and no where else) 这有一个makefile.top和makefile.bot都在顶级目录中(没有其他地方)

There are common files, in the top level directory, that are used by all the sub directories. 在顶级目录中有所有子目录使用的公共文件。

For your project, you would need to edit the 'alldirectories' macro in the makefile.top to list the sub directories that will contain the source and header files for each executable. 对于您的项目,您需要编辑makefile.top中的“alldirectories”宏以列出将包含每个可执行文件的源文件和头文件的子目录。

this is executed from the top level directory, using something like: make -f makefile.top 这是从顶级目录执行的,使用类似:make -f makefile.top

file: 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 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