Cygwin环境使用第三方ARMGCC编译eCos系统

第三方ARMGCC通常是基于Mingw32的,使用的是Windows路径,如C:\ecos\packages\infra\current\src\startup.cxx;而eCos配置工具生成的Makefile是基于Cygwin的,使用的是POSIX路径,如/cygdrive/c/packages/infra/current/src/startup.cxx。路径格式上的差别导致不能直接使用第三方ARMGCC编译eCos系统,而是需要一个中间程序来对路径进行转换。这里提供了执行路径转换的中间程序的源代码和编译使用说明。

eCos官网:http://ecos.sourceware.org

eCos中文技术网:http://www.52ecos.net

eCos交流QQ群:144940146。

http://blog.csdn.net/zoomdy/article/details/39553465

mingdu.zheng<at>gmail<dot>com

为什么需要第三方ARMGCC

eCos项目本身提供了GCC编译器,但是更新是比较慢的,在ARM公司已经推出Cortex-M7的年头还不支持Cortex-M4的FPU,毕竟eCos项目本身是做实时操作系统,编译器只是其配套工具之一。而第三方ARMGCC则几乎每个季度都会发布新版本以便支持最新的硬件。

第三方ARMGCC

这里推荐两款第三方ARMGCC

  • GNU Tools for ARM Embedded Processors

https://launchpad.net/gcc-arm-embedded

看这个项目的简介,应该是ARM公司官方参与,可以自由下载,无需注册。

  • Sourcery CodeBench Lite Edition

http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/

这个原先是CodeSourcery公司的产品,现在被MentorGraphics收购了,其Lite版本可以免费下载使用,但是需要注册登记。

路径转换的实现

有两个地方需要进行路径转换,一是:传递给GCC的命令行参数,eCos配置工具生成的Makefile使用的是POSIX路径,而GCC需要的是Windows路径,因此首先需要将命令行参数中出现的POSIX路径转换成Windows路径再传递给GCC;二是:eCos编译系统需要使用GCC输出的依赖关系文件,第三方GCC生成的该文件使用的是Windows路径,而eCos编译系统需要的是POSIX路径,接下来就需要将依赖关系文件中的Windows路径转换成POSIX路径,源代码如下。

// main.cxx
// by zoomdy (mingdu.zheng <at> gmail <dot> com)
#ifdef __CYGWIN__

#include <windows.h>
#include <sys/cygwin.h>
#include <sys/wait.h> // for waitpid
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for strstr, strchr
#include <unistd.h> // for execvp
#include <stdbool.h>

int main(int argc, char *argv[])
{
    // 首先处理程序名
    char *p = strchr(argv[0], '-');
    if(p == NULL)
    {
        fprintf(stderr, "invalid program name: %s", argv[0]);
        return EXIT_FAILURE;
    }
    p++;
    if(*p == '\0' || *p == '.')
    {
        fprintf(stderr, "invalid program name: %s", argv[0]);
        return EXIT_FAILURE;
    }

    char *q;
    for(q = argv[0]; *p != '\0'; q++, p++)
    {
        *q = *p;
    }
    *q = '\0';

    // 处理其它参数
    char buffer [MAX_PATH + 1];
    char *deps = NULL;
    for(int i = 1; i < argc; i++)
    {
        p = strstr(argv[i], "/cygdrive/");
        if(p != NULL)
        {
            cygwin_conv_to_win32_path(p, buffer);
            strcpy(p, buffer);
        }

        p = strstr(argv[i], "-Wp,-MD,");
        if(p != NULL)
        {
            deps = p + strlen("-Wp,-MD,");
        }

        // 如果发现所使用的参数名为null文件,那么创建一个空白文件
        if(strcmp(argv[i], "/dev/null") == 0)
        {
            FILE* file = fopen("null", "w");
            fclose(file);
            strcpy(argv[i], "null");
        }
    }

    // 打印变更后的命令行
    printf("==>");
    for(int i = 0; i < argc; i++)
    {
        printf(argv[i]);
        printf(" ");
    }
    printf("\n");

    // 调用变更后的命令行
    if(deps == NULL)
    {
        // 如果不需要处理依赖关系文件,直接调用目标程序
        int retval = execvp(argv[0], argv);
        if(retval == -1)
        {
            perror(argv[0]);
            return EXIT_FAILURE;
        }
        else
        {
            return EXIT_SUCCESS;
        }
    }
    else
    {
        // 如果需要处理依赖关系文件,那么创建子进程,并等子进程完成后处理依赖关系文件
        pid_t pid = fork();
        if(pid == -1)
        {
            perror(argv[0]);
            return EXIT_FAILURE;
        }
        else if(pid == 0)
        {
            int retval = execvp(argv[0], argv);
            if(retval == -1)
            {
                perror(argv[0]);
                return EXIT_FAILURE;
            }
            else
            {
                return EXIT_SUCCESS;
            }
        }
        else
        {
            int stat_val;
            waitpid(pid, &stat_val, 0);

            // 如果子进程正确完成,那么处理依赖关系文件
            if(WIFEXITED(stat_val))
            {
                if(WEXITSTATUS(stat_val) == EXIT_SUCCESS)
                {
                    // 处理生成的依赖关系文件
                    char deps_cyg [MAX_PATH + 1];
                    strcpy(deps_cyg, deps);
                    strcat(deps_cyg, ".cyg");

                    FILE* file_win = fopen(deps, "r");
                    FILE* file_cyg = fopen(deps_cyg, "w");

                    bool last_line = false;
                    size_t len_line;
                    for(int line = 0; last_line == false; line++)
                    {
                        p = fgets(buffer, sizeof(buffer), file_win);
                        if(p == NULL)
                        {
                            perror(deps);
                            return EXIT_FAILURE;
                        }

                        // 跳过前面的空格
                        for(size_t i = 0; i < sizeof(buffer); i++)
                        {
                            if(*p == ' ')
                            {
                                p++;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // 去掉尾部的回车换行符以及空格
                        len_line = strlen(p);
                        for(size_t i = len_line - 1; i != 0; i--)
                        {
                            if(p[i] == ' ' || p[i] == '\r' || p[i] == '\n')
                            {
                                p[i] = '\0';
                                len_line--;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // 判断是否为最后一行
                        if(p[len_line - 1] == '\\')
                        {
                            last_line = false;
                            p[len_line - 1] = '\0';
                            len_line--;
                        }
                        else
                        {
                            last_line = true;
                        }

                        // 去掉尾部的空格
                        for(size_t i = len_line - 1; i != 0; i--)
                        {
                            if(p[i] == ' ')
                            {
                                p[i] = '\0';
                                len_line--;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // 处理第一行的特殊情况,这种情况下,目标和依赖文件在同一行上
                        if(line == 0)
                        {
                            q = strstr(p, ".o:");
                            if(q != NULL)
                            {
                                p = q + strlen(".o:");

                                // 跳过前面的空格
                                for(size_t i = 0; i < sizeof(buffer); i++)
                                {
                                    if(*p == ' ')
                                    {
                                        p++;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                if(strlen(p) > 0)
                                {
                                    cygwin_conv_to_posix_path(p, p);
                                }
                            }
                        }

                        // 从第二行开始,转换路径
                        if(line > 0)
                        {
                            // 将Windows路径转换成POSIX路径
                            cygwin_conv_to_posix_path(p, p);
                        }

                        // 如果不是最后一行,加入空格以及反斜杆
                        if(!last_line)
                        {
                            strcat(buffer, " \\\n");
                        }
                        else
                        {
                            strcat(buffer, "\n");
                        }

                        int retval = fputs(buffer, file_cyg);
                        if(retval == EOF)
                        {
                            perror(deps_cyg);
                            return EXIT_FAILURE;
                        }
                    }

                    fclose(file_win);
                    fclose(file_cyg);

                    // 删除原文件,将处理后的文件重命名为原文件名
                    remove(deps);
                    rename(deps_cyg, deps);

                    return EXIT_SUCCESS;
                } // WEXITSTATUS(stat_val)
            } // WIFEXITED(stat_val)
        }// pid > 0
    } // deps == NULL

    return EXIT_FAILURE;
}

#else
#error "invoke native tool only use for cygwin environment"
#endif

编译

把上面的源代码内容保存文件为mian.cxx,然后把下面的代码内容保存文件为Makefile,放在同一个目录下,然后打开Cygwin终端,进入存放上述两个文件的地方,敲入make。

# Makefile
all: native.exe
	cp native.exe native-arm-none-eabi-gcc.exe
	cp native.exe native-arm-none-eabi-ar.exe
	cp native.exe native-arm-none-eabi-objcopy.exe

native.exe: main.cxx
	gcc -Wall -O2 -o [email protected] $<

clean:
	rm -rf *.exe

使用

把生成的native-arm-none-eabi-*.exe文件存储到你希望存储的目录,然后将该目录追加到系统的PATH环境变量中。接下来,在eCos配置工具中设置Global build options >> Global command prefix为native-arm-none-eabi。

将会发生什么

编译eCos系统时,凡是需要调用gcc的地方,都会首先调用native-arm-none-eabi-gcc,native-arm-none-eabi-gcc将命令行参数中的POSIX路径转换成Windows路径后调用arm-none-eabi-gcc,如果命令行中包含生成依赖关系文件的参数,那么native-arm-none-eabi-gcc将等待arm-none-eabi-gcc编译完成后处理依赖关系文件中的路径转换。

最佳解决方案

使用Linux系统,而不是Cygwin作为eCos开发环境。在Linux下开发eCos使用第三方ARMGCC就完全没有这个麻烦,因为大家使用的都是POSIX路径,没必要做任何转换,而且在Linux环境下的编译速度远快于Cygwin环境下的编译速度,毕竟Cygwin增加了系统调用的层次,而且Windows的文件访问缓存机制不如Linux,而且还有杀毒软件在中间掺和。当然,不是所有人都会用Linux,所有才有eCos的Cygwin版,有时间尝试一下Linux也是很好的,现如今的Linux桌面系统已经相当成熟。

时间: 2024-08-27 05:05:33

Cygwin环境使用第三方ARMGCC编译eCos系统的相关文章

STLport-5.2.1 STL port配置; cl.exe 编译cpp:ms和cygwin两种模式;cygwin环境配置和使用、GCC编译入门

1.在ms中要使用windows sdk和相关的lib设置实在太麻烦啦,以及dll等文件缺失是在严重.所以我简单地利用了vs安装目录下的批处理文件,在命令窗口中进入: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC ,直接运行vcvarsall.bat加载vs中以及配置好的环境,就可以使用命令行: cl -GX hello.cpp去实现编译并运行.2012版本的vs中-GX换成-EHsc.同理我也可以使用vs2013.目前vs2013

iOS系统提供开发环境下命令行编译工具:xcodebuild

iOS系统提供开发环境下命令行编译工具:xcodebuild[3] xcodebuild 在介绍xcodebuild之前,需要先弄清楚一些在XCode环境下的一些概念[4]: Workspace:简单来说,Workspace就是一个容器,在该容器中可以存放多个你创建的Xcode Project, 以及其他的项目中需要使用到的文件. 使用Workspace的好处有: 1),扩展项目的可视域,即可以在多个项目之间跳转,重构,一个项目可以使用另一个项目的输出.Workspace会负责各个Project

Windows环境下log4cxx的编译及使用(转载)

1.介绍 Log4cxx是开放源代码项目Apache Logging Service的子项目之一,是Java社区著名的log4j的c++移植版,用于为C++程序提供日志功能,以便开发者对目标程序进行调试和审计.有关log4cxx的更多信息可以从Apache Loggin Service的网站http://logging.apache.org获得.当前的最新版本为0.10.0,本文内容及示例代码都是基于此版本. 2.获取软件包 可以从官方网站(http://logging.apache.org/l

windows下用ADT进行AndroidNDK开发的详细教程(从环境搭建 配置到编译全过程)

这几天在学习android NDK的开发,那么首先让我们来看看android NDK开发的本质是什么. NDK(Native Development Kit),即本地开发工具,简单地说,就是在开发android应用程序的时候,在java类中调用native函数,而native函数的接口也是在java类中定义的,但是native函数最终由本地的C/C++代码实现.简单地说,就是在java中调用C/C++函数.至于为什么要用NDK,我总结了一下,大致有以下几方面原因: 1.提升程序运行效率:众所周知

【转】Android 4.3源码的下载和编译环境的安装及编译

原文网址:http://jingyan.baidu.com/article/c85b7a641200e0003bac95a3.html  告诉windows用户一个不好的消息,windows环境下没法编译android源码.用cygwin?不行,因为cygwin模拟的环境太简单,编译android源码需要好多工具,比如gnupg flex bison gperf libsdl-dev libesd0-dev …有的环境还需要wine.单纯的cygwin肯定是不能满足需要的.那么windows环境

012.Windows Cygwin环境搭建

Windows Cygwin环境搭建 1.引言 Cygwin是一个在Windows平台上运行的类UNIX模拟环境,在一些芯片开发场景下,开发人员并不使用IDE(集成开发环境),也不使用Linux,而是使用在Windows下的Cygwin环境去Makefile.本文介绍下基于Cygwin以RH850芯片使用GHS编译的开发环境搭建. 2.下载安装 前往官网https://www.cygwin.com/下载在线安装包,也可以上网搜下离线安装包,本文以官网在线安装包进行说明,在官网首页找到如下界面,

windows环境下使用apxs编译添加apache模块

windows环境下使用apxs编译添加apache模块 简介说明:本文使用mod_limitipconn模块为例. 环境: windows7 x86系统 apache 2.4.18 目标: 在windows环境下,利用mod_limitipconn0.24源码.apxs为apache2.4.18添加mod_limitipconn模块. 分析: limitipconn模块最新版已经支持apache2.4了.但是没有编译好的对应版本.因此需要自己动手编译模块.在windows下要实现这个目标,需要

LNAMP服务器环境搭建(手动编译安装)

LNAMP服务器环境搭建(手动编译安装) 一.准备材料 阿里云主机一台,操作系统CentOS 6.5 64位 lnamp.zip包(包含搭建环境所需要的所有软件) http://123.56.144.36:8001/tools/lnamp.zip 二.确认环境 #确认CentOS YUM安装使用正常 yum clean all yum makecache #确认c gc gc-c++安装正常 yum install -y gc gcc gcc-c++ #确认安装环境需要的软件 yum insta

编译Android系统源码和内核源码

好长时间没有写blog了,之所以没有写,主要还是工作上的事,发现最近的脑子不够用了,今天写点什么呢?就把我之前编译Android系统源码和内核源码的过程记录一下,因为这个过程真的是受益匪浅,看重的不是结果,主要是过程,在这个过程中,我感觉最大的收获就是学习的耐心和毅力,因为在这个过程中那个问题就像是雨点似的天天打在你的脸上,虽然现在网上有很多文章介绍怎么去操作,但是我说句真心话,那些只能提供参考,因为你的工作环境毕竟和他不一样,所以等你按照他的步骤去操作的时候还是会遇到很多问题,当然我写这篇文章