最近在linux上跑一些开源库做学习用, 顺手就搭了一下vscode的c++开发环境, 这里分享一下vscode进行C++开发的基本环境结构.

1. 首先是编辑器, vscode直接官网下载的, 后期可以用 apt 直接更新, 个人觉得还是挺方便的, 有喜欢折腾的小伙伴可以去github上拉开源版本的下来自己编译, 这里不过多赘述

2. 其次是编译器, 我使用的是GNU编译器g++, 生成脚本我选择了makefile

以上是基础工具, 如果把vscode换成vim + shell脚本, 调试直接gdb的话, 就基本上是原生环境开发了

接下来就是开发环境的搭建了, 这里我先整理一下一个工程量稍微大一些的项目所应该包含的项目种类, 再根据整理的结果给出一个我写的例子, 之后再对该例进行不断完善

对于一个大型工程来说, 可能至少会包含以下几种不同的工程:

1. 可执行程序 : 即项目主要的目标

2. 静态库 : 集成一些基础的工具函数和一些基础功能的封装

3. 动态库 : 作为插件, 非核心功能之类的东西

4. 资源文件 : 各种图片, 文件, 音频, xml等等

以上是我认为的一个工程量稍大的程序可能会包含的项目种类, 根据上面这四类, 我构建了如下的文件结构 :

.
├── debug
├── lib
├── project
│   ├── debug.makefile
│   ├── exe_test
│   │   ├── compile
│   │   ├── .d
│   │   ├── header
│   │   │   └── test.h
│   │   ├── makefile
│   │   └── src
│   │       └── test.cpp
│   ├── lib_a
│   │   ├── compile
│   │   ├── .d
│   │   ├── header
│   │   │   ├── a_1st.h
│   │   │   ├── a_2nd.h
│   │   │   └── a_3rd.h
│   │   ├── makefile
│   │   └── src
│   │       ├── a_1st.cpp
│   │       ├── a_2nd.cpp
│   │       └── a_3rd.cpp
│   ├── lib_so
│   │   ├── compile
│   │   ├── .d
│   │   ├── header
│   │   │   ├── so_1st.h
│   │   │   ├── so_2nd.h
│   │   │   └── so_3rd.h
│   │   ├── makefile
│   │   └── src
│   │       ├── so_1st.cpp
│   │       ├── so_2nd.cpp
│   │       └── so_3rd.cpp
│   └── makefile
├── release
└── .vscode
    ├── c_cpp_properties.json
    ├── launch.json
    ├── settings.json
    └── tasks.json

20 directories, 23 files

在当前项目目录下共有4个子目录和一个vscode专用的隐藏目录 :

1. debug : 所有我们生成的debug版本的可执行程序以及debug版本程序所需的资源都会生成在这个目录中

2. release : 同上, 但可执行程序和资源文件都是release版的

3. lib : 所有动态库, 静态库会生成在这个目录中, debug版和release版用文件名结尾是否带 D 来区分

4. project : 所有当前项目相关的工程都在这个目录中

5. .vscode : vscode专用目录, 其中包含了当前项目相关的vscode配置信息

下面再看一下project目录, 该目录下共有3个项目目录和两个makefile :

1. lib_a : 该项目最终会生成一个静态库供程序使用

2. lib_so : 该项目最终会生成一个动态库供程序使用

3. exe_test : 该项目最终会生成一个可执行程序, 该程序会使用到上述静态库和动态库

4. 两个makefile用于控制所有项目的debug版, release版生成

最后再解析一下每一个项目目录, 每个项目都包含了4个子目录和一个makefile :

1. src : 所有的源文件放置在该目录中

2. header : 所有的头文件放置在该目录中

3. compile : 编译后的.o文件会在这个目录中生成

4. .d : 该目录用于存放每个源文件的依赖关系

5. makefile : 该makefile控制当前项目的生成

以上是例子文件结构的大概说明, 下面我们就这个例子进行完善, 针对每一个工程和整个项目, 编写makefile, 完成代码的编译生成

首先针对整个项目, 我们要生成每一个工程, 并保证工程的生成顺序符合每个工程间的依赖关系

这里先看一下project/makefile, 这个makefile用于生成所有工程release版本

 export BUILD_VER := RELEASE
export CXXFLAGS := -Wall -std=c++
export RM := rm -f .PHONY:build_all clean_all clean_all_cache build_all:
cd ./lib_so && make
cd ./lib_a && make
cd ./exe_test && make clean_all:
cd ./lib_so && make clean
cd ./lib_a && make clean
cd ./exe_test && make clean clean_all_cache:
cd ./lib_so && make clean_cache
cd ./lib_a && make clean_cache
cd ./exe_test && make clean_cache

该makefile首先会覆写3个变量, 并将变量导出成为全局变量, 其中BUILD_VER用于控制生成程序的版本, 紧随其后的是3个伪目标, 分别用于生成每个工程, 清理所有生成文件以及清理生成过程中的产生的.o和.d

接下来再来看project/debug.makefile, 这个makefile用于生成所有工程的debug版本

 include ./makefile

 BUILD_VER := DEBUG

该makefile引入release版的makefile, 并修改BUILD_VER为DEBUG, 该makefile名称不是make能够自动识别的名称, 使用需要加上 -f 参数, 如 : make -f debug.makefile

通过上面两个makefile, 我们基本完成了对代码生成的版本控制和整个项目的生成流程, 下面只需要针对每一个工程, 编写对应的makefile即可

下面是3个工程的makefile :

首先是静态库工程lib_a

 vpath %.cpp ./src
vpath %.h ./header .PHONY: all clean clean_cache
all : # 默认目标 CXXINCLUDES = -I ./header
ARFLAGS = -rcs
SRCS_WITH_PATH = $(wildcard ./src/*.cpp)
SRCS = $(SRCS_WITH_PATH:./src/%.cpp=%.cpp)
DEPS = $(SRCS:.cpp=.d)
DEPS_WITH_PATH = $(SRCS:%.cpp=./.d/%.d)
OBJS = $(SRCS:.cpp=.o)
OBJS_WITH_PATH = $(SRCS:%.cpp=./compile/%.o)
TARGET_NAME = tsi.a
OUTDIR = ../../lib/ ifeq ($(BUILD_VER), DEBUG)
CXXFLAGS += -g3
TARGET_NAME := tsiD.a
endif ifeq ($(BUILD_VER), RELEASE)
CXXFLAGS += -O2
endif #生成依赖关系,保证修改.h时也会重新编译相关.cpp
-include $(DEPS) %.d:$(SRCS)
@set -e;\
$(RM) $@;\
$(CXX) $(CXXINCLUDES) -MM $< > .d/$@; %.o:%.cpp
$(CXX) $(CXXFLAGS) $(CXXINCLUDES) -c $< -o ./compile/$@ all:$(TARGET_NAME) $(TARGET_NAME):$(OBJS)
$(AR) $(ARFLAGS) $(OUTDIR)$(TARGET_NAME) $(OBJS_WITH_PATH) clean:
$(RM) $(OUTDIR)$(TARGET_NAME) $(OBJS_WITH_PATH) $(DEPS_WITH_PATH) clean_cache:
$(RM) $(OBJS_WITH_PATH) $(DEPS_WITH_PATH)

makefile中首先读取了当前工程下的两个目录, 保证正确搜索.h和.cpp之后声明三个伪目标, 并以all为终极目标, 之后声明了一系列变量, 这里详细解释一下每一个变量, 跟大家解释一下我的思路

CXXINCLUDES : 该变量包含了生成时c++的包含目录

ARFLAGS : 静态库打包标志

SRCS_WITH_PATH : 包含路径的所有源文件, 该写法可以自动匹配指定目录下的所有.cpp, 大型工程中可能会有很多源文件, 每次更新删除都要修改makefile的话会很不方便

SRCS : 剔除所有源文件的前缀路径

DEPS : 对每一个源文件, 生成一个对应的写有依赖关系的.d文件

DEPS_WITH_PATH : 包含前缀路径的全部.d文件

OBJS : 源文件编译生成的全部.o文件

OBJS_WITH_PATH : 包含前缀路径的全部.o文件

TARGET_NAME : 生成目标的名称

OUTDIR : 输出目录

在声明了以上这些变量之后, 通过对全局变量BUILD_VER的值的判断, 在CXXFLAGS里添加不同的参数以控制版本, 并对文件名等信息做修改

接下来我用-include让当前makefile读取所有.d依赖关系, 当前文件由于没有找到这些.d文件, 会在文件中搜索有无生成的静态目标, 这时, make会搜索到下方的%.d:$(SRCS)

根据该静态目标, .d文件便会被生成出来并被加载

假设我们当前指明生成的是伪目标all

all所依赖的目标是我们指定的文件名$(TARGET_NAME), 该变量所指向的目标又依赖于所有的.o文件, 由于.o文件没有被生成, make又会搜索并调用静态目标%.o:%.cpp进行.o文件的生成

在生成完所有的.o文件之后, 目标$(TARGET_NAME)才会被执行, 最终在../../lib目录中生成tsi.a或tsiD.a

理解了上面的内容之后, 接下来两个工程 : 动态库以及可执行文件的makefile基本也可以套用上面的内容再进行修改得到, 这里我贴出我的写法供大家参考

动态库makefile

 vpath %.cpp ./src
vpath %.h ./header .PHONY: all clean clean_cache
all : # 默认目标 CXXFLAGS += -fPIC
CXXINCLUDES = -I ./header
SRCS_WITH_PATH = $(wildcard ./src/*.cpp)
SRCS = $(SRCS_WITH_PATH:./src/%.cpp=%.cpp)
DEPS = $(SRCS:.cpp=.d)
DEPS_WITH_PATH = $(SRCS:%.cpp=./.d/%.d)
OBJS = $(SRCS:.cpp=.o)
OBJS_WITH_PATH = $(SRCS:%.cpp=./compile/%.o)
TARGET_NAME = libtest.so
OUTDIR = ../../lib/ ifeq ($(BUILD_VER), DEBUG)
CXXFLAGS += -g3
TARGET_NAME := libtestD.so
endif ifeq ($(BUILD_VER), RELEASE)
CXXFLAGS += -O2
endif #生成依赖关系,保证修改.h时也会重新编译相关.cpp
-include $(DEPS) %.d:$(SRCS)
@set -e;\
$(RM) $@;\
$(CXX) $(CXXINCLUDES) -MM $< > .d/$@; %.o:%.cpp
$(CXX) $(CXXFLAGS) $(CXXINCLUDES) -c $< -o ./compile/$@ all:$(TARGET_NAME) $(TARGET_NAME):$(OBJS)
$(CXX) -shared -o $(OUTDIR)$(TARGET_NAME) $(OBJS_WITH_PATH) clean:
$(RM) $(OUTDIR)$(TARGET_NAME) $(OBJS_WITH_PATH) $(DEPS_WITH_PATH) clean_cache:
$(RM) $(OBJS_WITH_PATH) $(DEPS_WITH_PATH)

可执行程序makefile

 vpath %.cpp ./src
vpath %.h ./header .PHONY: all clean clean_cache
all : # 默认目标 CXXINCLUDES = -I ./header -I ../lib_a/header -I ../lib_so/header
SRCS_WITH_PATH = $(wildcard ./src/*.cpp)
SRCS = $(SRCS_WITH_PATH:./src/%.cpp=%.cpp)
DEPS = $(SRCS:.cpp=.d)
DEPS_WITH_PATH = $(SRCS:%.cpp=./.d/%.d)
OBJS = $(SRCS:.cpp=.o)
OBJS_WITH_PATH = $(SRCS:%.cpp=./compile/%.o)
LINK_LIB = ../../lib/tsi.a
LINK_USR_SO = -L ../../lib -Wl,-rpath=../lib -ltest
TARGET_NAME = test
OUTDIR = ../../release/ ifeq ($(BUILD_VER), DEBUG)
CXXFLAGS += -g3
LINK_LIB := ../../lib/tsiD.a
LINK_USR_SO := -L ../../lib -Wl,-rpath=../lib -ltestD
TARGET_NAME := testD
OUTDIR := ../../debug/
endif ifeq ($(BUILD_VER), RELEASE)
CXXFLAGS += -O2
endif #生成依赖关系,保证修改.h时也会重新编译相关.cpp
-include $(DEPS) %.d:$(SRCS)
@set -e;\
$(RM) $@;\
$(CXX) $(CXXINCLUDES) -MM $< > .d/$@; %.o:%.cpp
$(CXX) $(CXXFLAGS) $(CXXINCLUDES) -c $< -o ./compile/$@ all:$(TARGET_NAME) $(TARGET_NAME):$(OBJS)
$(CXX) -o $(OUTDIR)$(TARGET_NAME) $(OBJS_WITH_PATH) $(LINK_LIB) $(LINK_USR_SO) clean:
$(RM) $(OUTDIR)$(TARGET_NAME) $(OBJS_WITH_PATH) $(DEPS_WITH_PATH) clean_cache:
$(RM) $(OBJS_WITH_PATH) $(DEPS_WITH_PATH)

这里有几点需要注意的是, 在可执行程序链接时, 我用-Wl,-rpath指定了程序执行时回去何处寻找libtest.so这个动态库, 如果不想这样写, 需要指定动态库生成到系统默认加载的路径中去, 比如/usr/lib, 同样程序在其他机器上部署时也需要做同样的操作

另外就是关于.d依赖生成我使用的参数是-MM, 因为GNU编译器如果使用-M参数会自动加入一些其它的依赖关系, 具体内容可以用g++ -M xxx.cpp做简单验证, 如下图:

-MM:

-M(后面还有....):

在完成了上述步骤之后, 我们的项目其实已经可以正常编译生成执行了, 只是跟vscode没什么联系, 这里我们先在project目录中运行make, make clean_all, make, make clean_all_cache来看一下辛苦编写makefile的成果

很成功, 舒服了

接下来, 为了做到一键运行(F5)或者一键debug调试, 我们要对vscode进行项目配置, 这里我们要修改.vscode目录下的三个文件:launch.json task.json c_cpp_properties.json

在此之前先贴一下我在vscode中安装的插件, 这些插件能让开发环境更美观, 代码编写更顺畅

其中C/C++提供了只能高亮头文件查找等功能, Chinese是一些选项的汉化, Font Switcher可以快速更换字体(这个无所谓...), One Dark Pro是一款比较美观的主题配色, Python(个人需求, 写一些简单的脚本还是很方便的), TabOut可以针对各种括号按tab快速跳出, vscode-icons美化各种图标

下面到了vscode的启动配置, 在vscode的运行选项卡中, 我们可以选择当前项目启动的配置, 该配置集由launch.json来控制, 这里我先贴出我的launch.json, 再进行详细说明

 {
"configurations": [
{
"name": "run release",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/release/test",
"args": ["-r", "-debug"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/release",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "make release"
},
{
"name": "run debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/debug/testD",
"args": ["-r", "-debug"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}/debug",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "make debug"
}
]
}

这里我配置了两个启动选项, 一个直接运行release程序, 另一个运行debug程序, 这里针对debug启动项进行解释说明

name : 我们在启动选项卡里看到的启动项名称

type : cppdbg就可以, 具体可以查阅vscode官方说明

request : 启动项类型, 一种是附加程序一种是直接启动, 这里是直接启动

program : 启动程序路径, 在vscode里打开的根目录即为${workspaceFolder}, 后面加上release路径

args : 传入程序的参数

stopAtEntry : 程序是否自动在入口暂停, debug版才有用哦

cwd : 程序运行时的目录

environment :要添加到程序环境中的环境变量, 具体可以查阅vscode官方说明, 这里我直接没填

externalConsole : 选择程序是在新的控制台中启动还是在集成控制台启动

MIMode : 调试器选择

setupCommands : vscode官方文档查, 这里我是直接用默认配置的

preLaunchTask : 这个是最重要的选项了, 该选项指明了在运行当前选项卡之前要运行的task任务, 这个task任务配置在同目录下的tasks.json中, 这里填的内容是task的label

为了解释preLaunchTask这个选项, 我们引入tasks.json, 这里贴出我的tasks.json, 进行说明

 {
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "make release",
"command": "make",
"args": [],
"options": {
"cwd": "${workspaceFolder}/project"
},
"group": "build"
},
{
"type": "shell",
"label": "make debug",
"command": "make -f debug.makefile",
"args": [],
"options": {
"cwd": "${workspaceFolder}/project"
},
"group": "build"
},
{
"type": "shell",
"label": "make clean",
"command": "make",
"args": ["clean_all"],
"options": {
"cwd": "${workspaceFolder}/project"
},
"group": "build"
},
{
"type": "shell",
"label": "make clean debug",
"command": "make -f debug.makefile",
"args": ["clean_all"],
"options": {
"cwd": "${workspaceFolder}/project"
},
"group": "build"
},
{
"type": "shell",
"label": "make clean cache",
"command": "make",
"args": ["clean_all_cache"],
"options": {
"cwd": "${workspaceFolder}/project"
},
"group": "build"
}
]
}

在这个文件中我配置了5个task, 其中前2个task : make release 和 make debug用于执行不同的makefile

这里我针对make debug做个简单说明

type : task的类型, 这里填shell相当于执行shell命令

label : task的名字

command : 要执行的指令, 这里要注意 make -f xxx.file这种命令, -f xxx这个内容要直接写到命令内容中, 而不能写到下面的args里, 会无法识别, 这里大家可以自行验证一下

args : command要附加的参数

options : 其他选项

cwd : task执行的目录

group : task的分组, 可以查一下vscode官方说明

经过以上配置, vscode就和我们的makefile联系在一起了, 选好启动项f5就完事了, 这里我贴出我的test.cpp, test.h, 和vscode断点调试运行截图

 #include "test.h"

 int main(int argc, char* argv[])
{
if (argc > )
{
std::cout << "input param : ";
for (int idx = ; idx < argc; ++idx)
{
std::cout << argv[idx] << " ";
}
std::cout << std::endl;
} std::cout << std::endl << "using a" << std::endl;
std::cout << tsi::a1st::lib_name() << std::endl
<< tsi::a2nd::lib_author() << std::endl
<< tsi::a3rd::lib_version() << std::endl; std::cout << std::endl << "using so" << std::endl;
std::cout << tsi::so1st::lib_name() << std::endl
<< tsi::so2nd::lib_author() << std::endl
<< tsi::so3rd::lib_version() << std::endl;
return ;
}
 #ifndef _TSI_TEST_
#define _TSI_TEST_ #include <iostream> #include "a_1st.h"
#include "a_2nd.h"
#include "a_3rd.h"
#include "so_1st.h"
#include "so_2nd.h"
#include "so_3rd.h" #endif

这样, 一个简单的项目工程的开发环境就搭建成功了. PS: 在调试时, 我遇到了一个小问题, 这里也贴一下

这里一开始我无法进行gdb调试, 提示无法读取文件云云, 点击创建后, 有了上述提示, 在网上检索了一下, 只有解决方案, 没有详细解释其中机理, 这里我先贴出解决办法

在/目录下建立build目录,在该目录中建立错误提示中对应的目录, 并下载提示对应版本glibc到目录中并解压即可解决问题

关于该错误我认为是gdb调试加载路径错误导致, 如果有了解详细原因的朋友, 请务必留言指点, 在此谢过

以上, 上方示例只是一个简单的项目结构, 其中一定还有很多不足之处, 本文仅起到一个抛砖引玉的作用, 如有错误疏漏, 请务必指出, 有问题欢迎讨论, 转载注明出处, 感谢

linux下使用vscode和makefile搭建C++开发环境的更多相关文章

  1. linux(ubuntu)和windows下面快速搭建android开发环境

    在windows和linux下面搭建android开发环境,一般要安装以下几个软件: 1.JDK安装 2.Eclipse安装 3.Android SDK安装 4.在eclipse里面安装ADT 5.e ...

  2. 珠联壁合地设天造|M1 Mac os(Apple Silicon)基于vscode(arm64)配置搭建Java开发环境(集成web框架Springboot)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_194 也许有人从未听说过Python,但是不会有人没听说过Java,它作为一个拥有悠久历史的老牌编程语言,常年雄踞TIOBE编程语 ...

  3. Linux(ubuntu 12.04桌面版) 搭建Android开发环境

    因为一些工作上的原因,需要切换到Linux环境下做点开发,我选择的Linux发行版本为ubuntu(我不建议使用fedora,我最开始就是使用的fedora,但发现并不是特别好使,有些插件没办法安装, ...

  4. Linux(4)- centos7安装python3、Linux下安装、配置virtualenv、确保开发环境的一致性、虚拟环境之virtualenvwrapper、vim

    一.centos7安装python3 1.下载python3的源码包 下载地址:https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz cd ...

  5. 使用vsCode配合IAR搭建arm开发环境

    众所周知IAR的编辑功能就是个垃圾,但是不得不承认IAR的编译器相当的牛X,经常以稳定可靠而著称,为此我们把VSCODE强大的编辑功能和IAR结合一下来加快我们的开发周期. 一.下载VSCODE并安装 ...

  6. Linux环境下使用VSCode编译makefile文件的注意事项

    Linux环境下使用VSCode编译makefile文件的注意事项 首先安装C/C++的两个依赖 在debug,launch会自动的生成下方的launch.json launch.json { // ...

  7. Linux下快速搭建php开发环境

    php开发环境快速搭建 一.Linux下快速搭建php开发环境 1.安装XAMPP for Linux XAMPP(Apache+MySQL+PHP+PERL)是一个功能强大的建站集成软件包,使用XA ...

  8. Linux环境下搭建Android开发环境

    最近在折腾linux.因为咱是搞安卓开发的,所以少不了需要搭建Android开发环境,就此小记,希望能给向我一样的开发者一点帮助!开干! 1.安装JDK 下载JDK包,得到的是类似于jdk-8u65- ...

  9. Ubuntu 12.04下搭建Qt开发环境

    http://download.qt.io/official_releases/qt/ Ubuntu 环境下Gtk与Qt编译环境安装与配置(系统环境是Ubuntu 12.04) 1.配置基础开发环境G ...

随机推荐

  1. 【树形DP】洛谷P2585 [ZJOI2006] 三色二叉树

    [树形DP]三色二叉树 标签(空格分隔): 树形DP [题目] 一棵二叉树可以按照如下规则表示成一个由0.1.2组成的字符序列,我们称之为"二叉树序列S": 0 该树没有子节点 1 ...

  2. Least Cost Bracket Sequence,题解

    题目链接 题意: 给你一个含有(,),?的序列,每个?变成(或)有一定的花费,问变成课匹配的括号的最小花费. 分析: 首先如果能变成匹配的,那么就有右括号的个数始终不多于左括号且左右括号数量相等,那就 ...

  3. Fetch.AI的最新发布speaks your language

    更新增强长期网络的稳定性 包括新的Etch功能,使我们的代码比以往对开发人员更加友好.我们现在支持太阳下的每一种语言,包括普通话,希腊语和希伯来语-甚至表情符号 介绍我们很高兴地宣布我们最新的技术更新 ...

  4. 题解:2018级算法第三次上机 C3-Zexal的浩瀚星辰

    题目描述: 样例: 实现解释: 一道结合了火箭发射的贪心题目 知识点: 贪心,优先队列 题目分析: 根据题目描述可知,延迟后时间是正常推进的,也就是假设共有n个火箭,推迟k小时.则在到达k+1小时时, ...

  5. CVE-2020-0796 漏洞复现

    漏洞介绍 2020年3月10日,微软在其官方SRC发布了CVE-2020-0796的安全公告(ADV200005,MicrosoftGuidance for Disabling SMBv3 Compr ...

  6. scrapy 源码解析 (三):启动流程源码分析(三) ExecutionEngine执行引擎

    ExecutionEngine执行引擎 上一篇分析了CrawlerProcess和Crawler对象的建立过程,在最终调用CrawlerProcess.start()之前,会首先建立Execution ...

  7. 迎难而上ArrayList,源码分析走一波

    先看再点赞,给自己一点思考的时间,思考过后请毫不犹豫微信搜索[沉默王二],关注这个长发飘飘却靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有技术大佬整理 ...

  8. [Cordova]Cordova6.x自定义插件之Andorid

    1.继承了CordovaPlugin的Java Class 需要重写execute方法,如下: 2.在res/xml/config.xml中关联上述java class 3.在assets/www/p ...

  9. mysql中常见约束

    #常见约束 /* 含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性 分类:六大约束 NOT NULL:非空,用于保证该字段的值不能为空 比如姓名.学号等 DEFAULT:默认,用于 ...

  10. Windows 磁盘分区后如何再合并&如何用Windows自带工具扩大某个分区

    Windows 磁盘分区后如何再合并&用Windows自带工具扩大某个分区 注:此方法有一定的成功率,更加完善可行的方法请看http://www.diskgenius.cn/help/part ...