|  | # Ceres Solver - A fast non-linear least squares minimizer | 
|  | # Copyright 2019 Google Inc. All rights reserved. | 
|  | # http://ceres-solver.org/ | 
|  | # | 
|  | # Redistribution and use in source and binary forms, with or without | 
|  | # modification, are permitted provided that the following conditions are met: | 
|  | # | 
|  | # * Redistributions of source code must retain the above copyright notice, | 
|  | #   this list of conditions and the following disclaimer. | 
|  | # * Redistributions in binary form must reproduce the above copyright notice, | 
|  | #   this list of conditions and the following disclaimer in the documentation | 
|  | #   and/or other materials provided with the distribution. | 
|  | # * Neither the name of Google Inc. nor the names of its contributors may be | 
|  | #   used to endorse or promote products derived from this software without | 
|  | #   specific prior written permission. | 
|  | # | 
|  | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
|  | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
|  | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 
|  | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
|  | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|  | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|  | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|  | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
|  | # POSSIBILITY OF SUCH DAMAGE. | 
|  | # | 
|  | # Author: darius.rueckert@fau.de (Darius Rueckert) | 
|  |  | 
|  | # The directory containing the following files | 
|  | #   - codegen_include.h.in | 
|  | #   - generate_code_from_functor.cc.in | 
|  | set(CODEGEN_CMAKE_SCRIPT_DIR "${CMAKE_CURRENT_LIST_DIR}") | 
|  |  | 
|  | # Generates C-code implementation of Ceres' CostFunction::Evaluate() API from a | 
|  | # templated C++ cost functor derived from ceres::CodegenCostFunction using | 
|  | # autodiff. The resulting implementation replaces the direct instantiation of | 
|  | # autodiff in client code, typically resulting in improved performance. | 
|  | # | 
|  | # Parameters: | 
|  | # | 
|  | # NAME | 
|  | #     The name of the cost functor. The name must exactly match the C++ type | 
|  | #     name of the functor. This is also the name of the CMake output target. | 
|  | # NAMESPACE [optional] | 
|  | #     The C++ namespace of the cost functor type. For example, if the full | 
|  | #     type name is ceres::BundleAdjust, then NAME should be "BundleAdjust" | 
|  | #     and NAMESPACE should be "ceres". | 
|  | # INPUT_FILE | 
|  | #     The path to the header defining the cost functor <NAME>. | 
|  | # OUTPUT_DIRECTORY [default = "generated"] | 
|  | #     The relative output directory of the generated header file. This is the | 
|  | #     prefix that has to be added to the #include of the generated files, i.e: | 
|  | #     #include "<OUTPUT_DIRECTORY>/<GENERATED_FILE.h>" | 
|  |  | 
|  | # | 
|  | # Example Usage: | 
|  | #   ceres_generate_cost_function_implementation_for_functor( | 
|  | #       NAME SquareFunctor | 
|  | #       INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/square_functor.h | 
|  | #       ) | 
|  | #   add_executable(helloworld_codegen helloworld_codegen.cc ) | 
|  | #   target_link_libraries(helloworld_codegen ceres SquareFunctor) | 
|  | function(ceres_generate_cost_function_implementation_for_functor) | 
|  | # Define and parse arguments | 
|  | set(OPTIONAL_ARGS) | 
|  | set(ONE_VALUE_ARGS NAME INPUT_FILE OUTPUT_DIRECTORY NAMESPACE) | 
|  | set(MULTI_VALUE_ARGS) | 
|  | cmake_parse_arguments( | 
|  | COST_FUNCTOR "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" | 
|  | "${MULTI_VALUE_ARGS}" ${ARGN} ) | 
|  |  | 
|  | # Default value of the output directory | 
|  | set(OUTPUT_DIRECTORY "generated") | 
|  | if(COST_FUNCTOR_OUTPUT_DIRECTORY) | 
|  | set(OUTPUT_DIRECTORY "${COST_FUNCTOR_OUTPUT_DIRECTORY}") | 
|  | endif() | 
|  |  | 
|  | set(CALLER_CODEGEN_BUILD_DIR "${PROJECT_BINARY_DIR}/codegen") | 
|  | set(CALLER_CODEGEN_INCLUDE_DIR "${CALLER_CODEGEN_BUILD_DIR}/include/") | 
|  |  | 
|  | file(MAKE_DIRECTORY | 
|  | "${CALLER_CODEGEN_BUILD_DIR}") | 
|  | file(MAKE_DIRECTORY | 
|  | "${CALLER_CODEGEN_INCLUDE_DIR}/${OUTPUT_DIRECTORY}") | 
|  | file(MAKE_DIRECTORY | 
|  | "${CALLER_CODEGEN_BUILD_DIR}/src") | 
|  |  | 
|  | # Convert the input file to an absolute path and check if it exists | 
|  | get_filename_component( | 
|  | COST_FUNCTOR_INPUT_FILE "${COST_FUNCTOR_INPUT_FILE}" REALPATH) | 
|  | if(NOT EXISTS "${COST_FUNCTOR_INPUT_FILE}") | 
|  | message(FATAL_ERROR | 
|  | "Could not find codegen input file ${COST_FUNCTOR_INPUT_FILE}") | 
|  | endif() | 
|  |  | 
|  |  | 
|  | # The full C++ type name of the cost functor. This is used inside the | 
|  | # generator to create an object of it. | 
|  | set(FULL_CXX_FUNCTOR_TYPE_NAME "${COST_FUNCTOR_NAME}") | 
|  | if(COST_FUNCTOR_NAMESPACE) | 
|  | set(FULL_CXX_FUNCTOR_TYPE_NAME | 
|  | "${COST_FUNCTOR_NAMESPACE}::${FULL_CXX_FUNCTOR_TYPE_NAME}") | 
|  | endif() | 
|  |  | 
|  | # 1. Generate a wrapper include file which is included by the user. | 
|  | #    This is required, because | 
|  | #      - It must exist during compiliation of the code generator (otherwise | 
|  | #        the #include will fail) | 
|  | #      - We don't want to have the users add macros to their code | 
|  | string(TOLOWER "${COST_FUNCTOR_NAME}" LOWER_CASE_FUNCTOR_NAME) | 
|  | set(INCLUDE_FILE | 
|  | "${CALLER_CODEGEN_INCLUDE_DIR}/${OUTPUT_DIRECTORY}/${LOWER_CASE_FUNCTOR_NAME}.h") | 
|  | configure_file("${CODEGEN_CMAKE_SCRIPT_DIR}/codegen_include.inc.in" "${INCLUDE_FILE}") | 
|  |  | 
|  | # 2. Generate the source file for the code generator | 
|  | set(GENERATOR_SOURCE | 
|  | "${CALLER_CODEGEN_BUILD_DIR}/src/${LOWER_CASE_FUNCTOR_NAME}_code_generator.cc") | 
|  | set(GENERATED_EVALUATION_IMPL_FILE | 
|  | "${CALLER_CODEGEN_INCLUDE_DIR}/${OUTPUT_DIRECTORY}/${LOWER_CASE_FUNCTOR_NAME}_evaluate_impl.inc") | 
|  | configure_file( | 
|  | "${CODEGEN_CMAKE_SCRIPT_DIR}/generate_code_for_functor.cc.in" "${GENERATOR_SOURCE}") | 
|  |  | 
|  | # 3. Build the executable that generates the autodiff code | 
|  | set(GENERATOR_TARGET ${COST_FUNCTOR_NAME}_generator) | 
|  | add_executable(${GENERATOR_TARGET} "${GENERATOR_SOURCE}") | 
|  | target_link_libraries(${GENERATOR_TARGET} ceres) | 
|  | set_target_properties(${GENERATOR_TARGET} PROPERTIES | 
|  | RUNTIME_OUTPUT_DIRECTORY "${CALLER_CODEGEN_BUILD_DIR}/bin") | 
|  | target_compile_definitions(${GENERATOR_TARGET} PRIVATE -DCERES_CODEGEN) | 
|  | target_include_directories(${GENERATOR_TARGET} | 
|  | PRIVATE "${CALLER_CODEGEN_INCLUDE_DIR}") | 
|  |  | 
|  | # 4. Execute the program from (3.) using a custom command | 
|  | add_custom_command(OUTPUT "${GENERATED_EVALUATION_IMPL_FILE}" | 
|  | COMMAND ${GENERATOR_TARGET} | 
|  | DEPENDS "${COST_FUNCTOR_INPUT_FILE}" | 
|  | VERBATIM | 
|  | ) | 
|  | set(GENERATE_TARGET ${COST_FUNCTOR_NAME}_generate) | 
|  | add_custom_target(${GENERATE_TARGET} DEPENDS "${GENERATED_EVALUATION_IMPL_FILE}" VERBATIM) | 
|  |  | 
|  | # 5. Create an output target which can be used by the client. This is required, | 
|  | #    because custom targets can't have include directories. | 
|  | set(OUTPUT_TARGET ${COST_FUNCTOR_NAME}) | 
|  | add_library(${OUTPUT_TARGET} INTERFACE) | 
|  | target_include_directories( | 
|  | ${OUTPUT_TARGET} INTERFACE "${CALLER_CODEGEN_INCLUDE_DIR}") | 
|  | target_sources( | 
|  | ${OUTPUT_TARGET} INTERFACE "${INCLUDE_FILE}" "${GENERATED_EVALUATION_IMPL_FILE}") | 
|  | add_dependencies(${OUTPUT_TARGET} ${GENERATE_TARGET}) | 
|  | endfunction() |