diff options
author | Siva Chandra Reddy <sivachandra@google.com> | 2020-04-18 04:42:40 +0300 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@google.com> | 2020-04-21 19:24:17 +0300 |
commit | 8c2e66226fb74114fc0e57f239721065d800d33f (patch) | |
tree | c7e176e5d817c35c2a0771566388d9a34f550c6c /libc/cmake/modules/LLVMLibCObjectRules.cmake | |
parent | 177c065e5065ef140c1e83ab655c3aad904a3a40 (diff) |
[libc] [NFC] Split the CMake rules into multiple files.
Summary:
The single file was getting too long to be convenient to navigate. This
patch splits it up two into 4 files one each for header rules,
object rules, library rules, and test rules.
Reviewers: abrachet, alexshap
Subscribers: mgorny, tschuett, libc-commits
Tags: #libc-project
Differential Revision: https://reviews.llvm.org/D78536
Diffstat (limited to 'libc/cmake/modules/LLVMLibCObjectRules.cmake')
-rw-r--r-- | libc/cmake/modules/LLVMLibCObjectRules.cmake | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake new file mode 100644 index 000000000000..9879531e056d --- /dev/null +++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake @@ -0,0 +1,313 @@ +set(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY") + +# Rule which is essentially a wrapper over add_library to compile a set of +# sources to object files. +# Usage: +# add_object_library( +# <target_name> +# HDRS <list of header files> +# SRCS <list of source files> +# DEPENDS <list of dependencies> +# COMPILE_OPTIONS <optional list of special compile options for this target> +function(add_object_library target_name) + cmake_parse_arguments( + "ADD_OBJECT" + "" # No option arguments + "" # Single value arguments + "SRCS;HDRS;COMPILE_OPTIONS;DEPENDS" # Multivalue arguments + ${ARGN} + ) + + if(NOT ADD_OBJECT_SRCS) + message(FATAL_ERROR "'add_object_library' rule requires SRCS to be specified.") + endif() + + get_fq_target_name(${target_name} fq_target_name) + add_library( + ${fq_target_name} + OBJECT + ${ADD_OBJECT_SRCS} + ${ADD_OBJECT_HDRS} + ) + target_include_directories( + ${fq_target_name} + PRIVATE + ${LIBC_BUILD_DIR}/include + ${LIBC_SOURCE_DIR} + ${LIBC_BUILD_DIR} + ) + if(ADD_OBJECT_COMPILE_OPTIONS) + target_compile_options( + ${fq_target_name} + PRIVATE ${ADD_OBJECT_COMPILE_OPTIONS} + ) + endif() + + set(all_object_files $<TARGET_OBJECTS:${fq_target_name}>) + if(ADD_OBJECT_DEPENDS) + get_fq_deps_list(fq_deps_list ${ADD_OBJECT_DEPENDS}) + add_dependencies( + ${fq_target_name} + ${fq_deps_list} + ) + foreach(obj_target IN LISTS fq_deps_list) + if(NOT TARGET obj_target) + # Not all targets will be visible. So, we will ignore those which aren't + # visible yet. + continue() + endif() + get_target_property(obj_type ${obj_target} "TARGET_TYPE") + if((NOT obj_type) OR (NOT (${obj_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE}))) + continue() + endif() + # If a dependency is also a object file library, we will collect the list of + # object files from it. + get_target_property(obj_files ${obj_target} "OBJECT_FILES") + list(APPEND all_object_files ${obj_files}) + endforeach(obj_target) + endif() + list(REMOVE_DUPLICATES all_object_files) + + set_target_properties( + ${fq_target_name} + PROPERTIES + "TARGET_TYPE" ${OBJECT_LIBRARY_TARGET_TYPE} + "OBJECT_FILES" "${all_object_files}" + ) +endfunction(add_object_library) + +set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ") + +# A rule for entrypoint object targets. +# Usage: +# add_entrypoint_object( +# <target_name> +# [ALIAS|REDIRECTED] # Specified if the entrypoint is redirected or an alias. +# [NAME] <the C name of the entrypoint if different from target_name> +# SRCS <list of .cpp files> +# HDRS <list of .h files> +# DEPENDS <list of dependencies> +# COMPILE_OPTIONS <optional list of special compile options for this target> +# SPECIAL_OBJECTS <optional list of special object targets added by the rule `add_object`> +# ) +function(add_entrypoint_object target_name) + cmake_parse_arguments( + "ADD_ENTRYPOINT_OBJ" + "ALIAS;REDIRECTED" # Optional argument + "NAME" # Single value arguments + "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi value arguments + ${ARGN} + ) + + get_fq_target_name(${target_name} fq_target_name) + + if(ADD_ENTRYPOINT_OBJ_ALIAS) + # Alias targets help one add aliases to other entrypoint object targets. + # One can use alias targets setup OS/machine independent entrypoint targets. + list(LENGTH ADD_ENTRYPOINT_OBJ_DEPENDS deps_size) + if(NOT (${deps_size} EQUAL "1")) + message(FATAL_ERROR "An entrypoint alias should have exactly one dependency.") + endif() + list(GET ADD_ENTRYPOINT_OBJ_DEPENDS 0 dep_target) + get_fq_dep_name(fq_dep_name ${dep_target}) + if(NOT TARGET ${fq_dep_name}) + message(WARNING "Aliasee ${fq_dep_name} for entrypoint alias ${target_name} missing; " + "Target ${target_name} will be ignored.") + return() + endif() + + get_target_property(obj_type ${fq_dep_name} "TARGET_TYPE") + if((NOT obj_type) OR (NOT (${obj_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}))) + message(FATAL_ERROR "The aliasee of an entrypoint alias should be an entrypoint.") + endif() + + add_custom_target(${fq_target_name}) + add_dependencies(${fq_target_name} ${fq_dep_name}) + get_target_property(all_objects ${fq_dep_name} "OBJECT_FILES") + get_target_property(all_objects_raw ${fq_dep_name} "OBJECT_FILES_RAW") + set_target_properties( + ${fq_target_name} + PROPERTIES + "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE} + "OBJECT_FILES" "${all_objects}" + "OBJECT_FILES_RAW" "${all_objects_raw}" + ) + return() + endif() + + if(NOT ADD_ENTRYPOINT_OBJ_SRCS) + message(FATAL_ERROR "`add_entrypoint_object` rule requires SRCS to be specified.") + endif() + if(NOT ADD_ENTRYPOINT_OBJ_HDRS) + message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.") + endif() + + set(entrypoint_name ${target_name}) + if(ADD_ENTRYPOINT_OBJ_NAME) + set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME}) + endif() + + set(objects_target_name "${fq_target_name}_objects") + + add_library( + ${objects_target_name} + # We want an object library as the objects will eventually get packaged into + # an archive (like libc.a). + OBJECT + ${ADD_ENTRYPOINT_OBJ_SRCS} + ${ADD_ENTRYPOINT_OBJ_HDRS} + ) + target_compile_options( + ${objects_target_name} + BEFORE + PRIVATE + -fpie ${LLVM_CXX_STD_default} + ) + target_include_directories( + ${objects_target_name} + PRIVATE + ${LIBC_BUILD_DIR}/include + ${LIBC_SOURCE_DIR} + ${LIBC_BUILD_DIR} + ) + add_dependencies( + ${objects_target_name} + libc.src.__support.common + ) + set(dep_objects "") + if(ADD_ENTRYPOINT_OBJ_DEPENDS) + get_fq_deps_list(fq_deps_list ${ADD_ENTRYPOINT_OBJ_DEPENDS}) + add_dependencies( + ${objects_target_name} + ${fq_deps_list} + ) + foreach(dep_target IN LISTS fq_deps_list) + if(NOT TARGET ${dep_target}) + # Not all targets will be visible. So, we will ignore those which aren't + # visible yet. + continue() + endif() + get_target_property(obj_type ${dep_target} "TARGET_TYPE") + if((NOT obj_type) OR (NOT (${obj_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE}))) + # Even from among the visible targets, we will collect object files + # only from add_object_library targets. + continue() + endif() + # Calling get_target_property requires that the target be visible at this + # point. For object library dependencies, this is a reasonable requirement. + # We can revisit this in future if we need cases which break under this + # requirement. + get_target_property(obj_files ${dep_target} "OBJECT_FILES") + list(APPEND dep_objects ${obj_files}) + endforeach(dep_target) + endif() + list(REMOVE_DUPLICATES dep_objects) + + if(ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS) + target_compile_options( + ${objects_target_name} + PRIVATE ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS} + ) + endif() + + set(object_file_raw "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_raw.o") + set(object_file "${CMAKE_CURRENT_BINARY_DIR}/${target_name}.o") + + set(input_objects $<TARGET_OBJECTS:${objects_target_name}>) + add_custom_command( + OUTPUT ${object_file_raw} + DEPENDS ${input_objects} + COMMAND ${CMAKE_LINKER} -r ${input_objects} -o ${object_file_raw} + ) + + set(alias_attributes "0,function,global") + if(ADD_ENTRYPOINT_OBJ_REDIRECTED) + set(alias_attributes "${alias_attributes},hidden") + endif() + + add_custom_command( + OUTPUT ${object_file} + # We llvm-objcopy here as GNU-binutils objcopy does not support the 'hidden' flag. + DEPENDS ${object_file_raw} ${llvm-objcopy} + COMMAND $<TARGET_FILE:llvm-objcopy> --add-symbol + "${entrypoint_name}=.llvm.libc.entrypoint.${entrypoint_name}:${alias_attributes}" + ${object_file_raw} ${object_file} + ) + + add_custom_target( + ${fq_target_name} + ALL + DEPENDS ${object_file} + ) + set(all_objects ${object_file}) + list(APPEND all_objects ${dep_objects}) + set(all_objects_raw ${object_file_raw}) + list(APPEND all_objects_raw ${dep_objects}) + set_target_properties( + ${fq_target_name} + PROPERTIES + "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE} + "OBJECT_FILES" "${all_objects}" + "OBJECT_FILES_RAW" "${all_objects_raw}" + ) + + if(LLVM_LIBC_ENABLE_LINTING) + set(lint_timestamp "${CMAKE_CURRENT_BINARY_DIR}/.${target_name}.__lint_timestamp__") + + add_custom_command( + OUTPUT ${lint_timestamp} + # --quiet is used to surpress warning statistics from clang-tidy like: + # Suppressed X warnings (X in non-user code). + # There seems to be a bug in clang-tidy where by even with --quiet some + # messages from clang's own diagnostics engine leak through: + # X warnings generated. + # Until this is fixed upstream, we use -fno-caret-diagnostics to surpress + # these. + COMMAND $<TARGET_FILE:clang-tidy> "--extra-arg=-fno-caret-diagnostics" --quiet + # Path to directory containing compile_commands.json + -p ${PROJECT_BINARY_DIR} + ${ADD_ENTRYPOINT_OBJ_SRCS} + # We have two options for running commands, add_custom_command and + # add_custom_target. We don't want to run the linter unless source files + # have changed. add_custom_target explicitly runs everytime therefore we + # use add_custom_command. This function requires an output file and since + # linting doesn't produce a file, we create a dummy file using a + # crossplatform touch. + COMMAND "${CMAKE_COMMAND}" -E touch ${lint_timestamp} + COMMENT "Linting... ${target_name}" + DEPENDS ${clang-tidy} ${objects_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + + add_custom_target(${fq_target_name}.__lint__ + DEPENDS ${lint_timestamp}) + add_dependencies(lint-libc ${fq_target_name}.__lint__) + add_dependencies(${fq_target_name} ${fq_target_name}.__lint__) + endif() + +endfunction(add_entrypoint_object) + +# Rule build a redirector object file. +function(add_redirector_object target_name) + cmake_parse_arguments( + "REDIRECTOR_OBJECT" + "" # No optional arguments + "SRC" # The cpp file in which the redirector is defined. + "" # No multivalue arguments + ${ARGN} + ) + if(NOT REDIRECTOR_OBJECT_SRC) + message(FATAL_ERROR "'add_redirector_object' rule requires SRC option listing one source file.") + endif() + + add_library( + ${target_name} + OBJECT + ${REDIRECTOR_OBJECT_SRC} + ) + target_compile_options( + ${target_name} + BEFORE PRIVATE -fPIC + ) +endfunction(add_redirector_object) + |