linux 7z命令安装使用及其交叉编译移植到arm linux平台

作者:reille

本博客网址:http://blog.csdn.net/reille/,转载本博客原创文章请注明出处。

本文内容概要:7z具有很高的压缩率,这对存储空间资源比较敏感的嵌入式系统是很有用处的,相对于其它压缩软件,如tar命令,7z命令可以节省很大一部分存储空间。本文即说明在宿主机linux中7z命令的安装、交叉编译7z命令从而可在嵌入式arm平台上使用该命令、7z命令的使用等。

开发环境:

宿主 机:window XP;

虚 拟 机:ubuntu9.10;

交叉编译器:arm-uclibc-gcc (3.3版本)

———————————————————————————————————————————————————————————————————

1. 宿主机安装7z命令

宿主机上安装7z命令有两种方式。

1.1在线安装

如果你的宿主机Linux可以连接外网,推荐用这种方式,方便简单,执行命令:sudo apt-get install p7zip即可在线安装7z命令。

1.2 安装包安装

7z提供了线下的程序安装包,也可自己编译安装。这里讲的是用7z提供的bin包来安装。

宿主机linux一般是X86的,而7z提供编译好了的bin包,可以很方便的安装。步骤如下:

1) 去网站http://sourceforge.net/projects/p7zip/files/或http://sourceforge.net/projects/p7zip/files/p7zip/上下载p7zip的包,当前最新版本是9.20.1;

2) 找到对应版本号进去,页面会提供两个供你下载,一个是bin包,另一个是源码包,这里下的是bin包(事实上还是把两个包都下载下来吧,后面移植到嵌入式linux平台要用到源码包的),以9.20.1为例,下载的包名称是:p7zip_9.20.1_x86_linux_bin.tar.bz2;

3) 在Linux上执行下面命令(解压和安装):

tar xjvf p7zip_9.20.1_x86_linux_bin.tar.bz2cd p7zip_9.20.1sh install.sh

到此,就安装完成了。

2. 7z命令的使用2.1 解压缩7z文件

7za x phpMyAdmin-3.3.8.1-all-languages.7z -r -o./7za x phpMyAdmin-3.3.8.1-all-languages.7z -r -o./

参数含义:

x 代表解压缩文件,并且是按原始目录解压(还有个参数 e 也是解压缩文件,但其会将所有文件都解压到根下,而不是自己原有的文件夹下)

phpMyAdmin-3.3.8.1-all-languages.7z 是压缩文件,这里我用phpadmin做测试。这里默认使用当前目录下的phpMyAdmin-3.3.8.1-all-languages.7z

-r 表示递归解压缩所有的子文件夹

-o 是指定解压到的目录,-o后是没有空格的直接接目录

2.2 压缩文件/文件夹

7za a -t7z -r Mytest.7z /opt/phpMyAdmin-3.3.8.1-all-languages/*参数含义:a 代表添加文件/文件夹到压缩包

-t 是指定压缩类型,这里定为7z

-r 表示递归所有的子文件夹

Mytest.7z 是压缩好后的压缩包名

3. 7z交叉移植到arm-linux平台

有两种7z命令移植到arm-linux平台:一种是完整功能版本的7z命令移植;另一种精简版本的7z命令的移植(实际上只有解压7z格式包功能),下面分别进行说明。

3.1 完整功能7z命令即7za的移植

解压源码包p7zip_9.20.1_src_all.tar.bz2后,进入源码包,会发现有一个makefile和n多其它平台的m-akefile:makefile.aix_gcc、makefile.linux_s390x 、makefile.linux_cross_arm等。其中,makefile.linux_cross_arm就是我们要的makefile文件。此我,源码目录中提供了readme文件,其中有说明如下:

According to your OS, copy makefile.linux, makefile.freebsd, makefile.cygwin, … over makefile.machine

其中的 makefile.machine 就是平台相关性选项。所以我们可以这样做 :

编辑makefile.linux_cross_arm文件 ,指定其中的编译器路径,如下打红色地方所示:

## makefile for Linux (CROSS ARM)#

OPTFLAGS=-O

ALLFLAGS=${OPTFLAGS} -pipe -s \ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \-DNDEBUG -D_REENTRANT -DENV_UNIX \-D_7ZIP_LARGE_PAGES \$(LOCAL_FLAGS)

CXX=/usr/local/arm-uclibc/bin/arm-uclibc-g++ $(ALLFLAGS)CC=/usr/local/arm-uclibc/bin/arm-uclibc-gcc $(ALLFLAGS)CC_SHARED=-fPIC -DPICLINK_SHARED=-fPIC -DPIC -shared

LOCAL_LIBS=-lpthreadLOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl

OBJ_CRC32=$(OBJ_CRC32_C)

注:用这个编译器,会有一个错误:提示wine_date_and_time.cpp中112行的timegm未定义,可以在config.h的31行,把那个宏定义取消即可正常编译通过。

然后:$ mv makefile.machine makefile.machine.bak $ ln -s makefile.linux_cross_arm makefile.machine $ make make后,可以bin目录下看到有一个7za的文件,这就是我们要的,把其放到arm板上,即可正常运行。

完整功能版本的7z命令,交叉编译出来的7z命令即7za,其大小为1.38M,不同的编译器可能编译出来的大小有点出入,比如我在公司编译的是1.7M多。

3.2 精简功能7z命令即7zDec的移植

很显然,交叉编译的完整功能7za命令太大,达到了1M多,这对于嵌入式根文件系统来说,一般情况下是不能接收的。但如果从源码包p7zip_9.20.1_src_all.tar.bz2中进行裁减,发现难度很大。

幸好,7z开源项目提供了精简功能7z命令即7zDec。交叉编译后的大小为50KB左右。

1) 下载LZMA-SDK源码包,下载地址:http://www.7-zip.org/sdk.html,当前最新版本是9.20,即lzma920.tar.bz2包;

2) 解压:把源码包的程序文件解压到文件夹:lzma920中;

3) 解压后,建议先查看下其中的说明文件:7zC.txt和lzma.txt两文件;

4) 进入目录:lzma920/C/Util/7z,可以看到其中有两个makefile文件:makefile和makefile.gcc,因为是在linux下,所以用makefile.gcc这个makefile文件;

5) 更改makefile.gcc文件,更改如下:

PROG = 7zDecCXX = /usr/local/arm-uclibc/bin/arm-uclibc-g++STRIP = /usr/local/arm-uclibc/bin/arm-uclibc-stripLIB =RM = rm -fCFLAGS = -c -O2 -WallOBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.oall: $(PROG)$(PROG): $(OBJS)$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)$(STRIP) $(PROG)7zMain.o: 7zMain.c$(CXX) $(CFLAGS) 7zMain.c7zAlloc.o: ../../7zAlloc.c$(CXX) $(CFLAGS) ../../7zAlloc.c7zBuf.o: ../../7zBuf.c$(CXX) $(CFLAGS) ../../7zBuf.c7zBuf2.o: ../../7zBuf2.c$(CXX) $(CFLAGS) ../../7zBuf2.c7zCrc.o: ../../7zCrc.c$(CXX) $(CFLAGS) ../../7zCrc.c7zCrcOpt.o: ../../7zCrc.c$(CXX) $(CFLAGS) ../../7zCrcOpt.c7zDec.o: ../../7zDec.c$(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c7zIn.o: ../../7zIn.c$(CXX) $(CFLAGS) ../../7zIn.cCpuArch.o: ../../CpuArch.c$(CXX) $(CFLAGS) ../../CpuArch.cLzmaDec.o: ../../LzmaDec.c$(CXX) $(CFLAGS) ../../LzmaDec.cLzma2Dec.o: ../../Lzma2Dec.c$(CXX) $(CFLAGS) ../../Lzma2Dec.cBra.o: ../../Bra.c$(CXX) $(CFLAGS) ../../Bra.cBra86.o: ../../Bra86.c$(CXX) $(CFLAGS) ../../Bra86.cBcj2.o: ../../Bcj2.c$(CXX) $(CFLAGS) ../../Bcj2.cPpmd7.o: ../../Ppmd7.c$(CXX) $(CFLAGS) ../../Ppmd7.cPpmd7Dec.o: ../../Ppmd7Dec.c$(CXX) $(CFLAGS) ../../Ppmd7Dec.c7zFile.o: ../../7zFile.c$(CXX) $(CFLAGS) ../../7zFile.c7zStream.o: ../../7zStream.c$(CXX) $(CFLAGS) ../../7zStream.cclean:-$(RM) $(PROG) $(OBJS)

6) 编译:make -f makefile.gcc或make -f makefile.gcc clean all;则会在lzma920/C/Util/7z/目录下生成一个名为7zDec的可执行文件,即移植到精简功能版本7z命令。

7) 7zDec命令默认只支持完整7za命令的三个选项,如下所示:

e: Extract files from archive (without using directory names) l: List contents of archive t: Test integrity of archive x: eXtract files with full paths

而不支持"-o"选项,即 指定解压目录 功能,因为在使用过程中有这个需求,因此,对7zDec命令添加了7za命令中的“-o”选项功能。在lzma920/C/Util/7z/目录下,编辑7zMain.c文件,修改main函数如下:

int MY_CDECL main(int numargs, char *args[]){  CFileInStream archiveStream;  CLookToRead lookStream;  CSzArEx db;  SRes res;  ISzAlloc allocImp;  ISzAlloc allocTempImp;  UInt16 *temp = NULL;  size_t tempSize = 0;  // add start by gyr 2011.11.19  UInt16 *name = NULL;  UInt16 *outPath = NULL;  size_t outPathLen = 0;  // add end by gyr 2011.11.19  printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");  if (numargs == 1)  {    printf(      "Usage: 7zDec <command> <archive_name>\n\n"      "<Commands>\n"      "  e: Extract files from archive (without using directory names)\n"      "  l: List contents of archive\n"      "  t: Test integrity of archive\n"      "  x: eXtract files with full paths\n"      "  -o{Directory}: set Output directory");// add by gyr 2011.11.19    return 0;  }  if (numargs < 3)  {    PrintError("incorrect command");    return 1;  }// add start by gyr 2011.11.19  if (numargs == 4 && strstr(args[3], "-o") != NULL)  {  size_t outPathLenTemp = strlen(args[3]);if (outPathLenTemp <= 2){PrintError("set Output directory Error");return1;}outPathLen = outPathLenTemp - 2;if (args[3][outPathLenTemp-1] != '/'){outPathLen = outPathLen + 1;}outPath = (UInt16 *)SzAlloc(NULL, outPathLen * sizeof(outPath[0]));    if (outPath == NULL)    {    PrintError("can not allocate memory for set output dirctory");        return1;    }int j = 0;for (j=2; j<outPathLenTemp; j++){outPath[j-2] = args[3][j];}if (args[3][outPathLenTemp-1] != '/'){outPath[outPathLen-1] = '/';}  }// add end by gyr 2011.11.19  allocImp.Alloc = SzAlloc;  allocImp.Free = SzFree;  allocTempImp.Alloc = SzAllocTemp;  allocTempImp.Free = SzFreeTemp;  if (InFile_Open(&archiveStream.file, args[2]))  {    PrintError("can not open input file");    return 1;  }  FileInStream_CreateVTable(&archiveStream);  LookToRead_CreateVTable(&lookStream, False);  lookStream.realStream = &archiveStream.s;  LookToRead_Init(&lookStream);  CrcGenerateTable();  SzArEx_Init(&db);  res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);  if (res == SZ_OK)  {    char *command = args[1];    int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0;    if (strcmp(command, "l") == 0) listCommand = 1;    else if (strcmp(command, "t") == 0) testCommand = 1;    else if (strcmp(command, "e") == 0) extractCommand = 1;    else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }    else    {      PrintError("incorrect command");      res = SZ_ERROR_FAIL;    }    if (res == SZ_OK)    {      UInt32 i;      /*      if you need cache, use these 3 variables.      if you use external function, you can make these variable as static.      */      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */      for (i = 0; i < db.db.NumFiles; i++)      {        size_t offset = 0;        size_t outSizeProcessed = 0;        const CSzFileItem *f = db.db.Files + i;        size_t len;        if (listCommand == 0 && f->IsDir && !fullPaths)          continue;        len = SzArEx_GetFileNameUtf16(&db, i, NULL);        if (len > tempSize)        {          SzFree(NULL, temp);          tempSize = len;          temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));          if (temp == 0)          {            res = SZ_ERROR_MEM;            break;          }        }        SzArEx_GetFileNameUtf16(&db, i, temp);        if (listCommand)        {          char attr[8], s[32], t[32];          GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr);          UInt64ToStr(f->Size, s);          if (f->MTimeDefined)            ConvertFileTimeToString(&f->MTime, t);          else          {            size_t j;            for (j = 0; j < 19; j++)              t[j] = ' ';            t[j] = '\0';          }          printf("%s %s %10s  ", t, attr, s);          res = PrintString(temp);          if (res != SZ_OK)            break;          if (f->IsDir)            printf("/");          printf("\n");          continue;        }        fputs(testCommand ?            "Testing    ":            "Extracting ",            stdout);        res = PrintString(temp);        if (res != SZ_OK)          break;        if (f->IsDir)          printf("/");        else        {          res = SzArEx_Extract(&db, &lookStream.s, i,              &blockIndex, &outBuffer, &outBufferSize,              &offset, &outSizeProcessed,              &allocImp, &allocTempImp);          if (res != SZ_OK)            break;        }        if (!testCommand)        {          CSzFile outFile;          size_t processedSize;          size_t j;//        UInt16 *name = (UInt16 *)temp;// del by gyr 2011.11.19// add start by gyr 2011.11.19  if (name != NULL)          {  SzFree(NULL, name);  }  name = (UInt16 *)SzAlloc(NULL, (tempSize+outPathLen) * sizeof(name[0]));          if (name == NULL)          {            res = SZ_ERROR_MEM;            break;          }  for (j=0; j<outPathLen; j++)  {  name[j] = outPath[j];  }  for (j=outPathLen; j<(tempSize+outPathLen); j++)  {  name[j] = temp[j-outPathLen];  }// add end by gyr 2011.11.19          const UInt16 *destPath = (const UInt16 *)name;          for (j = 0; name[j] != 0; j++)            if (name[j] == '/')            {              if (fullPaths)              {                name[j] = 0;                MyCreateDir(name);                name[j] = CHAR_PATH_SEPARATOR;              }              else                destPath = name + j + 1;            }          if (f->IsDir)          {            MyCreateDir(destPath);            printf("\n");            continue;          }          else if (OutFile_OpenUtf16(&outFile, destPath))          {            PrintError("can not open output file");            res = SZ_ERROR_FAIL;            break;          }          processedSize = outSizeProcessed;          if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)          {            PrintError("can not write output file");            res = SZ_ERROR_FAIL;            break;          }          if (File_Close(&outFile))          {            PrintError("can not close output file");            res = SZ_ERROR_FAIL;            break;          }          #ifdef USE_WINDOWS_FILE          if (f->AttribDefined)            SetFileAttributesW(destPath, f->Attrib);          #endif        }        printf("\n");      }      IAlloc_Free(&allocImp, outBuffer);    }  }  SzArEx_Free(&db, &allocImp);  SzFree(NULL, temp);// add start by gyr 2011.11.19  SzFree(NULL, name);  SzFree(NULL, outPath);// add end by gyr 2011.11.19  File_Close(&archiveStream.file);  if (res == SZ_OK)  {    printf("\nEverything is Ok\n");    return 0;  }  if (res == SZ_ERROR_UNSUPPORTED)    PrintError("decoder doesn't support this archive");  else if (res == SZ_ERROR_MEM)    PrintError("can not allocate memory");  else if (res == SZ_ERROR_CRC)    PrintError("CRC error");  else    printf("\nERROR #%d\n", res);  return 1;}

我不敢说我明天便可以做一个快乐的人,面朝大海春暖花开。

linux 7z命令安装使用及其交叉编译移植到arm linux平台

相关文章:

你感兴趣的文章:

标签云: