{"id":6653,"date":"2020-09-16T08:59:43","date_gmt":"2020-09-16T15:59:43","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=6653"},"modified":"2020-10-01T07:19:20","modified_gmt":"2020-10-01T14:19:20","slug":"managing-multi-target-embedded-projects-with-visualgdb","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/cmake\/multitarget\/","title":{"rendered":"Managing Multi-Target Embedded Projects with VisualGDB"},"content":{"rendered":"<p>This project shows how to setup a large multi-target embedded project consisting of an executable, several static libraries, and multiple platforms (STM32 and Win32). We will use the Advanced CMake Project Subsystem that allows easily managing multiple configurations and reusing project-level settings between all targets. The final target layout will consist of the application itself, a basic cross-platform library, and an OS abstraction layer hiding the differences between Win32 and STM32 targets. The diagram below illustrates the layout:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/diagram-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6691\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/diagram-1.png\" alt=\"\" width=\"1062\" height=\"534\" \/><\/a><\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/08\/01-newprj-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6589\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/08\/01-newprj-1.png\" alt=\"\" width=\"966\" height=\"624\" \/><\/a><\/li>\n<li>Enter the name and location for the project, then click &#8220;Create&#8221; to start VisualGDB-specific part of the wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/01-newprj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6655\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/01-newprj.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>On the first page of the wizard, select &#8220;Create a new project -&gt; Embedded Binary -&gt; Advanced CMake&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/02a-type.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6656\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/02a-type.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the next page select your embedded toolchain and the target device. In this tutorial we will use the GCC ARM toolchain, however the Embedded CMake projects also support IAR and Keil compilers:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/03-device.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6657\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/03-device.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Pick the default &#8220;LEDBlink&#8221; sample and click &#8220;Next&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/04-blink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6658\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/04-blink.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Finally, select debugging settings that will work with your target and click &#8220;Finish&#8221; to generate the project: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/05-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6659\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/05-debug.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Once the project is generated, check the contents of Solution Explorer:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/struct.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6665\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/struct.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>The project will consist of the top-level node <strong>(1)<\/strong>, the BSP <strong>(2)<\/strong> and the main executable <strong>(3)<\/strong>:\n<ul>\n<li>The top-level node corresponds to the project itself. It defines common properties (e.g. toolchain, or debug settings) that affect all targets inside the project.<\/li>\n<li>The <strong>BSP<\/strong> target is a special meta-library automatically managed by VisualGDB. It contains the base support files (e.g. startup file and linker script) for the target device, and also additional frameworks (such as the STM32 HAL). The exact list of files included in BSP is managed by VisualGDB, and cannot be edited directly, unless you convert it to a stand-alone BSP. Instead, you can change various BSP parameters via VisualGDB Project Properties (e.g. whether to include the USB library) and VisualGDB will automatically recompute the necessary files.<\/li>\n<li>The main executable works just like a regular VS project. You can pick the sources included in it, and also set various compiler parameters. BSP-based executables inherit compiler settings from the BSP they reference, so in most of the cases we advise editing those ones instead.<\/li>\n<\/ul>\n<\/li>\n<li>We will now show how the targets are defined internally. Right-click on the main executable <strong>(3)<\/strong> and select &#8220;Go To Definition&#8221;: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/07-def.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6664\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/07-def.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>This will open the <strong>CMakeLists.txt<\/strong> file in the project directory, defining the project and the 2 targets. See how each target in Solution Explorer has a CMake statement corresponding to it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/08-struct.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6663\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/08-struct.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>You can step through the CMake configuration process. Right-click on the project node in Solution Explorer and select &#8220;Launch CMake Debugger&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/09-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6668\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/09-debug.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>You can use the regular debugging commands (e.g. F10 to step over or F11 to step in) to follow the CMake configuration process:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/10-debugger.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6666\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/10-debugger.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Try stepping over <strong>find_bsp()<\/strong> and into <strong>add_bsp_based_executable()<\/strong> to see how it is implemented:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/11-stepin.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6667\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/11-stepin.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Now we will move all STM32-specific code into a separate OS Abstraction Layer (OSAL) library. Right-click on the project node in Solution Explorer and select Add-&gt;New Item. Then proceed with adding a new static library in the <strong>OSAL\/STM32<\/strong> subdirectory:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/12-osal.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6669\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/12-osal.png\" alt=\"\" width=\"812\" height=\"420\" \/><\/a><\/li>\n<li>Once you add the library, VisualGDB will create another <strong>CMakeLists.txt<\/strong> file in the <strong>OSAL\\STM32<\/strong> subdirectory, and will reference it from the main file: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/13-subdir.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6670\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/13-subdir.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>Note that the second CMakeLists.txt file doesn&#8217;t have a <strong>project()<\/strong> statement because it&#8217;s included from the top-level file. You can have an arbitrary hierarchy of <strong>CMakeLists.txt<\/strong> files including each other.<\/li>\n<li>Locate the OSAL library in Solution Explorer and add a new header file (<strong>OSAL.h<\/strong>):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/14-header.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6671\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/14-header.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Every target referencing the OSAL library should be able to just include the <strong>&lt;OSAL.h&gt;<\/strong> file to get going, so add the current directory (&#8220;.&#8221;) to the exported include directories of the OSAL library:\u00a0<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/15-inc-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6678\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/15-inc-1.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Finally, reference the OSAL library from MultiTargetDemo:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/16-ref.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6673\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/16-ref.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>Note that in each of the steps above, VisualGDB will automatically edit CMakeLists.txt files to apply the changes you made. You can easily roll them back using the Undo command in VS, and save them to trigger a reload of Solution Explorer contents.<\/li>\n<li>Using Windows Explorer, move the <strong>system_stm32xxxx.c<\/strong> and <strong>stm32xxxx_hal_conf.h<\/strong> files to the directory of the OSAL library. Then, edit <strong>CMakeLists.txt<\/strong> files manually to move the file references:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/17-moved.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6674\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/17-moved.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>You could also use the <strong>Remove <\/strong>and <strong>Add-&gt;Existing Item<\/strong> commands in Solution Explorer so that VisualGDB would edit CMakeLists.txt for you.<\/li>\n<li>If you try building the project now, it will fail with the missing HAL configuration file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/18-noconf.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6675\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/18-noconf.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>This happens because the <strong>MultiTargetDemo<\/strong> target does reference <strong>OSAL<\/strong>, however the BSP itself does not. You can resolve it by adding <strong>OSAL\/STM32<\/strong> to the include directories underthe BSP settings:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/19-fixed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6676\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/19-fixed.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Update the source code of the following files, separating the STM32-specific part from the high-level logic:<br \/>\nOSAL.h:<\/p>\n<pre class=\"\">#pragma once\r\n\r\n#ifndef __cplusplus\r\nextern \"C\"\r\n{\r\n#endif\r\n\r\n    void led_init();\r\n    void led_on();\r\n    void led_off();\r\n    void delay(int msec);\r\n\r\n#ifndef __cplusplus\r\n}\r\n#endif<\/pre>\n<p>OSAL.cpp:<\/p>\n<pre class=\"\">#include \"OSAL.h\"\r\n#include &lt;stm32f4xx_hal.h&gt;\r\n#include &lt;stm32_hal_legacy.h&gt;\r\n\r\nextern \"C\" void SysTick_Handler(void)\r\n{\r\n    HAL_IncTick();\r\n    HAL_SYSTICK_IRQHandler();\r\n}\r\n\r\nvoid led_init()\r\n{\r\n    HAL_Init();\r\n\r\n    __GPIOC_CLK_ENABLE();\r\n    GPIO_InitTypeDef GPIO_InitStructure;\r\n    GPIO_InitStructure.Pin = GPIO_PIN_12;\r\n    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;\r\n    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;\r\n    GPIO_InitStructure.Pull = GPIO_NOPULL;\r\n    HAL_GPIO_Init(GPIOC, &amp;GPIO_InitStructure);\r\n}\r\nvoid led_on()\r\n{\r\n    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET);\r\n}\r\n\r\nvoid led_off()\r\n{\r\n    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET);\r\n}\r\n\r\nvoid delay(int msec)\r\n{\r\n    HAL_Delay(msec);\r\n}<\/pre>\n<p>MultiTargetDemo:<\/p>\n<pre class=\"\">#include &lt;OSAL.h&gt;\r\n\r\nint main(void)\r\n{\r\n    led_init();\r\n    for (;;)\r\n    {\r\n    \tled_on();\r\n    \tdelay(500);\r\n    \tled_off();\r\n    \tdelay(500);\r\n    }\r\n}<\/pre>\n<p>Now the project will build successfully:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/20-partitioned.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6677\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/20-partitioned.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Now that we have separated the platform-specific part from the main application, we can add another platform for running the code on Windows. Right-click on the project node in Solution Explorer and select &#8220;Add Simulation Platform&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/21-sim.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6680\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/21-sim.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Pick the MinGW32 toolchain and proceed with the default platform names: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/22-platform.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6681\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/22-platform.png\" alt=\"\" width=\"786\" height=\"228\" \/><\/a><\/li>\n<li>Right-click on the <strong>OSAL\/STM32<\/strong> folder and select &#8220;Add-&gt;New Item&#8221;. Create another OSAL library, but change the location to <strong>&lt;project&gt;\\OSAL\\Win32<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/23-osal.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6682\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/23-osal.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>As we now have 2 libraries called &#8220;OSAL&#8221;, the project won&#8217;t build successfully unless we make them mutually exclusive. The easiest way to achieve it would be to make the add_subdirectory() statements in main <strong>CMakeLists.txt<\/strong> file conditional:\n<pre class=\"\">if(SIMULATION)\r\nadd_subdirectory(OSAL\/Win32)\r\nelse()\r\nadd_subdirectory(OSAL\/STM32)\r\nendif()<\/pre>\n<p>Also, make the <strong>bsp_include_directories()<\/strong> statement conditional, or move it inside the <strong>OSAL\/STM32\/CMakeLists.txt<\/strong> file (you would need to change the path to &#8216;.&#8217; in that case). Now you will be able to switch between the <strong>OSAL\/Win32<\/strong> and <strong>OSAL\/STM32\u00a0<\/strong> libraries by selecting the <strong>Hardware<\/strong> or <strong>Simulation<\/strong> platform:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/24-libs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6683\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/24-libs.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Add another copy of <strong>OSAL.h<\/strong> in the OSAL\/Win32 directory with the same content, export the &#8220;.&#8221; include directory similarly to OSAL\/STM32 and replace the contents of <strong>WIN32\/OSAL.cpp<\/strong> file with the Win32 implementation:\n<pre class=\"\">#include &lt;windows.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\nextern \"C\" void SysTick_Handler(void)\r\n{\r\n}\r\n\r\nvoid led_init()\r\n{\r\n}\r\n\r\nvoid led_on()\r\n{\r\n    printf(\"[LED ON]\\n\");\r\n}\r\n\r\nvoid led_off()\r\n{\r\n    printf(\"[LED OFF]\\n\");\r\n}\r\n\r\nvoid delay(int msec)\r\n{\r\n    Sleep(msec);\r\n}<\/pre>\n<p>Now you will be able to build both the Win32 and STM32 versions of the project. Note that referencing the original OSAL library added the following code to the main CMakeLists.txt:<\/p>\n<pre class=\"\">target_link_libraries(MultiTargetDemo PRIVATE OSAL)<\/pre>\n<p>It references the OSAL library regardless of the actual place where it&#8217;s defined, making it possible to have several mutually exclusive versions of it.<\/li>\n<li>Try running the project. See how the Win32 implementation of LED and sleep functions get invoked:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/25-run.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6684\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/25-run.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>Note that switching to the simulation platform automatically inactivated the <strong>BSP<\/strong> library. All device-specific options (e.g. STM32 libraries) will be ignored while building the simulation platform, and the BSP library will always be empty.<\/li>\n<li>Finally, we will show how to add a platform-independent library. Right-click on the project node in Solution Explorer and add another library in the &#8220;libs&#8221; subdirectory: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/lib.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6685\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/lib.png\" alt=\"\" width=\"812\" height=\"420\" \/><\/a><\/li>\n<li>Reference the OSAL library from DemoLibrary and replace the main source file with the following code:\n<pre class=\"\">#include &lt;OSAL.h&gt;\r\n\r\nvoid DoSleep()\r\n{\r\n    delay(500);\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/26-dosleep.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6686\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/26-dosleep.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>Declare <strong>DoSleep()<\/strong> in the main file (we do it to avoid creating a new header file) and call it instead of calling <strong>delay()<\/strong> directly. Reference DemoLibrary from <strong>MultiTargetDemo<\/strong> and the project will build successfully:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/27-call.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6687\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/27-call.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>You can define various target properties conditionally by tweaking CMakeLists.txt files after VisualGDB edits them. Try adding MYMACRO to preprocessor definitions of <strong>DemoLibrary<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/28-mymacro.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6688\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/28-mymacro.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a><\/li>\n<li>VisualGDB will automatically insert the following statement in CMakeLists.txt:\n<pre class=\"\">target_compile_definitions(DemoLibrary PRIVATE MYMACRO)<\/pre>\n<p>One way to make it conditional would be by wrapping it in an <strong>if()<\/strong> block, e.g.:<\/p>\n<pre class=\"\">if (NOT SIMULATION)\r\ntarget_compile_definitions(DemoLibrary PRIVATE MYMACRO)\r\nendif()<\/pre>\n<p>However, that would get very confusing, since skipped statements won&#8217;t be shown in target properties. Instead use the temporary MY_MACROS variable combined with an unconditional <strong>target_compile_definitions()<\/strong> to achieve the same effect:<\/p>\n<pre class=\"\">if (NOT SIMULATION)\r\nset(MY_MACROS MYMACRO)\r\nelse()\r\nset(MY_MACROS)\r\nendif()\r\n\r\ntarget_compile_definitions(DemoLibrary PRIVATE ${MY_MACROS})<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/29-var.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6689\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/09\/29-var.png\" alt=\"\" width=\"1257\" height=\"843\" \/><\/a>Now MYMACRO will be defined when building DemoLibrary for the hardware, but not for simulation.<\/li>\n<\/ol>\n<p>You can find the project shown in this tutorial in our <a href=\"https:\/\/github.com\/sysprogs\/tutorials\/tree\/master\/visualgdb\/ARM\/CMake\/MultiTargetDemo\">GitHub repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This project shows how to setup a large multi-target embedded project consisting of an executable, several static libraries, and multiple<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[222],"tags":[77,133,223,61],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6653"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=6653"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6653\/revisions"}],"predecessor-version":[{"id":6693,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6653\/revisions\/6693"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=6653"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=6653"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=6653"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}