Diferență între revizuiri ale paginii „SDPT Lab 3”
| (Nu s-a afișat o versiune intermediară efectuată de același utilizator) | |||
| Linia 11: | Linia 11: | ||
* Master Modern CMake: out-of-source builds, targets, and static libraries. | * Master Modern CMake: out-of-source builds, targets, and static libraries. | ||
* Integrate remote third-party libraries using CMake <code>FetchContent</code>. | * Integrate remote third-party libraries using CMake <code>FetchContent</code>. | ||
| − | |||
| − | |||
== Part 1: Theoretical Reference == | == Part 1: Theoretical Reference == | ||
| Linia 87: | Linia 85: | ||
* [https://www.gnu.org/software/make/manual/make.html GNU Make Manual] | * [https://www.gnu.org/software/make/manual/make.html GNU Make Manual] | ||
* [https://cmake.org/cmake/help/latest/ CMake Official Documentation] | * [https://cmake.org/cmake/help/latest/ CMake Official Documentation] | ||
| − | |||
| − | |||
== Part 2: The Challenges == | == Part 2: The Challenges == | ||
| Linia 138: | Linia 134: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| − | |||
=== Challenge 1: The Scalable Makefile (Estimated time: 25 mins) === | === Challenge 1: The Scalable Makefile (Estimated time: 25 mins) === | ||
| Linia 152: | Linia 147: | ||
# Open <code>include/sensor.h</code> and add a dummy integer to the <code>SensorData</code> struct. Run <code>make</code> again. It MUST recompile both <code>.cpp</code> files automatically. If it doesn't, your dependency tracking is broken. | # Open <code>include/sensor.h</code> and add a dummy integer to the <code>SensorData</code> struct. Run <code>make</code> again. It MUST recompile both <code>.cpp</code> files automatically. If it doesn't, your dependency tracking is broken. | ||
| − | |||
=== Challenge 2: Migrating to CMake (Estimated time: 20 mins) === | === Challenge 2: Migrating to CMake (Estimated time: 20 mins) === | ||
| Linia 164: | Linia 158: | ||
'''Verification:''' | '''Verification:''' | ||
Your root directory should contain only your source files and the <code>CMakeLists.txt</code>. Inside the <code>build/</code> directory, running <code>make</code> should yield the executable. | Your root directory should contain only your source files and the <code>CMakeLists.txt</code>. Inside the <code>build/</code> directory, running <code>make</code> should yield the executable. | ||
| − | |||
| − | |||
=== Challenge 3: Modular Architecture (Estimated time: 25 mins) === | === Challenge 3: Modular Architecture (Estimated time: 25 mins) === | ||
| Linia 177: | Linia 169: | ||
'''Verification:''' | '''Verification:''' | ||
Run <code>make</code> inside the build folder. You must see it compile <code>libsensor_driver.a</code> first, and then link it to the main executable. | Run <code>make</code> inside the build folder. You must see it compile <code>libsensor_driver.a</code> first, and then link it to the main executable. | ||
| − | |||
| − | |||
=== Challenge 4: Third-Party Git Dependencies (Estimated time: 30 mins) === | === Challenge 4: Third-Party Git Dependencies (Estimated time: 30 mins) === | ||
| Linia 191: | Linia 181: | ||
'''Verification:''' | '''Verification:''' | ||
Running your executable should print a perfectly formatted, multi-line JSON string representing your sensor data. Check <code>build/_deps/</code> to see the downloaded source code. | Running your executable should print a perfectly formatted, multi-line JSON string representing your sensor data. Check <code>build/_deps/</code> to see the downloaded source code. | ||
| − | |||
| − | |||
== Lab Evaluation == | == Lab Evaluation == | ||
| − | To receive full credit, | + | To receive full credit, submit the following elements on Moodle: |
| − | # | + | # Final version of the Makefile. |
| − | # | + | # Final version of the CMakeLists.txt. |
| − | + | # Screenshot of the console output of your executable printing the JSON payload. | |
| − | # | ||
Versiunea curentă din 16 martie 2026 17:07
Lab 3: Build Automation - Makefiles and Modern CMake
Introduction
In professional embedded development, clicking a "Build" button in an IDE is a luxury you rarely have. When working with Embedded Linux, RTOS environments, or CI/CD pipelines, you must define exactly how your source code is translated into machine code.
This lab transitions you from manual terminal commands to scalable build automation.
Goals
- Understand the C++ compilation pipeline (Preprocessing $\rightarrow$ Compilation $\rightarrow$ Linking).
- Master GNU Make: pattern rules, automatic variables, and header dependency generation.
- Master Modern CMake: out-of-source builds, targets, and static libraries.
- Integrate remote third-party libraries using CMake
FetchContent.
Part 1: Theoretical Reference
Use this section as a reference manual to complete the tasks in Part 2.
1.1 GNU Make Fundamentals
Make tracks file modification timestamps to avoid recompiling code that hasn't changed. A Makefile consists of rules:
target: dependencies
<TAB> command
(Note: Makefiles strictly require a real TAB character for indentation, not spaces!)
Automatic Variables: Make provides shortcuts to avoid typing duplicate filenames:
$@: The target filename.$<: The first dependency.$^: All dependencies (space-separated).
Pattern Rules: Instead of writing a rule for every file, use a pattern template:
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
GCC Auto-Dependencies (The Header Problem):
If you change a .h file, Make won't normally detect it because object files depend on .cpp files. We ask GCC to generate dependency (.d) files for us:
- Add
-MMD -MPto yourCXXFLAGS. - Include the generated files at the bottom of your Makefile using:
-include $(DEPS)
1.2 Modern CMake Fundamentals
CMake is a meta-build system. It generates Makefiles (or Ninja files, or Visual Studio solutions) based on a high-level CMakeLists.txt script. Modern CMake is "Target-Based"—you define targets (executables/libraries) and attach properties to them.
Core Commands:
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)
# Build an executable from source
add_executable(my_app main.cpp)
# Build a static library (.a archive)
add_library(my_driver STATIC driver.cpp)
# Define where a target should look for header files
target_include_directories(my_driver PUBLIC include/)
# Link a library to an executable
target_link_libraries(my_app PRIVATE my_driver)
Out-of-Source Builds: Never pollute your source directory with binaries. Always build in a separate folder:
mkdir build && cd build
cmake ..
make
Fetching External Libraries: CMake can download libraries directly from Git during the configuration phase:
include(FetchContent)
FetchContent_Declare(
json_lib
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.2
)
FetchContent_MakeAvailable(json_lib)
1.3 Useful Resources
Part 2: The Challenges
Setup: The Raw Materials
Create a new directory for this lab (sdpt-lab3). Inside, create an include/ directory and a src/ directory. Populate them with the following three files to simulate an IoT sensor node.
include/sensor.h
#pragma once
struct SensorData {
int temperature;
int humidity;
};
void init_sensor();
SensorData read_sensor();
src/sensor.cpp
#include <iostream>
#include "../include/sensor.h"
void init_sensor() {
std::cout << "[Hardware] I2C Sensor Initialized." << std::endl;
}
SensorData read_sensor() {
return {24, 60};
}
src/main.cpp
#include <iostream>
#include "../include/sensor.h"
int main() {
std::cout << "Starting IoT Node..." << std::endl;
init_sensor();
SensorData data = read_sensor();
std::cout << "Temp: " << data.temperature << "C, Hum: " << data.humidity << "%" << std::endl;
return 0;
}
Challenge 1: The Scalable Makefile (Estimated time: 25 mins)
Your Task: Write a Makefile in the root directory that compiles these files into an executable named iot_node.bin.
- Do not hardcode the
.cppfile names. Use thewildcardfunction to find them dynamically. - Use variables for the compiler (
CXX) and flags (CXXFLAGS). - Use Pattern Rules and Automatic Variables to compile
.cppto.o. - Implement GCC header dependency tracking (
-MMD -MP).
Verification:
- Run
make. It should compile successfully. - Run
makeagain immediately. It should say "Nothing to be done". - Open
include/sensor.hand add a dummy integer to theSensorDatastruct. Runmakeagain. It MUST recompile both.cppfiles automatically. If it doesn't, your dependency tracking is broken.
Challenge 2: Migrating to CMake (Estimated time: 20 mins)
Makefiles are not cross-platform. We are moving to CMake. Your Task:
- Run
make clean(or manually delete all generated.o,.d, and.binfiles). - Create a
CMakeLists.txtfile to build the exact same executable. - Set the C++ standard to C++14.
- Perform an Out-of-Source build using a
build/directory.
Verification:
Your root directory should contain only your source files and the CMakeLists.txt. Inside the build/ directory, running make should yield the executable.
Challenge 3: Modular Architecture (Estimated time: 25 mins)
Dumping all source files into a single executable is bad practice. Hardware drivers should be isolated into static libraries.
Your Task: Modify your CMakeLists.txt.
- Remove
src/sensor.cppfrom your executable target. - Create a new STATIC library target named
sensor_driverfromsrc/sensor.cpp. - Attach the
include/directory to this library target usingtarget_include_directories. - Link the
sensor_driverlibrary to your main executable.
Verification:
Run make inside the build folder. You must see it compile libsensor_driver.a first, and then link it to the main executable.
Challenge 4: Third-Party Git Dependencies (Estimated time: 30 mins)
Our IoT node needs to transmit its data as a JSON payload, but writing a JSON parser from scratch is inefficient. Your Task:
- Use CMake's
FetchContentmodule to download the popular "Nlohmann JSON" library directly from GitHub.- Repo:
https://github.com/nlohmann/json.git - Tag:
v3.11.2
- Repo:
- Link the imported target (
nlohmann_json::nlohmann_json) to your main executable. - Modify
main.cppto include<nlohmann/json.hpp>. Serialize yourSensorDatainto a JSON object and print it to the console using.dump(4).
Verification:
Running your executable should print a perfectly formatted, multi-line JSON string representing your sensor data. Check build/_deps/ to see the downloaded source code.
Lab Evaluation
To receive full credit, submit the following elements on Moodle:
- Final version of the Makefile.
- Final version of the CMakeLists.txt.
- Screenshot of the console output of your executable printing the JSON payload.