Difference between revisions of "Creating a New EMAC OE SDK Project with CMake"

From wiki.emacinc.com
Jump to: navigation, search
m (Reviewed, notated, and marked buggy.)
Line 1: Line 1:
{{todo| Buggy (08.07.2015-12:59->KY+)(08.17.2015-12:07->KY+)(08.17.2015-14:25->KY+)(08.17.2015-17:40->MD-)(11.03.2015-13:38->KY+);(11.04.2015-11:20->MD-)|Klint Youngmeyer| project=OE 5.0,KY,MD,Buggy }}
+
{{todo| Review (08.07.2015-12:59->KY+)(08.17.2015-12:07->KY+)(08.17.2015-14:25->KY+)(08.17.2015-17:40->MD-)(11.03.2015-13:38->KY+);(11.04.2015-11:20->MD-)(11.04.2015-13:04->KY+-)|Klint Youngmeyer| project=OE 5.0,KY,MD,Review }}
 
{{#seo:
 
{{#seo:
 
|title=Creating a New EMAC OE SDK Project with CMake
 
|title=Creating a New EMAC OE SDK Project with CMake
Line 113: Line 113:
 
*Make a secondary (or tertiary) build directory. (Recommended)
 
*Make a secondary (or tertiary) build directory. (Recommended)
 
*Clean the current build directory and re-run CMake.
 
*Clean the current build directory and re-run CMake.
 +
The different levels of build type correlate to usage of different C Flags. When cross-compiling, these C Flags are located in the <code>toolchain.<architecture>.cmake</code> files located, by default, in <code>/opt/emac/5.X/</code>, with ''X'' being the specific version of SDK. The following table will give a brief overview of the different build types.
  
{{warning | We should really have a table showing the types of releases targets available, along with a description.  So, here's an example:}}
+
<!--{{warning | We should really have a table showing the types of releases targets available, along with a description.  So, here's an example:}}-->
 +
<br />
 +
<br />
 +
<table style="border-style:double; border-width:2px; margin-top:-10%; margin-bottom:-3%;"><tr style="border-style:double; border-width:2px;"><td>'''Name:'''</td><td>'''Type:'''</td><td>'''Debugging Features:'''</td><td>'''Description:'''</td><td>'''Optimization Level:'''</td><td>'''C Flags Used:'''</td></tr>
  
<table style="border-style:double; border-width:2px; margin-top:-10%; margin-bottom:-3%;"><tr style="border-style:double; border-width:2px;"><td>Name:</td><td>Type:</td><td>Debugging Features:</td><td>Description</td><td>Pre-Processor Defines</td></tr>
 
  
 +
<tr style="border-style:solid; border-width:2px;"><td>Release</td><td>Release</td><td>disabled</td><td>Release targeted build optimized for best performance.</td><td>-O2</td><td>CMAKE_C_FLAGS_RELEASE</td></tr>
  
<tr style="border-style:solid; border-width:2px;"><td>Release</td><td>Release</td><td>disabled</td><td>Release targeted build optimized for speed.</td><td>RELEASE_BUILD (???)</td></tr>
 
  
 +
<tr style="border-style:solid; border-width:2px;"><td>MinSizeRel</td><td>Release</td><td>disabled</td><td>Release targeted build with the most extreme optimizations. (Builds using this should be thoroughly tested.)</td><td>-O3</td><td>CMAKE_C_FLAGS_MINSIZEREL</td></tr>
  
<tr style="border-style:solid; border-width:2px;"><td>MinSizeRel</td><td>Release</td><td>disabled</td><td>Release targeted build optimized for small size.</td><td>RELEASE_BUILD (???)</td></tr>
 
  
 +
<tr style="border-style:solid; border-width:2px;"><td>Debug</td><td>Debug</td><td>enabled</td><td>A standard debugging oriented build, optimized for improved debugging.</td><td>-O0</td><td>CMAKE_C_FLAGS_DEBUG</td></tr>
  
<tr style="border-style:solid; border-width:2px;"><td>Debug</td><td>Debug</td><td>enabled</td><td>A standard debugging oriented build, optimized for speed with -O2 (this is a guess)</td><td>__DEBUG__ (???)</td></tr>
 
  
 +
<!--<tr style="border-style:solid; border-width:2px;"><td>etc.</td><td></td><td></td><td></td><td></td></tr>-->
 +
</table>
 +
<br />
 +
<br />
 +
<br />
 +
If you wish to add any additional flags to a build type, they can be defined in the project's <code>CMakeList.txt</code> file as shown in the code snippet below.
 +
<syntaxhighlight lang="cmake">
 +
project(example)
  
<tr style="border-style:solid; border-width:2px;"><td>etc.</td><td></td><td></td><td></td><td></td></tr>
+
SET(MAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wpedantic")
</table>
 
  
{{warning | This is really useful information for any developer.  Knowing the level of optimization is insightful, so that should be included.  Knowing whether or not the build was stripped of debugging information is important if they ever intend to release binaries to the public (such as for updates) and to ensure small size and max speed.  Knowing what preprocessor defines are #def'd with a target is really useful when writing debugging code.
+
# This will add the -Wall and -Wpedantic options to the existing debug build flags
 +
</syntaxhighlight>
 +
<!--{{warning | This is really useful information for any developer.  Knowing the level of optimization is insightful, so that should be included.  Knowing whether or not the build was stripped of debugging information is important if they ever intend to release binaries to the public (such as for updates) and to ensure small size and max speed.  Knowing what preprocessor defines are #def'd with a target is really useful when writing debugging code.
  
  
 
I would put all this in a table like the example I made above (but accurate and complete).  The border-radius and shadows will need to be overridden to make it look right.  Can always use css or a template for this.
 
I would put all this in a table like the example I made above (but accurate and complete).  The border-radius and shadows will need to be overridden to make it look right.  Can always use css or a template for this.
}}
+
}}-->
  
  
====Method 1====
+
====Method 1: Create separate build directory====
To create a Release build using the 1st (recommended) method, use the following steps:
+
To create a Release build using the 1st (recommended) method, use the following steps. This method is recommended because it allows both the Debug and the Release executable to exist at the same time.
 
<cl>
 
<cl>
 
1. In a terminal, navigate to the base directory of the project.
 
1. In a terminal, navigate to the base directory of the project.
Line 151: Line 163:
 
{{cli | username=developer | hostname=ldc | pwd=~/projects/hello_emac/hello_emac-build-arm | make }}  
 
{{cli | username=developer | hostname=ldc | pwd=~/projects/hello_emac/hello_emac-build-arm | make }}  
 
</cl>
 
</cl>
====Method 2====
+
<br />
 +
====Method 2: Re-use build directory====
 
Another option for creating a release build is as follows:
 
Another option for creating a release build is as follows:
 
<cl>
 
<cl>
Line 163: Line 176:
 
</cl>
 
</cl>
  
{{warning | What's the difference between these two build options?  One seems to just be a way to change build options and recompile, although you're using the exact same options for configuring CMake. How's the 2nd one different, and why is the 1st one recommended over the 2nd one?}}
+
===Renaming the Target Executable===
 +
To rename the executable, the <code>ADD_EXECUTABLE()</code> function arguments must be changed. The first argument refers to the name of the executable, and the second refers to the source code file.
 +
 
 +
To change the name of the executable from "main" to "new_name", change the <code>ADD_EXECUTABLE()</code> from the first code box to the second code box.
 +
<syntaxhighlight lang="cmake">
 +
ADD_EXECUTABLE(main main.cpp)
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="cmake">
 +
ADD_EXECUTABLE(new_name main.cpp)
 +
</syntaxhighlight>
  
 
===Adding Include Files===
 
===Adding Include Files===
Line 176: Line 199:
 
SET(SOURCES
 
SET(SOURCES
 
     ${PROJECT_SOURCE_DIR}/main.cpp
 
     ${PROJECT_SOURCE_DIR}/main.cpp
     ${PROJECT_SOURCE_DIR}/include/tools.cpp
+
     ${PROJECT_SOURCE_DIR}/include/include.cpp
     ${PROJECT_SOURCE_DIR}/include/tools.h
+
    )
 +
SET(HEADERS
 +
     ${PROJECT_SOURCE_DIR}/include/include.h
 
     )
 
     )
</syntaxhighlight>
 
 
{{warning | Implementation files don't belong in include/ directories.  People usually put them in src/ directories, the project root directory, or a directory named for the functionality (such as tools/).}}
 
 
===Renaming the Target Executable===
 
To rename the executable, the <code>ADD_EXECUTABLE()</code> function arguments must be changed. The first argument refers to the name of the executable, and the second refers to the source code file.
 
  
To change the name of the executable from "main" to "new_name", change the <code>ADD_EXECUTABLE()</code> from the first code box to the second code box.
+
ADD_EXECUTABLE(main ${SOURCES} ${HEADERS}
<syntaxhighlight lang="cmake">
 
ADD_EXECUTABLE(main main.cpp)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<syntaxhighlight lang="cmake">
 
ADD_EXECUTABLE(new_name main.cpp)
 
</syntaxhighlight>
 
 
{{warning | Don't you need to add tools.cpp to this list as well, if you added that to your project?}}
 
 
  
 
<!-- /*********************************************************************************************************/ -->
 
<!-- /*********************************************************************************************************/ -->

Revision as of 14:06, 4 November 2015

TODO: {{#todo: Review (08.07.2015-12:59->KY+)(08.17.2015-12:07->KY+)(08.17.2015-14:25->KY+)(08.17.2015-17:40->MD-)(11.03.2015-13:38->KY+);(11.04.2015-11:20->MD-)(11.04.2015-13:04->KY+-)|Klint Youngmeyer|OE 5.0,KY,MD,Review}}

The EMAC OE SDK is distributed with the intent that CMake be used with the EMAC OE toolchain and libraries to build most projects. This page demonstrates the process of creating and compiling a new project with CMake, and running it on the target machine.

General Information

Creating a new EMAC CMake project is accomplished with the use of the oe_init_project program. This program is included in the emac-tools-projects apt package, which is part of the EMAC SDK. For instructions on installing the EMAC SDK, please see this section in the getting started guide.

Creating a New EMAC OE SDK Project with CMake

This section demonstrates how to use the EMAC CMake tool, oe_init_project, to generate CMake files automatically for a project. When using the EMAC SDK there are currently two options for cross compiling:

  • arm
  • x86

For the purposes of this guide, the arm option will be used for the listed examples.

Host Machine Compiling

Navigate to the directory where the project will be located. Then run the CMake new project tool, oe_init_project.

developer@ldc:~/projects# oe_init_project -n hello.c

If desired, please enter a name for this project, otherwise press Enter to use the default: hello_emac

-- Creating new project directory...
-- Creating new source file...
-- Building custom CMakeLists.txt file...
-- Done.

Do you want to create a build directory for this project? (y/n) y

-- Creating build directory...

Do you want to run cmake for this project? (y/n) y

-- Using system compiler
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/developer/projects/hello_emac/hello_emac-build

Do you want to compile this project? (y/n) y

Scanning dependencies of target hello_emac
[100%] Building C object CMakeFiles/hello_emac.dir/hello.c.o
Linking C executable hello_emac
[100%] Built target hello_emac

The executable, in this case, is now inside the hello_emac/hello_emac-build directory.

Target Machine Compiling

The CMake project script has now made a project directory that contains the following:

  • CMakeLists.txt
  • Source code file (hello.c in this case)
  • README file
  • Desktop Build Directory (hello_emac-build in this case)

Despite what the file extension implies, the CMakeLists.txt is actually a script which contains the required information to automatically create a Makefile for any supported architecture. This file was generated by the EMAC oe_init_project tool, and will need to be modified over time as a project grows. The comments in the CMakeLists.txt file generated by the EMAC tool will provide a good starting point for how to add additional source files and how to perform other common tasks related to maintaining your CMake build system as you develop your software project. The CMake project provides extensive documentation on how to work with these files.

The source code file generated by the script (hello.c) contains a basic Hello World style program. This can provide a starting point for your application, or be replaced by another source file with the same name.

The README file contains more information on using CMake with the EMAC OE 5.0 SDK. You may refer to this file for quick reference.

The Desktop Build Directory (hello_emac-build) contains the executable, hello_emac, the Makefile, and various cache files. These were automatically created by CMake and by the build system, and can be recreated at any time.

It is useful to have a Desktop Build Directory because it is easier (in the beginning) to use the desktop to verify all code changes before cross-compiling for a target board. This will be useful until the application under development depends upon resources which are only available on the target hardware, such as certain device drivers or the touchscreen (if so equipped).

Use the following steps to cross-compile the project and send it to a target board.

  1. In a terminal, navigate to the base directory of the project.


    NOTE
    If the architecture of the target board you're using for your appliction x86, then you will need to change all occurrences of arm in the following sections below to x86.
  2. Create a build directory for cross compiling.

    developer@ldc:~/projects/hello_emac# mkdir hello_emac-build-arm
  3. Navigate into the newly created directory.

    developer@ldc:~/projects/hello_emac# cd hello_emac-build-arm
  4. Run cmake using the target architecture.

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# cmake .. -DARCH:STRING=arm
  5. Compile the code using make.

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# make

    The make command creates the target executable in the hello_emac-build-arm directory.

  6. Now copy the executable to the target board. For information on copying the executable file, see the Transferring Files section.

Examples

This section will illustrate how to complete various different tasks associated with building a CMake project.

Debug Build Types

By default, new projects will have the Debug build type. To compile the project with the Release or Minimum Size Release build types, there are two options:

  • Make a secondary (or tertiary) build directory. (Recommended)
  • Clean the current build directory and re-run CMake.

The different levels of build type correlate to usage of different C Flags. When cross-compiling, these C Flags are located in the toolchain.<architecture>.cmake files located, by default, in /opt/emac/5.X/, with X being the specific version of SDK. The following table will give a brief overview of the different build types.







Name:Type:Debugging Features:Description:Optimization Level:C Flags Used:
ReleaseReleasedisabledRelease targeted build optimized for best performance.-O2CMAKE_C_FLAGS_RELEASE
MinSizeRelReleasedisabledRelease targeted build with the most extreme optimizations. (Builds using this should be thoroughly tested.)-O3CMAKE_C_FLAGS_MINSIZEREL
DebugDebugenabledA standard debugging oriented build, optimized for improved debugging.-O0CMAKE_C_FLAGS_DEBUG




If you wish to add any additional flags to a build type, they can be defined in the project's CMakeList.txt file as shown in the code snippet below.

project(example)

SET(MAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wpedantic")

# This will add the -Wall and -Wpedantic options to the existing debug build flags


Method 1: Create separate build directory

To create a Release build using the 1st (recommended) method, use the following steps. This method is recommended because it allows both the Debug and the Release executable to exist at the same time.

  1. In a terminal, navigate to the base directory of the project.

  2. Create a new release build directory

    developer@ldc:~/projects/hello_emac# mkdir hello_emac-build-arm-release
  3. Change directories into the newly created directory.

    developer@ldc:~/projects/hello_emac# cd hello_emac-build-arm-release
  4. Run cmake using the target architecture.

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# cmake .. -DARCH:STRING=arm -DCMAKE_BUILD_TYPE:STRING=Release


    NOTE
    The string 'MinSizeRel' can be used in place of 'Release' for a potentially smaller executable
  5. Compile the code using make.

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# make


Method 2: Re-use build directory

Another option for creating a release build is as follows:

  1. In a terminal, navigate to the build directory of the project.

  2. Clean the directory with make

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# make clean
  3. Run cmake using the target architecture.

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# cmake .. -DARCH:STRING=arm -DCMAKE_BUILD_TYPE:STRING=Release


    NOTE
    The string 'MinSizeRel' can be used in place of 'Release' for a potentially smaller executable
  4. Compile the code using make.

    developer@ldc:~/projects/hello_emac/hello_emac-build-arm# make

Renaming the Target Executable

To rename the executable, the ADD_EXECUTABLE() function arguments must be changed. The first argument refers to the name of the executable, and the second refers to the source code file.

To change the name of the executable from "main" to "new_name", change the ADD_EXECUTABLE() from the first code box to the second code box.

ADD_EXECUTABLE(main main.cpp)
ADD_EXECUTABLE(new_name main.cpp)

Adding Include Files

To add an include file (in this case, the tools.cpp and tools.h in the include directory) to the cmake project, changes will need to be made to the CMakeLists.txt file. Please refer to the code sample below.

  1. The directory to be included must be specified by the INCLUDE_DIRECTORIES() function. The variable ${PROJECT_SOURCE_DIR} refers to the base path of the project which is generally where this README file is located.
  2. The SOURCES must be set. This list of files should include all of the source files in the project.
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)

SET(SOURCES
     ${PROJECT_SOURCE_DIR}/main.cpp
     ${PROJECT_SOURCE_DIR}/include/include.cpp
     )
SET(HEADERS
     ${PROJECT_SOURCE_DIR}/include/include.h
     )

ADD_EXECUTABLE(main ${SOURCES} ${HEADERS}

Further Information

Where to Go Next