转自:https://my.oschina.net/hevakelcj/blog/411944

摘要: 本文尝试用C++来开发一个cpp-demo包 遇到打包库依赖的问题,分析打包过程并解决了这个问题。

C++是本人的强项。如果在OpenWrt中不能用C++进行开发,那就有点大失所望了。

接下来将与大家一起来尝试写一个C++程序,并把它做成 ipk 包,并试运行。

各文件内容

在 SDK/package/ 路径下创建 cpp-demo 目录,并生成一个非常简单的 cpp 程序

$ cd SDK
$ mkdir -p package/cpp-demo
$ cd package/cpp-demo
$ touch Makefile
$ mkdir src
$ cd src
$ touch Makefile main.cpp 形成如下目录结构: $ tree package/demo-cpp
package/cpp-demo/
|-- Makefile
`-- src
|-- main.cpp
`-- Makefile package/cpp-demo/src/main.cpp内容: #include <iostream> using namespace std; int main(int argc, char **argv)
{
cout << "This is C++ Demo" << endl;
return ;
} package/cpp-demo/src/Makefile内容: target=cpp-demo ALL:$(target) objects=main.o cpp-demo: $(objects)
$(CXX) -o $(target) $(objects) clean:
@rm -rf $(objects) 注意:上面用的是CXX,而不是CC,就这点区别。 package/Makefile内容: include $(TOPDIR)/rules.mk PKG_NAME:=cpp-demo
PKG_RELEASE:=
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) include $(INCLUDE_DIR)/package.mk define Package/cpp-demo
SECTION:=utils
CATEGORY:=Utilties
TITLE:=cpp-demo
endef define Build/Prepare
$(MKDIR) -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)
endef define Package/cpp-demo/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/cpp-demo $(1)/bin
endef $(eval $(call BuildPackage,cpp-demo))

解决链接错误

在SDK目录下 make V=s,结果报错:

Package cpp-demo is missing dependencies for the following libraries:
libstdc++.so.

对错误的初步认识

说是要依赖 libstdc++.so. 这个库文件?

那好吧,在本地机上安装一个便是了。

$ sudo yum install libstdc++
...省略...
Package libstdc++-4.4.-.el6.i686 already installed and latest version
Nothing to do 说明本地已安排了libstdc++了的。难不成是版本对不上号? 我用 locate命令找了一下 libstdc++这个文件,发现存在 /usr/lib/libstdc++.so. 文件。这应该就是上面需要的库吧。 应该在LD_LIBRARY_PATH环境变量中没有将 /usr/lib 加入到其中。如下: $ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib make V=s 这次,报: Package cpp-demo is missing dependencies for the following libraries:
libc.so.
libm.so.
libstdc++.so. 不凑效?!

发现依赖的是目标机的动态库

不过静下心来想想,我编译cpp-demo需要的是开发机的动态库呢,还是目标机的动态库?

动态库是程序在运行起来后加载的库,那么cpp-demo在目标机上运行起来后,加载的动态库应该是目标机的,不应该是开发机的。所以,刚刚我在整开发机上的动态库,与这个应该是两码事儿。

在SDK路径下搜所有的动态库文件:

$ find -name lib*.so.*
./staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libzmq.so.
./staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libevent_openssl-2.0.so.
./staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/libpopt.so.0.0.
...<略>
./staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/mysql/libmysqlclient.so.
./staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/mysql/libmysqlclient_r.so.16.0.
...<略>
./staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/lib/libc.so.
./staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/lib/libstdc++.so.
...<略>
./staging_dir/host/lib/libltdl.so.
./staging_dir/host/lib/liblzma.so. 有很多,也看到了 libstdc++.so. 应该是在链接时将 libstdc++.so. 所在的路径加进来吧。就像: g++ -L./staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/lib/ -lstdc++ 这样。

排除编译错误

我们检查编译调试信息打印出来的LDFLAGS的值:

LDFLAGS="-L/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib\
-L/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/lib\
-L/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib\
-L/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/lib " 这说明,libstdc++.so.6已在LDFLAGS的路径范围之下,编译不应该出错。 还是好好研究一下错误提示: make[]: Entering directory `/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo'
make[]: Nothing to be done for `ALL'.
make[]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo'
touch /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/.built
mkdir -p /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/bin/ar71xx/packages /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/ipkg-ar71xx/cpp-demo/CONTROL /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/pkginfo
install -d -m0755 /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/ipkg-ar71xx/cpp-demo/bin
install -m0755 /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/cpp-demo /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/ipkg-ar71xx/cpp-demo/bin
find /home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/ipkg-ar71xx/cpp-demo -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| xargs -r rm -rf
Package cpp-demo is missing dependencies for the following libraries:
libc.so.
libm.so.
libstdc++.so.
make[]: *** [/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/bin/ar71xx/packages/base/cpp-demo_1_ar71xx.ipk] Error 从前3行看来,cpp-demo的编译好像是正常通过了的。 查看 build_dir/target-mips tree build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/
build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/
|-- cpp-demo
|-- ipkg-ar71xx
| `-- cpp-demo
| |-- bin
| | `-- cpp-demo
| `-- CONTROL
|-- main.cpp
|-- main.o
`-- Makefile directories, files 在这个路径下已经成功生成了cpp-demo可执行程序。证明,编译是通过了的。 为什么 find 执行完就报错?

深入研究错误根源

怎么入手?从错误提示入手吧,看看是在哪里提示"Package cpp-demo is missing dependencies for the following libraries"的。

在SDK目录下执行 grep 命令进行查找。

$ grep "is missing dependencies for the following libraries" ./* -R
./include/package-ipkg.mk: echo "Package $(1) is missing dependencies for the following libraries:" >&2; \ package-ipkg.mk 打开 include/package-ipkg.mk 文件看个究竟。

在74行输入错误提示信息,条件是存在文件 $(PKG_INFO_DIR)/$().missing 这个文件。那问题来了,这个文件是怎么产生的呢?

行70~71行的意思是:如果在 $(PKG_INFO_DIR)/$().provides 中没有找到$FILE的,就把$FILE写入到 $(PKG_INFO_DIR)/$().missing
其中 $()值为cpp-demo,相应的 cpp-demo.provides 与 cpp-demo.missing 都是在 SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/pkginfo/ 路径下的。 那么 xxx.provides 文件里的内容代码什么呢? ~68行为一个执行进程,它用管道与while语句连接起来。也就是说while里面的FILE变量就是63~68行标准输出的结果。
,,67是在根据平台设置环境变量的值,然后在68行执行 SDK/scripts/gen-dependencies.sh。 我猜gen-dependencise.sh执行输出的一定是cpp-demo所依赖的库名称。 研究gen-dependencise.sh 我们打开 SDK/scripts/gen-dependencise.sh 文件,其中最核心的一段: #!/usr/bin/env bash TARGETS=$*
XARGS="${XARGS:-xargs -r}" find $TARGETS -type f -a -exec file {} \; | \
sed -n -e 's/^\(.*\):.*ELF.*\(executable\|shared object\).*,.* stripped/\1/p' | \
$XARGS -n1 $READELF -d | \
awk '$2 ~ /NEEDED/ && $NF !~ /interpreter/ && $NF ~ /^\[?lib.*\.so/ { gsub(/[\[\]]/, "", $NF); print $NF }' | \
sort -u 从TARGETS目录下查看到所有的文件。对每个文件并用file命令输入该文件的基本信息。用sed对file的输出进行分析,找出有"ELF"且有"executable"或"shared object"关键字的文件。
再对这个文件用 readelf -d 命令输入ELF文件的信息,再用awk从中提取出所依赖的 *.so 文件名,并打印到标准输出。 我亲手用readelf查看一下cpp-demo依赖什么: $ readelf -d build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/cpp-demo Dynamic section at offset 0x934 contains entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libstdc++.so.]
0x00000001 (NEEDED) Shared library: [libm.so.]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.]
0x00000001 (NEEDED) Shared library: [libc.so.]
0x0000000c (INIT) 0x80484e8
...<省略> 它确实依赖 libstdc++.so., libm.so., libc.so. 这3个动态库文件。 现在 package-ipk.mk 文件中过程理清楚了。cpp-demo所依赖的库文件,在cpp-demo.provides 文件中找不到就会写入到 cpp-demo.missing。 如果纯粹是想让它打包成功的话,那就把差的文件写入到cpp-demo.provides文件就了事儿了。 这样做会不会有后有后遗症? 试试再说~,结果还是不成功。原因是cpp-demo.provides是自动生成的。就算是我手动改了它,下次make的时候还是会还原的。 那新问题是:Who在生成这个cpp-demo.provides文件?它是根据什么生成这个文件的? 那就grep一下关键字"$(1).provides",应该就可以找到。结果还是在 package-ipk.mk 文件里:

L185,将数据进行排序了之后写入到 cpp-demo.provides。数据由L179~184产生。

L179,将IDIR_$()目录下的所有 lib*.so*, *.ko 文件名打印出来,作为已有的库文件,由L185写入cpp-demo.provides文件。

IDIR_$()的定义如下:

L180~184这个for循环不太好理解。

其中patsubst,是个字串替换命令,其详细用法见:[makefile中的patsubst]

$(patsubst %,$(PKG_INFO_DIR)/%.provides,$(IDEPEND_$())) 返回的结果是:将$(IDEPEND_$())中的每个结果 item,变成:$(PKG_INFO_DIR)/$(item).provides返回。

那IDEPEND_$()是什么?

博主深深地感到脑容量不够了。有哪位高人知道的,请指点一下。

跳出这个洞,回到L180~184,的问题。它就是把其它的某个相关的 xxxx.provides 文件里的内容输出来。

博主通过经验推断,xxxx.provides 代表的是是与cpp-demo依赖的组件所依赖的库。

解决方案一:在 Makefile 中添加 Package/cpp-demo/extra_provides 宏

注意:L184,是 $(Package/$()/extra_provides)。也就是说,我们可以在 package/cpp-demo/Makefile 文件中定义 Package/cpp-demo/extra_provides 宏来强制性地将那几个库加进去。比如:

define Package/cpp-demo/extra_provides
echo "libstdc++.so.6"
echo "libc.so.6"
echo "libm.so.6"
endef 经过试验,正确的写法如下: define Package/cpp-demo/extra_provides
echo 'libstdc++.so.6'; \
echo 'libm.so.6'; \
echo 'libc.so.6';
endef 这样写果然凑效,再 make V=s,能够打包成功。 但是,有点我们必须明确的是:在打包中生成的ipk文件里,是没有libstdc++, libc, libm这3个库的。如果所安装的OpenWrt系统里也没有这3个库,那么我们安装的应用程序是不能正常使用的。
相当于是在骗ipk工具,我们已具备了上面这3个库文件。 比较稳妥的方法是采用方案二,如下:

解决方案二:在 Makefile 中的 Package/cpp-demo/install 宏中准备所需的库文件

还有另一个方法,注意L176,$(call Package/$()/install, $$(IDIR_$())),这个就是引用了我们在Makefile里写的 Package/cpp-demo/install 宏么?
我们可以在这个宏里,将它需要的几个库文件复制到 $() 对应的目录下。 如下修改: define Package/cpp-demo/install
$(INSTALL_DIR) $()/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/cpp-demo $()/bin $(INSTALL_DIR) $()/usr/lib
$(INSTALL_DATA) $(TOOLCHAIN_DIR)/lib/libstdc++.so. $()/usr/lib
$(INSTALL_DATA) $(TOOLCHAIN_DIR)/lib/libm.so $()/usr/lib/libm.so.
$(INSTALL_DATA) $(TOOLCHAIN_DIR)/lib/libc.so $()/usr/lib/libc.so.
endef 其中,INSTALL_DATA 与 TOOLCHAIN_DIR 这两个变量在 rules.mk 文件中定义。
之所以选用 TOOLCHAIN_DIR,是因为libstdc++.so.6这个文件就在这个变量所对应的路径下。不信,你可以用 find 命令查找一下。 好了,这样再make V=s,就能正常打包了。

解决方案三:在 Makefile 文件的 Package/cpp-demo 宏中加 DEPENDS 描述

这个方法不是我想到的,是[GunNRose]给我建议。修改 Makefile:

define Package/cpp-demo
...<略>
DEPENDS:+=libstdcpp
endef 经博主亲自尝试,是OK的。 不过,为什么是叫libstdcpp而不是libstdc++呢?这个有待研究一下。 官方Dependence文档:http://wiki.openwrt.org/doc/devel/dependencies

试用

将生成的 SDK/bin/ar71xx/packages/base/cpp-demo_1_ar71xx.ipk 文件用 scp 传到目标机上进行安装试用。

$ scp bin/ar71xx/packages/base/cpp-demo_1_ar71xx.ipk root@192.168.1.2:
root@192.168.1.2's password:
cpp-demo_1_ar71xx.ipk % 278KB .0KB/s :
$ 然后用 SSH 登陆到目标机上去安装。 root@OpenWrt:~# opkg install cpp-demo_1_ar71xx.ipk
Installing cpp-demo () to root...
Configuring cpp-demo. 试执行一下 cpp-demo root@OpenWrt:~# cpp-demo
/bin/cpp-demo: line : syntax error: unexpected word (expecting ")") Oops~ 运行不起来。

解决运行不起来的问题

检查一下那3个依赖的库文件,都还在。那为什么不能运行起来呢?

之前博主在排查上面库依赖的问题的时候已看出了端倪。

在 SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/ipkg-ar71xx/cpp-demo/ 路径下的所有内容都是直接打包的文件。而这里面的 bin/cpp-demo 可执行文件在开发机上居然都正常运行。

这明显不对,bin/cpp-demo 应该是运行在目标机上的ELF文件,怎么可以在开发机上运行?开发机与目标机都不是同类型的CPU。一定是这里出了问题!

博主在想,是不是在交叉编译的时候,选用了本机的gcc,而非目标机的gcc。如下为 SDK/package/cpp-demo/src/Makefile :

target=cpp-demo

ALL:$(target)

objects=main.o

cpp-demo: $(objects)
echo "CXX = $(CXX)"
$(CXX) -o $(target) $(objects) clean:
@rm -rf $(objects) 为了知道CXX到底是哪一个编译器。我特地加了 echo "CXX = $(CXX)" 调试信息。 把 SDK/build_dir 删了重新 make。为了方便分析, $ rm -rf build_dir
$ make V=s | less 分析打印的信息: CC="mips-openwrt-linux-uclibc-gcc" GCC="mips-openwrt-linux-uclibc-gcc" CXX="mips-openwrt-linux-uclibc-g++"
...
make[]: Entering directory `/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo'
make[]: Nothing to be done for `ALL'.
make[]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo'
... 咦?Nothing to be done for 'ALL',表示没有什么需要再编译的了。 我赶紧查看 [SDK]$ ls build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo/
cpp-demo ipkg-ar71xx main.cpp main.o Makefile 发现cpp-demo已经生成,而且在开发机上可运行。这个cpp-demo是怎么来的?难不出是从 package/cpp-demo/src里来的? 我突然想到,我之前进入 package/cpp-demo/src/ 路径下,执行过一次 make,那时一定生成了一个 cpp-demo 可执行程序。查看之: [SDK]$ ls package/cpp-demo/src/
cpp-demo main.cpp main.o Makefile 果然有它!在make时,由于它的存在,编译组件就认为已经有了就不必再编译,所以才导致了上述的问题。 删除cpp-demo以及main.o。回到SDK,重新make $ rm -rf build_dir
$ make V=s | less 分析打印的信息: CC="mips-openwrt-linux-uclibc-gcc" GCC="mips-openwrt-linux-uclibc-gcc" CXX="mips-openwrt-linux-uclibc-g++"
...
make[]: Entering directory `/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo'
mips-openwrt-linux-uclibc-g++ -Os -pipe -mno-branch-likely -mips32r2 -mtune=34kc -fno-caller-saves -fhonour-copts -Wno-error=unused-but-set-variable \
-msoft-float -mips16 -minterlink-mips16 -I/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/include \
-I/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/include \
-I/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include \
-I/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/include \
-c -o main.o main.cpp
echo "DEBUG: CXX = mips-openwrt-linux-uclibc-g++"
DEBUG: CXX = mips-openwrt-linux-uclibc-g++
mips-openwrt-linux-uclibc-g++ -o cpp-demo main.o
make[]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/cpp-demo'
... 根据调试信息可以知道cpp-demo是用mips-openwrt-linux-uclibs-g++来编译的。这下应该就对了! 再次尝试将ipk文件传到目标机上并安装。运行效果如下: root@OpenWrt:~# cpp-demo
This is C++ Demo 成功了!

总结

这一次,一个小小的cpp-demo实验,经历了太多波折。不过在尝试解决这些问题的过程中,我们可以更深入地了解其中的编译机制。

首先,我们知道了创建C++应用与C应用没什么区别,莫非就是在Makefile中将CC改成CXX。

然后我们了解到了在打包的时候,它是如何查找一个ELF文件依赖哪些动态包。并知道如何将所依赖的包加入到我们的ipk中。

最后,我们了解到了在rules.mk中定义了大量有用的变量,在include/package-ipk.mk文件中了解到打包的过程。

总之,这次折腾也算是蛮有收获的。

求被关注

我会坚持天天学习,并写博文。如果小伙伴们想一定来研究,那就关注我吧~

OpenWRT开发之——对C++的支持(解决库依赖问题)【转】的更多相关文章

  1. strace 解决库依赖问题

    解决库依赖问题 starce 的另一个用处是解决和动态库相关的问题.当对一个可执行文件运行ldd时,它会告诉你程序使用的动态库和找到动态库的位置.但是如果你正在使用一个比较老 的glibc版本(2.2 ...

  2. Android Studio 解决 Gradle 依赖冲突的问题

    Android Studio 解决 Gradle 依赖冲突的问题 参考链接: Android Studio(Gradle)解决库依赖冲突问题:http://www.mobibrw.com/2016/3 ...

  3. 产品经理如何赢得开发人员的尊重和支持?-摘自infoq

    对于产品经理来说,赢得开发人员的尊重和支持,从某种意义上讲,是产品迈向成功的坚实一步.最近,知乎社区上的开发人员和管理者在前.后两个帖子中对此展开了激烈的讨论,其中不乏真知灼见. 林志霖Cray认为产 ...

  4. 《连载 | 物联网框架ServerSuperIO教程》-4.如开发一套设备驱动,同时支持串口和网络通讯。附:将来支持Windows 10 IOT

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  5. ReactNative新手学习之路04 组件化开发轮播图swiper支持安卓和IOS

    react native 新手之路04 组件化开发轮播图swiper支持安卓和IOS npm install react-native-carousel --save git 地址Properties ...

  6. Senparc.Weixin.MP SDK 微信公众平台开发教程(七):解决用户上下文(Session)问题

    从这篇文章中我们已经了解了微信公众平台消息传递的方式,这种方式有一个先天的缺陷:不同用户的请求都来自同一个微信服务器,这使得常规的Session无法使用(始终面对同一个请求对象,况且还有对方服务器Co ...

  7. Android开发:ScrollView嵌套GridView的解决办法

    Android开发:ScrollView嵌套GridView的解决办法   前些日子在开发中用到了需要ScrollView嵌套GridView的情况,由于这两款控件都自带滚动条,当他们碰到一起的时候便 ...

  8. openwrt开发

    之前写过一篇日志,是关于如何搭建自己的OpenWRT开发环境.经过最近一段时间的开发学习和实践,对OpenWRT环境的开发有了一定的了解.在这里将我的开发心得做个整理. 1.搭建开发环境 首先,我们需 ...

  9. java开发中遇到的问题及解决方法(持续更新)

    摘自 http://blog.csdn.net/pony12/article/details/38456261 java开发中遇到的问题及解决方法(持续更新) 工作中,以C/C++开发为主,难免与其他 ...

随机推荐

  1. 个人作业3——个人总结AlPha阶段

    一.Alpha版本的总结 1.感受 Alpha版本已经结束了,回顾整个过程,我最大的遗憾就是项目完成得不是很理想,同时觉得自己做得不够多.不够好. 2.我做了哪些工作 数据库的连接,部分团队博客:部分 ...

  2. SSM 框架快速整合实例--学生查询

    一.快速准备 SSM 框架即 Spring 框架.SpringMVC 框架.MyBatis 框架,关于这几个框架的基础和入门程序,我前面已经写过几篇文章作为基础和入门介绍了.对于这 3 个框架还不熟悉 ...

  3. [知乎]关于WindowsXPx64SP2系统的说明

    自己简单安装了下发现 winxpsp3x86的系统版本为: 然后windowsXPx64sp2的版本为:   作者:qpi667链接:https://www.zhihu.com/question/29 ...

  4. k8s kubectl edit 方式修改 nodeport 的端口

    0. 买了一本 每天五分钟玩转 k8s 还有 刚才转帖的blog 里面有一个 kubectl edit 的语法能够在线更改端口号 ,之前一直没弄明白. 刚才做了下实验.发现很好用 这里记录一下. 1. ...

  5. 微信小游戏 项目配置文件 project.config.json

    一.项目配置文件project.config.json 小程序开发者工具在每个项目的根目录都会生成一个 project.config.json,在工具上做的任何配置都会写入到这个文件,当重新安装工具或 ...

  6. Codeforces 68D - Half-decay Tree

    题意 有一颗高度为 \(h\) 的完全二叉树(即点数为 \(2^{h+1}-1\) ),有两种操作: add x y 给 \(x\) 点的权值加 \(y\) decay 一次衰变定义为选择一个叶子节点 ...

  7. Luogu2257 YY的GCD/BZOJ2818 Gcd加强版(莫比乌斯反演+线性筛)

    一通套路之后得到 求出中间那个函数的前缀和的话就可以整除分块了. 暴力求的话复杂度其实很优秀了,大约在n~nlogn之间. 不过可以线性筛做到严格线性.考虑其最小质因子,如果是平方因子那么只有其有贡献 ...

  8. 洛谷P3950 部落冲突(LCT)

    洛谷题目传送门 最无脑LCT题解,Dalao们的各种算法都比这个好多啦... 唯一的好处就是只管码代码就好了 开战cut,停战link,询问findroot判连通性 太无脑,应该不用打注释了.常数大就 ...

  9. caffe多任务、多标签

    解决的目标问题:多分类问题,比如车辆的外形和颜色,苹果的大小和颜色:多任务:车牌角点的定位和车牌的颜色.定位在技术上属于回归,车牌颜色判断则属于分类. 技术点 caffe默认是单输入任务单标签的,也就 ...

  10. NetBeans无法使用svn相关功能

    本来中NetBeans使用subversion功能只要下载过subversion客户端就可以直接使用了,我也一直是这样的,可是今天忽然的不能用了,发现问题是因为我在文件中使用subversion的比较 ...