Makers Blog
1,267 views 1 comments

This article applies to PLCnext CLI version 22.0.0 LTS.


If you program PLCnext Control devices using C++, you have probably used code templates that are installed with the PLCnext CLI.

In Visual Studio and Eclipse, you must pick the project template you want to use when creating a new project with the PLCnext project wizard (installed with the PLCnext IDE extension).

When generating a new C++ project on the command-line with the PLCnext CLI, you must also specify a project template.

The three default project templates are:

  project              The project is a template for user programs.
                       They are managed by the PLM (Program Library Manager).

  acfproject           The acfproject is a template for component based platform development.
                       The resulting component will be managed by the ACF
                       (Application Component Framework).

  consumablelibrary    The consumable library is a template, that creates a library
	                   which can be used by other projects.

The above information can be seen by executing the plcncli new command. More information on these types of projects can be found in the PLCnext Info Center:

This article describes how to activate and use additional project templates that are installed with the PLCnext CLI, and how to create and use your own project template.

But first, let's look at how the PLCnext CLI Template system works.

The PLCnext CLI Template system

The PLCnext CLI includes a default setting called TemplateLocations, that tells it where to find code templates. You can see the value of this setting with the following command:

user@machine:~$ plcncli get setting TemplateLocations

{
  "setting": {
    "TemplateLocations": "./Templates/Templates.xml"
  }
}

The path to the xml file is relative to the plcncli installation path.

If you browse to the ./Templates directory, you will see the Templates.xml file, and a number of sub-directories.

Listing the contents of the Templates.xml file ...

user@machine:~/plcncli/Templates$ cat Templates.xml 
<?xml version="1.0" encoding="utf-8"?>
<Templates xmlns="http://www.phoenixcontact.com/schema/clitemplates">
  <Include type="Template">ProjectTemplate/TemplateDescription.xml</Include>
  <Include type="Template">ProgramTemplate/TemplateDescription.xml</Include>
  <Include type="Format">ProjectTemplate/FormatTemplates.xml</Include>
  <Include type="Template">ComponentTemplate/TemplateDescription.xml</Include>
  <Include type="Template">BaseTemplates/BaseTemplateDescription.xml</Include>
  <Include type="Template">BaseTemplates/CodeTemplateDescription.xml</Include>
  <Include type="Fields">BaseTemplates/FieldTemplates.xml</Include>
  <Include type="Types">BaseTemplates/TypeTemplates.xml</Include>
  <Include type="Format">BaseTemplates/FormatTemplates.xml</Include>
  <Include type="Template">AcfProjectTemplate/TemplateDescription.xml</Include>
  <Include type="Template">BaseProjectTemplate/TemplateDescription.xml</Include>
  <Include type="Template">AcfComponentTemplate/TemplateDescription.xml</Include>
  <Include type="Template">BaseComponentTemplate/TemplateDescription.xml</Include>
  <Include type="Template">ConsumableLibraryTemplate/TemplateDescription.xml</Include>
</Templates>

... you can see that there are references to TemplateDescription.xml files of various types in the directories below the Templates directory. These contain instructions that tell the PLCnext CLI what to do when that template is used.

The template description files shown above implement the three default project templates that you are already familiar with.

How to activate additional templates

There is one "hidden" project template installed by default with the PLCnext CLI, which is not available by default:

  minimumproject    This is the same as acfproject, but without the capability to create 
	                Port variables in the Global Data Space.

We can make this template available to the PLCnext CLI by adding the MinimalAcfTemplates.xml file - which you may have already noticed in the Templates directory - to the template locations setting:

user@machine:~$ plcncli set setting TemplateLocations ./Templates/MinimalAcfTemplates.xml --add

The new XML file has now been added to the template locations:

user@machine:~$ plcncli get setting TemplateLocations

{
  "setting": {
    "TemplateLocations": "./Templates/Templates.xml;./Templates/MinimalAcfTemplates.xml"
  }
}

... and when the plcncli new command is executed, minimumproject now appears in the list of options. This template can now be used to create a new C++ project from the command line.

Note: Adding a project template to the PLCnext CLI does not automatically add the project template to the Visual Studio or Eclipse project wizards.

How to create your own PLCnext CLI template

The creation of custom PLCnext CLI templates will be demonstrated using a simple example. A PLCnext CLI template will be created that generates a "Hello World!" console application in C++.

The procedure is as follows:

  1. Create a directory for the new PLCnext CLI project template.

    On Linux:

    user@machine:~/plcncli/Templates$ mkdir ExeTemplate && cd ExeTemplate
    
  2. Create a file containing template C++ code, which can be used as a starting point for every new project of this type.

    user@machine:~/plcncli/Templates/ExeTemplate$ touch Main.cpp
    

    The C++ code used in this example is:

    #include 
    
    int main() {
       std::cout << "Hello World!" << std::endl;
       return 0;
    }   
    
  3. Create a template cmake source file.

    user@machine:~/plcncli/Templates/ExeTemplate$ touch CMakeLists.txt
    

    The CMake code used in this example is:

    cmake_minimum_required(VERSION 3.13)
    
    project($(name))
    
    if(NOT CMAKE_BUILD_TYPE)
      set(CMAKE_BUILD_TYPE Release)
    endif()
    
    ################# create target #######################################################
    
    file(GLOB_RECURSE Headers CONFIGURE_DEPENDS src/*.h src/*.hpp src/*.hxx)
    file(GLOB_RECURSE Sources CONFIGURE_DEPENDS src/*.cpp)
    add_executable(${CMAKE_PROJECT_NAME} ${Headers} ${Sources})
    
    #######################################################################################
    
    ################# set install directories #############################################
    
    string(REGEX REPLACE "^.*\\(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*$" "\\1" _ARP_SHORT_DEVICE_VERSION ${ARP_DEVICE_VERSION})
    set(BIN_INSTALL_DIR ${ARP_DEVICE}_${_ARP_SHORT_DEVICE_VERSION}/${CMAKE_BUILD_TYPE})
    
    #######################################################################################
    
    ################# project include-paths ###############################################
    
    target_include_directories(${CMAKE_PROJECT_NAME}
        PRIVATE
        $)
    
    #######################################################################################
    
    ################# include arp cmake module path #######################################
    
    list(INSERT CMAKE_MODULE_PATH 0 "${ARP_TOOLCHAIN_CMAKE_MODULE_PATH}")
    
    #######################################################################################
    
    ################# set link options ####################################################
    # WARNING: Without --no-undefined the linker will not check, whether all necessary    #
    #          libraries are linked. When a library which is necessary is not linked,     #
    #          the firmware will crash and there will be NO indication why it crashed.    #
    #######################################################################################
    
    target_link_options(${CMAKE_PROJECT_NAME} PRIVATE LINKER:--no-undefined)
    
    #######################################################################################
    
    ################# add link targets ####################################################
    
    find_package(ArpDevice REQUIRED)
    find_package(ArpProgramming REQUIRED)
    
    target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ArpDevice ArpProgramming)
    
    #######################################################################################
    
    ################# install #############################################################
    
    install(TARGETS ${CMAKE_PROJECT_NAME} RUNTIME DESTINATION ${BIN_INSTALL_DIR})
    unset(_ARP_SHORT_DEVICE_VERSION)
    
    #######################################################################################	
    

    Note that the CMake code includes the placeholder $(name), which will be replaced with the name of the project that is passed to the plcncli new command.

  4. Optional: Add a README file to the new template directory, which can also be used to create a README file in each new project created from this template.

  5. Create a PLCnext CLI project configuration file.

    This file is used to store project configuration information for the PLCnext CLI, e.g. the list of targets that the project should be built for.

    For this example, the .proj file was copied from the ConsumableLibraryTemplate directory and edited to produce the following:

    <?xml version="1.0" encoding="utf-8"?>
    <ProjectSettings xmlns="http://www.phoenixcontact.com/schema/cliproject">
      <Type>exeproject</Type>
      <Version>0.1</Version>
      <Name>$(name)</Name>
    </ProjectSettings>
    

    The Type field should contain the unique name of this project template, which will also be included in the template description file in the next step.

    The Name field contains the placeholder $(name), which will be substituted with the project name during the creation of each new project.

  6. Create a template description file.

    For this example, the TemplateDescription.xml file was copied from the ConsumableLibraryTemplate directory and edited to produce the following:

    <?xml version="1.0" encoding="utf-8"?>
    <TemplateDescription name="exeproject" isRoot="true" basedOn="baseproject" supportedFirmwareVersions="19.0.0.16199" requiredCliVersion="19.0.0.660" version="1.0" 
                         xmlns="http://www.phoenixcontact.com/schema/clitemplates" identifier="ProjectSettingsIdentifier">
      <File name="plcnext.proj" template=".proj"/>
      <File name="CMakeLists.txt" template="CMakeLists.txt"/>
      <File name="README.md" template="README.md"/>
      <File name="$(name)Main.cpp" template="Main.cpp" path="src"/>
      <Description>Create a new stand-alone executable project.</Description>
      <Example>
        <Arguments>
          <Argument name="name" value="MyExe"/>
        </Arguments>
        <Description>creates a new stand-alone executable project in the directory 'MyExe'</Description>
      </Example>
    </TemplateDescription>
    

    The fields in the template description include:

    • name="exeproject" : Enables projects to be created from this template using the command plcncli new exeproject.
    • File name="A" template="B" path="C" : Creates a file in the new project, in the specified path, based on the specified template file. The file name can also include placeholders like $(name), which will be substituted with the project name during the creation of each new project.
    • Description and Example fields, which are displayed in the relevant sections of the plcncli help system.
  7. Create a new Templates file, which will be used to tell the PLCnext CLI about our new template(s).

    For this example, the MinimalAcfTemplates.xml file in the Templates directory was copied to a file named CustomTemplates.xml, and that file was edited to produce the following:

    <?xml version="1.0" encoding="utf-8"?>
    <Templates xmlns="http://www.phoenixcontact.com/schema/clitemplates">
             <Include type="Template">ExeTemplate/TemplateDescription.xml</Include>
    </Templates>
    
  8. Register the custom templates with the PLCnext CLI

    user@machine:~$ plcncli set setting TemplateLocations ./Templates/CustomTemplates.xml --add
    

    The path is relative to the PLCnext CLI installation directory.

  9. Try it out!

    The following list of bash commands demonstrate the features of the new template:

    plcncli new                                   # The help text includes the new template and description
    plcncli new exeproject --help                 # Displays the example showing how to use this template
    plcncli new exeproject --name "HelloWorld"    # Creates a new project based on the template
    cd HelloWorld
    plcncli set target -n AXCF2152 -v 2022 --add  # Sets the build target
    plcncli build                                 # Builds the project with the default template code
    scp bin/AXCF2152_22.0.3.129/Release/HelloWorld admin@192.168.1.10:~  # Copies the executable to the device
    ssh admin@192.168.1.10
    ./HelloWorld                                  # Runs the executable!
    

Contribute

In the future, it is planned that contributions to the PLCnext CLI Templates project on Github will be possible. Until then, you can open an issue with ideas for new templates, or with examples of templates that you have created yourself.

Questions or comments?

Post a comment below, or ask questions in the PLCnext Community Forum.

Note:

The Makers Blog shows applications and user stories of community members that are not tested or reviewed by Phoenix Contact. Use them at your own risk.

Discussion

Please login/register to comment

Login/Register

Leave a Reply

charkrit.orion 22.08.2022

When following this example, I encounter an error when running `plcncli new`. It reads "The argument 'name' used in an example is not defined in the template 'exeproject'."

Login / Register to reply
charkrit.orion 22.08.2022

I added the lines And solved the issue.

Newsletter
Never miss a new article
Sign up for the newsletter
Never miss news about PLCnext Technology
Get interesting content via newsletter four times a year
Receive exclusive information before all other users