diff --git a/cmake/README.md b/cmake/README.md index f083c6df4..bdc5d86a8 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -1,6 +1,6 @@ # Using CMake Build System -This is intended to be a general **how to** guide for using the new CFE/CFS build scripts (based on CMake) for a new mission project. +This is intended to be a general **how to** guide for using the cFS CMake-based build scripts and adapting to your project. Also see [OpenSatKit](https://github.com/OpenSatKit/OpenSatKit) and [CFS-101](https://github.com/nasa/CFS-101) for more in-depth guides. @@ -74,22 +74,27 @@ SET(TGT1_APPLIST sample_app) SET(TGT1_FILELIST cfe_es_startup.scr) ``` -This file is setting up some CMake variables that have special meaning to the build scripts: +This file sets up CMake variables that have special meaning to the build scripts: + +- `MISSION_NAME` and `SPACECRAFT_ID` are compiled into the executable and potentially used at run time by any application. In particular, the value specified for `SPACECRAFT_ID` will be returned by `CFE_PSP_GetSpacecraftId()`. +- `TGT1_NAME` provides a name for the first CPU. The build scripts will also look for a cross-compiler toolchain file by the same name, in this case toolchain-cpu1.cmake, to use for building the binaries used on this CPU. Important: The toolchain can also be specified by the `TGT1_PLATFORM` variable, which will override this if present. This allows the name and toolchain to specified independently. +- `TGT1_APPLIST` provides a space-separated list of applications to build for the target CPU. The application source code must be in a directory of the same name in one of the search path locations in the build scripts. These paths will be searched to find the source code for this application. +- `TGT1_FILELIST` is a space-separated list of files to copy to the target during the make install process. Note: Name clashes are common here, since all targets typically use a cfe_es_startup.scr to start the applications. This is handled by allowing a prefix to the filename to indicate which cpu the file belongs to. For instance, cpu1_cfe_es_startup.scr will be copied to cpu1 as cfe_es_startup.scr during the installation step. + +## Preparing to Build CFE/CFS -`MISSION_NAME` and `SPACECRAFT_ID` are compiled into the executable and potentially used at run time by any application. In particular, the value specified for `SPACECRAFT_ID` will be returned by `CFE_PSP_GetSpacecraftId()`. -`TGT1_NAME` provides a name for the first CPU. The build scripts will also look for a cross-compiler toolchain file by the same name, in this case toolchain-cpu1.cmake, to use for building the binaries used on this CPU. Important: The toolchain can also be specified by the `TGT1_PLATFORM` variable, which will override this if present. This allows the name and toolchain to specified independently. -`TGT1_APPLIST` provides a space-separated list of applications to build for the target CPU. The application source code must be in a directory of the same name in one of the search path locations in the build scripts. These paths will be searched to find the source code for this application. -`TGT1_FILELIST` is a space-separated list of files to copy to the target during the make install process. Note: Name clashes are common here, since all targets typically use a cfe_es_startup.scr to start the applications. This is handled by allowing a prefix to the filename to indicate which cpu the file belongs to. For instance, cpu1_cfe_es_startup.scr will be copied to cpu1 as cfe_es_startup.scr during the installation step. -Preparing to Build CFE/CFS The build procedure always uses "out-of-tree" builds; all generated files are stored in a separate directory from the source code. This is important for version control purposes, as the build will not modify or add any files within the source tree, and multiple builds can be done from a single source tree. + A special prep target is implemented in the example top-level makefile to facilitate setting up a new build directory. This in turn calls "cmake" with the right options to set up the build. Special variables used by the top-level makefile wrapper: -`O` Specifies the output directory, may be absolute or relative. If not specified then "build" is assumed. -SIMULATION: If set, this will override the architecture(s) specified in the targets file. The "native" keyword here will indicate to use the host machine's native compiler (e.g. /usr/bin/gcc) for all compilation tasks. For any other keyword/string, the scripts will search for a file called "toolchain-KEYWORD.cmake" that specifies the details of the toolchain. "i686-rtems4.11", "powerpc-440-linux-gnu" and "arm-cortexa8_neon-linux-gnueabi" are included as examples of how this works. +- `O`: Specifies the output directory, may be absolute or relative. This allows all the builds to coexist simultaneously from the same source tree. If `O` is not specified then "build" is assumed. + +- `SIMULATION`: Overrides the architecture(s) specified in the targets file. Setting "SIMULATION=native" will indicate to use the host machine's native compiler (e.g. /usr/bin/gcc) for all compilation tasks. For any other keyword/string, the scripts will search for a file called "toolchain-KEYWORD.cmake" that specifies the details of the toolchain. The sample_defs directory includes "i686-rtems4.11", "powerpc-440-linux-gnu" and "arm-cortexa8_neon-linux-gnueabi" as examples of how this works. ### Examples + To prepare a normal build for the target hardware: ```bash @@ -108,62 +113,79 @@ To prepare a "processor-in-the-loop" simulation build, assuming that the target make SIMULATION=arm-cortexa8_neon-linux-gnueabi O=build-pil prep ``` -NOTE: For any of these builds, the `O` variable can be supplied or modified to override the default output directory. This allows all the builds to coexist simultaneously from the same source tree. +For all builds, once the prep step has been completed, the variables used (such as "SIMULATION") are cached and therefore DO NOT need to be passed with any future invocation of the "make" commands. This allows the makefiles to be easily called from an IDE without needing to set up specific environment variables first. -For ALL builds, once the prep step has been completed, the variables used (such as "SIMULATION") are cached and therefore DO NOT need to be passed with any future invocation of the "make" commands. This is important because it allows the makefiles to be easily called from an IDE without needing to set up specific environment variables first. +After this initial preparation step, CMake is not used again unless the build scripts are modified. However, dependencies are built into the generated makefiles such that CMake generally runs automatically when necessary. The only major exception to this is if a source file is added to a build script that was using "wildcards" or shell glob commands to find source files. -After this initial preparation step, CMake is not used again unless the build scripts are modified. However, dependencies are built into the generated makefiles such that CMake is generally run automatically when necessary. The only major exception to this is if a source file is added to a build script that was using "wildcards" or shell glob commands to find source files. In this specific case of source file additions with no modifications to existing build scripts, the prep step will need to be manually re-run to pick up the new added files. +In the specific case of source file additions without modifications to existing build scripts, the prep step needs to be run again to pick up the new added files. ## Building and Installing + The CFS mission binary files may be generated by simply running: -make +```make``` + The CMake build scripts will generate the binary files in a deep build tree based on the original location of the source file from which it was built. This is generally not suitable for copying to a target machine, so an "install" target is also implemented to make this process easier: -make install +```make install``` + Will copy all the generated executable files (typically the "core" executable plus any loadable object files and/or configuration files specified in the mission configuration) to a common directory. The directory structure is organized by CPU name so that it is easy to copy the entire tree to a target, or the directory could be NFS mounted in the case of Linux targets. -Note that the default "all" target (which generates the binaries) is also a prerequisite of the "install" target, so running "make install" directly is generally sufficient to build the entire project. +The default "all" makefile target (which generates the binaries) is also a prerequisite of the "install" target, so running "make install" is typically sufficient to build the entire project. -Generating Documentation -The CMake build system can also be used to generate documentation. +### Generating Documentation + +The CMake build system can also generate documentation in latex, html, and pdf formats. To build all documentation: -make docs + +```make docs``` + To build the cFS User's Guide: -make usersguide + +```make usersguide``` To build the OSAL User's Guide: -make osalguide -Writing CMakeLists files for applications -Every application or module is expected to provide a CMakeLists.txt file at the top level of the respective source tree, containing the recipe for building that module. -The CMake build system provides two useful functions that can be used to simplify this task for most modules: +```make osalguide``` + +## Writing CMakeLists files for applications +Every application or module is expected to provide a top-level CMakeLists.txt file in its respective source tree that contains the recipe for building that module. + +The build system provides two useful functions that can be used to simplify this task for most modules: + +```cmake add_cfe_app(app_name source1.c source2.c ...) add_cfe_tables(app_name table1 table2 ...) -The add_cfe_app function will generate rules to compile and link the given source files into a module named app_name, using the configured cross compiler and all relevant switches/settings defined by the build system. The resulting module file will be installed to all targets that have app_name listed in their respective configuration in targets.cmake. +``` + +`add_cfe_app` generates rules to compile and link the given source files into a module named app_name, using the configured cross compiler and all relevant switches/settings defined by the build system. The resulting module file will be installed to all targets that have app_name listed in their respective configuration in targets.cmake. + +`add_cfe_tables` generates rules to compile a source file for each table name specified, then execute the appropriate conversion tool (such as elf2cfetbl) on the binary file to produce a cFE table file with a .tbl extension. The final .tbl file will be installed to the target directory. -The add_cfe_tables function will generate rules to compile a source file for each table name specified, then execute the appropriate conversion tool (such as elf2cfetbl) on the binary file to produce a cFE table file with a .tbl extension. The final .tbl file will be installed to the target directory. +`add_cfe_tables` will first search the mission-specific areas of the source tree for matching filenames. These mission-specific source files will be given preference over source files contained within the application module source tree, which are assumed to be "example" files. +Since table files are generally customized for mission-specific operation (as opposed to using an example table file "as-is" from the source distribution), the build system discourages modifying original source files for mission-specific purposes. -Since table files are generally customized for mission-specific operation (as opposed to using an example table file "as-is" from the source distribution) the add_cfe_tables function will first search the mission-specific areas of the source tree for matching filenames. These mission-specific source files will be given preference over source files contained within the application module source tree, which are assumed to be "example" files. (In general, the CMake build system discourages modifying original source files for mission-specific purposes). +For each table definition, `add_cfe_tables` will search the following paths: -The following paths are searched, in order, for each table definition: +- ${​​​​MISSION_DEFS}​​​​/tables/${​​​​CPUNAME}​​​​_${​​​​TBL}​​​​.c +- ${​​​​MISSION_SOURCE_DIR}​​​​/tables/${​​​​CPUNAME}​​​​_${​​​​TBL}​​​​.c +- ${​​​​MISSION_DEFS}​​​​/tables/${​​​​TBL}​​​​.c +- ${​​​​MISSION_SOURCE_DIR}​​​​/tables/${​​​​TBL}​​​​.c -${​​​​MISSION_DEFS}​​​​/tables/${​​​​CPUNAME}​​​​_${​​​​TBL}​​​​.c -${​​​​MISSION_SOURCE_DIR}​​​​/tables/${​​​​CPUNAME}​​​​_${​​​​TBL}​​​​.c -${​​​​MISSION_DEFS}​​​​/tables/${​​​​TBL}​​​​.c -${​​​​MISSION_SOURCE_DIR}​​​​/tables/${​​​​TBL}​​​​.c -Where MISSION_SOURCE_DIR is the mission top level source directory, MISSION_DEFS represents the "defs" directory (containing targets.cmake and others), CPUNAME represents the name of the CPU, and TBL represents the name of the table as indicated in the add_cfe_tables command. +`MISSION_DEFS` represents the "defs" directory which contains targets.cmake and others; `CPUNAME` represents the name of the CPU; `TBL` represents the name of the table as indicated in the add_cfe_tables command; and `MISSION_SOURCE_DIR` is the mission top-level source directory; -For a more concrete example, using the "sample_defs" configuration, if an application recipe contains the line add_cfe_tables(myapp table1), the following will be searched (relative to ${​​​​MISSION_SOURCE_DIR}​​​​): +For a concrete example using the included "sample_defs" configuration, if an application recipe contains `add_cfe_tables(myapp myapp_table1)`, the following will be searched relative to ${​​​​MISSION_SOURCE_DIR}​​​​: -sample_defs/tables/cpu1_table1.c -tables/cpu1_table1.c -sample_defs/tables/table1.c -tables/table1.c -Note that by searching first for filenames prefixed with the CPU name i.e. cpu1_table1.c, this allows different definitions of the table to be used on other CPUs, such as cpu2_table1.c if the application were also utilized on a cpu named cpu2. +- sample_defs/tables/cpu1_table1.c +- tables/cpu1_table1.c +- sample_defs/tables/table1.c +- tables/table1.c + +Note that first searching for filenames prefixed with the CPU name i.e. cpu1_table1.c allows different table definitions to be used on different CPUs. For example, `cpu2_table1.c` can be defined if the application is to be also used on a platform named "cpu2". ## Handling Multiple Configurations + The recommended way to build for multiple configurations depends on the purpose of the different configurations. *Purpose 1:* Software Runs on Multiple CPUS