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