From 84cb832919b503b8700e8381ce282878679c4b9b Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Fri, 4 Oct 2019 15:42:48 -0700 Subject: [PATCH 2/6] Initial version of darknet_vendor (#1) * Initial version of darknet_vendor Signed-off-by: Shane Loretz * Quote to make tag usable as string Signed-off-by: Shane Loretz * Add OpenCV option Signed-off-by: Shane Loretz * Fix include guards Signed-off-by: Shane Loretz * First cuda attempt Signed-off-by: Shane Loretz * Cuda builds and runs Signed-off-by: Shane Loretz Signed-off-by: Shane Loretz * Avoid -pthread flag Signed-off-by: Shane Loretz * Combine cuda blocks, trivial cleanup Signed-off-by: Shane Loretz * Add opencv and cuda dependencies Signed-off-by: Shane Loretz * Add license for FetchContent Signed-off-by: Shane Loretz * Add Apache 2.0 license Signed-off-by: Shane Loretz * FetchContent uses git Signed-off-by: Shane Loretz * Add CONTRIBUTING.md Signed-off-by: Shane Loretz --- CMakeLists.txt | 347 ++++++++ CONTRIBUTING.md | 18 + LICENSE | 202 +++++ README.md | 0 cmake/FetchContent.cmake | 1062 +++++++++++++++++++++++ cmake/FetchContent/CMakeLists.cmake.in | 24 + cmake/LICENSE.FetchContent | 132 +++ cmake/darknet_vendor-config.cmake.in | 20 + include/darknet_vendor/darknet_vendor.h | 32 + include/darknet_vendor/version.h.in | 24 + package.xml | 26 + 11 files changed, 1887 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/FetchContent.cmake create mode 100644 cmake/FetchContent/CMakeLists.cmake.in create mode 100644 cmake/LICENSE.FetchContent create mode 100644 cmake/darknet_vendor-config.cmake.in create mode 100644 include/darknet_vendor/darknet_vendor.h create mode 100644 include/darknet_vendor/version.h.in create mode 100644 package.xml diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..868da894 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,347 @@ +cmake_minimum_required(VERSION 3.10) +project(darknet_vendor VERSION 0.1.0) + +#################### +# Build options +#################### + +option(DARKNET_CUDA "Build darknet with CUDA support" ON) +option(DARKNET_OPENCV "Build darknet with OpenCV support" ON) + +#################### +# Download Darknet +#################### + +if(CMAKE_VERSION VERSION_LESS "3.11") + include("cmake/FetchContent.cmake") +endif() + +# Same version as Debian Buster +set(darknet_git_tag "61c9d02ec461e30d55762ec7669d6a1d3c356fb2") + +FetchContent_Declare(darknet-download + GIT_REPOSITORY + "https://github.com/pjreddie/darknet.git" + GIT_TAG + ${darknet_git_tag} +) + +FetchContent_GetProperties(darknet-download) +if(NOT darknet-download_POPULATED) + FetchContent_Populate(darknet-download) +endif() + +set(darknet_src_dir "${darknet-download_SOURCE_DIR}") + +#################### +# Classify files +#################### +set(darknet_public_headers + "${CMAKE_CURRENT_BINARY_DIR}/darknet-src/include/darknet.h" +) + +set(darknet_cuda_sources + "${darknet_src_dir}/src/activation_kernels.cu" + "${darknet_src_dir}/src/avgpool_layer_kernels.cu" + "${darknet_src_dir}/src/blas_kernels.cu" + "${darknet_src_dir}/src/col2im_kernels.cu" + "${darknet_src_dir}/src/convolutional_kernels.cu" + "${darknet_src_dir}/src/crop_layer_kernels.cu" + "${darknet_src_dir}/src/deconvolutional_kernels.cu" + "${darknet_src_dir}/src/dropout_layer_kernels.cu" + "${darknet_src_dir}/src/im2col_kernels.cu" + "${darknet_src_dir}/src/maxpool_layer_kernels.cu" +) + +set(darknet_exec_c_sources + "${darknet_src_dir}/examples/art.c" + "${darknet_src_dir}/examples/captcha.c" + "${darknet_src_dir}/examples/cifar.c" + "${darknet_src_dir}/examples/classifier.c" + "${darknet_src_dir}/examples/coco.c" + "${darknet_src_dir}/examples/darknet.c" + "${darknet_src_dir}/examples/detector.c" + "${darknet_src_dir}/examples/go.c" + "${darknet_src_dir}/examples/instance-segmenter.c" + "${darknet_src_dir}/examples/lsd.c" + "${darknet_src_dir}/examples/nightmare.c" + "${darknet_src_dir}/examples/super.c" + "${darknet_src_dir}/examples/rnn.c" + "${darknet_src_dir}/examples/regressor.c" + "${darknet_src_dir}/examples/segmenter.c" + "${darknet_src_dir}/examples/tag.c" + "${darknet_src_dir}/examples/yolo.c" +) + +set(darknet_lib_cpp_sources + "${darknet_src_dir}/src/image_opencv.cpp" +) + +set(darknet_lib_c_sources + "${darknet_src_dir}/src/activation_layer.c" + "${darknet_src_dir}/src/activations.c" + "${darknet_src_dir}/src/avgpool_layer.c" + "${darknet_src_dir}/src/batchnorm_layer.c" + "${darknet_src_dir}/src/blas.c" + "${darknet_src_dir}/src/box.c" + "${darknet_src_dir}/src/col2im.c" + # "${darknet_src_dir}/src/compare.c" + "${darknet_src_dir}/src/connected_layer.c" + "${darknet_src_dir}/src/convolutional_layer.c" + "${darknet_src_dir}/src/cost_layer.c" + "${darknet_src_dir}/src/crnn_layer.c" + "${darknet_src_dir}/src/crop_layer.c" + "${darknet_src_dir}/src/cuda.c" + "${darknet_src_dir}/src/data.c" + "${darknet_src_dir}/src/deconvolutional_layer.c" + "${darknet_src_dir}/src/demo.c" + "${darknet_src_dir}/src/detection_layer.c" + "${darknet_src_dir}/src/dropout_layer.c" + "${darknet_src_dir}/src/gemm.c" + "${darknet_src_dir}/src/gru_layer.c" + "${darknet_src_dir}/src/im2col.c" + "${darknet_src_dir}/src/image.c" + "${darknet_src_dir}/src/iseg_layer.c" + "${darknet_src_dir}/src/l2norm_layer.c" + "${darknet_src_dir}/src/layer.c" + "${darknet_src_dir}/src/list.c" + "${darknet_src_dir}/src/local_layer.c" + "${darknet_src_dir}/src/logistic_layer.c" + "${darknet_src_dir}/src/lstm_layer.c" + "${darknet_src_dir}/src/matrix.c" + "${darknet_src_dir}/src/maxpool_layer.c" + "${darknet_src_dir}/src/network.c" + "${darknet_src_dir}/src/normalization_layer.c" + "${darknet_src_dir}/src/option_list.c" + "${darknet_src_dir}/src/parser.c" + "${darknet_src_dir}/src/region_layer.c" + "${darknet_src_dir}/src/reorg_layer.c" + "${darknet_src_dir}/src/rnn_layer.c" + "${darknet_src_dir}/src/route_layer.c" + "${darknet_src_dir}/src/shortcut_layer.c" + "${darknet_src_dir}/src/softmax_layer.c" + "${darknet_src_dir}/src/tree.c" + "${darknet_src_dir}/src/upsample_layer.c" + "${darknet_src_dir}/src/utils.c" + "${darknet_src_dir}/src/yolo_layer.c" +) + +#################### +# Darknet Library +#################### +# set(THREADS_PREFER_PTHREAD_FLAG True) +find_package(Threads REQUIRED) + +if(DARKNET_CUDA) + enable_language(CUDA) + find_package(CUDA REQUIRED) + + # Flags taken from https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ + if(NOT DEFINED DARKNET_VENDOR_CUDA_FLAGS) + if(CUDA_VERSION VERSION_GREATER 10) + set(DARKNET_VENDOR_CUDA_FLAGS + "-arch=sm_50" + "-gencode=arch=compute_50,code=sm_50" + "-gencode=arch=compute_52,code=sm_52" + "-gencode=arch=compute_60,code=sm_60" + "-gencode=arch=compute_61,code=sm_61" + "-gencode=arch=compute_70,code=sm_70" + "-gencode=arch=compute_75,code=sm_75" + "-gencode=arch=compute_75,code=compute_75" + ) + elseif(CUDA_VERSION VERSION_GREATER 9) + set(DARKNET_VENDOR_CUDA_FLAGS + "-arch=sm_50" + "-gencode=arch=compute_50,code=sm_50" + "-gencode=arch=compute_52,code=sm_52" + "-gencode=arch=compute_60,code=sm_60" + "-gencode=arch=compute_61,code=sm_61" + "-gencode=arch=compute_70,code=sm_70" + "-gencode=arch=compute_70,code=compute_70" + ) + endif() + endif() + + add_library(darknet SHARED ${darknet_lib_c_sources} ${darknet_lib_cpp_sources} ${darknet_cuda_sources}) + target_compile_options(darknet INTERFACE + $<$:${DARKNET_VENDOR_CUDA_FLAGS}> + ) + target_compile_definitions(darknet PUBLIC GPU=1) + target_link_libraries(darknet PUBLIC + cuda cudart cublas curand + ) +else() # not using CUDA + add_library(darknet SHARED ${darknet_lib_c_sources} ${darknet_lib_cpp_sources}) +endif() + +set_target_properties(darknet PROPERTIES LINKER_LANGUAGE C) +target_include_directories(darknet PUBLIC + $ + $ + $ +) + +if(DARKNET_OPENCV) + find_package(OpenCV REQUIRED) + target_include_directories(darknet PRIVATE ${OpenCV_INCLUDE_DIRS}) + target_link_libraries(darknet PUBLIC ${OpenCV_LIBRARIES}) + target_compile_definitions(darknet PUBLIC OPENCV=1) +endif() + +# TODO(sloretz) pthread replacement on Windows? +target_link_libraries(darknet PUBLIC Threads::Threads) +if(UNIX) + # Need to link C math library on some platforms + target_link_libraries(darknet PUBLIC m) +endif() + +#################### +# Darknet_vendor target +#################### + +# Add interface library for darknet_vendor headers +add_library(darknet_vendor INTERFACE) +target_include_directories(darknet_vendor INTERFACE + $ + $ +) +target_link_libraries(darknet_vendor INTERFACE darknet) + +configure_file("include/darknet_vendor/version.h.in" "version.h" @ONLY) + +#################### +# Darknet Executable +#################### +add_executable(darknet_exec ${darknet_exec_c_sources}) +target_link_libraries(darknet_exec PUBLIC darknet) +set_target_properties(darknet_exec PROPERTIES OUTPUT_NAME "darknet") + +#################### +# ProjectConfig.cmake +#################### + +set(INCLUDE_INSTALL_DIR "include") +set(SHARE_CMAKE_INSTALL_DIR "share/darknet_vendor/cmake") +set(EXEC_INSTALL_DIR "bin") +include(CMakePackageConfigHelpers) +configure_package_config_file( + "cmake/darknet_vendor-config.cmake.in" + "darknet_vendor-config.cmake" + INSTALL_DESTINATION "${SHARE_CMAKE_INSTALL_DIR}" + PATH_VARS "INCLUDE_INSTALL_DIR" "SHARE_CMAKE_INSTALL_DIR" "EXEC_INSTALL_DIR" +) + +write_basic_package_version_file( + "darknet_vendor-version.cmake" + COMPATIBILITY SameMajorVersion) + +#################### +# Installation +#################### + +# Install darknet public headers +install( + DIRECTORY + "${darknet_src_dir}/include/" + DESTINATION + "include" +) + +# Install darknet_vendor public headers +install( + DIRECTORY + "include/" + DESTINATION + "include" + FILES_MATCHING PATTERN + "*.h" +) +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/version.h" + DESTINATION + "include/darknet_vendor" +) + +# Install darknet library +install( + TARGETS darknet + EXPORT "darknet_vendor-targets" + ARCHIVE DESTINATION "lib" + LIBRARY DESTINATION "lib" + RUNTIME DESTINATION "bin" +) + +# Install darknet_vendor interface library +install( + TARGETS darknet_vendor + EXPORT "darknet_vendor-targets" +) + +# Install darknet demo executable +install(TARGETS darknet_exec DESTINATION "${EXEC_INSTALL_DIR}") + +# Install config files and helper scripts +install( + DIRECTORY + "${darknet_src_dir}/cfg" + DESTINATION + "share/darknet" +) +install( + DIRECTORY + "${darknet_src_dir}/data" + DESTINATION + "share/darknet" +) +install( + DIRECTORY + "${darknet_src_dir}/scripts" + DESTINATION + "share/darknet" +) +install( + DIRECTORY + "${darknet_src_dir}/python" + DESTINATION + "share/darknet" +) + +# Install license files +install( + FILES + "${darknet_src_dir}/LICENSE" + "${darknet_src_dir}/LICENSE.fuck" + "${darknet_src_dir}/LICENSE.gen" + "${darknet_src_dir}/LICENSE.gpl" + "${darknet_src_dir}/LICENSE.meta" + "${darknet_src_dir}/LICENSE.mit" + "${darknet_src_dir}/LICENSE.v1" + DESTINATION + "share/darknet" +) + +# Install project-config.cmake and project-version.cmake +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/darknet_vendor-config.cmake" + DESTINATION + share/darknet_vendor/cmake +) +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/darknet_vendor-version.cmake" + DESTINATION + share/darknet_vendor/cmake +) + +# install exported targets +install( + EXPORT + "darknet_vendor-targets" + NAMESPACE + "darknet_vendor::" + DESTINATION + "share/darknet_vendor/cmake" +) + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..cfba094d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +Any contribution that you make to this repository will +be under the Apache 2 License, as dictated by that +[license](http://www.apache.org/licenses/LICENSE-2.0.html): + +~~~ +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. +~~~ + +Contributors must sign-off each commit by adding a `Signed-off-by: ...` +line to commit messages to certify that they have the right to submit +the code they are contributing to the project according to the +[Developer Certificate of Origin (DCO)](https://developercertificate.org/). diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 00000000..e69de29b diff --git a/cmake/FetchContent.cmake b/cmake/FetchContent.cmake new file mode 100644 index 00000000..375538a2 --- /dev/null +++ b/cmake/FetchContent.cmake @@ -0,0 +1,1062 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FetchContent +------------------ + +.. only:: html + + .. contents:: + +Overview +^^^^^^^^ + +This module enables populating content at configure time via any method +supported by the :module:`ExternalProject` module. Whereas +:command:`ExternalProject_Add` downloads at build time, the +``FetchContent`` module makes content available immediately, allowing the +configure step to use the content in commands like :command:`add_subdirectory`, +:command:`include` or :command:`file` operations. + +Content population details would normally be defined separately from the +command that performs the actual population. This separation ensures that +all of the dependency details are defined before anything may try to use those +details to populate content. This is particularly important in more complex +project hierarchies where dependencies may be shared between multiple projects. + +The following shows a typical example of declaring content details: + +.. code-block:: cmake + + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + ) + +For most typical cases, populating the content can then be done with a single +command like so: + +.. code-block:: cmake + + FetchContent_MakeAvailable(googletest) + +The above command not only populates the content, it also adds it to the main +build (if possible) so that the main build can use the populated project's +targets, etc. In some cases, the main project may need to have more precise +control over the population or may be required to explicitly define the +population steps (e.g. if CMake versions earlier than 3.14 need to be +supported). The typical pattern of such custom steps looks like this: + +.. code-block:: cmake + + FetchContent_GetProperties(googletest) + if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + endif() + +Regardless of which population method is used, when using the +declare-populate pattern with a hierarchical project arrangement, projects at +higher levels in the hierarchy are able to override the population details of +content specified anywhere lower in the project hierarchy. The ability to +detect whether content has already been populated ensures that even if +multiple child projects want certain content to be available, the first one +to populate it wins. The other child project can simply make use of the +already available content instead of repeating the population for itself. +See the :ref:`Examples ` section which demonstrates +this scenario. + +The ``FetchContent`` module also supports defining and populating +content in a single call, with no check for whether the content has been +populated elsewhere in the project already. This is a more low level +operation and would not normally be the way the module is used, but it is +sometimes useful as part of implementing some higher level feature or to +populate some content in CMake's script mode. + + +Declaring Content Details +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: FetchContent_Declare + + .. code-block:: cmake + + FetchContent_Declare( ...) + + The ``FetchContent_Declare()`` function records the options that describe + how to populate the specified content, but if such details have already + been recorded earlier in this project (regardless of where in the project + hierarchy), this and all later calls for the same content ```` are + ignored. This "first to record, wins" approach is what allows hierarchical + projects to have parent projects override content details of child projects. + + The content ```` can be any string without spaces, but good practice + would be to use only letters, numbers and underscores. The name will be + treated case-insensitively and it should be obvious for the content it + represents, often being the name of the child project or the value given + to its top level :command:`project` command (if it is a CMake project). + For well-known public projects, the name should generally be the official + name of the project. Choosing an unusual name makes it unlikely that other + projects needing that same content will use the same name, leading to + the content being populated multiple times. + + The ```` can be any of the download or update/patch options + that the :command:`ExternalProject_Add` command understands. The configure, + build, install and test steps are explicitly disabled and therefore options + related to them will be ignored. In most cases, ```` will + just be a couple of options defining the download method and method-specific + details like a commit tag or archive hash. For example: + + .. code-block:: cmake + + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + ) + + FetchContent_Declare( + myCompanyIcons + URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz + URL_HASH 5588a7b18261c20068beabfb4f530b87 + ) + + FetchContent_Declare( + myCompanyCertificates + SVN_REPOSITORY svn+ssh://svn.mycompany.com/srv/svn/trunk/certs + SVN_REVISION -r12345 + ) + +Populating The Content +^^^^^^^^^^^^^^^^^^^^^^ + +For most common scenarios, population means making content available to the +main build according to previously declared details for that dependency. +There are two main patterns for populating content, one based on calling +:command:`FetchContent_GetProperties` and +:command:`FetchContent_Populate` for more precise control and the other on +calling :command:`FetchContent_MakeAvailable` for a simpler, more automated +approach. The former generally follows this canonical pattern: + +.. _`fetch-content-canonical-pattern`: + +.. code-block:: cmake + + # Check if population has already been performed + FetchContent_GetProperties() + string(TOLOWER "" lcName) + if(NOT ${lcName}_POPULATED) + # Fetch the content using previously declared details + FetchContent_Populate() + + # Set custom variables, policies, etc. + # ... + + # Bring the populated content into the build + add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR}) + endif() + +The above is such a common pattern that, where no custom steps are needed +between the calls to :command:`FetchContent_Populate` and +:command:`add_subdirectory`, equivalent logic can be obtained by calling +:command:`FetchContent_MakeAvailable` instead (and should be preferred where +it meets the needs of the project). + +.. command:: FetchContent_Populate + + .. code-block:: cmake + + FetchContent_Populate( ) + + In most cases, the only argument given to ``FetchContent_Populate()`` is the + ````. When used this way, the command assumes the content details have + been recorded by an earlier call to :command:`FetchContent_Declare`. The + details are stored in a global property, so they are unaffected by things + like variable or directory scope. Therefore, it doesn't matter where in the + project the details were previously declared, as long as they have been + declared before the call to ``FetchContent_Populate()``. Those saved details + are then used to construct a call to :command:`ExternalProject_Add` in a + private sub-build to perform the content population immediately. The + implementation of ``ExternalProject_Add()`` ensures that if the content has + already been populated in a previous CMake run, that content will be reused + rather than repopulating them again. For the common case where population + involves downloading content, the cost of the download is only paid once. + + An internal global property records when a particular content population + request has been processed. If ``FetchContent_Populate()`` is called more + than once for the same content name within a configure run, the second call + will halt with an error. Projects can and should check whether content + population has already been processed with the + :command:`FetchContent_GetProperties` command before calling + ``FetchContent_Populate()``. + + ``FetchContent_Populate()`` will set three variables in the scope of the + caller; ``_POPULATED``, ``_SOURCE_DIR`` and + ``_BINARY_DIR``, where ```` is the lowercased ````. + ``_POPULATED`` will always be set to ``True`` by the call. + ``_SOURCE_DIR`` is the location where the + content can be found upon return (it will have already been populated), while + ``_BINARY_DIR`` is a directory intended for use as a corresponding + build directory. The main use case for the two directory variables is to + call :command:`add_subdirectory` immediately after population, i.e.: + + .. code-block:: cmake + + FetchContent_Populate(FooBar ...) + add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) + + The values of the three variables can also be retrieved from anywhere in the + project hierarchy using the :command:`FetchContent_GetProperties` command. + + A number of cache variables influence the behavior of all content population + performed using details saved from a :command:`FetchContent_Declare` call: + + ``FETCHCONTENT_BASE_DIR`` + In most cases, the saved details do not specify any options relating to the + directories to use for the internal sub-build, final source and build areas. + It is generally best to leave these decisions up to the ``FetchContent`` + module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` + cache variable controls the point under which all content population + directories are collected, but in most cases developers would not need to + change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if + developers change this value, they should aim to keep the path short and + just below the top level of the build tree to avoid running into path + length problems on Windows. + + ``FETCHCONTENT_QUIET`` + The logging output during population can be quite verbose, making the + configure stage quite noisy. This cache option (``ON`` by default) hides + all population output unless an error is encountered. If experiencing + problems with hung downloads, temporarily switching this option off may + help diagnose which content population is causing the issue. + + ``FETCHCONTENT_FULLY_DISCONNECTED`` + When this option is enabled, no attempt is made to download or update + any content. It is assumed that all content has already been populated in + a previous run or the source directories have been pointed at existing + contents the developer has provided manually (using options described + further below). When the developer knows that no changes have been made to + any content details, turning this option ``ON`` can significantly speed up + the configure stage. It is ``OFF`` by default. + + ``FETCHCONTENT_UPDATES_DISCONNECTED`` + This is a less severe download/update control compared to + ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and + update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the + update stage. Therefore, if content has not been downloaded previously, + it will still be downloaded when this option is enabled. This can speed up + the configure stage, but not as much as + ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default. + + In addition to the above cache variables, the following cache variables are + also defined for each content name (```` is the uppercased value of + ````): + + ``FETCHCONTENT_SOURCE_DIR_`` + If this is set, no download or update steps are performed for the specified + content and the ``_SOURCE_DIR`` variable returned to the caller is + pointed at this location. This gives developers a way to have a separate + checkout of the content that they can modify freely without interference + from the build. The build simply uses that existing source, but it still + defines ``_BINARY_DIR`` to point inside its own build area. + Developers are strongly encouraged to use this mechanism rather than + editing the sources populated in the default location, as changes to + sources in the default location can be lost when content population details + are changed by the project. + + ``FETCHCONTENT_UPDATES_DISCONNECTED_`` + This is the per-content equivalent of + ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option + is ``ON``, then updates will be disabled for the named content. + Disabling updates for individual content can be useful for content whose + details rarely change, while still leaving other frequently changing + content with updates enabled. + + + The ``FetchContent_Populate()`` command also supports a syntax allowing the + content details to be specified directly rather than using any saved + details. This is more low-level and use of this form is generally to be + avoided in favour of using saved content details as outlined above. + Nevertheless, in certain situations it can be useful to invoke the content + population as an isolated operation (typically as part of implementing some + other higher level feature or when using CMake in script mode): + + .. code-block:: cmake + + FetchContent_Populate( + [QUIET] + [SUBBUILD_DIR ] + [SOURCE_DIR ] + [BINARY_DIR ] + ... + ) + + This form has a number of key differences to that where only ```` is + provided: + + - All required population details are assumed to have been provided directly + in the call to ``FetchContent_Populate()``. Any saved details for + ```` are ignored. + - No check is made for whether content for ```` has already been + populated. + - No global property is set to record that the population has occurred. + - No global properties record the source or binary directories used for the + populated content. + - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and + ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored. + + The ``_SOURCE_DIR`` and ``_BINARY_DIR`` variables are still + returned to the caller, but since these locations are not stored as global + properties when this form is used, they are only available to the calling + scope and below rather than the entire project hierarchy. No + ``_POPULATED`` variable is set in the caller's scope with this form. + + The supported options for ``FetchContent_Populate()`` are the same as those + for :command:`FetchContent_Declare()`. Those few options shown just + above are either specific to ``FetchContent_Populate()`` or their behavior is + slightly modified from how :command:`ExternalProject_Add` treats them. + + ``QUIET`` + The ``QUIET`` option can be given to hide the output associated with + populating the specified content. If the population fails, the output will + be shown regardless of whether this option was given or not so that the + cause of the failure can be diagnosed. The global ``FETCHCONTENT_QUIET`` + cache variable has no effect on ``FetchContent_Populate()`` calls where the + content details are provided directly. + + ``SUBBUILD_DIR`` + The ``SUBBUILD_DIR`` argument can be provided to change the location of the + sub-build created to perform the population. The default value is + ``${CMAKE_CURRENT_BINARY_DIR}/-subbuild`` and it would be unusual + to need to override this default. If a relative path is specified, it will + be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. + + ``SOURCE_DIR``, ``BINARY_DIR`` + The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by + :command:`ExternalProject_Add`, but different default values are used by + ``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to + ``${CMAKE_CURRENT_BINARY_DIR}/-src`` and ``BINARY_DIR`` defaults to + ``${CMAKE_CURRENT_BINARY_DIR}/-build``. If a relative path is + specified, it will be interpreted as relative to + :variable:`CMAKE_CURRENT_BINARY_DIR`. + + In addition to the above explicit options, any other unrecognized options are + passed through unmodified to :command:`ExternalProject_Add` to perform the + download, patch and update steps. The following options are explicitly + prohibited (they are disabled by the ``FetchContent_Populate()`` command): + + - ``CONFIGURE_COMMAND`` + - ``BUILD_COMMAND`` + - ``INSTALL_COMMAND`` + - ``TEST_COMMAND`` + + If using ``FetchContent_Populate()`` within CMake's script mode, be aware + that the implementation sets up a sub-build which therefore requires a CMake + generator and build tool to be available. If these cannot be found by + default, then the :variable:`CMAKE_GENERATOR` and/or + :variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately + on the command line invoking the script. + + +.. command:: FetchContent_GetProperties + + When using saved content details, a call to :command:`FetchContent_Populate` + records information in global properties which can be queried at any time. + This information includes the source and binary directories associated with + the content and also whether or not the content population has been processed + during the current configure run. + + .. code-block:: cmake + + FetchContent_GetProperties( + [SOURCE_DIR ] + [BINARY_DIR ] + [POPULATED ] + ) + + The ``SOURCE_DIR``, ``BINARY_DIR`` and ``POPULATED`` options can be used to + specify which properties should be retrieved. Each option accepts a value + which is the name of the variable in which to store that property. Most of + the time though, only ```` is given, in which case the call will then + set the same variables as a call to + :command:`FetchContent_Populate(name) `. This allows + the following canonical pattern to be used, which ensures that the relevant + variables will always be defined regardless of whether or not the population + has been performed elsewhere in the project already: + + .. code-block:: cmake + + FetchContent_GetProperties(foobar) + if(NOT foobar_POPULATED) + FetchContent_Populate(foobar) + ... + endif() + + The above pattern allows other parts of the overall project hierarchy to + re-use the same content and ensure that it is only populated once. + + +.. command:: FetchContent_MakeAvailable + + .. code-block:: cmake + + FetchContent_MakeAvailable( [...] ) + + This command implements the common pattern typically needed for most + dependencies. It iterates over each of the named dependencies in turn + and for each one it loosely follows the same + :ref:`canonical pattern ` as + presented at the beginning of this section. One small difference to + that pattern is that it will only call :command:`add_subdirectory` on the + populated content if there is a ``CMakeLists.txt`` file in its top level + source directory. This allows the command to be used for dependencies + that make downloaded content available at a known location but which do + not need or support being added directly to the build. + + +.. _`fetch-content-examples`: + +Examples +^^^^^^^^ + +This first fairly straightforward example ensures that some popular testing +frameworks are available to the main build: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + ) + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.5.0 + ) + + # After the following call, the CMake targets defined by googletest and + # Catch2 will be defined and available to the rest of the build + FetchContent_MakeAvailable(googletest Catch2) + + +In more complex project hierarchies, the dependency relationships can be more +complicated. Consider a hierarchy where ``projA`` is the top level project and +it depends directly on projects ``projB`` and ``projC``. Both ``projB`` and +``projC`` can be built standalone and they also both depend on another project +``projD``. ``projB`` additionally depends on ``projE``. This example assumes +that all five projects are available on a company git server. The +``CMakeLists.txt`` of each project might have sections like the following: + +*projA*: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + projB + GIT_REPOSITORY git@mycompany.com:git/projB.git + GIT_TAG 4a89dc7e24ff212a7b5167bef7ab079d + ) + FetchContent_Declare( + projC + GIT_REPOSITORY git@mycompany.com:git/projC.git + GIT_TAG 4ad4016bd1d8d5412d135cf8ceea1bb9 + ) + FetchContent_Declare( + projD + GIT_REPOSITORY git@mycompany.com:git/projD.git + GIT_TAG origin/integrationBranch + ) + FetchContent_Declare( + projE + GIT_REPOSITORY git@mycompany.com:git/projE.git + GIT_TAG origin/release/2.3-rc1 + ) + + # Order is important, see notes in the discussion further below + FetchContent_MakeAvailable(projD projB projC) + +*projB*: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + projD + GIT_REPOSITORY git@mycompany.com:git/projD.git + GIT_TAG 20b415f9034bbd2a2e8216e9a5c9e632 + ) + FetchContent_Declare( + projE + GIT_REPOSITORY git@mycompany.com:git/projE.git + GIT_TAG 68e20f674a48be38d60e129f600faf7d + ) + + FetchContent_MakeAvailable(projD projE) + +*projC*: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + projD + GIT_REPOSITORY git@mycompany.com:git/projD.git + GIT_TAG 7d9a17ad2c962aa13e2fbb8043fb6b8a + ) + + # This particular version of projD requires workarounds + FetchContent_GetProperties(projD) + if(NOT projd_POPULATED) + FetchContent_Populate(projD) + + # Copy an additional/replacement file into the populated source + file(COPY someFile.c DESTINATION ${projd_SOURCE_DIR}/src) + + add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) + endif() + +A few key points should be noted in the above: + +- ``projB`` and ``projC`` define different content details for ``projD``, + but ``projA`` also defines a set of content details for ``projD``. + Because ``projA`` will define them first, the details from ``projB`` and + ``projC`` will not be used. The override details defined by ``projA`` + are not required to match either of those from ``projB`` or ``projC``, but + it is up to the higher level project to ensure that the details it does + define still make sense for the child projects. +- In the ``projA`` call to :command:`FetchContent_MakeAvailable`, ``projD`` + is listed ahead of ``projB`` and ``projC`` to ensure that ``projA`` is in + control of how ``projD`` is populated. +- While ``projA`` defines content details for ``projE``, it does not need + to explicitly call ``FetchContent_MakeAvailable(projE)`` or + ``FetchContent_Populate(projD)`` itself. Instead, it leaves that to the + child ``projB``. For higher level projects, it is often enough to just + define the override content details and leave the actual population to the + child projects. This saves repeating the same thing at each level of the + project hierarchy unnecessarily. + + +Projects don't always need to add the populated content to the build. +Sometimes the project just wants to make the downloaded content available at +a predictable location. The next example ensures that a set of standard +company toolchain files (and potentially even the toolchain binaries +themselves) is available early enough to be used for that same build. + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.14) + + include(FetchContent) + FetchContent_Declare( + mycom_toolchains + URL https://intranet.mycompany.com//toolchains_1.3.2.tar.gz + ) + FetchContent_MakeAvailable(mycom_toolchains) + + project(CrossCompileExample) + +The project could be configured to use one of the downloaded toolchains like +so: + +.. code-block:: shell + + cmake -DCMAKE_TOOLCHAIN_FILE=_deps/mycom_toolchains-src/toolchain_arm.cmake /path/to/src + +When CMake processes the ``CMakeLists.txt`` file, it will download and unpack +the tarball into ``_deps/mycompany_toolchains-src`` relative to the build +directory. The :variable:`CMAKE_TOOLCHAIN_FILE` variable is not used until +the :command:`project` command is reached, at which point CMake looks for the +named toolchain file relative to the build directory. Because the tarball has +already been downloaded and unpacked by then, the toolchain file will be in +place, even the very first time that ``cmake`` is run in the build directory. + +Lastly, the following example demonstrates how one might download and unpack a +firmware tarball using CMake's :manual:`script mode `. The call to +:command:`FetchContent_Populate` specifies all the content details and the +unpacked firmware will be placed in a ``firmware`` directory below the +current working directory. + +*getFirmware.cmake*: + +.. code-block:: cmake + + # NOTE: Intended to be run in script mode with cmake -P + include(FetchContent) + FetchContent_Populate( + firmware + URL https://mycompany.com/assets/firmware-1.23-arm.tar.gz + URL_HASH MD5=68247684da89b608d466253762b0ff11 + SOURCE_DIR firmware + ) + +#]=======================================================================] + + +set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent") + +#======================================================================= +# Recording and retrieving content details for later population +#======================================================================= + +# Internal use, projects must not call this directly. It is +# intended for use by FetchContent_Declare() only. +# +# Sets a content-specific global property (not meant for use +# outside of functions defined here in this file) which can later +# be retrieved using __FetchContent_getSavedDetails() with just the +# same content name. If there is already a value stored in the +# property, it is left unchanged and this call has no effect. +# This allows parent projects to define the content details, +# overriding anything a child project may try to set (properties +# are not cached between runs, so the first thing to set it in a +# build will be in control). +function(__FetchContent_declareDetails contentName) + + string(TOLOWER ${contentName} contentNameLower) + set(propertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) + if(NOT alreadyDefined) + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${ARGN}) + endif() + +endfunction() + + +# Internal use, projects must not call this directly. It is +# intended for use by the FetchContent_Declare() function. +# +# Retrieves details saved for the specified content in an +# earlier call to __FetchContent_declareDetails(). +function(__FetchContent_getSavedDetails contentName outVar) + + string(TOLOWER ${contentName} contentNameLower) + set(propertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) + if(NOT alreadyDefined) + message(FATAL_ERROR "No content details recorded for ${contentName}") + endif() + get_property(propertyValue GLOBAL PROPERTY ${propertyName}) + set(${outVar} "${propertyValue}" PARENT_SCOPE) + +endfunction() + + +# Saves population details of the content, sets defaults for the +# SOURCE_DIR and BUILD_DIR. +function(FetchContent_Declare contentName) + + set(options "") + set(oneValueArgs SVN_REPOSITORY) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + unset(srcDirSuffix) + unset(svnRepoArgs) + if(ARG_SVN_REPOSITORY) + # Add a hash of the svn repository URL to the source dir. This works + # around the problem where if the URL changes, the download would + # fail because it tries to checkout/update rather than switch the + # old URL to the new one. We limit the hash to the first 7 characters + # so that the source path doesn't get overly long (which can be a + # problem on windows due to path length limits). + string(SHA1 urlSHA ${ARG_SVN_REPOSITORY}) + string(SUBSTRING ${urlSHA} 0 7 urlSHA) + set(srcDirSuffix "-${urlSHA}") + set(svnRepoArgs SVN_REPOSITORY ${ARG_SVN_REPOSITORY}) + endif() + + string(TOLOWER ${contentName} contentNameLower) + __FetchContent_declareDetails( + ${contentNameLower} + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}" + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" + ${svnRepoArgs} + # List these last so they can override things we set above + ${ARG_UNPARSED_ARGUMENTS} + ) + +endfunction() + + +#======================================================================= +# Set/get whether the specified content has been populated yet. +# The setter also records the source and binary dirs used. +#======================================================================= + +# Internal use, projects must not call this directly. It is +# intended for use by the FetchContent_Populate() function to +# record when FetchContent_Populate() is called for a particular +# content name. +function(__FetchContent_setPopulated contentName sourceDir binaryDir) + + string(TOLOWER ${contentName} contentNameLower) + set(prefix "_FetchContent_${contentNameLower}") + + set(propertyName "${prefix}_sourceDir") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir}) + + set(propertyName "${prefix}_binaryDir") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir}) + + set(propertyName "${prefix}_populated") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} True) + +endfunction() + + +# Set variables in the calling scope for any of the retrievable +# properties. If no specific properties are requested, variables +# will be set for all retrievable properties. +# +# This function is intended to also be used by projects as the canonical +# way to detect whether they should call FetchContent_Populate() +# and pull the populated source into the build with add_subdirectory(), +# if they are using the populated content in that way. +function(FetchContent_GetProperties contentName) + + string(TOLOWER ${contentName} contentNameLower) + + set(options "") + set(oneValueArgs SOURCE_DIR BINARY_DIR POPULATED) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_SOURCE_DIR AND + NOT ARG_BINARY_DIR AND + NOT ARG_POPULATED) + # No specific properties requested, provide them all + set(ARG_SOURCE_DIR ${contentNameLower}_SOURCE_DIR) + set(ARG_BINARY_DIR ${contentNameLower}_BINARY_DIR) + set(ARG_POPULATED ${contentNameLower}_POPULATED) + endif() + + set(prefix "_FetchContent_${contentNameLower}") + + if(ARG_SOURCE_DIR) + set(propertyName "${prefix}_sourceDir") + get_property(value GLOBAL PROPERTY ${propertyName}) + if(value) + set(${ARG_SOURCE_DIR} ${value} PARENT_SCOPE) + endif() + endif() + + if(ARG_BINARY_DIR) + set(propertyName "${prefix}_binaryDir") + get_property(value GLOBAL PROPERTY ${propertyName}) + if(value) + set(${ARG_BINARY_DIR} ${value} PARENT_SCOPE) + endif() + endif() + + if(ARG_POPULATED) + set(propertyName "${prefix}_populated") + get_property(value GLOBAL PROPERTY ${propertyName} DEFINED) + set(${ARG_POPULATED} ${value} PARENT_SCOPE) + endif() + +endfunction() + + +#======================================================================= +# Performing the population +#======================================================================= + +# The value of contentName will always have been lowercased by the caller. +# All other arguments are assumed to be options that are understood by +# ExternalProject_Add(), except for QUIET and SUBBUILD_DIR. +function(__FetchContent_directPopulate contentName) + + set(options + QUIET + ) + set(oneValueArgs + SUBBUILD_DIR + SOURCE_DIR + BINARY_DIR + # Prevent the following from being passed through + CONFIGURE_COMMAND + BUILD_COMMAND + INSTALL_COMMAND + TEST_COMMAND + # We force both of these to be ON since we are always executing serially + # and we want all steps to have access to the terminal in case they + # need input from the command line (e.g. ask for a private key password) + # or they want to provide timely progress. We silently absorb and + # discard these if they are set by the caller. + USES_TERMINAL_DOWNLOAD + USES_TERMINAL_UPDATE + ) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_SUBBUILD_DIR) + message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}") + set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}") + endif() + + if(NOT ARG_SOURCE_DIR) + message(FATAL_ERROR "Internal error: SOURCE_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_SOURCE_DIR}") + set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SOURCE_DIR}") + endif() + + if(NOT ARG_BINARY_DIR) + message(FATAL_ERROR "Internal error: BINARY_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_BINARY_DIR}") + set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY_DIR}") + endif() + + # Ensure the caller can know where to find the source and build directories + # with some convenient variables. Doing this here ensures the caller sees + # the correct result in the case where the default values are overridden by + # the content details set by the project. + set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE) + set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE) + + # The unparsed arguments may contain spaces, so build up ARG_EXTRA + # in such a way that it correctly substitutes into the generated + # CMakeLists.txt file with each argument quoted. + unset(ARG_EXTRA) + foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS) + set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"") + endforeach() + + # Hide output if requested, but save it to a variable in case there's an + # error so we can show the output upon failure. When not quiet, don't + # capture the output to a variable because the user may want to see the + # output as it happens (e.g. progress during long downloads). Combine both + # stdout and stderr in the one capture variable so the output stays in order. + if (ARG_QUIET) + set(outputOptions + OUTPUT_VARIABLE capturedOutput + ERROR_VARIABLE capturedOutput + ) + else() + set(capturedOutput) + set(outputOptions) + message(STATUS "Populating ${contentName}") + endif() + + if(CMAKE_GENERATOR) + set(generatorOpts "-G${CMAKE_GENERATOR}") + if(CMAKE_GENERATOR_PLATFORM) + list(APPEND generatorOpts "-A${CMAKE_GENERATOR_PLATFORM}") + endif() + if(CMAKE_GENERATOR_TOOLSET) + list(APPEND generatorOpts "-T${CMAKE_GENERATOR_TOOLSET}") + endif() + + if(CMAKE_MAKE_PROGRAM) + list(APPEND generatorOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") + endif() + + else() + # Likely we've been invoked via CMake's script mode where no + # generator is set (and hence CMAKE_MAKE_PROGRAM could not be + # trusted even if provided). We will have to rely on being + # able to find the default generator and build tool. + unset(generatorOpts) + endif() + + # Create and build a separate CMake project to carry out the population. + # If we've already previously done these steps, they will not cause + # anything to be updated, so extra rebuilds of the project won't occur. + # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project + # has this set to something not findable on the PATH. + configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in" + "${ARG_SUBBUILD_DIR}/CMakeLists.txt") + execute_process( + COMMAND ${CMAKE_COMMAND} ${generatorOpts} . + RESULT_VARIABLE result + ${outputOptions} + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") + endif() + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + ${outputOptions} + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "Build step for ${contentName} failed: ${result}") + endif() + +endfunction() + + +option(FETCHCONTENT_FULLY_DISCONNECTED "Disables all attempts to download or update content and assumes source dirs already exist") +option(FETCHCONTENT_UPDATES_DISCONNECTED "Enables UPDATE_DISCONNECTED behavior for all content population") +option(FETCHCONTENT_QUIET "Enables QUIET option for all content population" ON) +set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/_deps" CACHE PATH "Directory under which to collect all populated content") + +# Populate the specified content using details stored from +# an earlier call to FetchContent_Declare(). +function(FetchContent_Populate contentName) + + if(NOT contentName) + message(FATAL_ERROR "Empty contentName not allowed for FetchContent_Populate()") + endif() + + string(TOLOWER ${contentName} contentNameLower) + + if(ARGN) + # This is the direct population form with details fully specified + # as part of the call, so we already have everything we need + __FetchContent_directPopulate( + ${contentNameLower} + SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild" + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-build" + ${ARGN} # Could override any of the above ..._DIR variables + ) + + # Pass source and binary dir variables back to the caller + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) + + # Don't set global properties, or record that we did this population, since + # this was a direct call outside of the normal declared details form. + # We only want to save values in the global properties for content that + # honours the hierarchical details mechanism so that projects are not + # robbed of the ability to override details set in nested projects. + return() + endif() + + # No details provided, so assume they were saved from an earlier call + # to FetchContent_Declare(). Do a check that we haven't already + # populated this content before in case the caller forgot to check. + FetchContent_GetProperties(${contentName}) + if(${contentNameLower}_POPULATED) + message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") + endif() + + string(TOUPPER ${contentName} contentNameUpper) + set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper} + "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}" + CACHE PATH "When not empty, overrides where to find pre-populated content for ${contentName}") + + if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}) + # The source directory has been explicitly provided in the cache, + # so no population is required + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + elseif(FETCHCONTENT_FULLY_DISCONNECTED) + # Bypass population and assume source is already there from a previous run + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + else() + # Support both a global "disconnect all updates" and a per-content + # update test (either one being set disables updates for this content). + option(FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper} + "Enables UPDATE_DISCONNECTED behavior just for population of ${contentName}") + if(FETCHCONTENT_UPDATES_DISCONNECTED OR + FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper}) + set(disconnectUpdates True) + else() + set(disconnectUpdates False) + endif() + + if(FETCHCONTENT_QUIET) + set(quietFlag QUIET) + else() + unset(quietFlag) + endif() + + __FetchContent_getSavedDetails(${contentName} contentDetails) + if("${contentDetails}" STREQUAL "") + message(FATAL_ERROR "No details have been set for content: ${contentName}") + endif() + + __FetchContent_directPopulate( + ${contentNameLower} + ${quietFlag} + UPDATE_DISCONNECTED ${disconnectUpdates} + SUBBUILD_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-subbuild" + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src" + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" + # Put the saved details last so they can override any of the + # the options we set above (this can include SOURCE_DIR or + # BUILD_DIR) + ${contentDetails} + ) + endif() + + __FetchContent_setPopulated( + ${contentName} + ${${contentNameLower}_SOURCE_DIR} + ${${contentNameLower}_BINARY_DIR} + ) + + # Pass variables back to the caller. The variables passed back here + # must match what FetchContent_GetProperties() sets when it is called + # with just the content name. + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) + set(${contentNameLower}_POPULATED True PARENT_SCOPE) + +endfunction() + +# Arguments are assumed to be the names of dependencies that have been +# declared previously and should be populated. It is not an error if +# any of them have already been populated (they will just be skipped in +# that case). The command is implemented as a macro so that the variables +# defined by the FetchContent_GetProperties() and FetchContent_Populate() +# calls will be available to the caller. +macro(FetchContent_MakeAvailable) + + foreach(contentName IN ITEMS ${ARGV}) + string(TOLOWER ${contentName} contentNameLower) + FetchContent_GetProperties(${contentName}) + if(NOT ${contentNameLower}_POPULATED) + FetchContent_Populate(${contentName}) + + # Only try to call add_subdirectory() if the populated content + # can be treated that way. Protecting the call with the check + # allows this function to be used for projects that just want + # to ensure the content exists, such as to provide content at + # a known location. + if(EXISTS ${${contentNameLower}_SOURCE_DIR}/CMakeLists.txt) + add_subdirectory(${${contentNameLower}_SOURCE_DIR} + ${${contentNameLower}_BINARY_DIR}) + endif() + endif() + endforeach() + +endmacro() + diff --git a/cmake/FetchContent/CMakeLists.cmake.in b/cmake/FetchContent/CMakeLists.cmake.in new file mode 100644 index 00000000..244be7e0 --- /dev/null +++ b/cmake/FetchContent/CMakeLists.cmake.in @@ -0,0 +1,24 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION ${CMAKE_VERSION}) + +# We name the project and the target for the ExternalProject_Add() call +# to something that will highlight to the user what we are working on if +# something goes wrong and an error message is produced. + +project(${contentName}-populate NONE) + +include(ExternalProject) +ExternalProject_Add(${contentName}-populate + ${ARG_EXTRA} + SOURCE_DIR "${ARG_SOURCE_DIR}" + BINARY_DIR "${ARG_BINARY_DIR}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" + USES_TERMINAL_DOWNLOAD YES + USES_TERMINAL_UPDATE YES +) + diff --git a/cmake/LICENSE.FetchContent b/cmake/LICENSE.FetchContent new file mode 100644 index 00000000..cb53a95f --- /dev/null +++ b/cmake/LICENSE.FetchContent @@ -0,0 +1,132 @@ +CMake - Cross Platform Makefile Generator +Copyright 2000-2019 Kitware, Inc. and Contributors +All rights reserved. + +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 Kitware, Inc. nor the names of 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 +HOLDER 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. + +------------------------------------------------------------------------------ + +The following individuals and institutions are among the Contributors: + +* Aaron C. Meadows +* Adriaan de Groot +* Aleksey Avdeev +* Alexander Neundorf +* Alexander Smorkalov +* Alexey Sokolov +* Alex Merry +* Alex Turbov +* Andreas Pakulat +* Andreas Schneider +* André Rigland Brodtkorb +* Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf +* Benjamin Eikel +* Bjoern Ricks +* Brad Hards +* Christopher Harvey +* Christoph Grüninger +* Clement Creusot +* Daniel Blezek +* Daniel Pfeifer +* Enrico Scholz +* Eran Ifrah +* Esben Mose Hansen, Ange Optimization ApS +* Geoffrey Viola +* Google Inc +* Gregor Jasny +* Helio Chissini de Castro +* Ilya Lavrenov +* Insight Software Consortium +* Jan Woetzel +* Julien Schueller +* Kelly Thompson +* Laurent Montel +* Konstantin Podsvirov +* Mario Bensi +* Martin Gräßlin +* Mathieu Malaterre +* Matthaeus G. Chajdas +* Matthias Kretz +* Matthias Maennich +* Michael Hirsch, Ph.D. +* Michael Stürmer +* Miguel A. Figueroa-Villanueva +* Mike Jackson +* Mike McQuaid +* Nicolas Bock +* Nicolas Despres +* Nikita Krupen'ko +* NVIDIA Corporation +* OpenGamma Ltd. +* Patrick Stotko +* Per Øyvind Karlsen +* Peter Collingbourne +* Petr Gotthard +* Philip Lowman +* Philippe Proulx +* Raffi Enficiaud, Max Planck Society +* Raumfeld +* Roger Leigh +* Rolf Eike Beer +* Roman Donchenko +* Roman Kharitonov +* Ruslan Baratov +* Sebastian Holtermann +* Stephen Kelly +* Sylvain Joubert +* Thomas Sondergaard +* Tobias Hunger +* Todd Gamblin +* Tristan Carel +* University of Dundee +* Vadim Zhukov +* Will Dicharry + +See version control history for details of individual contributions. + +The above copyright and license notice applies to distributions of +CMake in source and binary form. Third-party software packages supplied +with CMake under compatible licenses provide their own copyright notices +documented in corresponding subdirectories or source files. + +------------------------------------------------------------------------------ + +CMake was initially developed by Kitware with the following sponsorship: + + * National Library of Medicine at the National Institutes of Health + as part of the Insight Segmentation and Registration Toolkit (ITK). + + * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel + Visualization Initiative. + + * National Alliance for Medical Image Computing (NAMIC) is funded by the + National Institutes of Health through the NIH Roadmap for Medical Research, + Grant U54 EB005149. + + * Kitware, Inc. + diff --git a/cmake/darknet_vendor-config.cmake.in b/cmake/darknet_vendor-config.cmake.in new file mode 100644 index 00000000..52f932d1 --- /dev/null +++ b/cmake/darknet_vendor-config.cmake.in @@ -0,0 +1,20 @@ +@PACKAGE_INIT@ + +find_package(Threads) + +if(@DARKNET_OPENCV@) + find_package(OpenCV REQUIRED) +endif() + +# Export targets for modern-style CMake code +if(NOT TARGET darknet_vendor::darknet_vendor) + include("@PACKAGE_SHARE_CMAKE_INSTALL_DIR@/darknet_vendor-targets.cmake") +endif() + +# Set standard variables for old-style CMake code +set_and_check(darknet_vendor_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@") +set(darknet_vendor_LIBRARIES "darknet_vendor::darknet_vendor") +set_and_check(darknet_vendor_EXECUTABLE "@PACKAGE_EXEC_INSTALL_DIR@/darknet") +set(darknet_vendor_VERSION_MAJOR "@PROJECT_VERSION_MAJOR@") +set(darknet_vendor_VERSION_MINOR "@PROJECT_VERSION_MINOR@") +set(darknet_vendor_VERSION_PATCH "@PROJECT_VERSION_PATCH@") diff --git a/include/darknet_vendor/darknet_vendor.h b/include/darknet_vendor/darknet_vendor.h new file mode 100644 index 00000000..0543b1dc --- /dev/null +++ b/include/darknet_vendor/darknet_vendor.h @@ -0,0 +1,32 @@ +// Copyright 2019 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef DARKNET_VENDOR__DARKNET_VENDOR_H_ +#define DARKNET_VENDOR__DARKNET_VENDOR_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#ifdef __cplusplus +} +#endif + + +#endif // DARKNET_VENDOR__DARKNET_VENDOR_H_ + diff --git a/include/darknet_vendor/version.h.in b/include/darknet_vendor/version.h.in new file mode 100644 index 00000000..9d3c0683 --- /dev/null +++ b/include/darknet_vendor/version.h.in @@ -0,0 +1,24 @@ +// Copyright 2019 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef DARKNET_VENDOR__DARKNET_VERSION_H_ +#define DARKNET_VENDOR__DARKNET_VERSION_H_ + +#define DARKNET_VENDOR_MAJOR_VERSION @PROJECT_VERSION_MAJOR@ +#define DARKNET_VENDOR_MINOR_VERSION @PROJECT_VERSION_MINOR@ +#define DARKNET_VENDOR_PATCH_VERSION @PROJECT_VERSION_PATCH@ + +#define DARKNET_GIT_TAG "@darknet_git_tag@" + +#endif // DARKNET_VENDOR__DARKNET_VERSION_H_ diff --git a/package.xml b/package.xml new file mode 100644 index 00000000..0f8ec10b --- /dev/null +++ b/package.xml @@ -0,0 +1,26 @@ + + + darknet_vendor + 0.1.0 + CMake wrapper around darknet, an open source neural network framework. + + Shane Loretz + Shane Loretz + + Apache License 2.0 + + cmake + git + + libopencv-dev + + + nvidia-cuda-dev + + + nvidia-cuda + + + cmake + + From 4ad6ed7b0a11ded66eee3d25a1fa4f7411d47dea Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Fri, 4 Oct 2019 16:05:31 -0700 Subject: [PATCH 3/6] Initial readme draft (#2) * Initial readme draft Signed-off-by: Shane Loretz * Add USING section Signed-off-by: Shane Loretz * Make it more clear what definitions do Signed-off-by: Shane Loretz --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/README.md b/README.md index e69de29b..ad1d2c49 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,68 @@ +# darknet_vendor + +This is a CMake wrapper around [darknet](https://pjreddie.com/darknet), an open source neural network framework. + +# Building + +``` +cd darknet_vendor/ +mkdir build/ +cd build/ +cmake -DCMAKE_BUILD_TYPE=Release .. +make +``` + +The package offers two CMake options to control how it is built. + +* `DARKNET_CUDA` (default: `On`) - Whether or not to build with CUDA support +* `DARKNET_OPENCV` (default: `On`) - Whether or not to build with OpenCV support + +These can be disabled prior to compiling if you don't need either of those dependencies. + +``` +cmake -DDARKNET_CUDA=Off -DDARKNET_OPENCV=Off .. +``` + +# ROS 2 and Colcon + +The package includes `package.xml` and should build fine using ROS 2 Dashing. + +``` +colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release --packages-select darknet_vendor +``` + +# Using darknet + +If you are using `ament_cmake`, use `ament_target_dependencies()` as normal. + +```CMake + +find_package(darknet_vendor REQUIRED) + +#... + +ament_target_dependencies(my_library_or_executable_target + darknet_vendor) +``` + +Otherwise, use the exported target `darknet_vendor::darknet_vendor` + +```CMake +find_package(darknet_vendor REQUIRED) + +#... + +target_link_libraries(my_library_or_executable_target PUBLIC darknet_vendor::darknet_vendor) +``` + +Then include the `darknet.h` header in your project to make darknet functions available. + +```C +#include +``` + +Alternatively, include `darknet_vendor/darknet_vendor.h` to get preprocessor definitions with info about the installed `darknet_vendor` version. + +```C +#include +``` From c8d68fbe1e3c1d74c9e3837b2c9a256546fada9d Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 9 Oct 2019 11:08:29 -0700 Subject: [PATCH 4/6] Fix cuda build downstream (#4) * Cuda flags should not be exported to downstream targets Signed-off-by: Shane Loretz * Fix c linkage with C++ cuda code Signed-off-by: Shane Loretz --- CMakeLists.txt | 2 +- include/darknet_vendor/darknet_vendor.h | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 868da894..d66643c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,7 +163,7 @@ if(DARKNET_CUDA) endif() add_library(darknet SHARED ${darknet_lib_c_sources} ${darknet_lib_cpp_sources} ${darknet_cuda_sources}) - target_compile_options(darknet INTERFACE + target_compile_options(darknet PRIVATE $<$:${DARKNET_VENDOR_CUDA_FLAGS}> ) target_compile_definitions(darknet PUBLIC GPU=1) diff --git a/include/darknet_vendor/darknet_vendor.h b/include/darknet_vendor/darknet_vendor.h index 0543b1dc..862aa895 100644 --- a/include/darknet_vendor/darknet_vendor.h +++ b/include/darknet_vendor/darknet_vendor.h @@ -15,18 +15,8 @@ #ifndef DARKNET_VENDOR__DARKNET_VENDOR_H_ #define DARKNET_VENDOR__DARKNET_VENDOR_H_ -#ifdef __cplusplus -extern "C" -{ -#endif - #include #include -#ifdef __cplusplus -} -#endif - - #endif // DARKNET_VENDOR__DARKNET_VENDOR_H_ From 7f9693b325ce2c3bc43f763168b2da662490b240 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Fri, 6 Mar 2020 12:03:17 -0500 Subject: [PATCH 5/6] Ament index marker (#3) * Add ament_index marker file Signed-off-by: Shane Loretz * Install ament index marker Signed-off-by: Shane Loretz --- CMakeLists.txt | 8 ++++++++ resource/darknet_vendor | 0 2 files changed, 8 insertions(+) create mode 100644 resource/darknet_vendor diff --git a/CMakeLists.txt b/CMakeLists.txt index d66643c5..54ab11ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -307,6 +307,14 @@ install( "share/darknet" ) +# Add an entry to the ament index +install( + FILES + resource/darknet_vendor + DESTINATION + "share/ament_index/resource_index/packages/" +) + # Install license files install( FILES diff --git a/resource/darknet_vendor b/resource/darknet_vendor new file mode 100644 index 00000000..e69de29b From 4d609295280bf9b50cde69bb9a483a8db839ba0b Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Fri, 6 Mar 2020 16:13:56 -0500 Subject: [PATCH 6/6] Include FetchContent on CMake >= 3.11 (#6) Fixes #5 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54ab11ae..c19cf58b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ option(DARKNET_OPENCV "Build darknet with OpenCV support" ON) if(CMAKE_VERSION VERSION_LESS "3.11") include("cmake/FetchContent.cmake") +else() + include(FetchContent) endif() # Same version as Debian Buster