{"id":8292,"date":"2023-03-08T22:08:01","date_gmt":"2023-03-08T20:08:01","guid":{"rendered":"https:\/\/blue.pri.ee\/ttu\/?p=8292"},"modified":"2026-03-17T09:38:34","modified_gmt":"2026-03-17T07:38:34","slug":"pr2en6-makefile-and-logging","status":"publish","type":"post","link":"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/","title":{"rendered":"PR2EN6: Makefile and logging"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Lab_materials\" >Lab materials<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Lab_tasks\" >Lab tasks<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Task_part_1_2_W06-1_Reading_data_and_processing\" >Task part\u00a0 1 \/ 2 [W06-1]: Reading data and processing<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Requirements\" >Requirements<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Hints\" >Hints<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Testing\" >Testing<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Task_part_2_2_W06-2_Logging\" >Task part 2 \/ 2 [W06-2]: Logging<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Requirements-2\" >Requirements<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Hints-2\" >Hints<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Extra_task_1_W06-3_logging_library\" >Extra task 1 [W06-3]: logging library<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Requirements-3\" >Requirements<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Extra_task_2_W06-4_Reading_simplified_CSV\" >Extra task 2 [W06-4]: Reading simplified CSV<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Requirements-4\" >Requirements<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Walkthrough\" >Walkthrough<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#After_this_class_you_should\" >After this class, you should<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/#Additional_content\" >Additional content<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Lab_materials\"><\/span>Lab materials<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>Slides: <a href=\"https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/slaidid-en\/06_debugging.pdf\"><strong>Debugging<\/strong><\/a><\/li>\n<li>Slides: <a href=\"https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/slaidid-en\/06_makefile_logging.pdf\"><strong>Makefile and logging<\/strong><\/a><\/li>\n<li>Additional examples: <a href=\"https:\/\/blue.pri.ee\/ttu\/programming-ii\/code-samples\/creating-a-library\/\"><strong>Making reusable code in the form of a\u00a0 library\u00a0<\/strong><\/a><\/li>\n<li>Additional reading: <strong><a href=\"https:\/\/blue.pri.ee\/ttu\/coding-guides\/fun-with-valgrind\/\">Fun with valgrind<\/a><\/strong><\/li>\n<li>Test files for valgrind: <strong><a href=\"https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/demokood\/valgrind.zip\">https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/demokood\/valgrind.zip<\/a><\/strong><\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"Lab_tasks\"><\/span>Lab tasks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In this lab you have one task, which is divided into two parts. The task is extended by two extra tasks.<\/p>\n<p>NB! Even though you can develop on any platform you want, one part of the proof will be to execute your program through Valgrind. Valgrind is known to work well on Linux and is known to be available on MacOS, however not on Windows. If\u00a0 you wish to develop on Windows, you need to transfer the file to a Linux environment when defending.<\/p>\n<p><strong>Download the data files: <a href=\"https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/andmefailid\/6_make_data.zip\">https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/andmefailid\/6_make_data.zip<\/a><\/strong><\/p>\n<p>The archive contains the files for both the base and extra task!<\/p>\n<h4><span class=\"ez-toc-section\" id=\"Task_part_1_2_W06-1_Reading_data_and_processing\"><\/span>Task part\u00a0 1 \/ 2 [W06-1]: Reading data and processing<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In the first part of the task, we need to read the data, process and print it. You will also need to demonstrate your use of compiling using a Makefile and testing memory errors using valgrind.<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Read data from the input file\n<ul>\n<li>Data file structure<br \/>\n<span class=\"lang:default highlight:0 decode:true crayon-inline \">&lt;subject name&gt; &lt;number of grade&gt; &lt;grades&gt;<\/span><\/li>\n<li>Data must be stored in a structure array. For grades, you can create a reasonably sized array in the struct &#8211; e.g. 20 grades (based on the data file for the task)<\/li>\n<\/ul>\n<\/li>\n<li>Print the following information\n<ul>\n<li>Name of the subject<\/li>\n<li>Grades given in the subject<\/li>\n<li>Average grade for the subject<\/li>\n<\/ul>\n<\/li>\n<li>Keep your reading, calculating average and output in separate functions (i.e. all called from main).<\/li>\n<li>Code must be divided into two code files, which both have their own header files. Division must make sense, but details are up to you.<\/li>\n<li>Code must be compiled using a Makefile\n<ul>\n<li>At minimum, Makefile must describe the recipe <span class=\"lang:default highlight:0 decode:true crayon-inline\">all<\/span> , have a variable\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline\">CFLAGS<\/span>\u00a0 \u00a0and use the following flags for compilation:\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline \">-Wall -Wextra -Wconversion -g -fanalyzer<\/span><\/li>\n<\/ul>\n<ul>\n<li>Other aspects of the complexity and structure of the Makefile are up to you!<\/li>\n<\/ul>\n<\/li>\n<li>During the defence\n<ul>\n<li>Show compilation using a Makefile<\/li>\n<li>Show the output through valgrind to prove that there are no issues.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h5><span class=\"ez-toc-section\" id=\"Hints\"><\/span>Hints<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>The number of grades for each subject can be different, which means that every line in the file might have a different length. Due to this, we cannot read the data file with just a single <span class=\"lang:c highlight:0 decode:true crayon-inline \">fscanf()<\/span>\u00a0 function call like shown on previous weeks.<\/p>\n<p>Due to this, we need to perform the reading of the data using nested loops<\/p>\n<ul>\n<li>The outer loop will read the name of the subject and the number of grades in that subject<\/li>\n<li>The inner loop will use the number of grades obtained from the outer loop to specify the number of iterations. Do not forget to check the return value of <span class=\"lang:c highlight:0 decode:true crayon-inline \">fscanf()<\/span>\u00a0 of the inner loop<\/li>\n<\/ul>\n<h5><span class=\"ez-toc-section\" id=\"Testing\"><\/span>Testing<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>This is an example of the code structure that you could have.<\/p>\n<p><strong>NB!<\/strong> Names of files are not determined, it&#8217;s just a sample. Also the data file can be in the same folder as the code files.<\/p>\n<pre class=\"toolbar:2 nums:false lang:default highlight:0 decode:true\">.\r\n\u251c\u2500\u2500 data\r\n\u2502   \u251c\u2500\u2500 data_grades.csv\r\n\u2502   \u2514\u2500\u2500 data_grades.txt\r\n\u251c\u2500\u2500 analyzer.c\r\n\u251c\u2500\u2500 analyzer.h\r\n\u251c\u2500\u2500 Makefile\r\n\u251c\u2500\u2500 subjects_processor.c\r\n\u251c\u2500\u2500 subjects_processor.h<\/pre>\n<p><strong>NB! <\/strong>The following output exampel doesn&#8217;t show valgrind output. Make sure to test using valgrind as well!<\/p>\n<pre class=\"theme:cisco-router toolbar:2 nums:false lang:default highlight:0 decode:true\">Subject: Programming\r\nGrades:  4 5 5 4 2 5 1 4 2 5\r\nAverage: 3.70\r\n\r\nSubject: Databases\r\nGrades:  5 3 3 4 4 3\r\nAverage: 3.67\r\n\r\nSubject: Mechatronics\r\nGrades:  3 3 4 4 5 0\r\nAverage: 3.17\r\n\r\nSubject: Physics\r\nGrades:  5 5 3 3 2 3 4 5 1 1 2 4\r\nAverage: 3.17\r\n\r\nSubject: Ethics\r\nGrades:  5 5 5 4 5 3\r\nAverage: 4.50\r\n\r\nSubject: Scientology\r\nGrades:  N\/A\r\nAverage: N\/A\r\n\r\nSubject: Chemistry\r\nGrades:  4 4 3 4 5 4 5\r\nAverage: 4.14<\/pre>\n<h4><span class=\"ez-toc-section\" id=\"Task_part_2_2_W06-2_Logging\"><\/span>Task part 2 \/ 2 [W06-2]: Logging<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In this part of the task, you need to add logging to your program.<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements-2\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Add logging for the program\n<ul>\n<li>One log per line. Logs cannot be on two lines!<\/li>\n<li>Every log starts with a timestamp. Timestamp must contain the date (day, month, year) and the time (hours, minutes, seconds)<\/li>\n<\/ul>\n<\/li>\n<li>When executing the program again, the logs must not be erased from the previous executions.<\/li>\n<li>Events to log\n<ul>\n<li>Opening and closing of the input file<\/li>\n<li>Reading of the input file completed. Print the number of lines read.<\/li>\n<li>Reading of the input file aborted due to reaching the limit of the array. Print the max size in the log. NB! You have two arrays &#8211; struct array and grades array in each struct!<\/li>\n<li>Error calculating average grade.<\/li>\n<\/ul>\n<\/li>\n<li>Integrity of the log must be ensured even if the program crashes\n<ul>\n<li>Option 1: You can force writing of the output buffer to the file using\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline\">fflush()<\/span><\/li>\n<\/ul>\n<ul>\n<li>Option 2:Close the log file after each write &#8211; closing of the file writes the buffer to the file.<\/li>\n<\/ul>\n<\/li>\n<li>If the log file fails to open, program must continue its work (and not exit!). Notify the user of failure.<\/li>\n<\/ul>\n<h5><span class=\"ez-toc-section\" id=\"Hints-2\"><\/span>Hints<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Prepare the string before calling the logger function! Do not overwhelm the logging function with parameters, you want it to be simple to call. To prepare the string, a good option would be to use\u00a0<span class=\"lang:default highlight:0 decode:true crayon-inline\">snprintf()<\/span><\/li>\n<li>To simplify the logger function, it is recommended to pass it the name of the file or the pointer to the log file. Some possible options:\n<ul>\n<li>Open and close the file in the log function<\/li>\n<li>This is also one place where are global variable would not be out of place. If you wish, you can create the file pointer as a global variable (not a good solution, but an acceptable one). However an even better solution would be to complete the extra task.<\/li>\n<\/ul>\n<\/li>\n<li>E.g. Calling the logger function might something like this:<br \/>\n<span class=\"lang:default decode:true crayon-inline\">Logger(&#8220;Program started&#8221;);<\/span><\/li>\n<\/ul>\n<h4><span class=\"ez-toc-section\" id=\"Extra_task_1_W06-3_logging_library\"><\/span>Extra task 1 [W06-3]: logging library<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In this task, you will create a logging library. Hint: you can use it for homework 2.<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements-3\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Add a set of .c and .g files and move your logging code there<\/li>\n<li>Add 4 levels for logging: OFF, ERROR, WARNING ja INFO &#8211; these are enums!\n<ul>\n<li>On each line of the log file, print the logging level of the message<\/li>\n<li>Log should be only written to the file if the set logging level permits it.<br \/>\nI.e.<br \/>\nINFO level means that all messages will be logged;<br \/>\nWARNING level means that only messages with the logging level WARNING and ERROR are logged;<br \/>\nERROR level means that only messages with the logging level ERROR are logged<br \/>\nOFF means logs are not produced<\/li>\n<\/ul>\n<\/li>\n<li>To call logger, you now needs to include the level of the log (ERROR, WARNING v\u00f5i INFO)<br \/>\nE.g. <span class=\"lang:default highlight:0 decode:true crayon-inline\">Logger(LOG_INFO, &#8220;Program started&#8221;);<\/span><\/li>\n<li>Your library must support giving a specific name to the log file<br \/>\nE.g. <span class=\"lang:default highlight:0 decode:true crayon-inline\">LoggerSetOutputName(&#8220;log.txt&#8221;);<\/span><\/li>\n<li>Your library must support setting the logging level<br \/>\nE.g. <span class=\"lang:default highlight:0 decode:true crayon-inline\">LoggerSetLoggingLevel(LOG_INFO);<\/span><\/li>\n<li>The settings for the log must be kept internally in the logging library. Settings include the log file name and logging level (you can add additional ones if you want). Keep these as global variables in your logging library.<\/li>\n<li>Settings for the logger should have default values &#8211; e.g. if developer forgets or does not want to set them up, then defaults would be used and program wouldn&#8217;t crash.<\/li>\n<li>All logs must be timestamped as described in the base task.<\/li>\n<\/ul>\n<h4><span class=\"ez-toc-section\" id=\"Extra_task_2_W06-4_Reading_simplified_CSV\"><\/span>Extra task 2 [W06-4]: Reading simplified CSV<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>In this task our purpose is to show a simplified way to read names that consist of multiple words.<\/p>\n<h5><span class=\"ez-toc-section\" id=\"Requirements-4\"><\/span>Requirements<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<ul>\n<li>Use the simple CSV version of the input file<\/li>\n<li>Data fields are separated from each other by a comma, data fields do not contain commas.<\/li>\n<\/ul>\n<h5><span class=\"ez-toc-section\" id=\"Walkthrough\"><\/span>Walkthrough<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>NB! We are using a simplified version of CSV files and reading then. <strong>You\u00a0cannot read any CSV file in this manner!\u00a0<\/strong>If a fields would contain a comma, this method of reading could not be used!<\/p>\n<p>If you need complete CSV support, either use a library (e.g. libcsv) or write your own that could be based on a finite state machine (FSM) &#8211; you read a character and then depending on the current state and that character, you choose what to do.<\/p>\n<hr \/>\n<p>scanf() family of function supports describing simple regular expressions for reading and describing data.<\/p>\n<p>E.g. to read a time, we can use the format\u00a0<span class=\"lang:default decode:true crayon-inline\">scanf(&#8220;%d:%d&#8221;, &amp;hours, &amp;minutes);<\/span>\u00a0 &#8211; with this format, the user can enter the time as\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline \">14:35<\/span> . Variable <span class=\"lang:default highlight:0 decode:true crayon-inline\">hours<\/span>\u00a0 would get <span class=\"lang:default highlight:0 decode:true crayon-inline\">14<\/span> as a value and\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline\">minutes<\/span>\u00a0 would get <span class=\"lang:default highlight:0 decode:true crayon-inline\">35<\/span> . However, if the user chose to enter <span class=\"lang:default highlight:0 decode:true crayon-inline\">14 35<\/span> , it would not match the format &#8211; <span class=\"lang:default highlight:0 decode:true crayon-inline \">hours<\/span>\u00a0 would still get <span class=\"lang:default highlight:0 decode:true crayon-inline \">14<\/span> , because we didn&#8217;t expect a space in the format, the reading stops and\u00a0 <span class=\"lang:default highlight:0 decode:true crayon-inline\">minutes<\/span>\u00a0 will be left uninitialized.<\/p>\n<p>Based on this knowledge, we can compose a format \u00a0<span class=\"lang:default highlight:0 decode:true crayon-inline \">fscanf(fp, &#8220;%[^,],%d&#8221;, &#8230;)\u00a0<\/span> . Replace the file pinter with your own and instead of three dots, put your variables where to store the data.<\/p>\n<ul>\n<li>First field will be read as a string, until the comma (comma is not read).<\/li>\n<li>Then the comma will be read out of the buffer (and thrown away)<\/li>\n<li>Then, a single integer will be read (number of grades in the subject).<\/li>\n<\/ul>\n<p>This method allows you to read the first two data fields. The rest of the format for getting the grades you must make on your own (don&#8217;t forget the commas!).<\/p>\n<h3><span class=\"ez-toc-section\" id=\"After_this_class_you_should\"><\/span>After this class, you should<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>be able to compose a simple Makefile\n<ul>\n<li>Know how to declare a variable and use one<\/li>\n<li>Know how to write a recipe, including multiple recipes in a file<\/li>\n<li>Know what goes into a recipe<\/li>\n<li>Know about implicit rules for Makefiles<\/li>\n<\/ul>\n<\/li>\n<li>be able to compile code using Makefiles<\/li>\n<li>Know to to use valgrind and read its output to test your programs for bugs<\/li>\n<li>Know how to get the current time inside of a program and be able to format the time string<\/li>\n<li>Know basics about logging and its importance<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"Additional_content\"><\/span>Additional content<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>Make manual<br \/>\n<strong><a href=\"https:\/\/www.gnu.org\/software\/make\/manual\/make.html\">https:\/\/www.gnu.org\/software\/make\/manual\/make.html<\/a><\/strong><\/li>\n<li>What is a Makefile and how does it work?<br \/>\n<strong><a href=\"https:\/\/opensource.com\/article\/18\/8\/what-how-makefile\">https:\/\/opensource.com\/article\/18\/8\/what-how-makefile<\/a><\/strong><\/li>\n<li>Compiling Programs with Make<br \/>\n<strong><a href=\"https:\/\/web.stanford.edu\/class\/archive\/cs\/cs107\/cs107.1194\/resources\/make\">https:\/\/web.stanford.edu\/class\/archive\/cs\/cs107\/cs107.1194\/resources\/make<\/a><\/strong><\/li>\n<li>Makefile tutor project (sample projects with Makefile&#8217;iga)<br \/>\n<strong><a href=\"https:\/\/github.com\/clemedon\/Makefile_tutor\">https:\/\/github.com\/clemedon\/Makefile_tutor<\/a><\/strong><\/li>\n<li>Makefile tutorial<br \/>\n<strong><a href=\"https:\/\/makefiletutorial.com\">https:\/\/makefiletutorial.com<\/a><\/strong><\/li>\n<li>VMWare VSphere Logging options (levels)<br \/>\n<strong><a href=\"https:\/\/docs.vmware.com\/en\/VMware-vSphere\/8.0\/vsphere-vcenter-configuration\/GUID-0439D577-66F7-4584-AF05-5EB41A761873.html\">https:\/\/docs.vmware.com\/en\/VMware-vSphere\/8.0\/vsphere-vcenter-configuration\/GUID-0439D577-66F7-4584-AF05-5EB41A761873.html<\/a><\/strong><\/li>\n<li>An example of a logging library for C\u00a0 (more complex than we need)<br \/>\n<strong><a href=\"https:\/\/github.com\/rxi\/log.c\">https:\/\/github.com\/rxi\/log.c<\/a><\/strong><\/li>\n<li>strftime() function<br \/>\n<strong><a href=\"https:\/\/www.cplusplus.com\/reference\/ctime\/strftime\/\">https:\/\/www.cplusplus.com\/reference\/ctime\/strftime\/<\/a><\/strong><\/li>\n<li>Valgrind documentation<br \/>\n<strong><a href=\"https:\/\/valgrind.org\/docs\/manual\/index.html\">https:\/\/valgrind.org\/docs\/manual\/index.html<\/a><\/strong><\/li>\n<li>Compiling as a library guide<br \/>\n<strong><a href=\"http:\/\/www.yolinux.com\/TUTORIALS\/LibraryArchives-StaticAndDynamic.html\">http:\/\/www.yolinux.com\/TUTORIALS\/LibraryArchives-StaticAndDynamic.html<\/a><\/strong><\/li>\n<li>Address Sanitizer documentation<br \/>\n<strong><a href=\"https:\/\/github.com\/google\/sanitizers\/wiki\/AddressSanitizer\">https:\/\/github.com\/google\/sanitizers\/wiki\/AddressSanitizer<\/a><\/strong><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Lab materials Slides: Debugging Slides: Makefile and logging Additional examples: Making reusable code in the form of a\u00a0 library\u00a0 Additional reading: Fun with valgrind Test files for valgrind: https:\/\/blue.pri.ee\/ttu\/files\/iax0584\/demokood\/valgrind.zip Lab tasks In this lab you have one task, which is divided into two parts. The task is extended by two extra tasks. NB! Even though &hellip; <a href=\"https:\/\/blue.pri.ee\/ttu\/labs\/pr2en6-makefile-and-logging\/\" class=\"more-link\">Loe edasi <span class=\"screen-reader-text\">PR2EN6: Makefile and logging<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[75,105],"tags":[],"class_list":["post-8292","post","type-post","status-publish","format-standard","hentry","category-labs","category-pr2_en"],"_links":{"self":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts\/8292","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/comments?post=8292"}],"version-history":[{"count":12,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts\/8292\/revisions"}],"predecessor-version":[{"id":11301,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/posts\/8292\/revisions\/11301"}],"wp:attachment":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/media?parent=8292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/categories?post=8292"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/tags?post=8292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}