建设有类似的规则多个可执行文件 [英] Building multiple executables with similar rules

查看:179
本文介绍了建设有类似的规则多个可执行文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写东西像℃的互动教程++。本教程将包括两部分:一是被编译成库(我使用的是使用SCons来构建),其他(教训)是随教程由最终用户进行编译。目前我正在寻找的人来构建这些经验教训的好,简单的方法。

I am writing something like an interactive tutorial for C++. The tutorial will consist of two parts: one is compiled into a library (I'm using Scons to build that), and the other (the lessons) is shipped with the tutorial to be compiled by the end user. I'm currently looking for a good, easy way for people to build these lessons.

基本上,第二部分是在这一切的教训,在其各自的目录的目录。每节课至少有一个 lesson.cpp 的main.cpp 文件,有可能还有其他文件,其中,我不知道,直到它出厂后的存在 - 最终用户将创建这些。它看起来是这样的:

Basically, the second part is a directory with all the lessons in it, each in its own directory. Each lesson will have at least a lesson.cpp and a main.cpp file, there may be also other files, the existence of which I will not know until after it is shipped -- the end user will create these. It will look something like this:

all_lessons/
    helloworld/
        lesson.cpp
        main.cpp
    even_or_odd/
        lesson.cpp
        main.cpp
    calculator/
        lesson.cpp
        main.cpp
        user_created_add.cpp

每个这些都将需要编译按照几乎相同的规则,用于编译命令应该可以从课程目录中(的HelloWorld / 运行等)。

Each of these will need to be compiled according to almost the same rules, and the command for compiling should be possible to run from one of the lesson directories (helloworld/, etc.).

看到作为该项目的其余部分与使用SCons建成,这将是有意义的使用它的这部分了。然而,使用SCons搜索该目录中的 SConstruct 文件是从运行:它是可以接受把一个 SConstruct 文件中的每一节课目录,加上 SConscript 中,让一般规则的 all_lessons / 目录?这似乎违背的典型方式使用SCons预计将举办项目:什么是这种做法的潜在隐患?我可以把SConstruct文件,而不是SConscript之一,从而使人们有可能从任一目录下建(用出口来避免无限递归,我猜)?

Seeing as the rest of the project is built with Scons, it would make sense to use it for this part, too. However, Scons searches for the SConstruct file in the directory it is run from: would it be acceptable to put a SConstruct file in each lesson directory, plus a SConscript in the all_lessons/ directory that gives the general rules? This seems to go against the typical way Scons expects projects to be organised: what are the potential pitfalls of this approach? Could I put a SConstruct file instead of the SConscript one, and thereby make it possible to build from either directory (using exports to avoid endless recursion, I'm guessing)?

另外,我可能会在某些时候要替换 lesson.cpp lesson.py 产生必要的文件;将使用SCons让我与建设者做到这一点很容易,还是有一个框架,那就更方便了?

Also, I may at some point want to replace the lesson.cpp with a lesson.py that generates the necessary files; will Scons allow me to do this easily with builders, or is there a framework that would be more convenient?

在最后,我想用下面的(或相当不同的构建系统)来结束:

In the end, I want to end up with the following (or equivalent with different build systems):

all_lessons/
    SConstruct
    helloworld/
        SConstruct
        lesson.cpp
        main.cpp
    even_or_odd/
        SConstruct
        lesson.py
        main.cpp
    calculator/
        SConstruct
        lesson.cpp
        main.cpp
        user_created_add.cpp

运行 scons的所有 all_lessons 目录将需要:


  • 运行 even_or_odd / lesson.py 生成 even_or_odd / lesson.cpp

  • 要意识到了 user_created_add.cpp 也需要进行编译。

  • 为每个课的可执行文件。

  • Run even_or_odd/lesson.py to generate even_or_odd/lesson.cpp.
  • Realise that user_created_add.cpp also needs to be compiled.
  • Produce an executable for each lesson.

运行 scons的 even_or_odd / scons的even_or_odd all_lessons / 应该产生与上面一个一个可执行文件(相同的编译标志)。

Running scons in even_or_odd/, or scons even_or_odd in all_lessons/ should produce an executable identical to the one above (same compile flags).

摘要:


  1. 是使用SCons适合/能够这样?

  2. 是否使用SCons正常工作时 SConscript 文件是上面 SConstruct 文件?

  3. 是否使用SCons与多个合作以及 SConstrcut 文件一个项目,SConscripting对方?

  4. 是使用SCons助洗剂体系适用于使用Python脚本生成的C ++文件?

  5. 有没有使用不同的构建系统/写,我很想念我自己的构建框架的任何优势?

  1. Is Scons suitable for/capable of this?
  2. Does Scons work well when SConscript files are above SConstruct files?
  3. Does Scons work well with multiple SConstrcut files for one project, SConscripting each other?
  4. Is the Scons builder system suitable for using Python scripts to generate C++ files?
  5. Is there any advantage of using a different build system/writing my own build framework that I'm missing?

任何进一步的评论是,当然是欢迎的。

Any further comments are, of course, welcome.

感谢。

推荐答案

您可以用实际的GNU几行做做到这一点。

You can actually do this with a few lines of GNU Make.

下面是两个makefile文件,允许从 all_lessons 目录和各项目目录建筑和清洁。它假定所有的C ++在该目录来源包括它获取其目录命名的可执行文件。在构建和顶级源目录清洗( all_lessons ),它建立并清除所有项目。在构建并从项目的目录清洗它只生成和清除项目的二进制文件。

Below are two makefiles that allow building and cleaning from all_lessons directory and individual project directories. It assumes that all C++ sources in that directory comprise an executable file which gets named after its directory. When building and cleaning from the top level source directory (all_lessons) it builds and cleans all the projects. When building and cleaning from a project's directory it only builds and cleans the project's binaries.

这些makefile还自动生成的依赖,并完全并行(使-j 友好)。

These makefiles also automatically generate dependencies and are fully parallelizable (make -j friendly).

有关在下面的例子中我用同样的源文件结构有:

For the following example I used the same source file structure as you have:

$ find all_lessons
all_lessons
all_lessons/even_or_odd
all_lessons/even_or_odd/main.cpp
all_lessons/Makefile
all_lessons/helloworld
all_lessons/helloworld/lesson.cpp
all_lessons/helloworld/main.cpp
all_lessons/project.mk
all_lessons/calculator
all_lessons/calculator/lesson.cpp
all_lessons/calculator/user_created_add.cpp
all_lessons/calculator/main.cpp

要能够从individial项目目录建立 project.mk 必须作为符号链接项目/ Makefile文件第一

To be able to build from individial project directories project.mk must be symlinked as project/Makefile first

[all_lessons]$ cd all_lessons/calculator/
[calculator]$ ln -s ../project.mk Makefile
[helloworld]$ cd ../helloworld/
[helloworld]$ ln -s ../project.mk Makefile
[even_or_odd]$ cd ../even_or_odd/
[even_or_odd]$ ln -s ../project.mk Makefile

让我们建立一个项目:

[even_or_odd]$ make
make -C .. project_dirs=even_or_odd all
make[1]: Entering directory `/home/max/src/all_lessons'
g++ -c -o even_or_odd/main.o -Wall -Wextra   -MD -MP -MF even_or_odd/main.d even_or_odd/main.cpp
g++ -o even_or_odd/even_or_odd even_or_odd/main.o  
make[1]: Leaving directory `/home/max/src/all_lessons'
[even_or_odd]$ ./even_or_odd
hello, even_or_odd

现在建的所有项目:

[even_or_odd]$ cd ..
[all_lessons]$ make
g++ -c -o calculator/lesson.o -Wall -Wextra   -MD -MP -MF calculator/lesson.d calculator/lesson.cpp
g++ -c -o calculator/user_created_add.o -Wall -Wextra   -MD -MP -MF calculator/user_created_add.d calculator/user_created_add.cpp
g++ -c -o calculator/main.o -Wall -Wextra   -MD -MP -MF calculator/main.d calculator/main.cpp
g++ -o calculator/calculator calculator/lesson.o calculator/user_created_add.o calculator/main.o  
g++ -c -o helloworld/lesson.o -Wall -Wextra   -MD -MP -MF helloworld/lesson.d helloworld/lesson.cpp
g++ -c -o helloworld/main.o -Wall -Wextra   -MD -MP -MF helloworld/main.d helloworld/main.cpp
g++ -o helloworld/helloworld helloworld/lesson.o helloworld/main.o  
[all_lessons]$ calculator/calculator 
hello, calculator
[all_lessons]$ helloworld/helloworld
hello, world

清洁一个项目:

[all_lessons]$ cd helloworld/
[helloworld]$ make clean
make -C .. project_dirs=helloworld clean
make[1]: Entering directory `/home/max/src/all_lessons'
rm -f helloworld/lesson.o helloworld/main.o helloworld/main.d helloworld/lesson.d helloworld/helloworld
make[1]: Leaving directory `/home/max/src/all_lessons'

清除所有项目:

[helloworld]$ cd ..
[all_lessons]$ make clean
rm -f calculator/lesson.o calculator/user_created_add.o calculator/main.o even_or_odd/main.o helloworld/lesson.o helloworld/main.o calculator/user_created_add.d calculator/main.d calculator/lesson.d even_or_odd/main.d  calculator/calculator even_or_odd/even_or_odd helloworld/helloworld

Makefile的:

The makefiles:

[all_lessons]$ cat project.mk 
all :
% : forward_ # build any target by forwarding to the main makefile
    $(MAKE) -C .. project_dirs=$(notdir ${CURDIR}) $@
.PHONY : forward_

[all_lessons]$ cat Makefile 
# one directory per project, one executable per directory
project_dirs := $(shell find * -maxdepth 0 -type d )

# executables are named after its directory and go into the same directory
exes := $(foreach dir,${project_dirs},${dir}/${dir})

all : ${exes}

#  the rules

.SECONDEXPANSION:

objects = $(patsubst %.cpp,%.o,$(wildcard $(dir ${1})*.cpp))

# link
${exes} : % : $$(call objects,$$*) Makefile
    g++ -o $@ $(filter-out Makefile,$^) ${LDFLAGS} ${LDLIBS}

# compile .o and generate dependencies
%.o : %.cpp Makefile
    g++ -c -o $@ -Wall -Wextra ${CPPFLAGS} ${CXXFLAGS} -MD -MP -MF ${@:.o=.d} $<

.PHONY: clean

clean :
    rm -f $(foreach exe,${exes},$(call objects,${exe})) $(foreach dir,${project_dirs},$(wildcard ${dir}/*.d)) ${exes}

# include auto-generated dependency files
-include $(foreach dir,${project_dirs},$(wildcard ${dir}/*.d))

这篇关于建设有类似的规则多个可执行文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆