Skip to content

Instantly share code, notes, and snippets.

@mcourteaux
Created August 24, 2017 11:10
Show Gist options
  • Save mcourteaux/66ada94604d1122fb1c3b99f43dca380 to your computer and use it in GitHub Desktop.
Save mcourteaux/66ada94604d1122fb1c3b99f43dca380 to your computer and use it in GitHub Desktop.
include(CMakeParseArguments)
function(halide_use_image_io TARGET)
target_include_directories(${TARGET} PRIVATE "${HALIDE_ROOT_DIR}/tools")
foreach(PKG PNG JPEG)
# It's OK to call find_package() for the same package multiple times.
find_package(${PKG} QUIET)
if(${PKG}_FOUND)
target_compile_definitions(${TARGET} PRIVATE ${${PKG}_DEFINITIONS})
target_include_directories(${TARGET} PRIVATE ${${PKG}_INCLUDE_DIRS})
target_link_libraries(${TARGET} ${${PKG}_LIBRARIES})
else()
message(STATUS "${PKG} not found for ${TARGET}; compiling with -DHALIDE_NO_${PKG}")
target_compile_definitions(${TARGET} PRIVATE -DHALIDE_NO_${PKG})
endif()
endforeach()
endfunction()
function(halide_project name folder)
add_executable("${name}" ${ARGN})
if (MSVC)
else()
target_compile_options("${name}" PUBLIC "-fno-rtti")
endif()
target_link_libraries("${name}" PUBLIC Halide ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
#target_include_directories("${name}" PRIVATE "${HALIDE_ROOT_DIR}/tools")
set_target_properties("${name}" PROPERTIES FOLDER "${folder}")
if (MSVC)
# 4006: "already defined, second definition ignored"
# 4088: "/FORCE used, image may not work"
# (Note that MSVC apparently considers 4088 too important to allow us to ignore it;
# I'm nevertheless leaving this here to document that we don't care about it.)
set_target_properties(${name} PROPERTIES LINK_FLAGS "/ignore:4006 /ignore:4088")
target_compile_definitions("${name}" PRIVATE _CRT_SECURE_NO_WARNINGS)
target_link_libraries("${name}" PRIVATE Kernel32)
endif()
endfunction(halide_project)
function(halide_generator_genfiles_dir NAME OUTVAR)
set(GENFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}/generator_genfiles/${NAME}")
file(MAKE_DIRECTORY "${GENFILES_DIR}")
set(${OUTVAR} "${GENFILES_DIR}" PARENT_SCOPE)
endfunction()
function(halide_generator_get_exec_path TARGET OUTVAR)
if(MSVC)
# In MSVC, the generator executable will be placed in a configuration specific
# directory specified by ${CMAKE_CFG_INTDIR}.
set(${OUTVAR} "${CMAKE_CURRENT_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/${TARGET}${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
elseif(XCODE)
# In Xcode, the generator executable will be placed in a configuration specific
# directory, so the Xcode variable $(CONFIGURATION) is passed in the custom build script.
set(${OUTVAR} "${CMAKE_CURRENT_BINARY_DIR}/bin/$(CONFIGURATION)/${TARGET}${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
else()
set(${OUTVAR} "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
endif()
endfunction()
function(halide_generator_add_exec_generator_target)
set(options )
set(oneValueArgs GENERATOR_TARGET GENFILES_DIR)
set(multiValueArgs OUTPUTS GENERATOR_ARGS)
cmake_parse_arguments(args "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
message("Generator.exec target for '${args_GENERATOR_TARGET}'.")
halide_generator_get_exec_path(${args_GENERATOR_TARGET} EXEC_PATH)
list(GET args_OUTPUTS 0 CODE_FILE)
list(GET args_OUTPUTS 1 HDR_FILE)
message("${CODE_FILE}")
message("${HDR_FILE}")
message("Outputs: ${args_OUTPUTS}")
add_custom_command(
OUTPUT ${CODE_FILE} ${HDR_FILE}
DEPENDS "${args_GENERATOR_TARGET}"
COMMAND ${EXEC_PATH} ${args_GENERATOR_ARGS}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Executing Generator ${args_GENERATOR_TARGET} with args ${args_GENERATOR_ARGS}..."
)
endfunction()
# This function adds custom build steps to invoke a Halide generator executable
# and produce a static library containing the generated code.
#
# The generator executable must be produced separately, e.g. using a call to the
# function halide_add_generator() or halide_project(...) or add_executable(...)
# and passed to this function in the GENERATOR_TARGET parameter.
#
# Usage:
# halide_add_aot_library(<name>
# GENERATOR_TARGET <target>
# GENERATOR_NAME <string>
# GENERATED_FUNCTION <string>
# GENERATOR_OUTPUTS <arg> <arg> ...
# GENERATOR_ARGS <arg> <arg> ...)
#
# <name> is the name of the library being defined.
# GENERATOR_TARGET is the name of the generator executable target, which is assumed to be
# defined elsewhere.
# GENERATOR_TARGET is the name of the generator executable target, which is assumed to be
# defined elsewhere.
# GENERATOR_NAME is the registered name of the Halide::Generator derived object
# GENERATED_FUNCTION is the name of the C function to be generated by Halide, including C++
# namespace (if any); if omitted, default to GENERATOR_NAME
# GENERATOR_OUTPUTS are the values to pass to -e; if omitted, defaults to "h static_library"
# GENERATOR_ARGS are optional extra arguments passed to the generator executable during
# build.
function(halide_add_aot_library AOT_LIBRARY_TARGET)
# Parse arguments
set(options )
set(oneValueArgs GENERATOR_TARGET GENERATOR_NAME GENERATED_FUNCTION)
set(multiValueArgs GENERATOR_ARGS GENERATOR_OUTPUTS FILTER_DEPS)
cmake_parse_arguments(args "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (args_GENERATED_FUNCTION STREQUAL "")
set(args_GENERATED_FUNCTION ${args_GENERATOR_NAME})
endif()
# Create a directory to contain generator specific intermediate files
halide_generator_genfiles_dir(${AOT_LIBRARY_TARGET} GENFILES_DIR)
# Determine the name of the output files
set(FILTER_LIB "${AOT_LIBRARY_TARGET}${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(FILTER_HDR "${AOT_LIBRARY_TARGET}.h")
set(FILTER_CPP "${AOT_LIBRARY_TARGET}.cpp")
set(GENERATOR_EXEC_ARGS "-o" "${GENFILES_DIR}")
if (NOT ${args_GENERATED_FUNCTION} STREQUAL "")
list(APPEND GENERATOR_EXEC_ARGS "-f" "${args_GENERATED_FUNCTION}" )
endif()
if (NOT ${args_GENERATOR_NAME} STREQUAL "")
list(APPEND GENERATOR_EXEC_ARGS "-g" "${args_GENERATOR_NAME}")
endif()
if (NOT "${args_GENERATOR_OUTPUTS}" STREQUAL "")
string(REPLACE ";" "," _tmp "${args_GENERATOR_OUTPUTS}")
list(APPEND GENERATOR_EXEC_ARGS "-e" ${_tmp})
endif()
# GENERATOR_ARGS always come last
list(APPEND GENERATOR_EXEC_ARGS ${args_GENERATOR_ARGS})
if ("${args_GENERATOR_OUTPUTS}" STREQUAL "")
set(args_GENERATOR_OUTPUTS static_library h)
endif()
set(OUTPUTS )
# This is the CMake idiom for "if foo in list"
list(FIND args_GENERATOR_OUTPUTS "static_library" _lib_index)
list(FIND args_GENERATOR_OUTPUTS "h" _h_index)
list(FIND args_GENERATOR_OUTPUTS "cpp" _cpp_index)
string(LENGTH "${CMAKE_BINARY_DIR}" BINARY_PATH_LENTH)
MATH(EXPR BINARY_PATH_LENTH "${BINARY_PATH_LENTH}+1")
string(SUBSTRING "${GENFILES_DIR}" ${BINARY_PATH_LENTH} -1 OUTPUT_DIR)
if (${_lib_index} GREATER -1)
list(APPEND OUTPUTS "${GENFILES_DIR}/${FILTER_LIB}")
endif()
if (${_h_index} GREATER -1)
list(APPEND OUTPUTS "${GENFILES_DIR}/${FILTER_HDR}")
set_source_files_properties("${GENFILES_DIR}/${FILTER_HDR}" PROPERTIES GENERATED TRUE)
endif()
if (${_cpp_index} GREATER -1)
list(APPEND OUTPUTS "${GENFILES_DIR}/${FILTER_CPP}")
set_source_files_properties("${GENFILES_DIR}/${FILTER_HDR}" PROPERTIES GENERATED TRUE)
endif()
halide_generator_add_exec_generator_target(
GENERATOR_TARGET ${args_GENERATOR_TARGET}
GENERATOR_ARGS "${GENERATOR_EXEC_ARGS}"
GENFILES_DIR ${GENFILES_DIR}
OUTPUTS "${OUTPUTS}"
)
add_library("${AOT_LIBRARY_TARGET}" INTERFACE)
target_link_libraries(${AOT_LIBRARY_TARGET} INTERFACE "${GENFILES_DIR}/${FILTER_LIB}")
endfunction(halide_add_aot_library)
# Usage:
# halide_add_aot_library_dependency(TARGET AOT_LIBRARY_TARGET)
function(halide_add_aot_library_dependency TARGET AOT_LIBRARY_TARGET)
halide_generator_genfiles_dir(${AOT_LIBRARY_TARGET} GENFILES_DIR)
set(FILTER_LIB "${AOT_LIBRARY_TARGET}${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(FILTER_HDR "${AOT_LIBRARY_TARGET}.h")
target_link_libraries("${TARGET}" PUBLIC "${AOT_LIBRARY_TARGET}")
target_include_directories("${TARGET}" PUBLIC "${GENFILES_DIR}")
add_dependencies("${TARGET}" "${AOT_LIBRARY_TARGET}")
target_sources("${TARGET}" PRIVATE "${GENFILES_DIR}/${FILTER_HDR}")
if (WIN32)
if (MSVC)
# /FORCE:multiple allows clobbering the halide runtime symbols in the lib
# linker warnings disabled:
# 4006: "already defined, second definition ignored"
# 4088: "/FORCE used, image may not work"
# (Note that MSVC apparently considers 4088 too important to allow us to ignore it;
# I'm nevertheless leaving this here to document that we don't care about it.)
set_target_properties("${TARGET}" PROPERTIES LINK_FLAGS "/STACK:8388608,1048576 /FORCE:multiple /ignore:4006 /ignore:4088")
else()
set_target_properties("${TARGET}" PROPERTIES LINK_FLAGS "-Wl,--allow-multiple-definition")
endif()
else()
target_link_libraries("${TARGET}" PRIVATE dl pthread z)
endif()
endfunction(halide_add_aot_library_dependency)
function(halide_add_generator NAME)
set(options WITH_STUB)
set(oneValueArgs STUB_GENERATOR_NAME)
set(multiValueArgs SRCS STUB_DEPS)
cmake_parse_arguments(args "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
halide_project("${NAME}"
"generator"
"${HALIDE_ROOT_DIR}/tools/GenGen.cpp"
"${args_SRCS}")
set_target_properties(${NAME} PROPERTIES FOLDER "generator")
endfunction(halide_add_generator)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment