简单一句话就是,google打算使用soong代替庞大的mk文件群,从而让aosp的开发更方便一些.
使用这个工具可以将mk
文件中的变量、模块、评论或者一些其他的条件转化为Android.bp
文件,比较复杂的
需要手工转换。
androidmk Android.mk > Android.bp
mk文件和bp文件的差别在于,mk文件可以允许有相同名字的多个模块,但是bp文件就不能这样,但是后者可以有 多个变量。
整体的build逻辑使用GO的blueprint
编写。所有的build 规则被bp文件搜集并且写入ninja
build 文件。
流程:
上面的流程有待确定
Blueprint更像是一个库,专门来翻译blueprint文件,关于Blueprint文件格式可以参考build/blueprint/Blueprints文件,soong是在blueprint上面的扩展,基于blueprint的语法定制产生Android.bp语法,解析Android.bp文件生成ninja文件。 来源 jianshu
着四者之间的关系你看看下面的build
目录就行了.
从aosp 7.0开始,aosp在prebuilts/go/
目录下新增go语言的运行环境就是为了他们之间的转换。
kati就是上文所说的 androidmk
的工具,源码位于:
user@host037-ubuntu-1804:~/zhimo-aosp/build$ ls
blueprint buildspec.mk.default CleanSpec.mk core envsetup.sh kati make soong target tools
kati下面的内容也是巨多,看来就是实现了一个虚拟机的功能(或者需要编译原理),这个门槛怎么也绕不过去。根据他内部的文档,kati也是一个短期的项目.
目前,kati的主要 mode是 ninja
mode.(build.ninja)
下面我翻译一下谷歌的官方文档:
...相反通过他自己执行build命令,kati产生`build.ninja`文件去执行上述命令。kati目前的形式是多次试验的结果,一些实验成功了,然而另外一些实验却失败了。我们甚至改变语言。期初,我们使用go编写的kati,我们天真的期待着在编译性能上有足够的提升。至少,我们可以得出三个结论...其实,谷歌自己也在为go的性能担心,当然,这不是这篇文章的核心,我们的目前是如何快速的编译出aosp系统,而不是讨论哪种方法更好,c的效率足够高,但是GNU的Makefile内容太臃肿. test
std::ostream& operator << (std::ostream& out, Box& B){
out << B.getLength() << " " << B.getBreadth() << " " << B.getHeight();
return out;
}
this is “«” overload. Note it will be defined at beside of class.
bool operator < (const Box& B){ // overload operator "<"
if (this->l < B.l)
return true;
else if (this->l == B.l && this->b < B.b)
return true;
else if (this->l == B.l && this->b == B.b && this->h < B.h)
return true;
else
return false;
};
This is <
’s override,which is defined in class,Why it is different from
above example.Yes, the reason that is we can use keyword this
pointer to
access private numbers of class.
c++的智能指针可以说是一个高级用法,尤其是在大型项目中,一定少不了这个东西的参与。 也许,你不必亲自探究它的源码构成,但是看一看它是如何工作的,对自己的c++基础还有有莫大的帮助。
所有的智能指针头文件是memory
.智能指针的意图是解决内存管理的问题,如果你使用了智能指针去
申请内存,可以放心地保证减少内存泄漏的问题的产生。
首先看一下自己如何实现自动删除资源的class:
class smartPtr{
int *ptr; // actual pointer
public:
explicit smartPtr(int *p = NULL) { ptr = p; } // constructor
~smartPtr() { delete(ptr); }
int& operator *() { return *ptr; }
};
int main()
{
smartPtr ptr(new int());
*ptr = 20;
cout << *ptr << endl;
return 0;
}
这里有一些东西有待确证,实例化的对象是不是在程序退出后、也就是obj的生命周期结束后
自动调用析构函数,而且,你看,在类中还重载了\*
符号。
std::auto_ptr
这个指针类已经被丢弃了,能不用这个就不用它吧。显而易见,推荐使用unique_ptr
这个问题也需要总结一下,因为最明显的方案有两种。孰好孰坏,还得看情况。 题目来自于hackerrank
这个在开源代码里比较常见,据说效率上比较快的。因为是构造函数吗,这里就涉及到
多参函数和无参函数。请看以下代码,是初始化一个Box()
中的长宽高(l,b,h).
class Box{
private:
int l, b, h;
public:
Box() : l(0), b(0), h(0){}
Box(int length, int breath, int height) :
l(length),b(breath),h(height) // be carefully ","
{
} // this is initialzer list method
Box (const Box& obj) :
l(obj.l), b(obj.b),h(obj.h)
{} // copy constructor
int getLength() {
return this->l;
}
int getBreadth() {
return this->b;
}
int getHeight() {
return this->h;
}
long long int CalculateVolume() // 必须大数梳理
{
long long int result = 1LL * this->l * this->b * this->h;
return result;
}
};
Please note the initialized list model is :
Box(int length, int breath, int height) :
l(length),b(breath),h(height) // be carefully ","
{
} // this is initialzer list method
There is copy constructor function
Box(const Box& obj)
The fundamental principle of copy constructor i dont understand.But we first
have a glance at :
Box(int length, int breath, int height):l(length),b(breathr, h(height) {}
and l
,b
,h
is private variables that we want to pass constructor
function’s arguments.
Notes: There will be must use initialized list
as below:
class Box() {
private:
int m_length;
int m_height;
public:
Box(int length, int height) : m_length(length),m_height(height){}
} // below must use it ^_^
class red_Box: public Box{
public:
red_Box(int length, int height, int type) :
Box(length, height){
;
} // must use initialized list
private:
int type;
}
class Box() {
private:
int m_length;
int m_height;
public:
Box(int length, int height) : m_length(length),m_height(height){}
} // below must use it ^_^
class red_Box: public Box{
public:
red_Box(int length, int height, int type) :
Box(length, height),
TYPE(2)
{
// if TYPE = 4 is error
} // must use initialized list
private:
int type;
const int TYPE;
```c Box(){ l = 0, b = 0, h = 0; } // default value is 0, maybe use below method
# 拷贝构造函数
```c
Box (const Box& obj) :
l(obj.l), b(obj.b),h(obj.h)
{} // copy constructor
任何一门编程语言的输入输出都应该彻底的掌握,c++更应该是这样的。
这个直接使用
int main() {
int a; long b; char c; float d; double e;
cin >> a >> b >> c >> d >>e;
cout << a << endl << b << endl << c << endl;
cout << setiosflags(ios::fixed) << setprecision(3);
cout << d << endl;
cout << setiosflags(ios::fixed) << setprecision(9);
cout << e << endl;
return 0;
}
方法setiosflags
具有后效性,一旦你设置了,一直到程序结束,精确度会一直保持下去的.
有两种方式: getline()和cin.getline().
该函数可以直接读取c++的string。
string str;
getline(cin, str);
cout << str << endl;
结果:
vimer@host:~/test$ g++ -g getline.cpp -o getline
vimer@host:~/test$ ./getline
[null,2,3,null,] # input
[null,2,3,null,] # output
这是一种类似c的方式使用数组。
char str2[1024];
cin.getline(str2, 1024);
cout << str2 << endl;
结果:
vimer@host:~/test$ g++ -g getline.cpp -o getline
vimer@host:~/test$ ./getline
[2,3,,null] # input
[2,3,,null] # output
leetcode的c++代码,尤其是二叉树的那部分,其测试用例都是使用,例如:
[1, null,3,4,5]
这类的数组形式的输入,那如果自己写测试用例怎么办?我的思路是,首先按照上面的方式整行读取文本内容,然后再借助c++的 strtok函数分别提取出来或者存储在另外一个数组。
还记得在初次接触c++的时候,根本看不见去有关模板的任何东西。现在看上去还好一些,现在就将一些基本的总结下来。
其实,按照c++的学习规律看,应该先介绍函数模板后再介绍class模板,可是因为做题需要,就先介绍这个东西。 函数模板中定义的类型参数可以用在函数声明和函数定义中,类模板中定义的类型参数可以用在类声明和类实现中。类模板的目的同样是将数据的类型参数化。
template<typename 类型参数1 , typename 类型参数2 , …> class 类名{
//TODO:
};
一旦定义好了类模板,就可以将类型参数用于类的成员函数了,也就是原来使用 int float char等关键词的地方都可以用类型参数来代替。下面是一个
网站的学习例子 ,假设设计一个类模板,首先先使用一个参数初始化容器,后面使用add(x)
方法将初始化 的参数和add
里面的参数求和后再输出,要求这个类可以处理 int long string等.
输入的格式为:
3
string John Doe
int 1 2
float 4.0 1.5
则输出为:
JohnDoe
3
5.5
先看一下主函数是怎么处理的 :
int main () {
int n,i;
cin >> n;
for(i=0;i<n;i++) {
string type;
cin >> type;
if(type=="float") {
double element1,element2;
cin >> element1 >> element2;
AddElements<double> myfloat (element1);
cout << myfloat.add(element2) << endl;
}
else if(type == "int") {
int element1, element2;
cin >> element1 >> element2;
AddElements<int> myint (element1);
cout << myint.add(element2) << endl;
}
else if(type == "string") {
string element1, element2;
cin >> element1 >> element2;
AddElements<string> mystring (element1);
cout << mystring.concatenate(element2) << endl;
}
}
return 0;
}
那么,这个模板应该如何定义?
template <class T>
class AddElements {
private:
T m_x; // 这是成员变量,其类型一定是泛型的
public:
AddElements(T x): m_x(x) {} // 这是构造函数初始化参数的一个方法
// 如果两个参数 Point(T1 x, T2 y): m_x(x), m_y(y){ }
T add(T x) const; // 成员函数的返回值类型 返回和
T concatenate(T x) const;
};
// class的成员函数需要在类外定义,仍需带上模板头
template <class T>
T AddElements<T>::add(T sec) const {
return sec + this->m_x;
}
template <class T>
T AddElements<T>::concatenate(T str) const {
return this->m_x + str;
}
这个问题的难点在于如何找到第一次定义时的参数?幸好我会前理解了下this
指针,
而且一下子就命中。这里作为新手有几个部分需要注意一下:
定义成员函数的形式,别忘了<T>
与函数模板不同的是,类模板在实例化时必须显式地指明数据类型,编译器不能根据给定的数据推演出数据类型。 这也是一个参数的。
这里需要再澄清一次,你的参数一定是传递给class的成员变量处理,这也就是为什么必须 模板参数。下面的例子就是打印一个数组:很简单,但是很直接。这是无参数的
template <class T>
class Array{
private:
T *ptr;
int size;
public:
Array(T arr[], int s);
void print();
};
template <class T>
Array<T>::Array(T arr[], int s){
ptr = new T[s]; // ptr 是class的私有变量,这里可以直接使用
size = s;
for(int i = 0; i < size; i++){
ptr[i] = arr[i];
}
}
template <class T>
void Array<T>::print(){
for (int i = 0; i < size; i++){
cout << " " << *(ptr + i);
}
cout << endl;
}
int main()
{
int arr[6] = {1,2,4,6,7,4};
Array<int> a(arr, 6);
a.print();
return 0;
}
template <class T, class U>
class testClass {
private:
T x;
U y;
public:
testClass(){
cout << "Constructor called" << endl;
}
};
int main()
{
testClass<char, char> a;
testClass<int , char> b;
}
如果想使用默认参数,也是在声明对象时,能不能设置一个默认的参数?
可以的,只需在声明模板的时候指定就可以了。比如, template<class T, Class U = char>,
在使用的时候可以testClass<char, > a
就可以的。
其实与class 模板是一致的,只不过这里处理的是函数,class 在处理上稍微更复杂一些。 还是上代码:
template <typename T>
T myMax(T x, T y){
return x > y ? x : y;
}
int main()
{
cout << myMax<int>(3, 7) << endl;
cout << myMax<char>('a', 'b') << endl;
}
这句是对函数进行模板化的。
相似
的事情,函数模板是多个函数做相同
的操作。