 Hello, everyone. Hi, my name is Victor Rodriguez and welcome everyone to the ELC 2020. Today, I'm going to present about tool change in the new area, how to update SAFE. My name is Victor Rodriguez and I'm going to be talking this time about this impressive topic that I really enjoy and hope that you really enjoy too. So, a few months ago, before all these chaos around December, November, one of my friends told me something really amazing that he found amazing at that moment that you didn't realize before. And it was how much work the GNU tool change community actually do every year, right? And I was like, okay, we have two releases in GNU every year around the beginning of the year and end of the year. And we have one release every year for the GCC compiler. We have GCC 10 a few months ago in May, a few weeks ago. But it was something that he told me. He said, you know, the community is very healthy. It's a great community, great developers, but they are not that many. I mean, there are very few people involved in this great amazing job that we, everyone in the Linux world and outside of the Linux world actually enjoy, which is the compiler tool change being utils and other things that actually is very few developers. So, GNU compiler community, for example, do a lot of work per developer. But the question that I was wondering a few days ago is how much in terms of commits per developer? Well, here it is. So, the number of commits per developer in our history with GCC, it's around 200 commits per developer. And in the Linux kernel, it's around less than 50. So, we are very good community. We have a great community. However, it's not that many people that create all these amazing topics, all these amazing new features, all these amazing things that everyone can enjoy. The first thing that we're going to be checking is GCC new features in terms of security. One of the flags that came up in this new version of GCC 10 that was released in May is FNALISER. FNALISER is an amazing thing, right? This is an option enabled in the static analysis of the program flow that looks back to the source code and issues warning for the problem found on this thing. So, it's pretty much what we had before about, hey, I need to find a new tool to actually go and do static analysis of my code to figure out if something is wrong, like security issues, some other stuff that I could be forcing in the runtime to happen there. Now, FNALISER comes with a proper static analysis tool for you in the compiler. You don't have to go and search or pay for another. Of course, you can go and pay, but in this case, you can initially go and try with the FNALISER flag and see how many errors actually the GCC compiler actually find. So, enable this option, effectively enable some of these warnings. So, it's a union of multiple warnings that actually enables. Things like FNALISER double F close, analyzer for double three. It's going to give you a warning if you have a double three. It's going to give you a warning if you have exposure throughout the file, if you have a file leak, if you have a free of non-heap, right, and a mild leak. So, and there are more. I just put six in this small lease, but you can see the full documentation of the GCC release notes and you will find it how many there are there, like five more. Well, the first one, FNALISER for double three. So, FNALISER for double three is the diagnostics of warnings for when you have a double three in your code, right? How does it look? Okay. So, it looks like this. You have a main. You have a main. And in this case, we asked to the memory management, hey, can you give me a pointer? Sure. And then ASA NICE developer have to free the pointer because it's a proper thing to do. But then, of course, here is very obvious and it just made it for an example. Later, I free that pointer again. And in this case, as I said, it's very obvious, but we have seen this thing a lot of times because it between the two frees that are hundreds lines of codes, and we as humans, despite the fact that we're very smart, we can commit mistakes. And after 100, 200 lines of code, we say, oh, I need to free my pointer or by the logic that we have, we free the pointer two times or three times. So a double three, it's an issue on runtime. As we know, it's critical in terms of security. And now with this F analyzer, when we compile this basic code with GCC test.c F analyzer, you will see that the warning of a double three pointer, it's about in the end in your screen. So you will see actually the line codes that you will have the error free pointer and free pointer, say, second free here, first free line one point one, right. So actually it's very helpful because it's telling you where in your source code, it's actually the double three. Now comes to a much more serious things that we can come up in this thing. A good example is the dangerous F print out. So for your mind, no, not every now it's evil at some point. And here we have a good example. So we have this thing, which is a main and basic main to see arguments. We have declared a buffer and run a rate of charge and we set a string copy from whatever I pass as my argument to the buffer passing actually the length correctly. And when the problem is that we print F buffer, and we never cast to see if it's in the string or if it's and the thing here is that when we pass something that it's not actually in a string, something else, for example, when after we compile this basic code, and we run a assembly that output and we pass this this huge a string actually passing a bunch of days and later over floating the F print F, we can see that actually start to bring the stack. How do we know that because 41 41 41 is actually these aids that we're seeing over here passing to ask you. So the thing of funny here is that print F can be a security vulnerability for sure. There is a ton of documentation about that how to fix it how to how to avoid this thing with the consciousness of the developer. The problem is that print F determines how many arguments it shows get by examining the format string in format string doesn't agree with the actual arguments. For example, that we have here, you have undefined behavior which can manifest a security vulnerability. What kind of vulnerability it's a format string exploits, the attacker can perform writes to arbitrary memory address, which is very dangerous. Right. So what happened with a real code? Here is nothing that we know or have a little bit background about the print F. The F print F, it's going to go and do the same thing, but we put this inside a logger, right. And these logger is going to be executed by a handler. So signal has the name of these flag safe, event analyzer and safe call signal handler. It's because we have a handler like these ones. It's a special function from Siege to actually have a signal request. It's going to say, oh, I have a function called handler. And later inside, I have an F print. GCC will detect and say, wait a minute, F print F, it's not properly or safe. And you're also calling that from a handler. So it's the unit of a really, really bad situation where you can perform a security vulnerability. So when we compile this thing and say, hey, call to print F from within signal handler, it's the warning that I was actually telling us. So it's telling us that the signal Siege handler, it's going to call later to a print F here over here, F print F, call to F print F from within a single handler, which is a bad combination. So GCC now is that is more with this new flag to actually detect this kind of thing. It's very impressive. Now, extra options, because you can see, okay, I have this in my compiler and me as a developer, I can say, okay, compile. But as you can imagine, the codes that we compile every day are not that simple and are not that easy to actually start reading all the lines that pop up in the window. That's insane, right? So there are two extra options of the agnostic path format separate events, which is going to separate the events one by one and also agnostic format equal JSON. So now you can generate a JSON file at the end of your compilation file, pass process that with Python, PHP, Perot, whatever you want. And later that printed in a nice dashboard. So as you can imagine, the CI CD, for example, in this case, for the previous example that we have with Bubble Free, it's possible to print a JSON file that is telling us the line, the file, the column, the description, the function, all the information that is printed on the standard output in our screen, it's possible to have on the JSON file. So now your application will be built and in the end, generate a JSON file, pass process that and give the warning to the developers. You can even imagine a CI CD, of course, that warns things before actually having it pushed to the main repository, to the main branch. And it's pretty healthy for us as developers to figure it out that we are committing a mistake in terms of security, right? And prevent that instead of going to production. Now, what it means to have these things in terms of next steps, a real example on where to use it. This is taken from a really nice article, this information reading by one of good developers. So you can hear the credits to developers Red Hat, block 2020, static analysis in GCC 10. So I highly recommend that you go and check this blog, some examples we're taking from there. And in this blog, they mentioned something about CBE that happened 15 years ago, CBE 2005, 1689. As you know, the CBEs are databases that are for everyone outside in the open source to actually check when a new security ability has been detected and proofed and tested, we create a new CBE community, and now we're ready to track, fix and propose the patch. So this happened 15 years ago. It happened in Kerberos, version five, Kerberos is a computer network authentication problem. And the problem with that thing when I double, I checked the CBE in the database of the CBEs and the description is very straightforward. It was a double free vulnerability in the Kerberos five, REC vout function in MIT Kerberos five, 1.4.1. And earlier allows remote attackers to execute arbitrary code by certain error conditions. So that's one of the things that we have, we have double free, allow things like executing arbitrary codes by double free, double free the memory. So in things things, we have Kerberos five. And if we compile Kerberos with GC10, with FNLizer flag enable, we figure out that it correctly identifies the box with no false positives. The only thing that needs to be fixed is to improve the warnings without overwhelming. Of course, it could be printed to a JSON file and then post-process and clean a little bit more. However, it does the thing that it's supposed to do. How does it look? Okay, you pay attention to this part. It in file included from, and you can see the file actually installing the line in function, REC vout common, which is the same one that was described on the in the description of the CBE. Double free off. And then the value, right? And it is telling us here that Kerberos X free of the input.data, it's been freed here and then free later. Now, when I checked the patch, I was looking for the patch that I was actually for this one. I was very surprised that the patch for this one, it's exactly the piece of code that the warning on the compiler is, it's telling me. So it goes and fix and into the same position that the compiler was suggesting to fix. So it matched actually that the compiler is telling us a warning and the community 15 years ago discovered the same fix and that was the fix that actually solved the issue. So this proved that this flag actually works in real environments, right? So my recommendation from this first part of the presentation is let's use it in our daily CICD, in our daily jobs and try to go ahead and say, hey, maybe I should go and double check with FNLizer with the GCC latest version and see if I'm committing a mistake or if I can find something useful or if of some way that I can improve my code always. Now, the next feature that I want to talk, it's GCC new feature about profiling. Now, profiling is the best topic and the topic that we're going to be touching in this part is F-profiling for partial training. For profiling for partial training, it's a new flag that came out with GCC 10. This flag enables that now we can inform the compiler that the functions that are not executed during the profile execution or not exercised it during the profile execution should not be optimized. Now, what happened before this flag? Because it's important to understand what is the before and the after to have a feeling of the change that we have. So imagine that you have a code function A, function B, and function C. Now, for the steps for profiling is we compile, we instrument your code to let the compiler later know when we execute, what are the paths that are actually being exercised, and later the compiler can optimize the paths that are much more exercised. And we will see a little bit more about profiling for developers in a minute. But I want to highlight the before and after. So before this flag came up a year ago, a few months ago, if a function A was not executed during training, then function B was not executed during the training or not exercised during the training. Now, function C, okay, function C means that I have a new binary that now it's instrumented. I want to run a benchmark on top of disk B. So that the profiler have better information, much more accurate about what is the real and common use case for these binaries for libraries. So it will detect what function are being executed during the train. And the good thing is that once we detect that and pass back to the compiler, the compiler is going to say, hey, I'm going to optimize that function. And what happened before with a function that was not executing during your training, the compiler say, you know, I'm going to optimize those ones, but for size, because maybe I increase a little bit the size, but I need to do something else with the other function. So it goes three forward and optimize these other functions, but now for size. Optimizing for size, despite the fact that it sounds pretty amazing, it has an issue. And it's that sometimes optimizing for size affect the performance of the function in terms of how much time, how much memory you're using or the time of the execution of that function. So optimizing for size is good for embedded things and it's good for application when the size matters, IOT and stuff. However, it be taking with caution because it's not always the rule of say, hey, I want you to optimize for size all the time. No, sometimes optimizing for size could have a penalty in terms of performance. Now what happened now with the f-profile partial training? With the f-profile partial training, the functions that are not exercised during the profiling are just ignored. If you can see function A and B, it's just ignored. And the compiler say, hey, I did not exercise during the profiling, during the execution of the benchmark on the instrumented binary these functions. I'm just going to ignore it and create the same function A and B as I did before. So we have an optimized function and just the same function that was optimized before without any penalization in performance or size, nothing. Of course, as you can imagine, the new binary, it's going to be way much more heavy than the previous one, right? What happened with the f-profile kind of optimization? Well, it was thought years ago I said, hey, why would be nice if we could actually provide something to the compiler about where does it go? And the reason why I put this picture is because the best analogy that I can figure out is if you are training of a kids soccer team and you want to improve the performance of your team, right? It's a chaos. It's similar to what we have in our code when it's running into a CPU, multiple branches, multiple variables, multiple paths. And of course, one instruction pointer, which in this case will be the ball that it's go. How does it go? But it's an analogy that I want to propose to you about how this profile data can be used to work. So to extract good performance out of the program, it will be nice if programmers could provide hints of annotation to the compiler and say, hey, compiler, I get the idea of where is it going? And the binary is being executed more into this path and never actually taking these other paths. So PGR is a method used by compilers to produce optimal code by using application runtime data. Because this data come up from directly from the application, the compiler can make much more accurate guesses. So it's giving a hint to the compiler and say, hey, actually, you should go. We go most of the time during runtime for these five. Oh, great. So the compiler now can optimize better. And we will see what kind of optimization could happen. Profile optimizations have three stages. The compilation of an instrumented binary, the profile execution and the compile optimization. And the reason why I put the picture before is imagine that you're the coach of the soccer game and you want to know the soccer team and you want to know which one of the players actually run more, which one runs less and so on. But you lack of technology. You have it thrown on top of that. And it's very complicated, expensive. And you have extra virtual reality technology. Yeah, it's not. So a solution that we were going to propose is going to put a huge cry on the back of each one of the players. And we are going to make it to run and it's going to paint over the field where does it go, right? Or a lot of paint can in the back. And it's going to let me know actually where, where each player it's going. Or if a player is talking one place and never running, right? So it's going to be at the end of a picture of the field. And let me know good information. That's that's an analogy for how the speech you're worried. Now, the first part is I have to put this huge pain into the back of the player. And as you can imagine, the player isn't going to run the same speed. Why? Because it's heavy. That happens the same with instrumentation. Instrumentation produced an executable that now has counters. And every time that we take a branch, it's going to increase the counter. Take another against the branch, increase the counter again, go for the branch, increase the counter again. And it's going to happen for branches, blocks in variables. So it which proves sensors count the numbers of time of a basic block runs. If the block is a branch before it records the direct taken by that branch, how do I generate this part? So it's very simple. You have your application code. So you're going to compile as GCC app profile, generate and the profile directory. Here is where all the GCBA files that is going to be the extension that is going to be curated, are going to be saved or recorded, right? The second one is, okay, I now that I put in my player sensors or groups, go and play grade. It's going to be way much more slow because the groups are heavy in the back of the players. Now, with the profile execution, you have to simulate the most real conditions. So what I have to do, bring in a team or a friend team that tell me to actually go and get the photo of where my team is failing or where can I improve my team. So the profile execution actually gets an execution of a benchmark or a regular basic application for the daily test cases that we execute at the end. So when it's executed, the instrumented program generates data that a file that contains the execution counts for the specific role of the program. So it's going to leave a path of where each one of the players is actually going. And the compile optimization part, now that we have the pane on the field, we can go and now take the picture pound and I can have pictures say, okay, so player green, yellow and red are not moving, blue it's moving only to the left, and purple it's moving only to the corner, but it's in the top. Okay, that's great. So now I can analyze my data that's recent of this picture and actually go and think about how can I improve my team, right? So information from the profile execution of program needs feedback to the compiler. The compiler now doesn't have to hint that much. And the data is used to make a better estimator of the program flow. The compiler uses the information to reduce the executable file reliant this data rather than the statistic heuristics. So the GCC in the end, it's going to say, hey, GCC that profile use and you pass the data that they're actually want to work for all the GCD. All these could be offended. Yes. So can you run multiple benchmarks and information will you send? Yes. However, there are a few things that we will check in a minute. It's not sometimes very good idea to append that much data. So we will check that. But before, what kind of optimization should I expect once I have all these jobs? Well, the first one, it's functioning line. Function is lining at the logic has been with us for a long time with the compiler. It's a techniques where the inline high frequency function into one of the calling functions to reduce function call overheads. The function in line needs to reduce the use of the call overheads to many functions, which will force to use the amount of cash that you might going to need. Remember that you're going to need memory to move from one function to another and so on. So the lesson of memory is also important for the performance of an application. Let's take an example as easily. We have function A, which is going to be our main function. And it could go into, we have an if and else, and it could go into function B or C. And function B could go into function D or E, or in function C, it could go into our function F and J, based on the condition that they could define. This could be a counter, this could be a Boolean, an external database injection, whatever you want, that it could display the branch of the execution. Now, 70 times from A, it's going to be, and only 30 times it's going to C. When you are in function B, 80 times it's going to function D, and 20 times it's going to function E. And from C, we go 90 times to function F, and only 10 times to function D. If the amount will be 100, in terms of portion, as we can see that most of the times function A go to function B, and function B most of the time goes to function B. Function C most of the times go to function F. Now, in line, in function lining, it's going to go and merge the functions that are very tight, and most of the time one called the other. So in this case, B and E could be in line, C could be in line into F, and very risky A could be in line into B. So that would reduce the amount of function all over heads on the execution of your binary. The next one, and this could happen if we pass the PGO profile data optimization back to the compiler, the compiler actually can figure it out, say, most of the time you go from this function to this function, and from C to F. So I'm going to try to inline these functions. Now block ordering. The second part of this could be improved is block ordering. The compiler would aim to achieve all locally to perform minimum amount of memory operation. Functions which are tightly bound should be allocated to minimize instruction capabilities. Sometimes we said, oh, I have my code. I'm just compile and let the compiler do the magic, and we forget what's happening behind the scenes. Well, behind the scenes, the compiler has to figure it out on the text sides and how an arranged text data heap, how does it work in terms of doing much more efficient. Let's take into the example of this one. Function A, we have function A if condition is equal to true, and it's going to call function B else, it's going to call function C. And at the end, function B, it's going to be calling function D. So we can figure out more or less any, and we have A, it's going to call function B if it's true or call function C. And function B, it's going to call function D. Now, what happened? If most of the time we realize that the condition, it's always false because it's for some reason or during the training of our file guide optimization, most of the times the conditions were false, well, we rearrange things and say, you know, A now it's going to call C immediately, C it's going to call, and A it's going to call B sometimes, but B it's going to be closer to D. So here before, B was very far, far away from D, and C was far, far away from A. Now, A is closer from C, and B is closer to D. This is because we have lock reordering based on the information that we get from the protocol guide instrumentation entering the training, right? And the third one, it's going to be the death code elimination. Death code elimination, it's an optimization that removes code that does not affect the program result. It's important to differentiate from death code elimination to enrichable code. Death code is code that it's, despite the fact that it could be executed, it will not affect the end result of what we have. So it's going to consider a waste of CPU performance. And when you are trying to increase performance, every single step matters, every single step matters, every bottleneck that you fix, it's a third thing for your application. So a good example, well, in the other case, a reachable code is a code that will never be reached. It doesn't matter, it's like you said, okay, if condition equal true, and condition you defined by before as true, it always goes into that branch. Else, do something else. You know that it will never reach that else, because condition was hardcoded to be true, right? That is a reachable code that can code that will never be reached regardless of the logic flow. The difference, it's not executed, it's never executed. However, the death code is executed and it's dangerous. So what we want to eliminate is death code, not a reachable code in the beginning, but the death code, it's much more dangerous. Now, the death code, here is a good example. We have a function true, we have index and y, and then return a, and a, it's equal one here. And before we have a equal x plus y, and later re-assign one to a. So it doesn't matter what value we pass, a will always be one. So this is death code. This over here, red, is an example of death code, because it will never be, despite the fact that it's executed, the result will never change between one and this function. So it's a waste of CPU cycles and performance. So with the profile kind of optimization, now compiler knows, hey, you know, actually, if this function is highly executed, and I can figure out that our codes that it will, despite the fact that I executed will never change the result based on the training that I have, I'm just going to remove that. Okay. So it's very interesting that death code elimination, it's being performed. There is another flag that you can actually exercise that is not based on profile kind of optimization, which is FDCE. It's the death code elimination for profile kind of optimization. It's similar to this one, but with runtime information, this one only gets the death code elimination by PGO actually knows that this is a waste of CPU, right? Now, next steps and real example where to use it. If the application behaves something important you have in your mind and say, hey, this is magic. I'm going to use it most of the time. Well, be careful. If the application behaves differently for different datasets, it's possible to have a performance regression. We have had examples where we have executed one benchmark and then we append another benchmark, another one, and surprise, performance is worse than the original. Why? Because we're trying that the compiler gets multiple paths and the compiler decreases. Hey, you first let me know that the condition was always true and then condition was false. I don't know at this point. So the point with what is going to be the common scenario that it's really close to the application, how the application should behave when it's in print production, right? For large applications that are run frequently, it is observable that PGOs can provide, can prove to be a significant source of performance. So example of that is Python. I don't really provide these options. So for Python, it goes in terms of developing very yet and how to use more technology to compiler. And you can compile Python by yourself and put it into your path. And you can file with Python, compile your flags, enable optimization, and make profile OPT and SMTP flags. This profile dash OPT, compile the Python service code into again, path using PGO. So inside this make file, you will see that the three steps that we saw before, which are compile instrumentation, profile execution, and compile optimization. Sure, the time that your Python is going to be taken to compile is going to increase because we are actually running a benchmark. What we did in Clear was modify the very simple flag in a variable, sorry, and define what is going to be the training model that we want to optimize for. So I encourage you that if you want to optimize your Python, select before in that patch what training model that you want to use so that you will be optimizing for your application. And the steps are going to be very simple. Build, run the benchmark, and recompile. That is what happens inside the make profile OPT. The next thing is something new. Be the dynamic range of big floats extreme. It's created that the floating bits, floating point 16, a little bit of history. Floating be float 16. It's going to have one bit for sign, eight bits for exponent, and seven bits for the fraction. The float 32 that we are used to when we have a long float number, it's going to have one sign, one bit for sign, eight bit for the exponent, and 23 more for the fraction that we want to use. In the history, people said I don't need that much precision. I'm going to split the registry of the floating point for just using 16 bits in terms of 32. Be float 16, it's a range that changes because before for float 16, it was using five bits and 10 bits. Now it's going to be using eight bits and seven bits. Now, the float 16 range is used for things like radians that can outside the dynamic for machine learning, and it's better, but float 16. It requires lots of scaling, but be float 16 can represent source grading straightforward. In addition to that, something you can use be float 16 format to accurately represent all the integers from minus 256 to 256, which means that you can encode integer A in float 16 without lose of accuracy, which is a good idea. So Cooper Lake, this new platform that it's coming in the compiler with MRG, Cooper Lake, enable these kinds of things with three different instructions. Now, my kind of instructions we have, it's split it into two kind of operation on the ISA. One is going to be for FMA, fusing application addition of two be float 16 input operands, and the other one will be conversion between floating point 32 and be float 16, because it's important. There might be the case that your application is expecting be floating point 32, and you want to perform actually the instruction on hardware with be float 16. Well, on the Lisa Pintel ABX 12, be float 16 vectoral network instruction includes these three instructions, which is bct need to be float 16. As you can see, it says two be float 16, two be float 16, and it's going to be two precision single or precision single, right? And this one to precision single means because it's doing the conversion of two packet single data, two one packet data data, two packet single data, two be float 16, and here is converting packet single data to be float 16. There's the reason of these accounting, and it's a kind of conversion. On the last one, it's be float 16 PS, it's the dot product of be float 16 pairs accumulating into package single precision, right? So, remember, the application addition is the core instruction for matrix multiplication, that you can go and take two elements, multiply them, and then add them to the accumulation that was before into the third element. So, it's going to receive three elements. All this instruction could be performed in a registry of 128 bits, 256 bits, and 512 bit nodes. So, software developers can define the level that they prefer, and they use that they prefer. They didn't want to say, hey, I want to use all the full 512 register. I want to use, which is a CETA MM register. I want to use a much more shorter register on XMM or YMM. It's okay for them. As long as it's inside a Cooper Lake platform, because a Cooper Lake platform is the only one that support these instructions. FMA with be float 16 is going to take as an input the be float 16 serves one and serves two. And the source destination is going to be a floating point 32. Do the multiplication and addition in one single operation. And of course, number of cycle will be less than if you do that separately in addition and then multiplication, moving the things from a register to registry. It's way much more expensive in terms of performance and power actually execution you want to use. This unit takes two be float 16 values and multiply and adds them, and it will be extended to floating point 32 numbers with the lower 16 bits to zero. The be float 16 multiplication is performing without loss of precision that is important. It resolves passive to the general floating point 32 later with a form of settings, right? So in the end, you will have the source destination have a floating point 32, and that is a cool because you actually have a good precision by exercising the be float 16. Example in code, you can click here for a full example of repositories I have. It's going to have, how do I use this instruction in my coding C? Well, the good thing is that we have intrinsics. So in intrinsics, it's translated to CBTNAPS, PBH, and then you pass the register that you want to convert, or with the two registries that you want to convert also, convert packet of single position 32 bits, floating point elements in two vectors AMB to packet be float 16, floating point and the store the resource in single vector destination, right? And the last one, the float, first multiplication addition that we saw, we have AMB and source, and it's going to be doing the multiplication of AMB and addition to source. Now, how does it look in terms of a demo? Taking the last one, we're going to multiply 8 times B and then add back to A and if AMB is going to be 10 and 6, it's going to be 10 multiplied by 6 and then add that plus 8. And as you can see in the result, we have 70, which is the result of 10 times 6, which is 16, plus 10, it's going to be 70. So it works. It actually works the instructions that we want to perform with the float 16. How do I manage to move to a new tool change in these extremely rapid world that requesting super fast production in two, three weeks and old containers, cloud, and super, well, the recommendation that I have to you is take it easy, take a breath. Moving from one compiler to another, it's definitely not something that you can take as a joke and say, yeah, that morning I'm going to do it in one hour. No, take it easy, be very conscious about what you're going to do because it could affect you a lot in future problems. So, but if you manage correctly, it could go as straightforward and enjoy all the benefits of the new tool change. First thing that you want, you need to do is build the new GCC. In this case, we're going to focus through the compiler. It's a different story for Tillip C, but we'll focus for now just for the demo. Download the terrible from wherever you want. If you say you want to download that version, good for you. You want to use GCC9, GCC10, GCC8. According to the version you want to go. Then download the prerequisites. Something very interesting about GCC is that they always have a form to go and dash country download from requisites. It's very interesting. Go and check what they do and actually install things you need to compile. It's not that many. You don't believe it's going to be your computer with garbage now. Create a build directory. We're going to get out from the repository, from the inside of the repository, one step back, create a GCC build or whatever you want. Go back into the GCC build. And then start first to configure, make, and make install. Now, here comes the tricky part. Confir will require some specific flags for your consideration that with my personal story, I was stepping my head into the wall and saying, why am I still compiling? Why am I still compiling? Because I was missing some of these important things. So to save you time of that pumping your head into the wall and saying, what am I missing? What am I missing? Here is the receipt that worked for me that I thought that works for you. The source code of the business script, it's there in my personal YouTube repository. And it's very simple. I'm just going to explain a bit. So we specify a prefix. Where do you want to install your new GCC, right? You want to install just the test in the middle in user log car or you define your prefix. Enable share. It's for sure mandatory. We live in a shared world. It's very rare that you have a static world where all the drivers need to be compiled statically. You need to be shared and loaded dynamically. So that's for sure. Enable system seed leave. This is important because in terms of performance, it will help you to improve the compression size. And if you think that your system, it's way much more in terms of seed leave, it has better performance than the one that it's loaded with GCC. Go ahead and set with system seed leave because it will improve the performance quite a bit. Enable the kind of threats. As we know, we have different kind of threats formats. The POSIX is the most much more user one. So this is the one that I use in normal machine. So you have a specific needs. In the documentation of enable threats for configuring the seed, you will find all the possible frustration that you can use. For the ethics, it's when you clean out the function and how do you clean up problems with the memory. Enable collocate, continue. Again, there are multiple versions. For us, it's going to be the mandatory or recommended. Enable language. These will save you a lot of time. You just need C++4 trend. That's good enough. If you don't need any other thing else, for all the language that the GNUD compiler collection, that's the reason why it's called GCC GNUD compiler collection, because in the beginning it was just for C, now it was just for C++4 trend goal and other things. So I highly recommend that you do not put here all and specify straightforward which one you need. And after that, just go make and make install. We're going to go into the install. Here are some examples or description about just for the record about what does each one of these one do. And again, also, another one that you want to put over here, it's disable multilip. Disable multilip, it's very important. This parameter ensures that they are created for the specific architecture. This was the one that I was bumping my head because you will see an error, something that say, hey, compiler bill fails with fatal error, you need to stop 32.h not to fail directly. If you're like me in a 64-bit system, it's supposed to have the libc that you want to compile. So remember, the compiler will require libraries to do it and those libraries are going to be in GNUDC. So if you are asking, you don't disable multilip or disable multiart, it will just go and bill for multiple architecture and for multiple libraries definition. So we'll bill for 32 and 64. And when it goes and bill for 32 and say, I don't have the libraries for 32 bits and it's going to fail horrible. So please disable multilip or disable multiart, also highly recommend that all the descriptions, it's put it there. So it's the one that I use and disable both. So if it works for you, I'm happy to share. Now that I have my GCC, what I do is I put into, in my personal experience, what we have here, clear, at least it's, we use Mock and we use Koji. So you can use other options if you're using Davian or Suze or according to your architecture and your bill system up to you. But the idea is you have a new compiler. And what you have to do is compile all the minimum packages to create a new image and say, okay, I'm going to grab, now I'm going to grab the new compiler, the source code of the compiler. Does it compile, okay, with the new compiler? Yes, okay. So I'm going to put that in my new repo, my local repo. I'm going to tell my Mock and say, hey, use please this one. Mock's going to tell me, hey, do I have a new version of the compiler? Yes, I'm going to use it. Okay. So in this one is redundant, but it's going to happen with the kernel, gdpc, tcl, spec, encorses, bash, or utl, getex, rep, gc, and formake, pack, grow, set, and tar. Another important ones that you might think in the beginning that it's useful. This list is the minimal package to build a Linux system taking from the instrument scratch, which is a great source. And I just added system D because you know, system D is important to rebuild. And once you start to rebuild, of course, when you rebuild, you're going to need sometimes bash, getex, rep. Mock is going to take from the old one, all packages. The idea is that in the end, you grow that much, this local repo, that it's similar to this one. And when you build a new thing like hello world, or a test case, it's going to go and grab instead of from the old packages, the new packages, because the version is going to be changing in this part when you upgrade your build system, try to upgrade the version, so that Mock takes the latest one and compile with the new packages here. In the end, if there is a niche and does not compile, okay, well, it's time to debug. What happened a few weeks ago, we have by ethanol common many mistakes. We have to go grab the patch, fix it, or apply ethanol common, F common, and keep moving. But in the end, it was the written file of the minimum. What are the minimum systems that you need to rebuild? The recommendation is to rebuild the full distro. In these terms, however, if you want to build your application statically with new features for GCC, you don't have to, of course, build the full stop, but be cautious about future problems of my health. So it's not a role you have to, but it's recommended that you build as much packages you're going to be using in this part. What can I ask for help? If you are in a lot of problems, top of your head, GCC provides a porting to GCC documentation. Go and check. It's very well documented. The people and maintainers have figured out there is an issue with their new things. Go and post how to do the porting to the new GCC. GCC held mail needs. There are specific mail needs where people ask and ask and ask, and they get pretty good answers about how to fix the issue. GCC mail needs for packaging problems, and GCC also mentioned that they have a new mail needs for the package problem. So if there is an issue, they can post it over there into the mail needs. In summary, the tool chain is simply tool to build software, compile or assemble a link, your libraries, and a few useful utilities, and that was taken actually from entering from the position of what is a tool chain. The answer is no. It's not entirely true. Actually, the tool chain is a set of optimized tools to build better software. It's like in this picture, we have a lot of tools that are optimized to build better software for you. We are in the tool chain's team. Our goal is to create you tools that help you to create better software with better performance, with higher security, with better code with less errors for your end user. We are happy when you, as a community, success with our tools that we create for you. So let use it and have fun with this. Thank you so much. Have a great day and now we are open for any question. Thank you.