交叉编译Python-2.7.13到ARM(aarch32)—— 支持sqlite3

时间:2022-09-08 19:48:29

作者:彭东林

邮箱:pengdonglin137@163.com

QQ: 405728433

环境

主机: ubuntu14.04 64bit

开发板: qemu + vexpress-a9 (参考: http://www.cnblogs.com/pengdonglin137/p/6442583.html

工具链: arm-none-linux-gnueabi-gcc  (gcc version 4.8.3 20140320)

Python版本: Python-2.7.13

概述

前面一篇博文(交叉编译Python-2.7.13到ARM(aarch32)平台)介绍了移植python到aarch32上面,但是发现有很多模块都不能用,可以在板子上面执行下面的命令测试一下:

 [root@vexpress ]# python /usr/lib/python2.7/test/test___all__.py
Traceback (most recent call last):
File "/usr/lib/python2.7/test/test___all__.py", line 3, in <module>
import unittest
File "/usr/lib/python2.7/unittest/__init__.py", line 58, in <module>
from .result import TestResult
File "/usr/lib/python2.7/unittest/result.py", line 9, in <module>
from . import util
File "/usr/lib/python2.7/unittest/util.py", line 2, in <module>
from collections import namedtuple, OrderedDict
File "/usr/lib/python2.7/collections.py", line 20, in <module>
from _collections import deque, defaultdict
ImportError: No module named _collections

可以看到这里找不到_collections模块。

对比x86_64的编译结果:

 ls x86_64/build/lib.linux-x86_64-2.7/
array.so* _codecs_hk.so* cPickle.so* _curses_panel.so* future_builtins.so* itertools.so* mmap.so* parser.so* _socket.so* _sysconfigdata.py time.so*
audioop.so* _codecs_iso2022.so* crypt.so* _curses.so* grp.so* _json.so* _multibytecodec.so* pyexpat.so* spwd.so* _sysconfigdata.pyc unicodedata.so*
binascii.so* _codecs_jp.so* cStringIO.so* datetime.so* _hashlib.so* linuxaudiodev.so* _multiprocessing.so* _random.so* _sqlite3.so* _sysconfigdata.pyo zlib.so*
_bisect.so* _codecs_kr.so* _csv.so* _elementtree.so* _heapq.so* _locale.so* nis.so* readline.so* _ssl.so* syslog.so*
cmath.so* _codecs_tw.so* _ctypes.so* fcntl.so* _hotshot.so* _lsprof.so* operator.so* resource.so* strop.so* termios.so*
_codecs_cn.so* _collections.so* _ctypes_test.so* _functools.so* _io.so* math.so* ossaudiodev.so* select.so* _struct.so* _testcapi.so*

而aarch32的编译结果:

 $ls aarch32/build/lib.linux2-arm-2.7/
audioop.so* _codecs_iso2022.so* _codecs_tw.so* _ctypes.so* _elementtree.so* _json.so* mmap.so* nis.so* resource.so* termios.so*
_codecs_cn.so* _codecs_jp.so* crypt.so* _ctypes_test.so* future_builtins.so* linuxaudiodev.so* _multibytecodec.so* parser.so* _sysconfigdata.py _testcapi.so*
_codecs_hk.so* _codecs_kr.so* _csv.so* datetime.so* _hotshot.so* _lsprof.so* _multiprocessing.so* pyexpat.so* _sysconfigdata.pyc

可以看到,aarch32上面缺少了很多库, 比如_collections.so,将来这些库会被安装到/usr/lib/python2.7/lib-dynload下面, 所以下面要说的就是将缺少的这些库弄回来!

正文

1、通过分析setup.py发现问题

在函数build_extensions中刚开始self.extensions中存放的是需要编译库, 通过在加打印:

 diff --git a/setup.py b/setup.py
index 54054c2..bc16bb1
--- a/setup.py
+++ b/setup.py
@@ -, +, @@ class PyBuildExt(build_ext): def build_extensions(self): + print "build_extensions enter."
# Detect which modules should be compiled
missing = self.detect_modules() @@ -, +, @@ class PyBuildExt(build_ext):
extensions.append(ctypes)
self.extensions = extensions + for ext in self.extensions:
+ print "extensions: ", ext.name
+
# Fix up the autodetected modules, prefixing all the source files
# with Modules/ and adding Python's include directory to the path.
(srcdir,) = sysconfig.get_config_vars('srcdir')
@@ -, +, @@ class PyBuildExt(build_ext):
# Python header files
headers = [sysconfig.get_config_h_filename()]
headers += glob(os.path.join(sysconfig.get_path('include'), "*.h"))
+
+ print "builtin_module_names: ", sys.builtin_module_names
for ext in self.extensions[:]:
ext.sources = [ find_module_file(filename, moddirlist)
for filename in ext.sources ]
@@ -, +, @@ class PyBuildExt(build_ext):
remove_modules.append(line[])
input.close() + print "remove_modules: ", remove_modules
+
for ext in self.extensions[:]:
if ext.name in remove_modules:
self.extensions.remove(ext) + for ext in self.extensions[:]:
+ print "extensions: ", ext.name
+
# When you run "make CC=altcc" or something similar, you really want
# those environment variables passed into the setup.py phase. Here's
# a small set of useful ones.
@@ -, +, @@ class PyBuildExt(build_ext): # Platform-specific libraries
- if host_platform == 'linux2':
+ if host_platform == 'linux2' or host_platform == 'linux2-arm':
# Linux-specific modules
exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
else:
missing.append('linuxaudiodev') - if (host_platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6',
+ if (host_platform in ('linux2','linux2-arm' 'freebsd4', 'freebsd5', 'freebsd6',
'freebsd7', 'freebsd8')
or host_platform.startswith("gnukfreebsd")):
exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
@@ -, +, @@ class PyBuildExt(build_ext):
## ext = Extension('xx', ['xxmodule.c'])
## self.extensions.append(ext) +# print "missing: ", missing
+# for ext in self.extensions:
+# print "extensions: ", ext.name
+
return missing def detect_tkinter_explicitly(self):
@@ -, +, @@ Topic :: Software Development
""" def main():
+ print "sys.path: ", sys.path
+ print "cross_compiling: ", cross_compiling
# turn off warnings when deprecated modules are imported
import warnings
warnings.filterwarnings("ignore",category=DeprecationWarning)

然后执行./mk2_make.sh可以看到:

 sys.path:  ['/home/pengdonglin/src/qemu/python_cross_compile/Python-2.7.13', '/home/pengdonglin/src/qemu/python_cross_compile/aarch32/build/lib.linux2-arm-2.7', '/home/pengdonglin/src/qemu/python_cross_compile/Python-2.7.13/Lib', '/home/pengdonglin/src/qemu/python_cross_compile/Python-2.7.13/Lib/plat-linux2', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload']
cross_compiling: True
build_extensions enter.
extensions: _struct
extensions: _ctypes_test
extensions: array
extensions: cmath
extensions: math
extensions: strop
extensions: time
extensions: datetime
extensions: itertools
extensions: future_builtins
extensions: _random
extensions: _collections
extensions: _bisect
extensions: _heapq
extensions: operator
extensions: _io
extensions: _functools
extensions: _json
extensions: _testcapi
extensions: _hotshot
extensions: _lsprof
extensions: unicodedata
extensions: _locale
extensions: fcntl
extensions: pwd
extensions: grp
extensions: spwd
extensions: select
extensions: parser
extensions: cStringIO
extensions: cPickle
extensions: mmap
extensions: syslog
extensions: audioop
extensions: crypt
extensions: _csv
extensions: _socket
extensions: _sha
extensions: _md5
extensions: _sha256
extensions: _sha512
extensions: termios
extensions: resource
extensions: nis
extensions: binascii
extensions: pyexpat
extensions: _elementtree
extensions: _multibytecodec
extensions: _codecs_kr
extensions: _codecs_jp
extensions: _codecs_cn
extensions: _codecs_tw
extensions: _codecs_hk
extensions: _codecs_iso2022
extensions: _multiprocessing
extensions: linuxaudiodev
extensions: _ctypes
builtin_module_names: ('__builtin__', '__main__', '_ast', '_bisect', '_codecs', '_collections', '_functools', '_heapq', '_io', '_locale', '_md5', '_random', '_sha', '_sha256', '_sha512', '_socket', '_sre', '_struct', '_symtable', '_warnings', '_weakref', 'array', 'binascii', 'cPickle', 'cStringIO', 'cmath', 'errno', 'exceptions', 'fcntl', 'gc', 'grp', 'imp', 'itertools', 'marshal', 'math', 'operator', 'posix', 'pwd', 'select', 'signal', 'spwd', 'strop', 'sys', 'syslog', 'thread', 'time', 'unicodedata', 'xxsubtype', 'zipimport', 'zlib')
remove_modules: ['DESTLIB=$(LIBDEST)', 'MACHDESTLIB=$(BINLIBDEST)', 'DESTPATH=', 'SITEPATH=', 'TESTPATH=', 'MACHDEPPATH=:$(PLATDIR)', 'EXTRAMACHDEPPATH=', 'TKPATH=:lib-tk', 'OLDPATH=:lib-old', 'COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH)', 'PYTHONPATH=$(COREPYTHONPATH)', 'posix', 'errno', 'pwd', '_sre', '_codecs', '_weakref', 'zipimport', '_symtable', 'GLHACK=-Dclear=__GLclear', 'xxsubtype']
extensions: _ctypes_test
extensions: datetime
extensions: future_builtins
extensions: _json
extensions: _testcapi
extensions: _hotshot
extensions: _lsprof
extensions: parser
extensions: mmap
extensions: audioop
extensions: crypt
extensions: _csv
extensions: termios
extensions: resource
extensions: nis
extensions: pyexpat
extensions: _elementtree
extensions: _multibytecodec
extensions: _codecs_kr
extensions: _codecs_jp
extensions: _codecs_cn
extensions: _codecs_tw
extensions: _codecs_hk
extensions: _codecs_iso2022
extensions: _multiprocessing
extensions: linuxaudiodev
extensions: _ctypes
Python build finished, but the necessary bits to build these modules were not found:
_bsddb _curses _curses_panel
_sqlite3 _ssl _tkinter
bsddb185 bz2 dbm
dl gdbm imageop
ossaudiodev readline sunaudiodev
zlib
To find the necessary bits, look in setup.py in detect_modules() for the module's name.

在刚开始的时候,self.extensions中还是全的,但是经过下面的处理后, 很多库都被remove了:

         for ext in self.extensions[:]:
ext.sources = [ find_module_file(filename, moddirlist)
for filename in ext.sources ]
if ext.depends is not None:
ext.depends = [find_module_file(filename, moddirlist)
for filename in ext.depends]
else:
ext.depends = []
# re-compile extensions if a header file has been changed
ext.depends.extend(headers)
# platform specific include directories
ext.include_dirs.extend(incdirlist)
# If a module has already been built statically,
# don't build it here
if ext.name in sys.builtin_module_names:
self.extensions.remove(ext)

第15行的注释可以看到,如果sys.builtin_module_names中含有extensions中的库,那么这个库就会从extensions中remove。从目前的分析看,交叉编译的时候,setup.py的import sys导入的应该是PC机上面的环境,导致sys.builtin_module_names的值也是PC上面python运行环境的值(可以在PC的终端下输入python,查看sys.builtin_module_names的值)。

2、 解决

这里为了简单起见,我们只需把刚才出问题的判断注释掉,如下:

 @@ -, +, @@ class PyBuildExt(build_ext):

              # If a module has already been built statically,
# don't build it here
- if ext.name in sys.builtin_module_names:
- self.extensions.remove(ext)
+ #if ext.name in sys.builtin_module_names:
+ # self.extensions.remove(ext) # Parse Modules/Setup and Modules/Setup.local to figure out which
# modules are turned on in the file.

然后重新配置、编译、安装, 最后重新制作ramdisk文件,启动板子,重新执行下面的测试:

 [root@vexpress ]# python /usr/lib/python2./test/test___all__.py
test_all (__main__.AllTest) ... BaseHTTPServer
Bastion
CGIHTTPServer
ConfigParser
Cookie
DocXMLRPCServer
HTMLParser
MimeWriter
Queue
SimpleHTTPServer
... ...
'xml.sax.xmlreader', 'xmllib', 'xmlrpclib']
Following modules failed to be imported: ['ctypes.wintypes', 'dbhash', 'gzip', 'idlelib.AutoComplete']
ok
----------------------------------------------------------------------
Ran test in .345s
OK

可以看到,测试成功了。

下面开始一致sqlite3到板子上面,同时让python也增加多sqlite3的支持。

3、支持sqlite3

首先到http://www.sqlite.org/download.html 下载最新的sqlite3的源码,这里我用的是sqlite-autoconf-3170000.tar.gz,然后进行交叉编译,下面是交叉编译的脚本mk.sh:

 #!/bin/bash
export PATH=/home/pengdonglin/src/qemu/aarch32/arm-2014.05/bin:$PATH ../sqlite-autoconf-/configure --host=arm-none-linux-gnueabi \
--prefix=`pwd` make -j4
make install

然后修改制作ramdisk的脚本:

 #!/bin/bash

 sudo rm -rf rootfs
sudo rm -rf tmpfs
sudo rm -rf ramdisk* sudo mkdir rootfs
sudo cp ../busybox-1.24./_install/* rootfs/ -raf sudo mkdir -p rootfs/proc/
sudo mkdir -p rootfs/sys/
sudo mkdir -p rootfs/tmp/
sudo mkdir -p rootfs/root/
sudo mkdir -p rootfs/var/
sudo mkdir -p rootfs/mnt/ sudo cp etc rootfs/ -arf sudo cp -arf ../arm-2014.05/arm-none-linux-gnueabi/libc/lib rootfs/ #python
sudo mkdir -p rootfs/usr
pushd rootfs/usr
sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/bin .
sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/lib .
sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/include .
sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/share .
sudo /home/pengdonglin/qemu/aarch32/arm-2014.05/bin/arm-none-linux-gnueabi-strip lib/python*
popd 31 #sqlite3
32 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/bin/* rootfs/bin/
33 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/include/* rootfs/include/
34 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/lib/* rootfs/lib/
35 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/share/* rootfs/usr/share
sudo mkdir -p rootfs/dev/
sudo mknod rootfs/dev/tty1 c 4 1
sudo mknod rootfs/dev/tty2 c 4 2
sudo mknod rootfs/dev/tty3 c 4 3
sudo mknod rootfs/dev/tty4 c 4 4
sudo mknod rootfs/dev/console c 5 1
sudo mknod rootfs/dev/null c 1 3 sudo rm -rf rootfs/lib/*.a
sudo rm -rf rootfs/lib/*.la
sudo ../arm-2014.05/bin/arm-none-linux-gnueabi-strip rootfs/lib/* sudo dd if=/dev/zero of=ramdisk bs=1M count=100
sudo mkfs.ext4 -F ramdisk sudo mkdir -p tmpfs
sudo mount -t ext4 ramdisk ./tmpfs/ -o loop
sudo cp -raf rootfs/* tmpfs/
sudo umount tmpfs sudo gzip --best -c ramdisk > ramdisk.gz
sudo mkimage -n "ramdisk" -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.img

这样在板子上面就可以使用sqlite3了,但是此时python还无法使用,需要重新编译python,并指定sqlite3的lib和include的路径,修改mk1_config.sh如下:

#!/bin/bash

export PATH=/home/pengdonglin/qemu/aarch32/arm-2014.05/bin:$PATH

../Python-2.7./configure --prefix=`pwd` \
--host=arm-none-linux-gnueabi \
--build=x86_64-linux-gnu \
--enable-ipv6 \
--enable-shared \
ac_cv_file__dev_ptmx="yes" \
ac_cv_file__dev_ptc="no" \
LDFLAGS="-L/home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/lib" \
CPPFLAGS="-I/home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/include"

这样在Makefile调用setup.py时就会将sqlite3相关的模块编译进来,然后再次执行mk2_make.sh和mk3_install.sh,然后我们可以检查一下:

 $ls aarch32/build/lib.linux2-arm-2.7/
array.so* _codecs_hk.so* cPickle.so* datetime.so* _heapq.so* _locale.so* _multiprocessing.so* _random.so* _socket.so* _sysconfigdata.pyc
audioop.so* _codecs_iso2022.so* crypt.so* _elementtree.so* _hotshot.so* _lsprof.so* nis.so* resource.so* spwd.so* syslog.so*
binascii.so* _codecs_jp.so* cStringIO.so* fcntl.so* _io.so* math.so* operator.so* select.so* _sqlite3.so* termios.so*
_bisect.so* _codecs_kr.so* _csv.so* _functools.so* itertools.so* _md5.so* ossaudiodev.so* _sha256.so* strop.so* _testcapi.so*
cmath.so* _codecs_tw.so* _ctypes.so* future_builtins.so* _json.so* mmap.so* parser.so* _sha512.so* _struct.so* time.so*
_codecs_cn.so* _collections.so* _ctypes_test.so* grp.so* linuxaudiodev.so* _multibytecodec.so* pyexpat.so* _sha.so* _sysconfigdata.py unicodedata.so*

可以看到,库已经很全了。

4、测试

重新制作ramdisk文件,启动系统。

编写测试sqlite3的脚本sq_demo.py如下:

 #!/usr/bin/python

 import sqlite3                   

 #open database
conn = sqlite3.connect('test.db')
print "Opened database successfully"; conn.execute('''CREATE TABLE COMPANY
(ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL);''')
print "Table created successfully"; #insert
conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
VALUES (1, 'Paul', 32, 'California', 20000.00 )"); conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
VALUES (2, 'Allen', 25, 'Texas', 15000.00 )"); conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
VALUES (3, 'Teddy', 23, 'Norway', 20000.00 )"); conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \
VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 )"); conn.commit()
print "Records created successfully"; #select
cursor = conn.execute("SELECT id, name, address, salary from COMPANY")
for row in cursor:
print "ID = ", row[0]
print "NAME = ", row[1]
print "ADDRESS = ", row[2]
print "SALARY = ", row[3], "\n" print "Operation done successfully"; #delect
conn.execute("DELETE from COMPANY where ID=2;")
conn.commit()
print "Total number of rows deleted :", conn.total_changes cursor = conn.execute("SELECT id, name, address, salary from COMPANY")
for row in cursor:
print "ID = ", row[0]
print "NAME = ", row[1]
print "ADDRESS = ", row[2]
print "SALARY = ", row[3], "\n" print "Operation done successfully"; conn.close()

下面是输出结果:

[root@vexpress ]# python /tmp/sq_demo.py
Opened database successfully
Table created successfully
Records created successfully
ID =
NAME = Paul
ADDRESS = California
SALARY = 20000.0 ID =
NAME = Allen
ADDRESS = Texas
SALARY = 15000.0 ID =
NAME = Teddy
ADDRESS = Norway
SALARY = 20000.0 ID =
NAME = Mark
ADDRESS = Rich-Mond
SALARY = 65000.0 Operation done successfully
Total number of rows deleted :
ID =
NAME = Paul
ADDRESS = California
SALARY = 20000.0 ID =
NAME = Teddy
ADDRESS = Norway
SALARY = 20000.0 ID =
NAME = Mark
ADDRESS = Rich-Mond
SALARY = 65000.0 Operation done successfully

完。

交叉编译Python-2.7.13到ARM(aarch32)—— 支持sqlite3的更多相关文章

  1. 交叉编译Python-3&period;6&period;0到aarch64&sol;aarch32 —— 支持sqlite3

    参考 https://datko.net/2013/05/10/cross-compiling-python-3-3-1-for-beaglebone-arm-angstrom/ 平台 主机: ubu ...

  2. 交叉编译Python-2&period;7&period;13到ARM(aarch32)平台

    作者:彭东林 邮箱:pengdonglin137@163.com QQ:405728433 环境 主机: ubuntu14.04 64bit 开发板: qemu + vexpress-a9 (参考: ...

  3. 交叉编译Python-2&period;7&period;13到ARM(aarch64)平台

    方法跟交叉编译Python-2.7.13到ARM(aarch32)平台基本一样, 不同的地方只是把工具链换成编译aarch64的工具链,这里可以参考用qemu搭建aarch64学习环境. 创建目录: ...

  4. 如何交叉编译Python到ARM-Linux平台(转)

    源: 如何交叉编译Python到ARM-Linux平台

  5. ubuntu 交叉编译qt 5&period;7 程序到 arm 开发板

    ubuntu 交叉编译qt 5.7 程序到 arm 开发板平台1 ubuntu 12.042 arm-linux-gcc 4.5.13 QT 5.74 开发板210 armcortex-A8 一 概述 ...

  6. ipython&comma; 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数

    一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 若用的是fish s ...

  7. Python内置的urllib模块不支持https协议的解决办法

    Django站点使用django_cas接入SSO(单点登录系统),配置完成后登录,抛出“urlopen error unknown url type: https”异常.寻根朔源发现是python内 ...

  8. Xamarin图表开发基础教程(13)OxyPlot框架支持的其它图表

    Xamarin图表开发基础教程(13)OxyPlot框架支持的其它图表 除了以上提到的图表外,OxyPlot组件还包含了6种类型的其它图表,分别为等高线图.箱线图.饼图.热图.散点图和散点误差图,如图 ...

  9. VS Code Python 全新发布!Jupyter Notebook 原生支持终于来了!

    VS Code Python 全新发布!Jupyter Notebook 原生支持终于来了! 北京时间 2019 年 10 月 9 日,微软发布了全新的 VS Code Python 插件,带来了众多 ...

随机推荐

  1. 分析nuget源码,用nuget &plus; nuget&period;server实现winform程序的自动更新

    源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...

  2. 怎么把Windows主机上的目录共享到Ubuntu上

    使用Oracle VM VirtualBox在Windows主机上创建了一台Ubuntu虚拟机,怎么把宿主机上的目录共享到Ubuntu上,可使用以下方法: eg.把Windows主机上D盘里的test ...

  3. Spring 下载与安装以及spring 3&period;2&period;9 jar包详解

    一.Spring简介  Spring官网改版后,很多项目的完整zip包下载链接已经隐掉了,虽然Spring旨在引导大家用更“高大上”的maven方式来管理所依赖的jar包,但是完全没想到中国的国情,在 ...

  4. svn status详解

    svn 是在提交前查看本地文本和版本库里面的文件的区别.返回值有许多种具体含义如下: [url=]  L    abc.c               # svn已经在.svn目录锁定了abc.c M ...

  5. java中super关键字的作用

    1.super关键字可以在子类的构造方法中显示地调用父类的构造方法,super()必须为子类构造函数中的第一行. 2.super可以用来访问父类的成员方法或变量,当子类成员变量或方法与父类有相同的名字 ...

  6. Solr系列四:Solr(solrj 、索引API 、 结构化数据导入)

    一.SolrJ介绍 1. SolrJ是什么? Solr提供的用于JAVA应用中访问solr服务API的客户端jar.在我们的应用中引入solrj: <dependency> <gro ...

  7. tpshop商品属性表关系

    TPshop 里面的商品属性, 首先看看TPshop商品详情中的属性介绍, 纯展示给用户看的. 再来tpshop看看商品列表帅选页面的属性,可以根据属性帅选不同的商品 再来看看tpshop后台属性管理 ...

  8. 【PHP】善用php-fpm的慢执行日志slow log,分析php性能问题

    (转)善用php-fpm的慢执行日志slow log,分析php性能问题  众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题.作为mysql的好 ...

  9. paraview isosurface

    参考:https://www.youtube.com/watch?v=UjoSvWdxlTA

  10. 调用Linux的busybox,通过linux命令来获取AndRoidIP

    //根据busybox获取本地Mac public static String getLocalMacAddressFromBusybox(){ String result = "&quot ...