www.gusucode.com > robotsimulink 工具箱 matlab源码程序 > robotsimulink/robotslros/+robotics/+codertarget/+internal/onAfterCodeGen.m
function onAfterCodeGen(hCS, buildInfo) %This function is for internal use only. It may be removed in the future. %ONAFTERCODEGEN Hook point for after code generation % Copyright 2014-2016 The MathWorks, Inc. data = codertarget.data.getData(hCS); modelName = buildInfo.ModelName; % Open new stage in diagnostic viewer and close it when function exits or % if an error occurs archiveStage = sldiagviewer.createStage(message('robotics:robotslros:deploy:BuildArchiveStage').getString, 'ModelName', modelName); stageCleanup = onCleanup(@() delete(archiveStage)); disp(message('robotics:robotslros:deploy:CreateArchiveFile', modelName).getString); disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator); % Add node related build artifacts to buildInfo nodeInfo = robotics.slros.internal.cgen.postCodeGenHook(hCS, buildInfo); % Update buildInfo extList = {'.c' '.C' '.cpp' '.CPP' '.s' '.S'}; incExtList = {'.h' '.H', '.hpp'}; updateFilePathsAndExtensions(buildInfo, extList, incExtList); % findIncludeFiles(buildInfo, {'*.h' '*.hpp'}); % By default, findIncludeFiles errors out if finds an unknown % header (e.g., ros/ros.h, geometry_msgs/Point.h). % ignoreParseError converts the errors into warnings % ignoreMissingIncludes suppresses the warnings. findIncludeFiles(buildInfo, ... 'extensions', {'*.h' '*.hpp'}, ... 'ignoreParseError', true, ... 'ignoreMissingIncludes', true); % Temporary fix for C++ code generation if isequal(get_param(modelName, 'TargetLang'), 'C++') loc_removeSources(buildInfo, {'ert_main.c', 'rt_cppclass_main.cpp'}); end % Replace the define '-DRT' with '-DRT=RT'. This define clashes with a % definition in BOOST math library defToReplace.Name = 'RT'; defToReplace.ReplaceWith = 'RT=RT'; loc_replaceDefines(buildInfo, defToReplace); %% Replace host-specific UDP block files with target-specific ones fileToFind = fullfile('$(MATLAB_ROOT)','toolbox','shared','dspblks','extern','src','HostLib_Network.c'); found = loc_findInBuildInfoSrc(buildInfo,fileToFind); if ~isempty(found) rootDir = robotics.codertarget.internal.getRootDir; loc_addUDPBlocksToBuildInfo(buildInfo,rootDir); end % the zip file will be put in the start dir, the same as the final % executable or dll. sDir = getSourcePaths(buildInfo, true, {'StartDir'}); if isempty(sDir) sDir = {pwd}; end bDir = getSourcePaths(buildInfo, true, {'BuildDir'}); if isempty(bDir) bDir = {pwd}; end % Create CMakeLists.txt file for out node cmakeVersion = '2.8.3'; packageDep = {'roscpp', 'std_msgs'}; packageDep = unique([packageDep nodeInfo.nodeDependencies]); systemDep = {}; msgFiles = {}; msgDep = {}; % CMakelists.txt and package.xml both have to use the same ROS package name % (required to be all lowercase and start with a non-numeric letter). packageName = robotics.codertarget.internal.Util.modelNameToValidPackageName(modelName); writeCMakeListsTxt(buildInfo, cmakeVersion, packageName, packageDep, systemDep, msgFiles, msgDep); % Create package.xml file for our node writePackageXml(... modelName, ... packageName, ... data.Packaging.MaintainerName, ... data.Packaging.MaintainerEmail, ... data.Packaging.License, ... data.Packaging.Version, ... packageDep, ... packageDep); % Add CATKIN artifacts CMakeLists.txt and package.xml to the archive filePaths = getFullFileList(buildInfo); allFiles = [filePaths, ... fullfile(bDir{1}, 'CMakeLists.txt'), ... fullfile(bDir{1}, 'package.xml'), ... ]; % Create archive archiveName = [modelName, '.tgz']; archive = fullfile(sDir{1}, archiveName); tar(archive, allFiles); disp(message('robotics:robotslros:deploy:ArchiveTargetFile', archive).getString); % Copy build_model.sh to the same directory as the archive file rootDir = robotics.codertarget.internal.getRootDir; scriptName = 'build_ros_model.sh'; targetScript = fullfile(sDir{1}, scriptName); copyfile(fullfile(rootDir,'src',scriptName), targetScript, 'f'); disp(message('robotics:robotslros:deploy:ShellScriptTargetFile', targetScript).getString); disp(robotics.slros.internal.diag.DeviceDiagnostics.StepSeparator); disp(message('robotics:robotslros:deploy:CopyFilesToTarget').getString); end %-------------------------------------------------------------------------- % Internal functions %-------------------------------------------------------------------------- function writeCMakeListsTxt(buildInfo, cmakeVersion, packageName, packageDep, systemDep, msgFiles, msgDep) hs = StringWriter; % 1. Required CMake Version (cmake_minimum_required) % 2. Package Name (project()) hs.addcr(sprintf('cmake_minimum_required(VERSION %s)', cmakeVersion)); hs.addcr(sprintf('project(%s)', packageName)); hs.addcr('set(CMAKE_VERBOSE_MAKEFILE ON)'); hs.addcr(); %3. Find other CMake/Catkin packages needed for build (find_package()) if ~isempty(packageDep) hs.addcr('## Find catkin macros and libraries'); hs.addcr('## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)'); hs.addcr('## is used, also find other catkin packages'); hs.addcr('find_package(catkin REQUIRED COMPONENTS'); for k = 1:numel(packageDep) hs.addcr(sprintf('%s', packageDep{k})); end else hs.addcr('## Find catkin macros and libraries'); hs.addcr('## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)'); hs.addcr('## is used, also find other catkin packages'); hs.addcr('find_package(catkin REQUIRED'); end %% This is how you add BOOST components %hs.addcr('find_package(Boost REQUIRED COMPONENTS math)'); hs.addcr(')'); hs.addcr(); % 4. Message/Service/Action Generators (add_message_files(), add_service_files(), add_action_files()) if ~isempty(msgFiles) hs.addcr('## System dependencies are found with CMake''s conventions'); hs.addcr('# find_package(Boost REQUIRED COMPONENTS system)'); hs.addcr(); hs.addcr('################################################'); hs.addcr('## Declare ROS messages, services and actions ##'); hs.addcr('################################################'); hs.addcr('add_message_files('); hs.addcr('# FILES'); for k = 1:numel(msgFiles) hs.addcr(sprintf('%s', msgFiles{k})); end hs.addcr(')'); hs.addcr(); end %5. Invoke message/service/action generation (generate_messages()) if ~isempty(msgDep) && 0 hs.addcr('## Generate added messages and services with any dependencies listed here'); hs.addcr('generate_messages('); hs.addcr(' DEPENDENCIES'); for k = 1:numel(msgDep) hs.addcr(sprintf(' %s', msgDep{k})); end hs.addcr(')'); hs.addcr(); end % Add project specific definitions def = buildInfo.getDefines; if ~isempty(def) hs.addcr('add_definitions(') for k = 1:numel(def) hs.add(def{k}); hs.add(' '); end hs.addcr(')'); hs.addcr(); end %6. Specify package build info export (catkin_package()) hs.addcr('## The catkin_package macro generates cmake config files for your package'); hs.addcr('## Declare things to be passed to dependent projects'); hs.addcr('## INCLUDE_DIRS: uncomment this if you package contains header files'); hs.addcr('## LIBRARIES: libraries you create in this project that dependent projects also need'); hs.addcr('## CATKIN_DEPENDS: catkin_packages dependent projects also need'); hs.addcr('## DEPENDS: system dependencies of this project that dependent projects also need'); hs.addcr('catkin_package('); libraries = {}; includeDirs = {}; %# INCLUDE_DIRS include if ~isempty(includeDirs) hs.add(' INCLUDE_DIRS '); for k = 1:numel(includeDirs) hs.add(includeDirs{k}); hs.add(' '); end hs.addcr(); end %# LIBRARIES beginner_tutorials if ~isempty(libraries) hs.add(' LIBRARIES '); for k = 1:numel(libraries) hs.add(libraries{k}); hs.add(' '); end hs.addcr(); end %# CATKIN_DEPENDS roscpp rospy std_msgs if ~isempty(packageDep) hs.add(' CATKIN_DEPENDS '); for k = 1:numel(packageDep) hs.add(packageDep{k}); hs.add(' '); end hs.addcr(); end %# DEPENDS system_lib if ~isempty(systemDep) hs.add(' DEPENDS '); for k = 1:numel(systemDep) hs.add(systemDep{k}); hs.add(' '); end hs.addcr(); end hs.addcr(')'); hs.addcr(); % buildInfo.getLinkFlags % % buildInfo.getIncludePaths(true) % 7. Libraries/Executables to build (add_library()/add_executable()/target_link_libraries()) % The PROJECT_SOURCE_DIRECTORY is listed explicitly to pick up header % files that are included using angle brackets hs.addcr('###########'); hs.addcr('## Build ##'); hs.addcr('###########'); hs.addcr(); hs.addcr('## Specify additional locations of header files'); hs.addcr('## Your package locations should be listed before other locations'); hs.addcr('# include_directories(include)'); hs.addcr('include_directories('); hs.addcr(' include'); hs.addcr(' ${PROJECT_SOURCE_DIR}'); hs.addcr(' ${Boost_INCLUDE_DIRS}'); hs.addcr(' ${catkin_INCLUDE_DIRS}'); hs.addcr(')'); hs.addcr(); hs.addcr('## Get list of .c files in project source directory'); hs.addcr('file(GLOB ${PROJECT_NAME}_C_SOURCES RELATIVE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/*.c)'); hs.addcr(); hs.addcr('## Declare executable'); hs.addcr('add_executable(${PROJECT_NAME}_node'); srcFiles = getSourceFiles(buildInfo, false, false); for k = 1:numel(srcFiles) [~, name, ext] = fileparts(srcFiles{k}); hs.addcr(sprintf(' %s', [name, ext])); end hs.addcr(' ${${PROJECT_NAME}_C_SOURCES}'); hs.addcr(')'); hs.addcr(); % Add dependencies for custom messages hs.addcr('## Add cmake target dependencies of the executable/library'); hs.addcr('## as an example, message headers may need to be generated before nodes'); hs.addcr('add_dependencies(${PROJECT_NAME}_node ${catkin_EXPORTED_TARGETS})'); hs.addcr(); % Add dependent libraries such as librt, libpthread, etc. hs.addcr('## Specify libraries to link a library or executable target against'); hs.addcr('target_link_libraries(${PROJECT_NAME}_node'); hs.addcr(' ${catkin_LIBRARIES}'); hs.addcr(' ${Boost_LIBRARIES}'); systemLibs = getSystemLibraries(buildInfo); for k = 1:numel(systemLibs) hs.addcr([' ', systemLibs{k}]); end hs.addcr(')'); hs.addcr(); % % The link flags: -L % linkObjects = getLinkObjects(buildInfo) % if ~isempty(linkObjects) % hs.add('set_target_properties(${PROJECT_NAME}_node PROPERTIES LINK_FLAGS "'); % for k = 1:numel(linkObjects) % hs.add(linkFlags); % hs.add('"'); % hs.addcr(')'); % hs.addcr(); % end % The compile flags compileFlags = strtrim(buildInfo.getCompileFlags); if ~isempty(compileFlags) hs.add('set_target_properties(${PROJECT_NAME}_node PROPERTIES COMPILE_FLAGS "'); for k = 1:numel(compileFlags) if ~strcmp(compileFlags{k}, '-fpermissive') % -fpermissive is needed to build the C++ POSIX scheduler. % This is only needed for C++ and is handled by the % CMAKE_CXX_FLAGS statement below hs.add([compileFlags{k}, ' ']); end end hs.add('"'); hs.addcr(')'); end hs.addcr('SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive" )'); % stdbool.h is needed for C sources that use true/false keywords hs.addcr('SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -include stdbool.h" )'); % 8. Tests to build (catkin_add_gtest()) % if 0 % % 9. Install rules (install()) % hs.addcr('install(TARGETS ${PROJECT_NAME}_node'); % hs.addcr(' ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}'); % hs.addcr(' LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}'); % hs.addcr(' RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}'); % hs.addcr(')'); % hs.addcr(); % end hs.write('CMakeLists.txt'); end %-------------------------------------------------------------------------- function writePackageXml(modelName, packageName, maintainerName, maintainerEmail, licenseType, version, buildDep, runDep) hs = StringWriter; % Create package.xml file hs.addcr('<package>'); hs.addcr(sprintf(' <name>%s</name>', packageName)); hs.addcr(sprintf(' <version>%s</version>', version)); hs.addcr(' <description>'); hs.addcr(sprintf(' This package is generated from %s Simulink model.', modelName)); hs.addcr(' </description>'); hs.addcr(sprintf(' <maintainer email="%s">%s</maintainer>', maintainerEmail, maintainerName)); hs.addcr(' <license>%s</license>', licenseType); hs.addcr(); hs.addcr(' <buildtool_depend>catkin</buildtool_depend>'); hs.addcr(); if ~isempty(buildDep) for k = 1:numel(buildDep) hs.addcr(' <build_depend>%s</build_depend>', buildDep{k}); end end hs.addcr(); if ~isempty(runDep) for k = 1:numel(runDep) hs.addcr(' <run_depend>%s</run_depend>', runDep{k}); end end hs.addcr('</package>'); hs.write('package.xml'); end %-------------------------------------------------------------------------- function libs = getSystemLibraries(buildInfo) linkFlags = strtrim(buildInfo.getLinkFlags); libs = {}; for k = 1:numel(linkFlags) tmp = regexp(linkFlags{k}, '-l(\w+)', 'tokens'); if ~isempty(tmp) for j = 1:numel(tmp) libs = [libs, tmp{j}{1}]; %#ok<AGROW> end end end end %-------------------------------------------------------------------------- function loc_removeSources(buildInfo, sourcesToRemove) for i = 1:length(sourcesToRemove) srcs = buildInfo.getSourceFiles(false, false); found = strcmp(srcs, sourcesToRemove{i}); buildInfo.Src.Files(found) = []; end end %-------------------------------------------------------------------------- function loc_replaceDefines(buildInfo, defToRemove) def = buildInfo.getDefines; for j = 1:numel(defToRemove) for k = 1:numel(def) if isequal(def{k}, ['-D', defToRemove(j).Name]) buildInfo.deleteDefines(defToRemove(j).Name); buildInfo.addDefines(defToRemove(j).ReplaceWith); break; end end end end %-------------------------------------------------------------------------- function found = loc_findInBuildInfoSrc(buildInfo,filename) filename = strrep(filename,'$(MATLAB_ROOT)',matlabroot); found = []; for j=1:length(buildInfo.Src.Files) iFile = fullfile(buildInfo.Src.Files(j).Path, buildInfo.Src.Files(j).FileName); iFile = strrep(iFile,'$(MATLAB_ROOT)',matlabroot); if ~isempty(strfind(iFile, filename)) found = iFile; break; end end end %-------------------------------------------------------------------------- function loc_addUDPBlocksToBuildInfo(buildInfo,rootDir) filePathToAdd = fullfile(rootDir,'src'); fileNameToAdd = 'linuxUDP.c'; addLinkFlags(buildInfo,'-ldl'); if exist(fullfile(filePathToAdd,fileNameToAdd),'file') addSourceFiles(buildInfo,fileNameToAdd,filePathToAdd); addDefines(buildInfo,'_USE_TARGET_UDP_'); else % Could not find a valid UDP.c file; assuming this is a custom % target hardware, warn and proceed with code-generation warning(message('robotics:robotslros:cgen:FileNotFoundError',... fullfile(filePathToAdd,fileNameToAdd))); end end