Loading [MathJax]/jax/output/CommonHTML/config.js
社区首页 >问答首页 >使用类似的规则构建多个可执行文件

使用类似的规则构建多个可执行文件
EN

Stack Overflow用户
提问于 2011-08-19 06:55:18
回答 5查看 6.7K关注 0票数 7

我正在编写某物,就像C++的交互式教程。本教程将由两部分组成:一部分被编译成一个库(我使用Scon构建它),另一部分(课程)随教程一起随教程一起提供,由最终用户编译。我目前正在寻找一个好的,简单的方法,人们建立这些经验教训。

基本上,第二部分是一个目录,其中包含所有的经验教训,每个都在自己的目录中。每堂课都至少有一个lesson.cpp和一个main.cpp文件,可能还有其他的文件,直到它发布之后我才知道它们的存在--最终用户将创建这些文件。看起来会是这样的:

代码语言:javascript
代码运行次数:0
复制
all_lessons/
    helloworld/
        lesson.cpp
        main.cpp
    even_or_odd/
        lesson.cpp
        main.cpp
    calculator/
        lesson.cpp
        main.cpp
        user_created_add.cpp

其中每一个都需要按照几乎相同的规则进行编译,并且应该可以从一个课程目录(helloworld/等)运行编译命令。

考虑到项目的其余部分是用Scon构建的,因此将其用于此部分也是有意义的。然而,Scon在运行它的目录中搜索SConstruct文件:在每个教程目录中放置一个SConstruct文件,以及在给出一般规则的all_lessons/目录中放置一个SConscript是可以接受的吗?这似乎违背了Scon期望项目组织的典型方式:这种方法的潜在缺陷是什么?我是否可以放置一个SConstruct文件而不是SConscript文件,从而可以从任何一个目录构建(我猜,使用导出来避免无休止的递归)?

另外,我可能在某个时候想要用生成必要文件的lesson.cpp来代替lesson.py;Scon允许我用构建器轻松地完成这个任务吗?还是有一个更方便的框架?

最后,我想得到以下内容(或等效于不同的构建系统):

代码语言:javascript
代码运行次数:0
复制
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目录中运行all_lessons需要:

  • 运行even_or_odd/lesson.py生成even_or_odd/lesson.cpp
  • 意识到user_created_add.cpp也需要编译。
  • 为每堂课生成一个可执行文件。

even_or_odd/中运行even_or_odd/,或者在all_lessons/中运行scons even_or_odd,应该生成与上面相同的可执行文件(相同的编译标志)。

摘要:

  1. 斯堪的纳维亚人适合/有能力这样做吗?
  2. SConscript文件高于SConstruct文件时,Scons工作得好吗?
  3. 对于一个项目,SConscripting其他的多个SConscripting文件,Scons工作得好吗?
  4. Scon构建器系统是否适合使用Python生成C++文件?
  5. 使用不同的构建系统/编写我自己缺少的构建框架有什么好处吗?

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

谢谢。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-09-06 06:57:56

实际上,您可以使用GNU的几行代码来完成这一任务。

下面是两个makefile,允许从all_lessons目录和单独的项目目录构建和清理。它假定该目录中的所有C++源都包含一个以其目录命名的可执行文件。当从顶层源目录(all_lessons)构建和清理时,它构建和清理所有项目。当从项目目录构建和清理时,它只构建和清理项目的二进制文件。

这些makefile还会自动生成依赖项,并且完全可并行(make -j友好)。

对于下面的示例,我使用了与您相同的源文件结构:

代码语言:javascript
代码运行次数:0
复制
$ 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

为了能够从不可分割的项目目录中构建,project.mk必须首先作为project/Makefile进行符号链接。

代码语言:javascript
代码运行次数:0
复制
[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

让我们构建一个项目:

代码语言:javascript
代码运行次数:0
复制
[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

现在构建所有项目:

代码语言:javascript
代码运行次数:0
复制
[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

清洁一个项目:

代码语言:javascript
代码运行次数:0
复制
[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'

清洁所有项目:

代码语言:javascript
代码运行次数:0
复制
[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

制作人员:

代码语言:javascript
代码运行次数:0
复制
[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))
票数 13
EN

Stack Overflow用户

发布于 2012-05-17 21:35:18

作为一个学习技能的练习,我试着回答你的问题。不幸的是,我不是专家,所以我不能告诉你什么是最好的/理想的方式,但这里有一个方法是可行的。

  1. Scons 是适合/能够这样做的。(这正是构建工具的用途。)
  2. 不适用。(我不知道。)
  3. 对于一个项目,使用多个文件,Scon似乎运行得很好,即相互之间的SConstrcut文件。
  4. 可以使用脚本生成C++文件。
  5. 不同的构建系统?每个人都有自己的。

使用您定义的层次结构,每个文件夹中都有一个SConstruct文件。您可以在子文件夹中运行scons来构建该项目,也可以在顶层运行以构建所有项目(不确定如何将" all“别名为默认构建)。您可以运行scons -c来清理项目,scon会自动找出它创建和清除的文件(包括生成的lesson.cpp)。

但是,如果您希望编译器标志从顶级文件向下传播,我认为最好使用SConscript文件--但我不确定是否单独编译这些文件。

./建造

代码语言:javascript
代码运行次数:0
复制
env = Environment()
env.SConscript(dirs=['calculator', 'even_or_odd', 'helloworld'], name='SConstruct')

./计算器/SConstruct和./calculator/helloworld

代码语言:javascript
代码运行次数:0
复制
env = Environment()
env.Program('program', Glob('*.cpp'))

./偶_奇数/_

代码语言:javascript
代码运行次数:0
复制
env = Environment()

def add_compiler_builder(env):
    # filename transformation
    suffix = '.cpp'
    src_suffix = '.py'

    # define the build method
    rule = 'python $SOURCE $TARGET'

    bld = Builder(action = rule,
                  suffix = suffix,
                  src_suffix = src_suffix)
    env.Append(BUILDERS = {'Lesson' : bld})

    return env

add_compiler_builder(env)

env.Lesson('lesson.py')
env.Program('program', Glob('*.cpp'))

使用SConscripts

我将子文件夹的SConstructs转换为SConscripts,可以从子文件夹中提取代码构建细节,但是需要运行scons -u才能在子文件夹中生成(向上搜索根SConstruct)。

./建造

代码语言:javascript
代码运行次数:0
复制
def default_build(env):
    env.Program('program', Glob('*.cpp'))

env = Environment()
env.default_build = default_build

Export('env')
env.SConscript(dirs=['calculator', 'even_or_odd', 'helloworld'])

./helloworld/SConscript等.

代码语言:javascript
代码运行次数:0
复制
Import('env')
env.default_build(env)
票数 2
EN

Stack Overflow用户

发布于 2011-08-19 07:13:14

编译命令必须从“课”目录中运行吗?如果没有,我将亲自创建all_ the /makefile,其内容如下:

代码语言:javascript
代码运行次数:0
复制
lessons = helloworld even_or_odd calculator

all: $(lessons)

# for each $lesson, the target is $lesson/main built from $lesson/main.cpp and $lesson/lesson.cpp
# NB: the leading space on the second line *must* be a tab character
$(lessons:%=%/main): %/main: %/main.cpp %/lesson.cpp
   g++ -W -Wall $+ -o $@

然后,可以在all_lessons目录中使用"make“或"make all”构建所有课程,或者使用"make /main“等特定的课程。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7123431

复制
相关文章
关于 title 属性导致触发 mousedown 事件时连带触发 mousemove
  大家都知道,鼠标点击的整个事件的执行流程是:mousedown -> mouseup -> click ,而拖放的整个流程是:mousedown -> mousemove -> mouseup -> click
胡尐睿丶
2022/03/28
1.3K0
input输入中文时,拼音触发input事件
在上一篇文章中写到了函数防抖,在使用函数防抖来进行搜索框优化的时候会遇到一个问题,就是监听文本输入框的input事件,在拼写汉字(输入法)但汉字并未实际填充到文本框中时会触发input事件,会出现下图的效果
OECOM
2020/07/01
8.2K1
jQuery 双击事件(dblclick)时,不触发单击事件(click)
在jQuery的事件绑定中,执行双击事件(dblclick)时能触发两次单击事件(click)。即一个标签元素(如div等),如果元素同时绑定了单击事件(click)和双击事件(dblclick),那么执行单击事件(click)时,不会触发双击事件(dblclick), 执行双击事件(dblclick)时却会触发两次单击事件(click)。 先看一下点击事件的执行顺序:
飞奔去旅行
2019/06/13
5.3K0
Jenkins触发构建--事件触发
事件触发就是发生了某个事件就触发pipeline执行,这个事件可以是你能想到的任何事件,比如手动在界面上触发、其它job主动触发、HTTP API Webhook触发等。
陈不成i
2021/06/02
5.9K0
当提到“事件驱动”时,我们在说什么?
去年年底(2016年底),我和ThoughtWorks同事一起参加了一个研讨会,讨论“事件驱动”的本质。在过去的几年里,我们构建的很多系统都大量使用了事件。对于这些系统,人们常常赞誉有加,但批评的声音也不绝于耳。我们的北美办公室组织了一次峰会,来自世界各地的ThoughtWorks资深开发者出席会议并分享了他们的想法。
ThoughtWorks
2019/05/05
5150
当提到“事件驱动”时,我们在说什么?
双击事件(dblclick)时,不触发鼠标按下(mousedown) 动作事件
在一个dom节点的事件绑定中,如果同时绑定了dblclick和mousedown那么想要执行双击事件(dblclick)时能就会触发两次mousedown事件。
李维亮
2023/10/23
7410
双击事件(dblclick)时,不触发鼠标按下(mousedown) 动作事件
代码触发,手动触发touchstart事件,touch事件,click事件,自定义事件
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/150775.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/06
4.9K0
zabbix中配置当memory剩余不足20%时触发报警
在zabbix中默认当内存剩余量不足2G的时候触发报警,并没有使用百分比来触发如下: 现在需要配置:当memory剩余不足20%时触发报警,具体操作方法如下: 1)创建item Configurati
洗尽了浮华
2018/01/23
1.4K0
zabbix中配置当memory剩余不足20%时触发报警
onbeforeunload事件_pageload事件何时触发
注意:为了防止不需要的弹出窗口,浏览器可能不会显示在beforeunload事件处理程序中创建的提示,除非页面已与之交互,甚至根本不显示它们。
全栈程序员站长
2022/11/03
3K0
aos 事件触发失败
项目中遇到这个问题,网页往下滑动时加载 aos 事件触发不了,原因也很简单,因为 aos.js 是在页面加载时获取页面高度从而绑定一些事件进去,但是如果这个文件加载速度比框架加载的快,会导致两者高度不一致,从而动画效果触发失败。
子舒
2023/08/23
3620
js触发全屏事件
让用户端JS触发指的就是让用JS监听用户的操作事件,通过JS程序去实现F11全屏。这个事件可以是一个按钮的点击事件,当然也可以是键盘事件,比如用户按下F11。     1.F11键盘事件触发   当用户按下F11事件,浏览器为触发自身全屏功能,这个过程我们一般是不可控制的,即使是监听了F11的键盘事件,退出全屏的时候,我们也捕捉不到退出全屏触发的事件。所以,我们就用程序自己去实现F11的功能,首先需要禁用浏览器默认的事件动作。
山河木马
2019/03/05
16K0
vue 加载页面时触发时间_Vue 刷新页面时会触发事件吗「建议收藏」
使用localstorage做本地存储,然后我想在刷新页面或者离开页面的调用localstorage方法
全栈程序员站长
2022/09/27
1.6K0
Bootstrap- Modal对话框如何在关闭时触发事件
下表列出了模态框中要用到事件。这些事件可在函数中当钩子使用。 事件 描述 实例 show.bs.modal 在调用 show 方法后触发。 $('#identifier').on('show.bs.modal', function () { // 执行一些动作... }) shown.bs.modal 当模态框对用户可见时触发(将等待 CSS 过渡效果完成)。 $('#identifier').on('shown.bs.modal', function () { // 执行一些动作... }) hide
johnhuster的分享
2022/03/28
2K0
输入框在输入中文时回车误触发输入的回车事件
这个问题出现在:chatx.me的输入框 最近反应的人比较多,然后还是问了下前前端同事,解决了。
SingYi
2023/08/23
3060
js 手动触发input事件
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/138867.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/02
10.7K0
spreadTrading模块事件触发机制
本文主要介绍了价差交易模块的事件触发机制。感谢‘次第花开’和‘用户名呀’在维恩的派论坛里的分享!
用Python的交易员
2018/07/26
2.5K0
spreadTrading模块事件触发机制
探索 Flutter 模拟事件触发
如果可以模拟 PointerEvent 进行分发,那么在应用中就可以通过 代码 来触发手势事件,这样就能解放双手。如果结合语音监听,通过代码处理,说话也能触发手势操作,岂不美哉。 作为探索完 手势机制 和 滑动机制 ,又有完成这两本小册的我,感觉这个问题应该可解。下面就将整个问题的解决过程进行梳理,带大家再认识一下手势底层的相关实现。
张风捷特烈
2022/03/18
2.8K0
探索 Flutter 模拟事件触发
WdatePicker改变事件触发优化
如上,使用onpicked来绑定blur事件,就会在选择日期后自动触发onchangge事件
用户9131103
2023/07/17
3120
js后退按钮事件触发
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/164172.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/15
10.6K0
checkbox选中触发事件_jquery select change事件
<asp:DataGrid id=”DataGrid1″ runat=”server” AutoGenerateColumns=”False”> <Columns> <asp:BoundColumn DataField=”txtId”></asp:BoundColumn> <asp:BoundColumn DataField=”txtName”></asp:BoundColumn> <asp:TemplateColumn> <ItemTemplate> <asp:ImageButton id=”btnItem” runat=”server” CommandName=”LookDetail”></asp:ImageButton> <asp:DropDownList id=”ddl” runat=”server” AutoPostBack=”True”> <asp:ListItem Value=”asdf”>asdf</asp:ListItem> <asp:ListItem Value=”asdfasdf”>asdfasdf</asp:ListItem> <asp:ListItem Value=”wrwwewewee”>wrwwewewee</asp:ListItem> </asp:DropDownList> </ItemTemplate> </asp:TemplateColumn> </Columns> </asp:DataGrid>
全栈程序员站长
2022/10/01
4.2K0

相似问题

当队列几乎满时触发事件

11

当mediaPlayer停止时触发事件

20

当繁忙时,jqm停止点击事件队列。

33

当vimeo视频停止播放时触发事件?

32

Dropzone.js事件不触发

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档