如何在外部服务器上安装和使用嵌入式 C 的编译器?
Posted
技术标签:
【中文标题】如何在外部服务器上安装和使用嵌入式 C 的编译器?【英文标题】:How can I install and use compilers for embedded C on an external server? 【发布时间】:2011-07-10 06:14:50 【问题描述】:小问题 是否有一种可接受的方式在远程服务器上为嵌入式软件项目运行编译器/链接器,并且仍然能够在本地机器上对软件进行编程和调试。
注意我知道每个 IDE 都会有所不同,所以我所追求的是如何定义一个工作流程来完成这项任务,假设 IDE 可以使用 .o/.elf 文件运行从远程服务器构建。
关注领域 1) 与虚拟 Windows 机器联网。 2) 如何/何时将源代码传输到服务器进行构建。
背景 我们的软件团队使用的每个微处理器系列都需要它自己的编译器、IDE 和编程器。这,加班,创造了许多需要克服的困难。
1) 每个开发者都需要拥有自己的、通常价格不菲的许可证。 2) 选择另一个开发人员启动的项目需要格外小心,以确保所有编译器设置都相同。 3) 支持旧版软件可能需要与当前安装的编译器冲突的旧编译器。 ......名单还在继续。
编辑:2011 年 7 月 10 日下午 1:30 CST 1)我说的编译器确实是交叉编译器 2) 该系统理想支持的处理器系列的简短列表:摩托罗拉 Coldfire、PIC 和 STM8。 3) 我们的 Coldfire 编译器是 GCC 的一个变种,但我们必须支持它的多个版本。所有其他编译器都使用不提供浮动许可证的特定于目标的编译器。 4) 为了解决 littleadv,我想要完成的是外部构建服务器。 5) 我们目前使用托管在在线存储库上的 SVN 和 GIT 的组合来进行版本控制。事实上,我认为这就是我将文件传输到构建服务器的方式。 6) 对于大多数编译器,我们都坚持使用 Windows。
我现在相信前进的方向是外部构建服务器。还有一些障碍需要克服。我假设我们必须通过版本控制软件将源文件传输到服务器。看到多个产品线如何需要访问相同的编译器,每个项目都有一个实例似乎不切实际。
为每个编译器创建一个存储库是否有意义,其中包括用于构建、源代码、包含、输出等的文件夹...然后在用户端有脚本来处理从 IDE 的文件结构中移动文件到编译器所需的结构?这种方法可以防止项目存储库被破坏,并给出一个编译器被使用了多少次。感谢您迄今为止的所有好评!
【问题讨论】:
【参考方案1】:在我看来,实现自动构建服务器将是您想要实现的最简洁的解决方案。还有一个额外的好处……持续集成! (稍后我会谈到 CI)。
有很多工具可供使用。 @Clifford 已经提到过 CMake。但其他一些是:
Hudson(开源) CruiseControl(开源) TeamCity(商业 - 但它有一个相当慷慨的免费版本,最多允许 3 个构建代理和 20 个构建配置。TeamCity 的企业版是我公司使用的,所以我的答案将针对这个,因为这是我所知道的,但是概念可能适用于多种工具)首先,我将尝试解释我们所做的工作,并建议这对您有何帮助。我不建议这是 公认的做事方式,但它对我们有用。正如我提到的,我们使用 TeamCity 作为构建服务器。每个软件项目都添加到 TeamCity 中,并设置了构建配置。构建配置告诉 TeamCity 何时构建、如何构建以及项目的 SCM 存储库在哪里。我们为每个项目使用两种不同的构建配置,我们称之为“集成”,它监控项目的 SCM 存储库并在检测到签入时触发增量构建。我们称之为“nightly”的另一种配置每晚在设定的时间触发并执行完全干净的构建。
顺便提一下关于 SCM 的简短说明。为了让这个工作最干净,我认为每个项目的 SCM 都应该在稳定的主干拓扑中使用。如果您的开发人员都在他们自己的分支中工作,您可能需要为每个开发人员单独构建配置,我认为这会变得不必要的混乱。我们已经使用自己的 SCM 用户帐户设置了构建服务器,但具有只读访问权限。
因此,当针对特定构建配置触发构建时,服务器会从存储库中获取最新文件并将它们发送到“构建代理”,后者使用构建脚本执行构建。我们使用Rake 为我们的构建和自动化测试编写脚本,但您可以使用任何东西。构建代理可以与服务器在同一台 PC 上,但在我们的例子中,我们有一台单独的 PC,因为我们的构建服务器位于 ICT 部门的中心,而我们需要我们的构建代理与我的团队物理定位(用于自动化目标测试)。因此,您使用的工具链安装在您的构建代理上。
这对你有什么帮助?
假设您为 TidyDog 工作,并且您有两个项目正在进行中:
-
“PoopScoop”基于使用 C18 编译器编译的 PIC18F 目标,其主干位于您的 SCM 中
//PoopScoop/TRUNK/
“PoopBag”基于使用 GCC 编译的 ColdFire 目标,其主干位于 //PoopBag/TRUNK/
构建所有项目所需的编译器都安装在构建代理上(我们称之为 TidyDogBuilder)。是运行构建服务器的同一台 PC 还是单独的机器取决于您的情况。每个项目都有自己的构建脚本(例如//PoopScoop/Rakefile.rb
和//PoopBag/Rakefile.rb
),它处理源文件依赖关系和适当编译器的调用。例如,您可以在命令提示符下转到 //PoopScoop/,输入 rake
,构建脚本将负责在命令提示符下编译 PoopScoop 项目。
然后,您可以在构建服务器上设置构建配置。例如,PoopScoop 的构建配置将指定您正在使用的 SCM 工具和存储库位置(例如 //PoopScoop/TRUNK/
),指定要使用的构建代理(例如 TidyDogBuilder),指定在哪里可以找到适当的构建脚本和任何必要的命令使用(例如//PoopScoop/Rakefile.rb
与rake incremental:build
调用)并指定触发构建的事件(例如检测到//PoopScoop/TRUNK/
的签入)。所以想法是,如果有人向//PoopScoop/TRUNK/Source/Scooper.c
提交更改,构建服务器会检测到此更改,从存储库中获取源文件的最新版本并将它们发送到构建代理以使用构建脚本进行编译,最后将构建结果通过电子邮件发送给每个在构建中发生更改的开发人员。
如果您的项目需要针对多个目标进行编译,您只需修改项目的构建脚本来处理此问题(例如,您可能有 rake build:PIC18
或 rake build:Coldfire
之类的命令)并在构建服务器上设置单独的构建配置每个目标。
持续集成
因此,有了这个系统,您就可以启动并运行持续集成。修改您的构建脚本以运行单元测试以及编译您的项目,并且您可以在每次更改后自动执行单元测试。这样做的目的是尽可能早地发现问题,因为您正在开发,而不是在验证活动期间感到惊讶。
结语
没有安装所有工具链的开发人员在某种程度上取决于他们最常做的工作。如果是我,我的工作往往是低级的,与硬件交互很多,我的工作站上没有编译器会惹恼我。另一方面,如果我主要在应用程序级别工作并且可以排除硬件依赖关系,那可能不是这样的问题。 TeamCity 有一个用于 Eclipse 的插件,具有非常酷的特性。您可以进行个人构建,这意味着开发人员可以针对任何给定的构建配置运行挂起的更改列表的构建。这意味着开发人员在构建服务器上启动预先提交代码的构建,而无需实际将其代码提交给 SCM。由于我们昂贵的测试工具仅安装在构建代理上,因此我们使用它来针对我们当前的单元测试和静态分析来试验更改。 关于“在路上”访问构建工件,我同意,在您的 Intranet 中使用诸如 *** 之类的东西可能是最简单的选择。【讨论】:
+1 很棒的信息。我相信这个级别的构建服务器是我们的首席工程师想要完成的。我将仔细检查所有这些选项,并与我们的 IT 团队讨论如何尝试其中的一些想法。关于你结束的想法:项目符号1;我总是与硬件交谈,所以这确实是我们需要克服的问题。我会尝试发布我们对这个问题的解决方案(假设我们能找到一个) @Adam 看起来工作量很大,但实际上并不难。我的建议是大块地咬掉它。 @Adam:从你的构建脚本开始。我喜欢 Rake,它全在 Ruby 中。曾经有人向我推荐过 MSBuild,但它的 xml 格式让我眼花缭乱。即使没有构建服务器,构建脚本也很有用。例如Microchip MPLAB 很丑,所以脚本允许我们从 Eclipse 中构建。然后整理构建服务器,使其只是构建您的项目(使用 TeamCity 花了我不到一天的时间)。然后,当您准备好开始将单元测试连接到系统时。我们仍在改进,下一步是尽可能多地自动化系统验收测试。 感谢您的出发点!附带说明;我同意 MPLAB 8.X 是丑陋的,但 MPLAB X 现在处于测试阶段,并且基于 Netbeans。我没有太多时间玩它,但到目前为止它已经变得更好了。【参考方案2】:在其他答案中(至少在我撰写本文时)尚未解决的问题的一部分是如何将文件传输到构建服务器。我可以在这一点上提供一些经验,因为我自己的开发过程与您的情况相当接近。
就我而言,我使用“Unison”实用程序将我的开发笔记本电脑上的一部分主目录镜像到构建服务器上的一部分主目录。从程序员的角度来看,Unison 基本上是 rsync 的包装器,其中存储了一组校验和,以确定连接两端的文件是否已被修改。它使用它来进行双向同步;我在本地进行的任何修改都会传输到远程端,反之亦然。通常的操作模式是要求确认所有转账;您可以将其关闭,但我发现它可以方便地检查以确保我更改了我认为我更改的内容。
所以,我通常的工作流程是:
在我的开发机器上本地编辑文件。 运行“统一”以将这些编辑同步到构建服务器。 在与构建服务器的 ssh 连接中,运行编译器。 同样在该 ssh 连接中,运行程序,生成一个输出文件。 (这当然和你的情况有点不同。) 再次运行“unison”以将更改后的输出文件同步回我的开发机器。 (您将在此处同步已编译的程序。) 看看我的开发机器上的输出结果。它不如本地机器上的编辑-编译-运行循环那么快,但我发现它仍然足够快,不会令人讨厌。而且它比使用源代码管理作为中介要轻得多。您无需检查所做的每一次编辑并记录下来以备后用。
此外,Unison 还具有跨平台运行良好的优势;您可以在 Windows 上使用它(最容易使用 Cygwin,尽管这不是必需的),如果您在 Windows 机器上运行 SSH 服务器,它可以通过 SSH 连接建立隧道,在构建服务器上运行自己的连接服务,或者只是使用 Windows 文件共享并将构建服务器视为“本地”文件。 (或者您可以将服务器端文件放在服务器场中基于 Linux 的 Samba 共享上,然后将其挂载到您的 Windows 构建虚拟机上;这可能比在虚拟机中拥有“本地”文件更容易。)
编辑: 实际上,这是对 littleadv 文件传输讨论中选项 2 的修改;它取代了通过 Samba/NFS 共享直接在服务器上编辑文件。并且它与此并行工作得相当好——我发现拥有文件的本地缓存是理想的,并且在远程工作时避免了网络延迟问题,但我公司的其他工程师更喜欢像 sshfs 之类的东西(当然,在- 使用 Samba 或 NFS 的站点很好)。从构建服务器的角度来看,这一切都会产生相同的结果。
【讨论】:
【参考方案3】:我不确定我理解你的意思,但我会尝试回答我认为的问题:-)
首先,您说的是交叉编译器,对吧?您正在一个系统上编译要在另一个系统上运行的代码。
其次,您寻找“浮动”许可模型,而不是为每个开发人员提供专用的编译器许可。
第三,您希望拥有一个构建机器,每个人都可以编译,而不是每个开发人员都在自己的机器上编译。
这些问题并不相同。我会尽力掩盖它们:
交叉编译器 - 有些是免费的,有些是许可的。有些带有 IDE,有些只是可以集成到 Eclipse/VS/SlickEdit/vi/whatelse 中的命令行编译器。不知道你用的是哪一个,我们来看看 Tornado(VxWorks 编译器)。它有自己可怕的 IDE,但可以集成到其他 IDE 中(我直接使用 SlickEdit 和它的项目文件,就像一个魅力)。 Tornado 编译器需要许可证并且有几种不同的模型,因此我们将在接下来的两点中查看它。
浮动许可证。例如,Tornado 可以为每个安装模型提供单个许可证,也可以为每个请求分配许可证的浮动许可证。如果您使用的是构建机器 - 您将需要一个许可证(在这种情况下,您一次只能运行一个实例,这违背了目的),或者一次运行多个实例的浮动许可证。一些交叉编译器/库根本不需要许可证(例如各种 GCC 风格)。
构建机器 - 我体验过将 VxWorks Tornado 用作 PC 上的专用编译器和构建机器安装。
对于构建机器,您需要一种方法来传递代码以进行构建。这是你的第二个问题:
2) 如何/何时传输源 代码到服务器进行构建。
通过网络共享不是一个好主意,因为网络延迟会使编译时间难以忍受。相反,请执行以下操作之一:
在构建机器上安装源代码管理,让开发人员通过源代码管理传递代码。这带来了破坏源代码控制的风险,所以我们所做的是:
所有开发人员直接在构建机器上签出的文件(具有大量存储的大型 UNIX 系统),每个开发人员将使用网络共享(SAMBA 或 NFS)编辑文件,在1GB 公司 LAN 没问题,在构建机器上本地编译。有些人会使用我讨厌的 Tornado IDE 的 vi/emacs/Unix 版本直接在 Unix 系统上进行编辑。这也回答了您的问题 #1:
1) 与虚拟 Windows 联网 机器。
(它不必是虚拟的 Windows 机器,如果你有从 Linux 到嵌入式系统的交叉编译器,Linux 也可以工作)。
希望对您有所帮助。
【讨论】:
+1 有很多优点。查看我的编辑以回答您的一些问题/cmets。 @Adam - 为每个编译器创建一个存储库是否有意义,其中包括用于构建、源、包含、输出等的文件夹......然后在用户端有脚本负责将文件从 IDE 的文件结构移动到编译器所需的结构?这种方法可以防止项目存储库被破坏,并给出编译器被使用了多少次。 - 是的,我认为它会。自动化程度越高 - 出错的地方就越少。【参考方案4】:我不是这里的专家,但是否有可能为每个目标环境创建一个虚拟机。然后开发人员可以在他的本地机器上启动所需的 VM 映像。
【讨论】:
这会带来许可问题。您基本上是在为同一台机器创建不同的副本。【参考方案5】:似乎您正在尝试做的是一个“distributed build”,其中只有一个构建服务器。这可以通过CMake 之类的方式实现。然而,虽然这可能会“节省”您对编译器许可证的使用,但对于许多工具链来说,单用户许可证也(或在某些情况下专门)适用于调试器;如果您的开发人员无法调试和测试他们的代码,它可能不是特别有用。
一种解决方案可能是使用具有必要开发工具和目标硬件的单台机器,并通过远程桌面从多个工作站访问它,如果您只需要命令行界面,甚至可以通过 Telnet 访问它。远程桌面一次只允许一个用户访问,但在许多情况下,多个同时访问可能违反 EULA。
DIY 解决方案是创建您自己的 TCP/IP 应用程序,该应用程序接受构建命令和文件、执行本地编译器或链接器并返回结果(构建日志和/或目标文件等)。
通过将所有开发转移到 GCC 或 SDCC 等开源工具,可以完全避免该问题;这取决于您需要支持的目标。
【讨论】:
一般来说,我们的团队会尽可能使用开源,但很多都不适用于我们正在开发的目标系统。关于拥有一台与硬件对话的专用机器对我们来说根本不可行。我们都有笔记本电脑,并且经常需要在现场(测试期间)进行编程/调试。 @Adam:如果“外部服务器”无法访问以执行构建,那么在任何情况下都可能存在现场开发问题。您可能会考虑浮动或加密狗许可(如果可用);但可用性会因供应商而异;例如,IAR 提供这两种选项。 Keil 的浮动许可证管理器允许您在定义的时间段内手动签出许可证,以便您可以在与许可证服务器断开连接的情况下工作。关键是,只要不是所有开发人员都需要同时获得许可证,您的开发人员就可以多于您拥有的许可证。 我正在寻找的解决方案需要互联网连接(我们在路上使用移动热点)。有了这个连接,我会看到要么与服务器交谈,比如 Slice Host,要么 *** 连接到我们自己的 Intranet。我们的编译器不存在浮动加密狗:(。再次感谢您的输入! 我的建议是咨询您的编译器供应商;您也许可以获得让步。许多固定许可证允许为此目的进行两次安装(通常一个在台式机上,一个在笔记本电脑上)。仔细检查您的 EULA。以上是关于如何在外部服务器上安装和使用嵌入式 C 的编译器?的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot REST Controller 部署在外部 tomcat 9 服务器上时返回 404
尝试在外部在tomcat 9上运行带有rest控制器的spring boot war文件