Squashed 'libs/CommService/' content from commit 7ccc0fc
git-subtree-dir: libs/CommService git-subtree-split: 7ccc0fce88bbc5969df060058cf0fb57abe3bcf9
This commit is contained in:
3
libs/libbattle-com/.gitignore
vendored
Normal file
3
libs/libbattle-com/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
build
|
||||
src/config.hpp
|
||||
include/BC/endianess.hpp
|
||||
5
libs/libbattle-com/.gitreview
Normal file
5
libs/libbattle-com/.gitreview
Normal file
@@ -0,0 +1,5 @@
|
||||
[gerrit]
|
||||
host=webserver.ftewa.ti.unibw-hamburg.de
|
||||
port=29418
|
||||
project=libbattle-com
|
||||
defaultbranch=master
|
||||
140
libs/libbattle-com/CMakeLists.txt
Normal file
140
libs/libbattle-com/CMakeLists.txt
Normal file
@@ -0,0 +1,140 @@
|
||||
cmake_minimum_required (VERSION 3.1 FATAL_ERROR)
|
||||
project (libbattle-com++ VERSION 0.1.0 LANGUAGES CXX C)
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
|
||||
include(defaultOptions)
|
||||
|
||||
# export compile commands to json file to be used by atom c++ ide (clangd)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||
|
||||
IF(NOT TARGET Catch2)
|
||||
add_subdirectory(libs/Catch2 EXCLUDE_FROM_ALL)
|
||||
include(libs/Catch2/contrib/Catch.cmake)
|
||||
ENDIF()
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
|
||||
|
||||
# generate project specific configuration file
|
||||
configure_file(${PROJECT_SOURCE_DIR}/src/config.hpp.in ${PROJECT_SOURCE_DIR}/src/config.hpp @ONLY)
|
||||
|
||||
#generate global endianess config file
|
||||
configure_file(${PROJECT_SOURCE_DIR}/include/BC/endianess.hpp.in ${PROJECT_SOURCE_DIR}/include/BC/endianess.hpp @ONLY)
|
||||
|
||||
|
||||
add_library(bc STATIC
|
||||
include/BC/BC.hpp
|
||||
include/BC/Message.hpp
|
||||
include/BC/receiveable.hpp
|
||||
include/BC/transmittable.hpp
|
||||
include/BC/BasicService.hpp
|
||||
include/BC/SimpleServiceUDP.hpp
|
||||
include/BC/Payloads/HotPlugJoin.hpp
|
||||
include/BC/Payloads/HotPlugLeave.hpp
|
||||
include/BC/Payloads/Ping.hpp
|
||||
include/BC/Payloads/Pong.hpp
|
||||
include/BC/BasicMessageQueue.hpp
|
||||
include/BC/BasicQueueReceiver.hpp
|
||||
src/convert/stringConvert.cpp
|
||||
src/Message.cpp
|
||||
src/BasicService.cpp
|
||||
src/SimpleServiceUDP.cpp
|
||||
src/config.hpp
|
||||
src/Payloads/HotPlugJoin.cpp
|
||||
src/Payloads/HotPlugLeave.cpp
|
||||
src/Payloads/Ping.cpp
|
||||
src/Payloads/Pong.cpp
|
||||
src/BasicMessageQueue.cpp
|
||||
src/BasicQueueReceiver.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(bc ${CMAKE_THREAD_LIBS_INIT})
|
||||
IF (MINGW)
|
||||
target_link_libraries(bc -static-libstdc++ -static-libgcc -static ws2_32 winpthread -dynamic)
|
||||
ENDIF()
|
||||
|
||||
target_include_directories(bc PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
PRIVATE src
|
||||
libs/CRCpp/inc
|
||||
)
|
||||
|
||||
add_executable(bccli
|
||||
bccli/main.cpp
|
||||
bccli/testservice/testservice.hpp
|
||||
bccli/testservice/testservice.cpp
|
||||
bccli/ping/ping.hpp
|
||||
bccli/ping/ping.cpp
|
||||
)
|
||||
target_link_libraries(bccli bc)
|
||||
|
||||
target_include_directories(bccli
|
||||
PRIVATE bccli
|
||||
libs/CLI11/include
|
||||
src
|
||||
)
|
||||
|
||||
|
||||
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
target_compile_options(bc PUBLIC -Wall -g -O0 -fPIC)
|
||||
target_compile_options(bccli PUBLIC -Wall -g -O0)
|
||||
ELSE()
|
||||
IF(CMAKE_BUILD_TYPE MATCHES COVERAGE)
|
||||
target_compile_options(bc PUBLIC -g -O0 --coverage -fprofile-arcs -ftest-coverage -fPIC)
|
||||
set_target_properties(bc PROPERTIES LINK_FLAGS "-fprofile-arcs")
|
||||
target_compile_options(bccli PUBLIC -g -O0 --coverage -fprofile-arcs -ftest-coverage)
|
||||
set_target_properties(bccli PROPERTIES LINK_FLAGS "-fprofile-arcs")
|
||||
ELSE()
|
||||
target_compile_options(bc PUBLIC -O4 -fPIC)
|
||||
target_compile_options(bccli PUBLIC -O4)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Everything TEST related
|
||||
#
|
||||
option(TEST_LIBBATTLE_COM "Turn running of libbattle-com specific tests off" ON)
|
||||
|
||||
IF (${TEST_LIBBATTLE_COM})
|
||||
|
||||
add_my_test(TEST test_simple_conversion
|
||||
SOURCES tests/test_simple_conversion.cpp
|
||||
LIBS bc
|
||||
)
|
||||
|
||||
add_my_test(TEST test_simple_service_udp
|
||||
SOURCES tests/test_simple_service_udp.cpp
|
||||
LIBS bc
|
||||
)
|
||||
|
||||
add_executable(test_basic_queue_receiver tests/test_basic_queue_receiver.cpp)
|
||||
target_link_libraries(test_basic_queue_receiver Catch2::Catch2 bc)
|
||||
catch_discover_tests(test_basic_queue_receiver)
|
||||
|
||||
add_executable(test_basic_message_queue tests/test_basic_message_queue.cpp)
|
||||
target_link_libraries(test_basic_message_queue Catch2::Catch2 bc)
|
||||
catch_discover_tests(test_basic_message_queue)
|
||||
|
||||
|
||||
get_property(_mytests GLOBAL PROPERTY _mytests)
|
||||
FOREACH( _test ${_mytests})
|
||||
target_include_directories(${_test} PRIVATE src )
|
||||
|
||||
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
target_compile_options(${_test} PUBLIC -Wall -g -O0)
|
||||
ELSE()
|
||||
IF(CMAKE_BUILD_TYPE MATCHES COVERAGE)
|
||||
target_compile_options(${_test} PUBLIC -g -O0 --coverage -fprofile-arcs -ftest-coverage)
|
||||
set_target_properties(${_test} PROPERTIES LINK_FLAGS "-fprofile-arcs")
|
||||
ELSE()
|
||||
target_compile_options(${_test} PUBLIC -O4)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
|
||||
ENDIF()
|
||||
33
libs/libbattle-com/Jenkinsfile
vendored
Normal file
33
libs/libbattle-com/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
@Library('ftewa-jenkins-library@main') _
|
||||
import de.hsuhh.ti.jenkins.*
|
||||
|
||||
|
||||
p = new Pipelines()
|
||||
|
||||
p.FTEWAPipeline {
|
||||
name = "libbattle-com"
|
||||
gcc6 = false
|
||||
gcc7 = true
|
||||
gcc8 = true
|
||||
clang6 = false
|
||||
clang7 = true
|
||||
buildLinux = true
|
||||
buildWindows = false
|
||||
buildWine = false
|
||||
buildMacOS = false
|
||||
notifyFail = true
|
||||
notifySuccess = false
|
||||
runCPPCHECK = true
|
||||
runCodeChecker= true
|
||||
runValgrind = true
|
||||
origins = [
|
||||
'ssh://git@dev-gitea.ftewa.ti.unibw-hamburg.de:12000/CombatManagementSystem/libbattle-com.git',
|
||||
]
|
||||
dependencies =
|
||||
[
|
||||
cmake : [
|
||||
url : "ssh://git@dev-gitea.ftewa.ti.unibw-hamburg.de:12000/Tools/cmake.git",
|
||||
branch : "main"
|
||||
],
|
||||
]
|
||||
}
|
||||
373
libs/libbattle-com/LICENSE
Normal file
373
libs/libbattle-com/LICENSE
Normal file
@@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
55
libs/libbattle-com/README.md
Normal file
55
libs/libbattle-com/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# libbattle-com++
|
||||
![alt text][status]![alt text][high]![alt text][medium]![alt text][low]![alt text][unspecified]
|
||||
|
||||
[status]: https://jenkins-new.ftewa.ti.unibw-hamburg.de/job/FTEWA/job/libbattle-com/job/main/badge/icon
|
||||
[high]: https://tiweb.hsu-hh.de/build-status/libbattle-com_master_high.svg
|
||||
[medium]: https://tiweb.hsu-hh.de/build-status/libbattle-com_master_medium.svg
|
||||
[low]: https://tiweb.hsu-hh.de/build-status/libbattle-com_master_low.svg
|
||||
[unspecified]: https://tiweb.hsu-hh.de/build-status/libbattle-com_master_unspecified.svg
|
||||
## Description
|
||||
|
||||
libbattle-com++ is a c++ library for implementing a publish/subscribe based network infratructure.
|
||||
The main programming API is totally network- and transport-layer independent.
|
||||
|
||||
## Features
|
||||
|
||||
- publish/ subscribe based programming API
|
||||
- implementation of a UDP based protocol backend
|
||||
|
||||
### Planned backends
|
||||
|
||||
- LNK16 support
|
||||
- HLA support
|
||||
- DIS support
|
||||
|
||||
## Authors
|
||||
|
||||
### Lead Engineer
|
||||
- Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
|
||||
### Developers
|
||||
- Christina Sander <christina.sander@hsu-hh.de>
|
||||
|
||||
### Military Classfication
|
||||
|
||||
UNCLASSIFIED
|
||||
|
||||
## License
|
||||
|
||||
MPL v2.0
|
||||
|
||||
## Building
|
||||
|
||||
### Release
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make all
|
||||
- make test
|
||||
|
||||
### Debugging
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=DEBUG ..
|
||||
- make all
|
||||
- make test
|
||||
49
libs/libbattle-com/bccli/main.cpp
Normal file
49
libs/libbattle-com/bccli/main.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <BC/BC.hpp>
|
||||
#include <testservice/testservice.hpp>
|
||||
#include <ping/ping.hpp>
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::string broadcastAddress="127.0.0.255";
|
||||
std::string srcAddress="127.0.0.1";
|
||||
unsigned short port = 8888;
|
||||
// which devices we want to reach, default all
|
||||
BC::DataTypes::deviceIdType destination = 0;
|
||||
|
||||
CLI::App app("Command line tool for interacting with libbattle-com++");
|
||||
app.require_subcommand(1);
|
||||
|
||||
// command line options for testservice command
|
||||
auto testservice = app.add_subcommand("testservice", "start a battle-com service but to not subscribe to anything.");
|
||||
testservice->add_option("-b",broadcastAddress,"the broadcast address to use for the pub/sub service (Default: 127.0.0.255)");
|
||||
testservice->add_option("-s",srcAddress,"the source address to use for the pub/sub service (Default: 127.0.0.1 )");
|
||||
testservice->add_option("-p",port,"the broadcast port to use for the pub/sub service (Default: 8888)");
|
||||
|
||||
testservice->callback( [&](){
|
||||
BCCLI::testservice(broadcastAddress, srcAddress, port);
|
||||
});
|
||||
|
||||
|
||||
// command line options for ping command
|
||||
auto ping = app.add_subcommand("ping", "ping another service and print round trip times");
|
||||
ping->add_option("-b",broadcastAddress,"the broadcast address to use for the pub/sub service (Default: 127.0.0.255)");
|
||||
ping->add_option("-s",srcAddress,"the source address to use for the pub/sub service (Default: 127.0.0.1 )");
|
||||
ping->add_option("-p",port,"the broadcast port to use for the pub/sub service (Default: 8888)");
|
||||
ping->add_option("-d",destination,"the destionation to ping (Default: allDevices)");
|
||||
|
||||
ping->callback( [&](){
|
||||
BCCLI::ping(broadcastAddress, srcAddress, port,destination);
|
||||
});
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
179
libs/libbattle-com/bccli/ping/ping.cpp
Normal file
179
libs/libbattle-com/bccli/ping/ping.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief implementation file for the ping subcommand of the cmscli application
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-01-07
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <ping/ping.hpp>
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/SimpleServiceUDP.hpp>
|
||||
#include <BC/Message.hpp>
|
||||
#include <BC/Payloads/Ping.hpp>
|
||||
#include <BC/Payloads/Pong.hpp>
|
||||
#include <BC/receiveable.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __MINGW64__
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/// variable for stopping sending pings
|
||||
bool running=true;
|
||||
|
||||
/*
|
||||
* signal handler for Ctrl-C
|
||||
*/
|
||||
#ifdef __MINGW64__
|
||||
BOOL WINAPI killHandlerPing(DWORD dwType)
|
||||
{
|
||||
switch(dwType) {
|
||||
case CTRL_C_EVENT:
|
||||
running=false;
|
||||
break;
|
||||
case CTRL_BREAK_EVENT:
|
||||
running=false;
|
||||
break;
|
||||
default:
|
||||
printf("Some other event\n");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
void killHandlerPing(int s){
|
||||
|
||||
if (s == SIGINT)
|
||||
{
|
||||
running=false;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief receiver for pong messages
|
||||
*/
|
||||
class pongReceiver : public BC::receiveable
|
||||
{
|
||||
private:
|
||||
/// last received sequence number for identifying missing messages
|
||||
uint64_t lastSequenceNumber=0;
|
||||
|
||||
/// number of missing messages
|
||||
uint32_t missing;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief constructor for initializing member attributes
|
||||
*/
|
||||
pongReceiver() : lastSequenceNumber(0), missing(0), transmitted(0),nrMessages(0) {}
|
||||
|
||||
/// number of transmitted messages
|
||||
uint64_t transmitted;
|
||||
|
||||
/// number of received messages
|
||||
uint32_t nrMessages;
|
||||
|
||||
/// callback for receiving messages
|
||||
void receive(BC::Message *m) override
|
||||
{
|
||||
BC::Payloads::Pong pong(m->getRawData());
|
||||
nrMessages++;
|
||||
|
||||
if (lastSequenceNumber > 0 && pong.sequenceNr != lastSequenceNumber )
|
||||
{
|
||||
missing++;
|
||||
}
|
||||
|
||||
//claculate latency
|
||||
float latency = (float) (m->receptionTime - pong.pingTransmissionTime)/ (float)1000000.0;
|
||||
|
||||
std::cout << m->size() << " bytes from " << m->sourceID<<": seq="<< pong.sequenceNr << " time=" << std::setprecision(3) << latency << " ms" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief function implemting the ping subcommand
|
||||
*/
|
||||
void BCCLI::ping(const std::string &broadcastAddress, const std::string &srcAddress, unsigned short port, BC::DataTypes::deviceIdType dest)
|
||||
{
|
||||
// die if no destination is given
|
||||
if (dest == 0)
|
||||
{
|
||||
std::cerr << "Fatal Error: a valid destination address is mandatory" << std::endl;
|
||||
throw(CLI::RuntimeError(-1));
|
||||
}
|
||||
|
||||
// initialize the signal handler
|
||||
#ifdef __MINGW64__
|
||||
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)killHandlerPing,TRUE)) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
struct sigaction sigIntHandler;
|
||||
sigIntHandler.sa_handler = killHandlerPing;
|
||||
sigemptyset(&sigIntHandler.sa_mask);
|
||||
sigIntHandler.sa_flags = 0;
|
||||
sigaction(SIGINT, &sigIntHandler, NULL);
|
||||
#endif
|
||||
|
||||
// fetch us required random number device
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
|
||||
// set the distribution range of the numbers
|
||||
std::uniform_int_distribution<uint64_t> dist(UINT16_MAX, UINT32_MAX);
|
||||
|
||||
// instantiate a receiver
|
||||
pongReceiver pR;
|
||||
|
||||
// create a service to send pings and receive pongs
|
||||
BC::SimpleServiceUDP service(dist(mt), BC::DataTypes::deviceMajorType::UNKNOWN, "bccli ping service",port, broadcastAddress, srcAddress);
|
||||
|
||||
// subscribe to pong messages only
|
||||
service.subscribe(&pR,BC::Constants::cManagementDomain,BC::Constants::cPong);
|
||||
service.connect();
|
||||
|
||||
// create the base ping message
|
||||
BC::Message msg;
|
||||
msg.domain=BC::Constants::cManagementDomain;
|
||||
msg.topic=BC::Constants::cPing;
|
||||
msg.destinationID=dest;
|
||||
BC::Payloads::Ping ping;
|
||||
msg.setData(ping);
|
||||
|
||||
std::cout << "ping " << dest << " " << msg.size() << " bytes of data" << std::endl;
|
||||
|
||||
int seq=0;
|
||||
while(running) {
|
||||
// update ping message and payload
|
||||
ping.sequenceNr=seq;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> now = std::chrono::high_resolution_clock::now();
|
||||
ping.pingTime=std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
|
||||
msg.setData(ping);
|
||||
|
||||
// publish message
|
||||
service.publish(msg);
|
||||
pR.transmitted++;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
seq++;
|
||||
}
|
||||
service.disconnect();
|
||||
std::cout << "--- " << dest << " ping statistics ---" << std::endl;
|
||||
std::cout << pR.transmitted << " messages transmitted, " << pR.nrMessages << " received " << std::endl;
|
||||
}
|
||||
23
libs/libbattle-com/bccli/ping/ping.hpp
Normal file
23
libs/libbattle-com/bccli/ping/ping.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef __BCCLI_PING_HPP__
|
||||
#define __BCCLI_PING_HPP__
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief header file for the ping subcommand of the bccli application
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-07
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <string>
|
||||
#include <BC/BC.hpp>
|
||||
|
||||
namespace BCCLI
|
||||
{
|
||||
void ping(const std::string &broadcastAddress, const std::string &srcAddress, unsigned short port, BC::DataTypes::deviceIdType dest);
|
||||
};
|
||||
|
||||
#endif
|
||||
116
libs/libbattle-com/bccli/testservice/testservice.cpp
Normal file
116
libs/libbattle-com/bccli/testservice/testservice.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief implementation file for the testservice subcommand of the bccli application
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-01-06
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <testservice/testservice.hpp>
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/SimpleServiceUDP.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <signal.h>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
|
||||
#ifdef __MINGW64__
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/// variable for stopping sending pings
|
||||
bool runningTestService=true;
|
||||
|
||||
|
||||
/*
|
||||
* signal handler for Ctrl-C
|
||||
*/
|
||||
#ifdef __MINGW64__
|
||||
BOOL WINAPI killHandlerTestservice(DWORD dwType)
|
||||
{
|
||||
switch(dwType) {
|
||||
case CTRL_C_EVENT:
|
||||
runningTestService=false;
|
||||
break;
|
||||
case CTRL_BREAK_EVENT:
|
||||
runningTestService=false;
|
||||
break;
|
||||
default:
|
||||
printf("Some other event\n");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
void killHandlerTestservice(int s){
|
||||
|
||||
if (s == SIGINT)
|
||||
{
|
||||
runningTestService=false;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* message receiver class
|
||||
*/
|
||||
void BCCLI::testService::receiver::receive(BC::Message *m)
|
||||
{
|
||||
// print simple information about message
|
||||
std::cout << std::setw(10) << m->sourceID;
|
||||
std::cout << " ";
|
||||
std::cout << std::setw(10) << m->destinationID;
|
||||
std::cout << std::setw(20) << m->domain;
|
||||
std::cout << " ";
|
||||
std::cout << std::setw(20) << m->topic;
|
||||
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void BCCLI::testservice(const std::string &broadcastAddress, const std::string &srcAddress, unsigned short port)
|
||||
{
|
||||
// initialize the signal handler
|
||||
#ifdef __MINGW64__
|
||||
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)killHandlerTestservice,TRUE)) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
struct sigaction sigIntHandler;
|
||||
sigIntHandler.sa_handler = killHandlerTestservice;
|
||||
sigemptyset(&sigIntHandler.sa_mask);
|
||||
sigIntHandler.sa_flags = 0;
|
||||
sigaction(SIGINT, &sigIntHandler, NULL);
|
||||
#endif
|
||||
|
||||
BCCLI::testService::receiver r;
|
||||
|
||||
// fetch us required random number device
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
|
||||
// set the distribution range of the numbers
|
||||
std::uniform_int_distribution<uint64_t> dist(UINT16_MAX, UINT32_MAX);
|
||||
|
||||
BC::DataTypes::deviceIdType id = dist(mt);
|
||||
|
||||
std::cout << "Starting Test Service at id "<< id << std::endl;
|
||||
BC::SimpleServiceUDP service(id, BC::DataTypes::deviceMajorType::UNKNOWN, "bccli test service",port, broadcastAddress, srcAddress);
|
||||
service.subscribe(&r,BC::Constants::cAllDomains, BC::Constants::cAllTopics);
|
||||
service.connect();
|
||||
|
||||
std::cout << "Stop service with CTRL-C" << std::endl;
|
||||
|
||||
while(runningTestService)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
|
||||
service.disconnect();
|
||||
std::cout << "Test Service stopped" << std::endl;
|
||||
}
|
||||
34
libs/libbattle-com/bccli/testservice/testservice.hpp
Normal file
34
libs/libbattle-com/bccli/testservice/testservice.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef __BCCLI_TESTSERVICE_HPP__
|
||||
#define __BCCLI_TESTSERVICE_HPP__
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief header file for the testservice subcommand of the bccli application
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-06
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <string>
|
||||
#include <BC/receiveable.hpp>
|
||||
|
||||
namespace BCCLI
|
||||
{
|
||||
void testservice(const std::string &broadcastAddress, const std::string &srcAddress, unsigned short port);
|
||||
|
||||
namespace testService
|
||||
{
|
||||
|
||||
class receiver : public BC::receiveable
|
||||
{
|
||||
public:
|
||||
void receive(BC::Message *m) override;
|
||||
};
|
||||
|
||||
}; // namespace testService
|
||||
};
|
||||
|
||||
#endif
|
||||
59
libs/libbattle-com/cmake/Jenkinsfile
vendored
Normal file
59
libs/libbattle-com/cmake/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
@Library('ftewa-jenkins-library@main') _
|
||||
|
||||
@NonCPS
|
||||
def getPipelineJobNames() {
|
||||
Hudson.instance.getAllItems(org.jenkinsci.plugins.workflow.job.WorkflowJob)*.fullName
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
def triggerJobs() {
|
||||
def jobs = getPipelineJobNames();
|
||||
|
||||
for (job in jobs)
|
||||
{
|
||||
echo "Trigger ${job}"
|
||||
if (job.contains("Integration"))
|
||||
{
|
||||
build job: job,
|
||||
parameters: [
|
||||
string(name: 'REPO_NAME', value: "cmake"),
|
||||
string(name: 'TAG', value: "main")
|
||||
],
|
||||
wait: false
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
kubernetes {
|
||||
//workspaceVolume: dynamicPVC(accessModes: 'ReadWriteOnce', requestsSize: '20G', storageClassName: 'csi-rbd-sc')
|
||||
yaml libraryResource("files/pod-build.yml")
|
||||
defaultContainer 'clang-build'
|
||||
}
|
||||
} // agent
|
||||
options {
|
||||
// Only keep the 1 most recent builds
|
||||
buildDiscarder(logRotator(numToKeepStr: "1"))
|
||||
}
|
||||
|
||||
|
||||
stages {
|
||||
|
||||
stage("Build")
|
||||
{
|
||||
|
||||
steps {
|
||||
echo "build"
|
||||
triggerJobs()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // stage("Build")
|
||||
|
||||
}
|
||||
}
|
||||
1
libs/libbattle-com/cmake/Modules/CheckParent.cmake
Normal file
1
libs/libbattle-com/cmake/Modules/CheckParent.cmake
Normal file
@@ -0,0 +1 @@
|
||||
get_directory_property(hasParent PARENT_DIRECTORY)
|
||||
28
libs/libbattle-com/cmake/Modules/CppCheck.cmake
Normal file
28
libs/libbattle-com/cmake/Modules/CppCheck.cmake
Normal file
@@ -0,0 +1,28 @@
|
||||
option(CPPCHECK "Turns cppcheck processing on if executable is found." OFF)
|
||||
|
||||
find_program(CPPCHECK_PATH NAMES cppcheck)
|
||||
|
||||
# export compile commands to json file to be used by cppcheck
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||
set(CPPCHECK_COMPILE_COMMANDS "${CMAKE_BINARY_DIR}/compile_commands.json")
|
||||
|
||||
# output directory for codecheck analysis
|
||||
set(CPPCHECK_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/cppcheck_results)
|
||||
|
||||
if(CPPCHECK AND CPPCHECK_PATH AND NOT CPPCHECK_ADDED)
|
||||
|
||||
set(CPPCHECK_ADDED ON)
|
||||
|
||||
if (NOT TARGET cppcheck)
|
||||
|
||||
add_custom_target(cppcheck
|
||||
COMMAND rm -rf ${CPPCHECK_OUTPUT_DIRECTORY}\;
|
||||
mkdir -p ${CPPCHECK_OUTPUT_DIRECTORY}\;
|
||||
${CPPCHECK_PATH}
|
||||
--project=${CPPCHECK_COMPILE_COMMANDS}
|
||||
--plist-output=${CPPCHECK_OUTPUT_DIRECTORY}
|
||||
--enable=all
|
||||
--inline-suppr
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
76
libs/libbattle-com/cmake/Modules/FindGMP.cmake
Normal file
76
libs/libbattle-com/cmake/Modules/FindGMP.cmake
Normal file
@@ -0,0 +1,76 @@
|
||||
# Try to find the GMP library
|
||||
# https://gmplib.org/
|
||||
#
|
||||
# This module supports requiring a minimum version, e.g. you can do
|
||||
# find_package(GMP 6.0.0)
|
||||
# to require version 6.0.0 to newer of GMP.
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# GMP_FOUND - system has GMP lib with correct version
|
||||
# GMP_INCLUDES - the GMP include directory
|
||||
# GMP_LIBRARIES - the GMP library
|
||||
# GMP_VERSION - GMP version
|
||||
#
|
||||
# Copyright (c) 2016 Jack Poulson, <jack.poulson@gmail.com>
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
|
||||
find_path(GMP_INCLUDES NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR})
|
||||
|
||||
# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified
|
||||
if(NOT GMP_FIND_VERSION)
|
||||
if(NOT GMP_FIND_VERSION_MAJOR)
|
||||
set(GMP_FIND_VERSION_MAJOR 5)
|
||||
endif()
|
||||
if(NOT GMP_FIND_VERSION_MINOR)
|
||||
set(GMP_FIND_VERSION_MINOR 1)
|
||||
endif()
|
||||
if(NOT GMP_FIND_VERSION_PATCH)
|
||||
set(GMP_FIND_VERSION_PATCH 0)
|
||||
endif()
|
||||
set(GMP_FIND_VERSION
|
||||
"${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}")
|
||||
endif()
|
||||
|
||||
message("GMP_INCLUDES=${GMP_INCLUDES}")
|
||||
if(GMP_INCLUDES)
|
||||
# Since the GMP version macros may be in a file included by gmp.h of the form
|
||||
# gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them.
|
||||
file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h")
|
||||
foreach(gmp_header_filename ${GMP_HEADERS})
|
||||
file(READ "${gmp_header_filename}" _gmp_version_header)
|
||||
string(REGEX MATCH
|
||||
"define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match
|
||||
"${_gmp_version_header}")
|
||||
if(_gmp_major_version_match)
|
||||
set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)"
|
||||
_gmp_minor_version_match "${_gmp_version_header}")
|
||||
set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)"
|
||||
_gmp_patchlevel_version_match "${_gmp_version_header}")
|
||||
set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}")
|
||||
set(GMP_VERSION
|
||||
${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Check whether found version exists and exceeds the minimum requirement
|
||||
if(NOT GMP_VERSION)
|
||||
set(GMP_VERSION_OK FALSE)
|
||||
message(STATUS "GMP version was not detected")
|
||||
elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION})
|
||||
set(GMP_VERSION_OK FALSE)
|
||||
message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, "
|
||||
"but at least version ${GMP_FIND_VERSION} is required")
|
||||
else()
|
||||
set(GMP_VERSION_OK TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GMP DEFAULT_MSG
|
||||
GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK)
|
||||
mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES)
|
||||
25
libs/libbattle-com/cmake/Modules/FindValgrind.cmake
Normal file
25
libs/libbattle-com/cmake/Modules/FindValgrind.cmake
Normal file
@@ -0,0 +1,25 @@
|
||||
# Find Valgrind.
|
||||
#
|
||||
# This module defines:
|
||||
# VALGRIND_INCLUDE_DIR, where to find valgrind/memcheck.h, etc.
|
||||
# VALGRIND_PROGRAM, the valgrind executable.
|
||||
# VALGRIND_FOUND, If false, do not try to use valgrind.
|
||||
#
|
||||
# If you have valgrind installed in a non-standard place, you can define
|
||||
# VALGRIND_PREFIX to tell cmake where it is.
|
||||
#
|
||||
# NOTE: Copied from the opencog project, where it is distributed under the
|
||||
# terms of the New BSD License.
|
||||
|
||||
message(STATUS "Valgrind Prefix: ${VALGRIND_PREFIX}")
|
||||
|
||||
find_path(VALGRIND_INCLUDE_DIR valgrind/memcheck.h
|
||||
/usr/include /usr/local/include ${VALGRIND_PREFIX}/include)
|
||||
find_program(VALGRIND_PROGRAM NAMES valgrind PATH
|
||||
/usr/bin /usr/local/bin ${VALGRIND_PREFIX}/bin)
|
||||
|
||||
find_package_handle_standard_args(VALGRIND DEFAULT_MSG
|
||||
VALGRIND_INCLUDE_DIR
|
||||
VALGRIND_PROGRAM)
|
||||
|
||||
mark_as_advanced(VALGRIND_INCLUDE_DIR VALGRIND_PROGRAM)
|
||||
269
libs/libbattle-com/cmake/Modules/Findsodium.cmake
Normal file
269
libs/libbattle-com/cmake/Modules/Findsodium.cmake
Normal file
@@ -0,0 +1,269 @@
|
||||
# Written in 2016 by Henrik Steffen Gaßmann <henrik@gassmann.onl>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
#
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
#
|
||||
########################################################################
|
||||
# Tries to find the local libsodium installation.
|
||||
#
|
||||
# On Windows the sodium_DIR environment variable is used as a default
|
||||
# hint which can be overridden by setting the corresponding cmake variable.
|
||||
#
|
||||
# Once done the following variables will be defined:
|
||||
#
|
||||
# sodium_FOUND
|
||||
# sodium_INCLUDE_DIR
|
||||
# sodium_LIBRARY_DEBUG
|
||||
# sodium_LIBRARY_RELEASE
|
||||
#
|
||||
#
|
||||
# Furthermore an imported "sodium" target is created.
|
||||
#
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU"
|
||||
OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set(_GCC_COMPATIBLE 1)
|
||||
endif()
|
||||
|
||||
# static library option
|
||||
option(sodium_USE_STATIC_LIBS "enable to statically link against sodium")
|
||||
if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST))
|
||||
unset(sodium_LIBRARY CACHE)
|
||||
unset(sodium_LIBRARY_DEBUG CACHE)
|
||||
unset(sodium_LIBRARY_RELEASE CACHE)
|
||||
unset(sodium_DLL_DEBUG CACHE)
|
||||
unset(sodium_DLL_RELEASE CACHE)
|
||||
set(sodium_USE_STATIC_LIBS_LAST ${sodium_USE_STATIC_LIBS} CACHE INTERNAL "internal change tracking variable")
|
||||
endif()
|
||||
|
||||
|
||||
########################################################################
|
||||
# UNIX
|
||||
if (UNIX)
|
||||
# import pkg-config
|
||||
find_package(PkgConfig QUIET)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(sodium_PKG QUIET libsodium)
|
||||
endif()
|
||||
|
||||
if(sodium_USE_STATIC_LIBS)
|
||||
set(XPREFIX sodium_PKG_STATIC)
|
||||
else()
|
||||
set(XPREFIX sodium_PKG)
|
||||
endif()
|
||||
|
||||
find_path(sodium_INCLUDE_DIR sodium.h
|
||||
HINTS ${${XPREFIX}_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(sodium_LIBRARY_DEBUG NAMES ${${XPREFIX}_LIBRARIES} sodium
|
||||
HINTS ${${XPREFIX}_LIBRARY_DIRS}
|
||||
)
|
||||
find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES} sodium
|
||||
HINTS ${${XPREFIX}_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
|
||||
########################################################################
|
||||
# Windows
|
||||
elseif (WIN32)
|
||||
set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory")
|
||||
mark_as_advanced(sodium_DIR)
|
||||
|
||||
find_path(sodium_INCLUDE_DIR sodium.h
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
# detect target architecture
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.c" [=[
|
||||
#if defined _M_IX86
|
||||
#error ARCH_VALUE x86_32
|
||||
#elif defined _M_X64
|
||||
#error ARCH_VALUE x86_64
|
||||
#endif
|
||||
#error ARCH_VALUE unknown
|
||||
]=])
|
||||
try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/arch.c"
|
||||
OUTPUT_VARIABLE _COMPILATION_LOG
|
||||
)
|
||||
string(REGEX REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*" "\\1" _TARGET_ARCH "${_COMPILATION_LOG}")
|
||||
|
||||
# construct library path
|
||||
if (_TARGET_ARCH STREQUAL "x86_32")
|
||||
string(APPEND _PLATFORM_PATH "Win32")
|
||||
elseif(_TARGET_ARCH STREQUAL "x86_64")
|
||||
string(APPEND _PLATFORM_PATH "x64")
|
||||
else()
|
||||
message(FATAL_ERROR "the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake.")
|
||||
endif()
|
||||
string(APPEND _PLATFORM_PATH "/$$CONFIG$$")
|
||||
|
||||
if (MSVC_VERSION LESS 1900)
|
||||
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60")
|
||||
else()
|
||||
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50")
|
||||
endif()
|
||||
string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}")
|
||||
|
||||
if (sodium_USE_STATIC_LIBS)
|
||||
string(APPEND _PLATFORM_PATH "/static")
|
||||
else()
|
||||
string(APPEND _PLATFORM_PATH "/dynamic")
|
||||
endif()
|
||||
|
||||
string(REPLACE "$$CONFIG$$" "Debug" _DEBUG_PATH_SUFFIX "${_PLATFORM_PATH}")
|
||||
string(REPLACE "$$CONFIG$$" "Release" _RELEASE_PATH_SUFFIX "${_PLATFORM_PATH}")
|
||||
|
||||
find_library(sodium_LIBRARY_DEBUG libsodium.lib
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX}
|
||||
)
|
||||
find_library(sodium_LIBRARY_RELEASE libsodium.lib
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX}
|
||||
)
|
||||
if (NOT sodium_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll")
|
||||
find_library(sodium_DLL_DEBUG libsodium
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX}
|
||||
)
|
||||
find_library(sodium_DLL_RELEASE libsodium
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX}
|
||||
)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK})
|
||||
endif()
|
||||
|
||||
elseif(_GCC_COMPATIBLE)
|
||||
if (sodium_USE_STATIC_LIBS)
|
||||
find_library(sodium_LIBRARY_DEBUG libsodium.a
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
find_library(sodium_LIBRARY_RELEASE libsodium.a
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
else()
|
||||
find_library(sodium_LIBRARY_DEBUG libsodium.dll.a
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
find_library(sodium_LIBRARY_RELEASE libsodium.dll.a
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
|
||||
file(GLOB _DLL
|
||||
LIST_DIRECTORIES false
|
||||
RELATIVE "${sodium_DIR}/bin"
|
||||
"${sodium_DIR}/bin/libsodium*.dll"
|
||||
)
|
||||
find_library(sodium_DLL_DEBUG ${_DLL} libsodium
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES bin
|
||||
)
|
||||
find_library(sodium_DLL_RELEASE ${_DLL} libsodium
|
||||
HINTS ${sodium_DIR}
|
||||
PATH_SUFFIXES bin
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "this platform is not supported by FindSodium.cmake")
|
||||
endif()
|
||||
|
||||
|
||||
########################################################################
|
||||
# unsupported
|
||||
else()
|
||||
message(FATAL_ERROR "this platform is not supported by FindSodium.cmake")
|
||||
endif()
|
||||
|
||||
|
||||
########################################################################
|
||||
# common stuff
|
||||
|
||||
# extract sodium version
|
||||
if (sodium_INCLUDE_DIR)
|
||||
set(_VERSION_HEADER "${_INCLUDE_DIR}/sodium/version.h")
|
||||
if (EXISTS _VERSION_HEADER)
|
||||
file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT)
|
||||
string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_VERSION_STRING[ \t]*\"([^\n]*)\".*" "\\1"
|
||||
sodium_VERSION "${_VERSION_HEADER_CONTENT}")
|
||||
set(sodium_VERSION "${sodium_VERSION}" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# communicate results
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(sodium
|
||||
REQUIRED_VARS
|
||||
sodium_LIBRARY_RELEASE
|
||||
sodium_LIBRARY_DEBUG
|
||||
sodium_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
sodium_VERSION
|
||||
)
|
||||
|
||||
# mark file paths as advanced
|
||||
mark_as_advanced(sodium_INCLUDE_DIR)
|
||||
mark_as_advanced(sodium_LIBRARY_DEBUG)
|
||||
mark_as_advanced(sodium_LIBRARY_RELEASE)
|
||||
if (WIN32)
|
||||
mark_as_advanced(sodium_DLL_DEBUG)
|
||||
mark_as_advanced(sodium_DLL_RELEASE)
|
||||
endif()
|
||||
|
||||
# create imported target
|
||||
if(sodium_USE_STATIC_LIBS)
|
||||
set(_LIB_TYPE STATIC)
|
||||
else()
|
||||
set(_LIB_TYPE SHARED)
|
||||
endif()
|
||||
add_library(sodium ${_LIB_TYPE} IMPORTED)
|
||||
|
||||
set_target_properties(sodium PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${sodium_INCLUDE_DIR}"
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
)
|
||||
|
||||
if (sodium_USE_STATIC_LIBS)
|
||||
set_target_properties(sodium PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "SODIUM_STATIC"
|
||||
IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}"
|
||||
IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}"
|
||||
)
|
||||
else()
|
||||
if (UNIX)
|
||||
set_target_properties(sodium PROPERTIES
|
||||
IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}"
|
||||
IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}"
|
||||
)
|
||||
elseif (WIN32)
|
||||
set_target_properties(sodium PROPERTIES
|
||||
IMPORTED_IMPLIB "${sodium_LIBRARY_RELEASE}"
|
||||
IMPORTED_IMPLIB_DEBUG "${sodium_LIBRARY_DEBUG}"
|
||||
)
|
||||
if (NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND"))
|
||||
set_target_properties(sodium PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${sodium_DLL_DEBUG}"
|
||||
)
|
||||
endif()
|
||||
if (NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND"))
|
||||
set_target_properties(sodium PROPERTIES
|
||||
IMPORTED_LOCATION_RELWITHDEBINFO "${sodium_DLL_RELEASE}"
|
||||
IMPORTED_LOCATION_MINSIZEREL "${sodium_DLL_RELEASE}"
|
||||
IMPORTED_LOCATION_RELEASE "${sodium_DLL_RELEASE}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
47
libs/libbattle-com/cmake/Modules/GenerateCccc.cmake
Normal file
47
libs/libbattle-com/cmake/Modules/GenerateCccc.cmake
Normal file
@@ -0,0 +1,47 @@
|
||||
INCLUDE(CheckParent)
|
||||
# search for CCCC binary
|
||||
FIND_PROGRAM(CCCC cccc )
|
||||
|
||||
#
|
||||
# check if the GENERATE_CCCC function has already been defined
|
||||
#
|
||||
get_property(_GENERATE_CCCC GLOBAL PROPERTY _GENERATE_CCCC)
|
||||
IF (NOT _GENERATE_CCCC)
|
||||
|
||||
# set that we have defined GENERATE_CCCC
|
||||
set_property(GLOBAL PROPERTY _GENERATE_CCCC "YES")
|
||||
|
||||
|
||||
FUNCTION(GENERATE_CCCC)
|
||||
IF(CCCC)
|
||||
CMAKE_PARSE_ARGUMENTS(ARG "" "" "TARGETS" ${ARGN})
|
||||
get_property(_ccccfiles GLOBAL PROPERTY _ccccfiles)
|
||||
foreach(_target ${ARG_TARGETS})
|
||||
get_target_property(_sources ${_target} SOURCES)
|
||||
get_target_property(_source_dir ${_target} SOURCE_DIR)
|
||||
|
||||
foreach(_source ${_sources})
|
||||
set(_fullsource "${_source_dir}/${_source}")
|
||||
list(APPEND _ccccfiles "${_fullsource}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
set_property(GLOBAL PROPERTY _ccccfiles ${_ccccfiles})
|
||||
ENDIF()
|
||||
ENDFUNCTION()
|
||||
|
||||
FUNCTION(RESET_CCCC)
|
||||
set_property(GLOBAL PROPERTY _ccccfiles "")
|
||||
ENDFUNCTION()
|
||||
|
||||
FUNCTION(GENERATE_CCCC_TARGET)
|
||||
IF (NOT hasParent AND CCCC)
|
||||
get_property(_targetccccfiles GLOBAL PROPERTY _ccccfiles)
|
||||
|
||||
ADD_CUSTOM_TARGET(cccc
|
||||
COMMAND ${CCCC} --outdir=cccc ${_targetccccfiles}
|
||||
COMMENT "Generating cccc result")
|
||||
ENDIF()
|
||||
ENDFUNCTION()
|
||||
|
||||
|
||||
ENDIF()
|
||||
74
libs/libbattle-com/cmake/Modules/GenerateCppCheck.cmake
Normal file
74
libs/libbattle-com/cmake/Modules/GenerateCppCheck.cmake
Normal file
@@ -0,0 +1,74 @@
|
||||
INCLUDE(CheckParent)
|
||||
find_program(CPPCHECK NAMES cppcheck)
|
||||
|
||||
#
|
||||
# check if the GENERATE_CPPCHECK function has already been defined
|
||||
#
|
||||
get_property(_GENERATE_CPPCHECK GLOBAL PROPERTY _GENERATE_CPPCHECK)
|
||||
IF (NOT _GENERATE_CPPCHECK)
|
||||
|
||||
# set that we have defined GENERATE_CCCC
|
||||
set_property(GLOBAL PROPERTY _GENERATE_CPPCHECK "YES")
|
||||
|
||||
FUNCTION(GENERATE_CPPCHECK)
|
||||
IF(NOT TARGET cppcheck)
|
||||
IF(CPPCHECK)
|
||||
CMAKE_PARSE_ARGUMENTS(ARG "" "" "TARGETS" ${ARGN})
|
||||
get_property(_cppcheckfiles GLOBAL PROPERTY _cppcheckfiles)
|
||||
get_property(_cppcheckincludedirs GLOBAL PROPERTY _cppcheckincludedirs)
|
||||
|
||||
foreach(_target ${ARG_TARGETS})
|
||||
get_target_property(_sources ${_target} SOURCES)
|
||||
get_target_property(_source_dir ${_target} SOURCE_DIR)
|
||||
get_target_property(_include_dir ${_target} INCLUDE_DIRECTORIES)
|
||||
string(REPLACE "$<" ";" _include_dirs ${_include_dir})
|
||||
|
||||
foreach(_dir ${_include_dirs})
|
||||
list(APPEND _cppcheckincludedirs -I${_include_dir})
|
||||
endforeach()
|
||||
|
||||
foreach(_source ${_sources})
|
||||
set(_fullsource "${_source_dir}/${_source}")
|
||||
list(APPEND _cppcheckfiles ${_fullsource})
|
||||
endforeach()
|
||||
endforeach()
|
||||
set_property(GLOBAL PROPERTY _cppcheckfiles ${_cppcheckfiles})
|
||||
set_property(GLOBAL PROPERTY _cppcheckincludedirs ${_cppcheckincludedirs})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDFUNCTION()
|
||||
|
||||
FUNCTION(RESET_CPPCHECK)
|
||||
set_property(GLOBAL PROPERTY _cppcheckfiles "")
|
||||
set_property(GLOBAL PROPERTY _cppcheckincludedirs "")
|
||||
ENDFUNCTION()
|
||||
|
||||
|
||||
FUNCTION(GENERATE_CPPCHECK_TARGET)
|
||||
IF ( NOT hasParent AND CPPCHECK)
|
||||
message("generate cppcheck target")
|
||||
get_property(_targetcppcheckfiles GLOBAL PROPERTY _cppcheckfiles)
|
||||
get_property(_targetcppcheckincludedirs GLOBAL PROPERTY _cppcheckincludedirs)
|
||||
|
||||
add_custom_target(cppcheck
|
||||
COMMAND
|
||||
${CPPCHECK}
|
||||
--xml
|
||||
--xml-version=2
|
||||
--enable=all
|
||||
--inconclusive
|
||||
--force
|
||||
--inline-suppr
|
||||
${_targetcppcheckincludedirs}
|
||||
${_targetcppcheckfiles}
|
||||
2> cppcheck.xml
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT
|
||||
"cppcheck: Running cppcheck on target ${_targetname}..."
|
||||
VERBATIM)
|
||||
|
||||
ENDIF()
|
||||
ENDFUNCTION()
|
||||
|
||||
ENDIF()
|
||||
23
libs/libbattle-com/cmake/Modules/ProcessDOXYGEN.cmake
Normal file
23
libs/libbattle-com/cmake/Modules/ProcessDOXYGEN.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
INCLUDE(CheckParent)
|
||||
|
||||
IF(NOT hasParent)
|
||||
find_package(Doxygen)
|
||||
|
||||
|
||||
IF (DOXYGEN_FOUND)
|
||||
# set input and output files
|
||||
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in)
|
||||
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
|
||||
# request to configure the file
|
||||
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
|
||||
|
||||
# note the option ALL which allows to build the docs together with the application
|
||||
add_custom_target( doxygen
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen"
|
||||
VERBATIM )
|
||||
ENDIF()
|
||||
|
||||
ENDIF()
|
||||
17
libs/libbattle-com/cmake/Modules/ProcessGIT.cmake
Normal file
17
libs/libbattle-com/cmake/Modules/ProcessGIT.cmake
Normal file
@@ -0,0 +1,17 @@
|
||||
if (GIT_FOUND)
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Get the latest abbreviated commit hash of the working branch
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
endif()
|
||||
22
libs/libbattle-com/cmake/Modules/add_my_test.cmake
Normal file
22
libs/libbattle-com/cmake/Modules/add_my_test.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
get_property(_ADD_MY_TEST GLOBAL PROPERTY _ADD_MY_TEST)
|
||||
IF (NOT _ADD_MY_TEST)
|
||||
|
||||
# set that we have defined GENERATE_CCCC
|
||||
set_property(GLOBAL PROPERTY _ADD_MY_TEST "YES")
|
||||
|
||||
|
||||
FUNCTION(ADD_MY_TEST)
|
||||
CMAKE_PARSE_ARGUMENTS(ARG "" "TEST" "SOURCES;LIBS" ${ARGN})
|
||||
get_property(_mytests GLOBAL PROPERTY _mytests)
|
||||
|
||||
list(APPEND _mytests "${ARG_TEST}")
|
||||
|
||||
add_executable(${ARG_TEST} ${ARG_SOURCES})
|
||||
target_link_libraries(${ARG_TEST} ${ARG_LIBS})
|
||||
add_test(${ARG_TEST} ${ARG_TEST})
|
||||
|
||||
set_property(GLOBAL PROPERTY _mytests ${_mytests})
|
||||
ENDFUNCTION()
|
||||
|
||||
|
||||
ENDIF()
|
||||
66
libs/libbattle-com/cmake/Modules/c++-standards.cmake
Normal file
66
libs/libbattle-com/cmake/Modules/c++-standards.cmake
Normal file
@@ -0,0 +1,66 @@
|
||||
#
|
||||
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Set the compiler standard to C++11
|
||||
macro(cxx_11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10)
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("/std:c++11" _cpp_latest_flag_supported)
|
||||
if(_cpp_latest_flag_supported)
|
||||
add_compile_options("/std:c++11")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Set the compiler standard to C++14
|
||||
macro(cxx_14)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10)
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("/std:c++14" _cpp_latest_flag_supported)
|
||||
if(_cpp_latest_flag_supported)
|
||||
add_compile_options("/std:c++14")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Set the compiler standard to C++17
|
||||
macro(cxx_17)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10)
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("/std:c++17" _cpp_latest_flag_supported)
|
||||
if(_cpp_latest_flag_supported)
|
||||
add_compile_options("/std:c++17")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Set the compiler standard to C++20
|
||||
macro(cxx_20)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endmacro()
|
||||
588
libs/libbattle-com/cmake/Modules/code-coverage.cmake
Normal file
588
libs/libbattle-com/cmake/Modules/code-coverage.cmake
Normal file
@@ -0,0 +1,588 @@
|
||||
#
|
||||
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||
#
|
||||
# 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.
|
||||
|
||||
# USAGE: To enable any code coverage instrumentation/targets, the single CMake
|
||||
# option of `CODE_COVERAGE` needs to be set to 'ON', either by GUI, ccmake, or
|
||||
# on the command line.
|
||||
#
|
||||
# From this point, there are two primary methods for adding instrumentation to
|
||||
# targets: 1 - A blanket instrumentation by calling `add_code_coverage()`, where
|
||||
# all targets in that directory and all subdirectories are automatically
|
||||
# instrumented. 2 - Per-target instrumentation by calling
|
||||
# `target_code_coverage(<TARGET_NAME>)`, where the target is given and thus only
|
||||
# that target is instrumented. This applies to both libraries and executables.
|
||||
#
|
||||
# To add coverage targets, such as calling `make ccov` to generate the actual
|
||||
# coverage information for perusal or consumption, call
|
||||
# `target_code_coverage(<TARGET_NAME>)` on an *executable* target.
|
||||
#
|
||||
# Example 1: All targets instrumented
|
||||
#
|
||||
# In this case, the coverage information reported will will be that of the
|
||||
# `theLib` library target and `theExe` executable.
|
||||
#
|
||||
# 1a: Via global command
|
||||
#
|
||||
# ~~~
|
||||
# add_code_coverage() # Adds instrumentation to all targets
|
||||
#
|
||||
# add_library(theLib lib.cpp)
|
||||
#
|
||||
# add_executable(theExe main.cpp)
|
||||
# target_link_libraries(theExe PRIVATE theLib)
|
||||
# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target (instrumentation already added via global anyways) for generating code coverage reports.
|
||||
# ~~~
|
||||
#
|
||||
# 1b: Via target commands
|
||||
#
|
||||
# ~~~
|
||||
# add_library(theLib lib.cpp)
|
||||
# target_code_coverage(theLib) # As a library target, adds coverage instrumentation but no targets.
|
||||
#
|
||||
# add_executable(theExe main.cpp)
|
||||
# target_link_libraries(theExe PRIVATE theLib)
|
||||
# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target and instrumentation for generating code coverage reports.
|
||||
# ~~~
|
||||
#
|
||||
# Example 2: Target instrumented, but with regex pattern of files to be excluded
|
||||
# from report
|
||||
#
|
||||
# ~~~
|
||||
# add_executable(theExe main.cpp non_covered.cpp)
|
||||
# target_code_coverage(theExe EXCLUDE non_covered.cpp test/*) # As an executable target, the reports will exclude the non-covered.cpp file, and any files in a test/ folder.
|
||||
# ~~~
|
||||
#
|
||||
# Example 3: Target added to the 'ccov' and 'ccov-all' targets
|
||||
#
|
||||
# ~~~
|
||||
# add_code_coverage_all_targets(EXCLUDE test/*) # Adds the 'ccov-all' target set and sets it to exclude all files in test/ folders.
|
||||
#
|
||||
# add_executable(theExe main.cpp non_covered.cpp)
|
||||
# target_code_coverage(theExe AUTO ALL EXCLUDE non_covered.cpp test/*) # As an executable target, adds to the 'ccov' and ccov-all' targets, and the reports will exclude the non-covered.cpp file, and any files in a test/ folder.
|
||||
# ~~~
|
||||
|
||||
# Options
|
||||
option(
|
||||
CODE_COVERAGE
|
||||
"Builds targets with code coverage instrumentation. (Requires GCC or Clang)"
|
||||
OFF)
|
||||
|
||||
# Programs
|
||||
find_program(LLVM_COV_PATH NAMES llvm-cov llvm-cov-8 llvm-cov-7 llvm-cov-6)
|
||||
find_program(LLVM_PROFDATA_PATH NAMES llvm-profdata llvm-profdata-8 llvm-profdata-7 llvm-profdata-6)
|
||||
find_program(LCOV_PATH lcov)
|
||||
find_program(GENHTML_PATH genhtml)
|
||||
|
||||
# Variables
|
||||
set(CMAKE_COVERAGE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/ccov)
|
||||
|
||||
# Common initialization/checks
|
||||
if(CODE_COVERAGE AND NOT CODE_COVERAGE_ADDED)
|
||||
set(CODE_COVERAGE_ADDED ON)
|
||||
|
||||
# Common Targets
|
||||
add_custom_target(ccov-preprocessing
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-E
|
||||
make_directory
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}
|
||||
DEPENDS ccov-clean)
|
||||
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
# Messages
|
||||
message(STATUS "Building with llvm Code Coverage Tools")
|
||||
|
||||
if(NOT LLVM_COV_PATH)
|
||||
message(FATAL_ERROR "llvm-cov not found! Aborting.")
|
||||
else()
|
||||
# Version number checking for 'EXCLUDE' compatability
|
||||
execute_process(COMMAND ${LLVM_COV_PATH} --version
|
||||
OUTPUT_VARIABLE LLVM_COV_VERSION_CALL_OUTPUT)
|
||||
string(REGEX MATCH
|
||||
"[0-9]+\\.[0-9]+\\.[0-9]+"
|
||||
LLVM_COV_VERSION
|
||||
${LLVM_COV_VERSION_CALL_OUTPUT})
|
||||
|
||||
if(LLVM_COV_VERSION VERSION_LESS "7.0.0")
|
||||
message(
|
||||
WARNING
|
||||
"target_code_coverage()/add_code_coverage_all_targets() 'EXCLUDE' option only available on llvm-cov >= 7.0.0"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Targets
|
||||
add_custom_target(ccov-clean
|
||||
COMMAND rm -f
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list
|
||||
COMMAND rm -f
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list)
|
||||
|
||||
# Used to get the shared object file list before doing the main all-processing
|
||||
add_custom_target(ccov-libs
|
||||
COMMAND ;
|
||||
COMMENT "libs ready for coverage report.")
|
||||
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# Messages
|
||||
message(STATUS "Building with lcov Code Coverage Tools")
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} upper_build_type)
|
||||
if(NOT ${upper_build_type} STREQUAL "DEBUG")
|
||||
message(
|
||||
WARNING
|
||||
"Code coverage results with an optimized (non-Debug) build may be misleading"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(
|
||||
WARNING
|
||||
"Code coverage results with an optimized (non-Debug) build may be misleading"
|
||||
)
|
||||
endif()
|
||||
if(NOT LCOV_PATH)
|
||||
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||
endif()
|
||||
if(NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif()
|
||||
|
||||
# Targets
|
||||
add_custom_target(ccov-clean
|
||||
COMMAND ${LCOV_PATH}
|
||||
--directory
|
||||
${CMAKE_BINARY_DIR}
|
||||
--zerocounters)
|
||||
|
||||
else()
|
||||
message(FATAL_ERROR "Code coverage requires Clang or GCC. Aborting.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Adds code coverage instrumentation to a library, or instrumentation/targets
|
||||
# for an executable target.
|
||||
# ~~~
|
||||
# EXECUTABLE ADDED TARGETS:
|
||||
# GCOV/LCOV:
|
||||
# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter.
|
||||
# ccov-${TARGET_NAME} : Generates HTML code coverage report for the associated named target.
|
||||
# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report.
|
||||
#
|
||||
# LLVM-COV:
|
||||
# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter.
|
||||
# ccov-report : Generates HTML code coverage report for every target added with 'AUTO' parameter.
|
||||
# ccov-${TARGET_NAME} : Generates HTML code coverage report.
|
||||
# ccov-report-${TARGET_NAME} : Prints to command line summary per-file coverage information.
|
||||
# ccov-show-${TARGET_NAME} : Prints to command line detailed per-line coverage information.
|
||||
# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report.
|
||||
# ccov-all-report : Prints summary per-file coverage information for every target added with ALL' parameter to the command line.
|
||||
#
|
||||
# Required:
|
||||
# TARGET_NAME - Name of the target to generate code coverage for.
|
||||
# Optional:
|
||||
# AUTO - Adds the target to the 'ccov' target so that it can be run in a batch with others easily. Effective on executable targets.
|
||||
# ALL - Adds the target to the 'ccov-all' and 'ccov-all-report' targets, which merge several executable targets coverage data to a single report. Effective on executable targets.
|
||||
# EXTERNAL - For GCC's lcov, allows the profiling of 'external' files from the processing directory
|
||||
# EXCLUDE <REGEX_PATTERNS> - Excludes files of the patterns provided from coverage. **These do not copy to the 'all' targets.**
|
||||
# OBJECTS <TARGETS> - For executables ONLY, if the provided targets are shared libraries, adds coverage information to the output
|
||||
# ~~~
|
||||
function(target_code_coverage TARGET_NAME)
|
||||
# Argument parsing
|
||||
set(options AUTO ALL EXTERNAL)
|
||||
set(multi_value_keywords EXCLUDE OBJECTS)
|
||||
cmake_parse_arguments(target_code_coverage
|
||||
"${options}"
|
||||
""
|
||||
"${multi_value_keywords}"
|
||||
${ARGN})
|
||||
|
||||
if(CODE_COVERAGE)
|
||||
|
||||
# Add code coverage instrumentation to the target's linker command
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
target_compile_options(
|
||||
${TARGET_NAME}
|
||||
PRIVATE -fprofile-instr-generate -fcoverage-mapping)
|
||||
set_property(TARGET ${TARGET_NAME}
|
||||
APPEND_STRING
|
||||
PROPERTY LINK_FLAGS "-fprofile-instr-generate ")
|
||||
set_property(TARGET ${TARGET_NAME}
|
||||
APPEND_STRING
|
||||
PROPERTY LINK_FLAGS "-fcoverage-mapping ")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
target_compile_options(${TARGET_NAME}
|
||||
PRIVATE -fprofile-arcs -ftest-coverage)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE gcov)
|
||||
endif()
|
||||
|
||||
# Targets
|
||||
get_target_property(target_type ${TARGET_NAME} TYPE)
|
||||
|
||||
# Add shared library to processing for 'all' targets
|
||||
if(target_type STREQUAL "SHARED_LIBRARY" AND target_code_coverage_ALL)
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
add_custom_target(
|
||||
ccov-run-${TARGET_NAME}
|
||||
COMMAND echo
|
||||
"-object=$<TARGET_FILE:${TARGET_NAME}>"
|
||||
>>
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list
|
||||
DEPENDS ccov-preprocessing ${TARGET_NAME})
|
||||
|
||||
if(NOT TARGET ccov-libs)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'."
|
||||
)
|
||||
endif()
|
||||
|
||||
add_dependencies(ccov-libs ccov-run-${TARGET_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# For executables add targets to run and produce output
|
||||
if(target_type STREQUAL "EXECUTABLE")
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
|
||||
# If there are shared objects to also work with, generate the string to add them here
|
||||
foreach(SO_TARGET ${target_code_coverage_OBJECTS})
|
||||
# Check to see if the target is a shared object
|
||||
if(TARGET ${SO_TARGET})
|
||||
get_target_property(SO_TARGET_TYPE ${SO_TARGET} TYPE)
|
||||
if(${SO_TARGET_TYPE} STREQUAL "SHARED_LIBRARY")
|
||||
set(SO_OBJECTS ${SO_OBJECTS} -object=$<TARGET_FILE:${SO_TARGET}>)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Run the executable, generating raw profile data
|
||||
add_custom_target(
|
||||
ccov-run-${TARGET_NAME}
|
||||
COMMAND LLVM_PROFILE_FILE=${TARGET_NAME}.profraw
|
||||
$<TARGET_FILE:${TARGET_NAME}>
|
||||
COMMAND echo
|
||||
"-object=$<TARGET_FILE:${TARGET_NAME}>"
|
||||
>>
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list
|
||||
COMMAND echo
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.profraw "
|
||||
>>
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list
|
||||
DEPENDS ccov-preprocessing ccov-libs ${TARGET_NAME})
|
||||
|
||||
# Merge the generated profile data so llvm-cov can process it
|
||||
add_custom_target(ccov-processing-${TARGET_NAME}
|
||||
COMMAND ${LLVM_PROFDATA_PATH}
|
||||
merge
|
||||
-sparse
|
||||
${TARGET_NAME}.profraw
|
||||
-o
|
||||
${TARGET_NAME}.profdata
|
||||
DEPENDS ccov-run-${TARGET_NAME})
|
||||
|
||||
# Ignore regex only works on LLVM >= 7
|
||||
if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0")
|
||||
foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE})
|
||||
set(EXCLUDE_REGEX ${EXCLUDE_REGEX}
|
||||
-ignore-filename-regex='${EXCLUDE_ITEM}')
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Print out details of the coverage information to the command line
|
||||
add_custom_target(ccov-show-${TARGET_NAME}
|
||||
COMMAND ${LLVM_COV_PATH}
|
||||
show
|
||||
$<TARGET_FILE:${TARGET_NAME}>
|
||||
${SO_OBJECTS}
|
||||
-instr-profile=${TARGET_NAME}.profdata
|
||||
-show-line-counts-or-regions
|
||||
${EXCLUDE_REGEX}
|
||||
DEPENDS ccov-processing-${TARGET_NAME})
|
||||
|
||||
# Print out a summary of the coverage information to the command line
|
||||
add_custom_target(ccov-report-${TARGET_NAME}
|
||||
COMMAND ${LLVM_COV_PATH}
|
||||
report
|
||||
$<TARGET_FILE:${TARGET_NAME}>
|
||||
${SO_OBJECTS}
|
||||
-instr-profile=${TARGET_NAME}.profdata
|
||||
${EXCLUDE_REGEX}
|
||||
DEPENDS ccov-processing-${TARGET_NAME})
|
||||
|
||||
# Generates HTML output of the coverage information for perusal
|
||||
add_custom_target(
|
||||
ccov-${TARGET_NAME}
|
||||
COMMAND ${LLVM_COV_PATH}
|
||||
show
|
||||
$<TARGET_FILE:${TARGET_NAME}>
|
||||
${SO_OBJECTS}
|
||||
-instr-profile=${TARGET_NAME}.profdata
|
||||
-show-line-counts-or-regions
|
||||
-output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}
|
||||
-format="html"
|
||||
${EXCLUDE_REGEX}
|
||||
DEPENDS ccov-processing-${TARGET_NAME})
|
||||
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(COVERAGE_INFO
|
||||
"${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}.info")
|
||||
|
||||
# Run the executable, generating coverage information
|
||||
add_custom_target(ccov-run-${TARGET_NAME}
|
||||
COMMAND $<TARGET_FILE:${TARGET_NAME}>
|
||||
DEPENDS ccov-preprocessing ${TARGET_NAME})
|
||||
|
||||
# Generate exclusion string for use
|
||||
foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE})
|
||||
set(EXCLUDE_REGEX
|
||||
${EXCLUDE_REGEX}
|
||||
--remove
|
||||
${COVERAGE_INFO}
|
||||
'${EXCLUDE_ITEM}')
|
||||
endforeach()
|
||||
|
||||
if(EXCLUDE_REGEX)
|
||||
set(EXCLUDE_COMMAND
|
||||
${LCOV_PATH}
|
||||
${EXCLUDE_REGEX}
|
||||
--output-file
|
||||
${COVERAGE_INFO})
|
||||
else()
|
||||
set(EXCLUDE_COMMAND ;)
|
||||
endif()
|
||||
|
||||
if(NOT ${target_code_coverage_EXTERNAL})
|
||||
set(EXTERNAL_OPTION --no-external)
|
||||
endif()
|
||||
|
||||
# Generates HTML output of the coverage information for perusal
|
||||
add_custom_target(
|
||||
ccov-${TARGET_NAME}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-E
|
||||
remove
|
||||
${COVERAGE_INFO}
|
||||
COMMAND ${LCOV_PATH}
|
||||
--directory
|
||||
${CMAKE_BINARY_DIR}
|
||||
--zerocounters
|
||||
COMMAND $<TARGET_FILE:${TARGET_NAME}>
|
||||
COMMAND ${LCOV_PATH}
|
||||
--directory
|
||||
${CMAKE_BINARY_DIR}
|
||||
--base-directory
|
||||
${CMAKE_SOURCE_DIR}
|
||||
--capture
|
||||
${EXTERNAL_OPTION}
|
||||
--output-file
|
||||
${COVERAGE_INFO}
|
||||
COMMAND ${EXCLUDE_COMMAND}
|
||||
COMMAND ${GENHTML_PATH}
|
||||
-o
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}
|
||||
${COVERAGE_INFO}
|
||||
DEPENDS ccov-preprocessing ${TARGET_NAME})
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ccov-${TARGET_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT
|
||||
"Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
# AUTO
|
||||
if(target_code_coverage_AUTO)
|
||||
if(NOT TARGET ccov)
|
||||
add_custom_target(ccov)
|
||||
endif()
|
||||
add_dependencies(ccov ccov-${TARGET_NAME})
|
||||
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(NOT TARGET ccov-report)
|
||||
add_custom_target(ccov-report)
|
||||
endif()
|
||||
add_dependencies(ccov-report ccov-report-${TARGET_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ALL
|
||||
if(target_code_coverage_ALL)
|
||||
if(NOT TARGET ccov-all-processing)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'."
|
||||
)
|
||||
endif()
|
||||
|
||||
add_dependencies(ccov-all-processing ccov-run-${TARGET_NAME})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Adds code coverage instrumentation to all targets in the current directory and
|
||||
# any subdirectories. To add coverage instrumentation to only specific targets,
|
||||
# use `target_code_coverage`.
|
||||
function(add_code_coverage)
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
add_compile_options(-fprofile-instr-generate -fcoverage-mapping)
|
||||
add_link_options(-fprofile-instr-generate -fcoverage-mapping)
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
add_compile_options(-fprofile-arcs -ftest-coverage)
|
||||
link_libraries(gcov)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Adds the 'ccov-all' type targets that calls all targets added via
|
||||
# `target_code_coverage` with the `ALL` parameter, but merges all the coverage
|
||||
# data from them into a single large report instead of the numerous smaller
|
||||
# reports.
|
||||
# ~~~
|
||||
# Optional:
|
||||
# EXCLUDE <REGEX_PATTERNS> - Excludes files of the regex patterns provided from coverage.
|
||||
# ~~~
|
||||
function(add_code_coverage_all_targets)
|
||||
# Argument parsing
|
||||
set(multi_value_keywords EXCLUDE)
|
||||
cmake_parse_arguments(add_code_coverage_all_targets
|
||||
""
|
||||
""
|
||||
"${multi_value_keywords}"
|
||||
${ARGN})
|
||||
|
||||
if(CODE_COVERAGE)
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
|
||||
# Merge the profile data for all of the run executables
|
||||
add_custom_target(
|
||||
ccov-all-processing
|
||||
COMMAND ${LLVM_PROFDATA_PATH}
|
||||
merge
|
||||
-o
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||
-sparse
|
||||
`cat
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list`)
|
||||
|
||||
# Regex exclude only available for LLVM >= 7
|
||||
if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0")
|
||||
foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE})
|
||||
set(EXCLUDE_REGEX ${EXCLUDE_REGEX}
|
||||
-ignore-filename-regex='${EXCLUDE_ITEM}')
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Print summary of the code coverage information to the command line
|
||||
add_custom_target(
|
||||
ccov-all-report
|
||||
COMMAND
|
||||
${LLVM_COV_PATH}
|
||||
report
|
||||
`cat
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list`
|
||||
-instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||
${EXCLUDE_REGEX}
|
||||
DEPENDS ccov-all-processing)
|
||||
|
||||
# Export coverage information so continuous integration tools (e.g. Jenkins) can consume it
|
||||
add_custom_target(
|
||||
ccov-all-export
|
||||
COMMAND
|
||||
${LLVM_COV_PATH}
|
||||
export
|
||||
`cat
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list`
|
||||
-instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||
-format="text"
|
||||
${EXCLUDE_REGEX} > ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/coverage.json
|
||||
DEPENDS ccov-all-processing)
|
||||
|
||||
# Generate HTML output of all added targets for perusal
|
||||
add_custom_target(
|
||||
ccov-all
|
||||
COMMAND
|
||||
${LLVM_COV_PATH}
|
||||
show
|
||||
`cat
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list`
|
||||
-instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata
|
||||
-show-line-counts-or-regions
|
||||
-output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged
|
||||
-format="html"
|
||||
${EXCLUDE_REGEX}
|
||||
DEPENDS ccov-all-processing)
|
||||
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.info")
|
||||
|
||||
# Nothing required for gcov
|
||||
add_custom_target(ccov-all-processing COMMAND ;)
|
||||
|
||||
# Exclusion regex string creation
|
||||
foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE})
|
||||
set(EXCLUDE_REGEX
|
||||
${EXCLUDE_REGEX}
|
||||
--remove
|
||||
${COVERAGE_INFO}
|
||||
'${EXCLUDE_ITEM}')
|
||||
endforeach()
|
||||
|
||||
if(EXCLUDE_REGEX)
|
||||
set(EXCLUDE_COMMAND
|
||||
${LCOV_PATH}
|
||||
${EXCLUDE_REGEX}
|
||||
--output-file
|
||||
${COVERAGE_INFO})
|
||||
else()
|
||||
set(EXCLUDE_COMMAND ;)
|
||||
endif()
|
||||
|
||||
# Generates HTML output of all targets for perusal
|
||||
add_custom_target(ccov-all
|
||||
COMMAND ${LCOV_PATH}
|
||||
--directory
|
||||
${CMAKE_BINARY_DIR}
|
||||
--capture
|
||||
--output-file
|
||||
${COVERAGE_INFO}
|
||||
COMMAND ${EXCLUDE_COMMAND}
|
||||
COMMAND ${GENHTML_PATH}
|
||||
-o
|
||||
${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged
|
||||
${COVERAGE_INFO}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-E
|
||||
remove
|
||||
${COVERAGE_INFO}
|
||||
DEPENDS ccov-all-processing)
|
||||
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ccov-all POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT
|
||||
"Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged/index.html in your browser to view the coverage report."
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
83
libs/libbattle-com/cmake/Modules/codecheck.cmake
Normal file
83
libs/libbattle-com/cmake/Modules/codecheck.cmake
Normal file
@@ -0,0 +1,83 @@
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
option(CODECHECKER "Turns on codecheck processing if it is found." OFF)
|
||||
option(CODECHECKER_STORE "Store results on central codechecker server" OFF)
|
||||
option(CODECHECKER_RUN "Name of the codechecker run" "run-1")
|
||||
option(CODECHECKER_BRANCH "Name of the branch codecheker is run for" "unknown")
|
||||
option(CODECHECKER_URL "URL and product link to codechecker server" "http://localhost:8001/Default")
|
||||
option(CODECHECK_TRIM_PATH "beginning of the path to be removed when storing" "/tmp")
|
||||
|
||||
find_program(CODECHECKER_PATH
|
||||
NAME CodeChecker
|
||||
PATHS ~/bin/
|
||||
/usr/bin/
|
||||
/usr/local/bin
|
||||
)
|
||||
|
||||
if (CODECHECKER_PATH )
|
||||
message(STATUS "CodeChecker found")
|
||||
else()
|
||||
message(STATUS "CodeChecker not found")
|
||||
endif()
|
||||
|
||||
# export compile commands to json file to be used by atom c++ ide (clangd)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||
set(CODECHECKER_COMPILE_COMMANDS "${CMAKE_BINARY_DIR}/compile_commands.json")
|
||||
|
||||
# check if a skip file exists
|
||||
if(EXISTS ${CMAKE_SOURCE_DIR}/codecheck.skip)
|
||||
set(CODECHECKER_SKIP "-i${CMAKE_SOURCE_DIR}/codecheck.skip")
|
||||
endif()
|
||||
|
||||
|
||||
# output directory for codecheck analysis
|
||||
set(CODECHECKER_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/codechecker_results)
|
||||
|
||||
# html output directory
|
||||
set(CODECHECKER_HTML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/codechecker_html)
|
||||
|
||||
# Common initialization/checks
|
||||
if(CODECHECKER AND CODECHECKER_PATH AND NOT CODECHECKER_ADDED)
|
||||
set(CODECHECKER_ADDED ON)
|
||||
|
||||
IF(NOT TARGET codechecker)
|
||||
|
||||
add_custom_target(codechecker
|
||||
COMMAND ${CODECHECKER_PATH}
|
||||
analyze
|
||||
${CODECHECKER_SKIP}
|
||||
-j 4
|
||||
-o ${CODECHECKER_OUTPUT_DIRECTORY}
|
||||
${CODECHECKER_COMPILE_COMMANDS}
|
||||
)
|
||||
|
||||
add_custom_target(codechecker-clean
|
||||
COMMAND rm -rf ${CODECHECKER_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
|
||||
add_custom_target(codechecker-html
|
||||
COMMAND ${CODECHECKER_PATH}
|
||||
parse
|
||||
${CODECHECKER_OUTPUT_DIRECTORY}
|
||||
-e html
|
||||
-o ${CODECHECKER_HTML_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
if (CODECHECKER_STORE)
|
||||
add_custom_target(codechecker-store
|
||||
COMMAND ${CODECHECKER_PATH}
|
||||
store
|
||||
--trim-path-prefix \"${CODECHECK_TRIM_PATH}\"
|
||||
--tag \"${CODECHECKER_BRANCH}\"
|
||||
-n \"${CODECHECKER_RUN}\"
|
||||
--url ${CODECHECKER_URL}
|
||||
${CODECHECKER_OUTPUT_DIRECTORY}
|
||||
)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
23
libs/libbattle-com/cmake/Modules/compdb.cmake
Normal file
23
libs/libbattle-com/cmake/Modules/compdb.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
find_program(COMPDB_PATH
|
||||
NAME compdb
|
||||
PATHS ~/.local/bin/
|
||||
/bin
|
||||
/sbin
|
||||
/usr/bin
|
||||
/usr/sbin
|
||||
/usr/local/bin
|
||||
/usr/local/sbin
|
||||
)
|
||||
|
||||
|
||||
|
||||
if (COMPDB_PATH)
|
||||
IF(NOT TARGET COMPD)
|
||||
add_custom_target(COMPD
|
||||
ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ${COMPDB_PATH} -p ${CMAKE_CURRENT_BINARY_DIR} list >compile_commands.json
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
46
libs/libbattle-com/cmake/Modules/compiler-options.cmake
Normal file
46
libs/libbattle-com/cmake/Modules/compiler-options.cmake
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||
#
|
||||
# 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.
|
||||
|
||||
option(ENABLE_ALL_WARNINGS "Compile with all warnings for the major compilers."
|
||||
OFF)
|
||||
option(ENABLE_EFFECTIVE_CXX "Enable Effective C++ warnings." OFF)
|
||||
|
||||
if(ENABLE_ALL_WARNINGS)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# GCC
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
# Clang
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||
elseif(MSVC)
|
||||
# MSVC
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EFFECTIVE_CXX)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# GCC
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++")
|
||||
elseif("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
# Clang
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++")
|
||||
endif()
|
||||
endif()
|
||||
15
libs/libbattle-com/cmake/Modules/defaultIncludes.cmake
Normal file
15
libs/libbattle-com/cmake/Modules/defaultIncludes.cmake
Normal file
@@ -0,0 +1,15 @@
|
||||
include(c++-standards)
|
||||
include(compiler-options)
|
||||
include(sanitizers)
|
||||
include(codecheck)
|
||||
include(CppCheck)
|
||||
include(code-coverage)
|
||||
include(tools)
|
||||
include(GNUInstallDirs)
|
||||
include(CTest)
|
||||
include(doxygen)
|
||||
include(ProcessGIT)
|
||||
include(CheckParent)
|
||||
include(add_my_test)
|
||||
include(TestBigEndian)
|
||||
include(compdb)
|
||||
9
libs/libbattle-com/cmake/Modules/defaultOptions.cmake
Normal file
9
libs/libbattle-com/cmake/Modules/defaultOptions.cmake
Normal file
@@ -0,0 +1,9 @@
|
||||
include(defaultIncludes)
|
||||
find_package(Git)
|
||||
|
||||
enable_testing()
|
||||
cxx_20()
|
||||
build_docs(PROCESS_DOXYFILE DOXYFILE_PATH "docs/Doxyfile.in" )
|
||||
|
||||
add_code_coverage_all_targets(EXCLUDE ${PROJECT_SOURCE_DIR}/libs/* ${PROJECT_SOURCE_DIR}/test/*)
|
||||
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
|
||||
134
libs/libbattle-com/cmake/Modules/doxygen.cmake
Normal file
134
libs/libbattle-com/cmake/Modules/doxygen.cmake
Normal file
@@ -0,0 +1,134 @@
|
||||
#
|
||||
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||
#
|
||||
# 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.
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
option(BUILD_DOCUMENTATION "Build API documentation using Doxygen. (make doc)"
|
||||
${DOXYGEN_FOUND})
|
||||
|
||||
# Builds doxygen documentation with a default 'Doxyfile.in' or with a specified
|
||||
# one, and can make the results installable (under the `doc` install target)
|
||||
#
|
||||
# This can only be used once per project, as each target generated is as
|
||||
# `doc-${PROJECT_NAME}` unless TARGET_NAME is specified.
|
||||
# ~~~
|
||||
# Optional Arguments:
|
||||
#
|
||||
# ADD_TO_DOC
|
||||
# If specified, adds this generated target to be a dependency of the more general
|
||||
# `doc` target.
|
||||
#
|
||||
# INSTALLABLE
|
||||
# Adds the generated documentation to the generic `install` target, under the
|
||||
# `documentation` installation group.
|
||||
#
|
||||
# PROCESS_DOXYFILE
|
||||
# If set, then will process the found Doxyfile through the CMAKE `configure_file`
|
||||
# function for macro replacements before using it. (@ONLY)
|
||||
#
|
||||
# TARGET_NAME <str>
|
||||
# The name to give the doc target. (Default: doc-${PROJECT_NAME})
|
||||
#
|
||||
# OUTPUT_DIR <str>
|
||||
# The directory to place the generated output. (Default: ${CMAKE_CURRENT_BINARY_DIR}/doc)
|
||||
#
|
||||
# INSTALL_PATH <str>
|
||||
# The path to install the documenttation under. (if not specified, defaults to
|
||||
# 'share/${PROJECT_NAME})
|
||||
#
|
||||
# DOXYFILE_PATH <str>
|
||||
# The given doxygen file to use/process. (Defaults to'${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile')
|
||||
# ~~~
|
||||
function(build_docs)
|
||||
set(OPTIONS ADD_TO_DOC INSTALLABLE PROCESS_DOXYFILE)
|
||||
set(SINGLE_VALUE_KEYWORDS
|
||||
TARGET_NAME
|
||||
INSTALL_PATH
|
||||
DOXYFILE_PATH
|
||||
OUTPUT_DIR)
|
||||
set(MULTI_VALUE_KEYWORDS)
|
||||
cmake_parse_arguments(build_docs
|
||||
"${OPTIONS}"
|
||||
"${SINGLE_VALUE_KEYWORDS}"
|
||||
"${MULTI_VALUE_KEYWORDS}"
|
||||
${ARGN})
|
||||
|
||||
if(BUILD_DOCUMENTATION)
|
||||
if(NOT DOXYGEN_FOUND)
|
||||
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
|
||||
endif()
|
||||
|
||||
if(NOT build_docs_DOXYFILE_PATH)
|
||||
set(DOXYFILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile")
|
||||
elseif(EXISTS "${build_docs_DOXYFILE_PATH}")
|
||||
set(DOXYFILE_PATH "${build_docs_DOXYFILE_PATH}")
|
||||
else()
|
||||
set(DOXYFILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${build_docs_DOXYFILE_PATH}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${DOXYFILE_PATH}")
|
||||
message(
|
||||
SEND_ERROR
|
||||
"Could not find Doxyfile to use for procesing documentation at: ${DOXYFILE_PATH}"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(build_docs_PROCESS_DOXYFILE)
|
||||
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||
configure_file("${DOXYFILE_PATH}" "${DOXYFILE}" @ONLY)
|
||||
else()
|
||||
set(DOXYFILE "${DOXYFILE_PATH}")
|
||||
endif()
|
||||
|
||||
if(build_docs_OUTPUT_DIR)
|
||||
set(OUT_DIR "${build_docs_OUTPUT_DIR}")
|
||||
else()
|
||||
set(OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${OUT_DIR}")
|
||||
|
||||
if(build_docs_TARGET_NAME)
|
||||
set(TARGET_NAME ${build_docs_TARGET_NAME})
|
||||
else()
|
||||
set(TARGET_NAME doc-${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
IF(NOT TARGET ${TARGET_NAME})
|
||||
add_custom_target(${TARGET_NAME}
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} "${DOXYFILE}"
|
||||
WORKING_DIRECTORY "${OUT_DIR}"
|
||||
VERBATIM)
|
||||
ENDIF()
|
||||
|
||||
if(build_docs_ADD_TO_DOC)
|
||||
if(NOT TARGET doc)
|
||||
add_custom_target(doc)
|
||||
endif()
|
||||
|
||||
add_dependencies(doc ${TARGET_NAME})
|
||||
endif()
|
||||
|
||||
if(build_docs_INSTALLABLE)
|
||||
if(NOT build_docs_INSTALL_PATH)
|
||||
set(build_docs_INSTALL_PATH share/${PROJECT_NAME})
|
||||
endif()
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/
|
||||
COMPONENT documentation
|
||||
DESTINATION ${build_docs_INSTALL_PATH})
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
87
libs/libbattle-com/cmake/Modules/sanitizers.cmake
Normal file
87
libs/libbattle-com/cmake/Modules/sanitizers.cmake
Normal file
@@ -0,0 +1,87 @@
|
||||
#
|
||||
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||
#
|
||||
# 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.
|
||||
|
||||
set(
|
||||
USE_SANITIZER
|
||||
""
|
||||
CACHE
|
||||
STRING
|
||||
"Compile with a sanitizer. Options are: Address, Memory, MemoryWithOrigins, Undefined, Thread, Leak, 'Address;Undefined'"
|
||||
)
|
||||
|
||||
function(append value)
|
||||
foreach(variable ${ARGN})
|
||||
set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
|
||||
endforeach(variable)
|
||||
endfunction()
|
||||
|
||||
if(USE_SANITIZER)
|
||||
append("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
|
||||
if(UNIX)
|
||||
|
||||
if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
append("-O1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
|
||||
if(USE_SANITIZER MATCHES "([Aa]ddress);([Uu]ndefined)"
|
||||
OR USE_SANITIZER MATCHES "([Uu]ndefined);([Aa]ddress)")
|
||||
message(STATUS "Building with Address, Undefined sanitizers")
|
||||
append("-fsanitize=address,undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif("${USE_SANITIZER}" MATCHES "([Aa]ddress)")
|
||||
# Optional: -fno-optimize-sibling-calls -fsanitize-address-use-after-scope
|
||||
message(STATUS "Building with Address sanitizer")
|
||||
append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif(USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)")
|
||||
# Optional: -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2
|
||||
append("-fsanitize=memory" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
if(USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)")
|
||||
message(STATUS "Building with MemoryWithOrigins sanitizer")
|
||||
append("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(STATUS "Building with Memory sanitizer")
|
||||
endif()
|
||||
elseif(USE_SANITIZER MATCHES "([Uu]ndefined)")
|
||||
message(STATUS "Building with Undefined sanitizer")
|
||||
append("-fsanitize=undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
if(EXISTS "${BLACKLIST_FILE}")
|
||||
append("-fsanitize-blacklist=${BLACKLIST_FILE}" CMAKE_C_FLAGS
|
||||
CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
elseif(USE_SANITIZER MATCHES "([Tt]hread)")
|
||||
message(STATUS "Building with Thread sanitizer")
|
||||
append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif(USE_SANITIZER MATCHES "([Ll]eak)")
|
||||
message(STATUS "Building with Leak sanitizer")
|
||||
append("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR "Unsupported value of USE_SANITIZER: ${USE_SANITIZER}")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
if(USE_SANITIZER MATCHES "([Aa]ddress)")
|
||||
message(STATUS "Building with Address sanitizer")
|
||||
append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"This sanitizer not yet supported in the MSVC environment: ${USE_SANITIZER}"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "USE_SANITIZER is not supported on this platform.")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
64
libs/libbattle-com/cmake/Modules/tools.cmake
Normal file
64
libs/libbattle-com/cmake/Modules/tools.cmake
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca
|
||||
#
|
||||
# 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.
|
||||
|
||||
option(CLANG_TIDY "Turns on clang-tidy processing if it is found." OFF)
|
||||
option(IWYU "Turns on include-what-you-use processing if it is found." OFF)
|
||||
|
||||
# Adds clang-tidy checks to the compilation, with the given arguments being used
|
||||
# as the options set.
|
||||
macro(clang_tidy)
|
||||
if(CLANG_TIDY AND CLANG_TIDY_EXE)
|
||||
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} ${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Adds include_what_you_use to the compilation, with the given arguments being
|
||||
# used as the options set.
|
||||
macro(include_what_you_use)
|
||||
if(IWYU AND IWYU_EXE)
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${IWYU_EXE};${ARGN}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_program(CLANG_TIDY_EXE NAMES clang-tidy clang-tidy-8 clang-tidy-7 clang-tidy-6)
|
||||
if(CLANG_TIDY_EXE)
|
||||
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
|
||||
if(NOT CLANG_TIDY)
|
||||
message(STATUS "clang-tidy NOT ENABLED via 'CLANG_TIDY' variable!")
|
||||
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||
endif()
|
||||
elseif(CLANG_TIDY)
|
||||
message(SEND_ERROR "Cannot enable clang-tidy, as executable not found!")
|
||||
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||
else()
|
||||
message(STATUS "clang-tidy not found!")
|
||||
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||
endif()
|
||||
|
||||
find_program(IWYU_EXE NAMES "include-what-you-use")
|
||||
if(IWYU_EXE)
|
||||
message(STATUS "include-what-you-use found: ${IWYU_EXE}")
|
||||
if(NOT IWYU)
|
||||
message(STATUS "include-what-you-use NOT ENABLED via 'IWYU' variable!")
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it
|
||||
endif()
|
||||
elseif(IWYU)
|
||||
message(
|
||||
SEND_ERROR "Cannot enable include-what-you-use, as executable not found!")
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it
|
||||
else()
|
||||
message(STATUS "include-what-you-use not found!")
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it
|
||||
endif()
|
||||
43
libs/libbattle-com/cmake/Modules/xslt.cmake
Normal file
43
libs/libbattle-com/cmake/Modules/xslt.cmake
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
|
||||
IF(NOT CMAKE_SET_XSLT)
|
||||
|
||||
set(CMAKE_SET_XSLT true)
|
||||
|
||||
find_program(CMAKE_XSLTPROC NAME xsltproc HINTS ${CMAKE_SYSTEM_PROGRAM_PATH})
|
||||
|
||||
if (CMAKE_XSLTPROC)
|
||||
message(STATUS "XSLTPROC found")
|
||||
else()
|
||||
message(FATAL_ERROR "XSLTPROC not found")
|
||||
endif()
|
||||
|
||||
function(xslt_generate)
|
||||
set(OPTIONS )
|
||||
set(SINGLE_VALUE_KEYWORDS OUT_FILE XML_FILE XSL_FILE)
|
||||
set(MULTI_VALUE_KEYWORDS)
|
||||
cmake_parse_arguments(XSLT
|
||||
"${OPTIONS}"
|
||||
"${SINGLE_VALUE_KEYWORDS}"
|
||||
"${MULTI_VALUE_KEYWORDS}"
|
||||
${ARGN})
|
||||
|
||||
|
||||
message(STATUS "generating ${CMAKE_XSLTPROC} --nonet -o ${XSLT_OUT_FILE} ${XSLT_XSL_FILE} ${XSLT_XML_FILE} ")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_XSLTPROC} --nonet -o ${XSLT_OUT_FILE} ${XSLT_XSL_FILE} ${XSLT_XML_FILE}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE OUT
|
||||
ERROR_VARIABLE ERR
|
||||
)
|
||||
|
||||
message(STATUS ${OUT})
|
||||
message(STATUS ${ERR})
|
||||
|
||||
endfunction()
|
||||
|
||||
ENDIF()
|
||||
27
libs/libbattle-com/cmake/Toolchains/Toolchain-mingw64.cmake
Normal file
27
libs/libbattle-com/cmake/Toolchains/Toolchain-mingw64.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
# the name of the target operating system
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix)
|
||||
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix)
|
||||
|
||||
# here is the target environment located
|
||||
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
|
||||
|
||||
# adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
# programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
find_program(WINE_FOUND wine)
|
||||
|
||||
if(WINE_FOUND)
|
||||
message(STATUS "WINE found")
|
||||
SET(CMAKE_CROSSCOMPILING_EMULATOR wine)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
message(STATUS "Crosscompiling for ${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
3
libs/libbattle-com/codecheck.skip
Normal file
3
libs/libbattle-com/codecheck.skip
Normal file
@@ -0,0 +1,3 @@
|
||||
-/usr/*
|
||||
-*/tests/test_*
|
||||
-*/libs/*
|
||||
23
libs/libbattle-com/docs/Doxyfile.in
Normal file
23
libs/libbattle-com/docs/Doxyfile.in
Normal file
@@ -0,0 +1,23 @@
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = @PROJECT_NAME@
|
||||
PROJECT_NUMBER = "@GIT_BRANCH@ @GIT_COMMIT_HASH@"
|
||||
PROJECT_BRIEF = "library implementing basic classes for managing a Combat Management System (CMS)"
|
||||
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doxygen/
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
TAB_SIZE = 4
|
||||
MARKDOWN_SUPPORT = YES
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/README.md @CMAKE_CURRENT_SOURCE_DIR@/src/ @CMAKE_CURRENT_SOURCE_DIR@/tests/ @CMAKE_CURRENT_SOURCE_DIR@/docs @CMAKE_CURRENT_SOURCE_DIR@/include
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.hpp *.cpp *.md
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
RECURSIVE = YES
|
||||
385
libs/libbattle-com/include/BC/BC.hpp
Normal file
385
libs/libbattle-com/include/BC/BC.hpp
Normal file
@@ -0,0 +1,385 @@
|
||||
#pragma once
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2022 MPLv2
|
||||
*/
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <BC/endianess.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @brief main namespace of libbattle-com++
|
||||
*
|
||||
* Main namespace of the libbattle-com++, everything concerning the library can be found
|
||||
* in this namespace
|
||||
*/
|
||||
namespace BC
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Namespace for all BC wide DataTypes
|
||||
*/
|
||||
namespace DataTypes
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief namespace for conversion functions for different datatypes
|
||||
*/
|
||||
namespace Convert
|
||||
{
|
||||
|
||||
/*
|
||||
* @brief template function to byte swap int/uint datatypes - used for endianess conversion
|
||||
*
|
||||
* @param v - pointer to a variable of some int/uint datatype - in place byte swapped
|
||||
*/
|
||||
template<typename T>
|
||||
void swapBytes(T *v)
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof(T)/2; ++i)
|
||||
{
|
||||
std::swap(((char *)v)[i], ((char *)v)[sizeof(T)-1-i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief template for converting of simple datatypes to a byte_array, including endianness conversion to big endian
|
||||
*
|
||||
* @param variable - the variable to convert to a byte vector, needs to be int/uint datatype
|
||||
*
|
||||
* @return the std::vector<unsigned char>
|
||||
*/
|
||||
template<typename T>
|
||||
std::vector<unsigned char> fromSimpleToByteArray(T &variable)
|
||||
{
|
||||
std::vector<unsigned char> bytes;
|
||||
bytes.clear();
|
||||
bytes.resize(sizeof(T));
|
||||
|
||||
#ifndef IS_BIG_ENDIAN
|
||||
T convVariable = variable;
|
||||
swapBytes(&convVariable);
|
||||
std::memcpy(bytes.data(),reinterpret_cast<const unsigned char*>(&convVariable),sizeof(T));
|
||||
#else
|
||||
std::memcpy(bytes.data(),reinterpret_cast<const unsigned char*>(&variable),sizeof(T));
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief function to convert a std::string to an std::vector<unsigned char>
|
||||
*
|
||||
* for converting the string, first the length of the string is converted as
|
||||
* an uint32_t into the std::vector to be able to correctly parse the string
|
||||
* in a larger vector.
|
||||
*
|
||||
* @param variable - the std::string to convert
|
||||
*
|
||||
* @return the std::vector<unsigned char>
|
||||
*/
|
||||
std::vector<unsigned char> fromStringToByteArray(const std::string &variable);
|
||||
|
||||
|
||||
/**
|
||||
* @brief function to convert a std::vector<unsigned char> to an std::string
|
||||
*
|
||||
* this is the partner function to fromStringToByteArray. It takes the
|
||||
* first 4 byte of the vector as an uint32_t string length identifier and
|
||||
* uses the following length chars as the string
|
||||
*
|
||||
* @param v - the vector to convert to a string
|
||||
* @return the string read from the vector
|
||||
* @throw std::invalid_argument: "vector too short for <X> chars"
|
||||
*/
|
||||
std::string fromByteArrayToString(std::vector<unsigned char> &v);
|
||||
|
||||
/**
|
||||
* @brief function to convert a std::vector<unsigned char> to an simple datatype
|
||||
*
|
||||
* this is the partner function to fromSimpleToByteArray.
|
||||
* it extracts the simple datatype like int, double, etc. from the vector and
|
||||
* returns it
|
||||
*
|
||||
* @param v - the vector to convert to a simple datatype
|
||||
* @return simple datatype
|
||||
* @throw std::invalid_argument: "the bytevector is too small to fit the datatype"
|
||||
*/
|
||||
template<typename T>
|
||||
T fromByteArrayToSimple(std::vector<unsigned char> &bytes)
|
||||
{
|
||||
T convVariable;
|
||||
if(bytes.size() < sizeof(T))
|
||||
{
|
||||
throw(std::invalid_argument(std::string(__FILE__) + ":" + std::string(__PRETTY_FUNCTION__) + ":" + std::to_string(__LINE__) + ": the bytevector is too small to fit the datatype"));
|
||||
}
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&convVariable),bytes.data(),sizeof(T));
|
||||
#ifndef IS_BIG_ENDIAN
|
||||
swapBytes(&convVariable);
|
||||
#endif
|
||||
return std::move(convVariable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief function to convert a container of a simple datatype to a std::vector<unsigned char>
|
||||
*
|
||||
* this is the partner function to fromByteArrayToSimpleContainer.
|
||||
* the number of container elements is prepended to the std::vector and the simple datatype
|
||||
* elements follow.
|
||||
*
|
||||
* @param data - the container of a simple datatype
|
||||
*
|
||||
* @return the std::vector<unsigned char>;
|
||||
*/
|
||||
template<class T>
|
||||
std::vector<unsigned char> fromSimpleContainerToByteArray(T &data)
|
||||
{
|
||||
std::vector<unsigned char> bytes;
|
||||
std::vector<unsigned char> convert;
|
||||
|
||||
uint32_t size=data.size();
|
||||
bytes=BC::DataTypes::Convert::fromSimpleToByteArray(size);
|
||||
|
||||
for(auto it = data.begin(); it!=data.end(); ++it)
|
||||
{
|
||||
convert=BC::DataTypes::Convert::fromSimpleToByteArray(*it);
|
||||
bytes.insert(std::end(bytes), std::begin(convert), std::end(convert));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief function to convert a std::vector<unsigned char> to a container of simple datatype elements
|
||||
*
|
||||
* this is the partner function to fromSimpleContainerToByteArray. It takes the
|
||||
* first 4 byte of the vector as an uint32_t element count and parses the all the elements
|
||||
* from the vector.
|
||||
*
|
||||
* @param v - the vector to convert to a container of simple datatype elements
|
||||
*
|
||||
* @return the container
|
||||
*/
|
||||
template<class T, typename S>
|
||||
T fromByteArrayToSimpleContainer(std::vector<unsigned char> &v)
|
||||
{
|
||||
T data;
|
||||
uint32_t size = BC::DataTypes::Convert::fromByteArrayToSimple<S>(v);
|
||||
v.erase(v.begin(), v.begin()+sizeof(size));
|
||||
for(uint32_t i=0; i<size; i++)
|
||||
{
|
||||
S convert = BC::DataTypes::Convert::fromByteArrayToSimple<S>(v);
|
||||
v.erase(v.begin(), v.begin()+sizeof(convert));
|
||||
data.push_back(convert);
|
||||
}
|
||||
|
||||
return std::move(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief function to convert a container of strings to a std::vector<unsigned char>
|
||||
*
|
||||
* @param data - the container of std::string
|
||||
*
|
||||
* @return the std::vector<unsigned char>
|
||||
*/
|
||||
template<class T>
|
||||
std::vector<unsigned char> fromStringContainerToByteArray(T &data)
|
||||
{
|
||||
std::vector<unsigned char> bytes;
|
||||
std::vector<unsigned char> convert;
|
||||
|
||||
uint32_t size=data.size();
|
||||
bytes=BC::DataTypes::Convert::fromSimpleToByteArray(size);
|
||||
|
||||
for(auto it = data.begin(); it!=data.end(); ++it)
|
||||
{
|
||||
convert=BC::DataTypes::Convert::fromStringToByteArray(*it);
|
||||
bytes.insert(std::end(bytes), std::begin(convert), std::end(convert));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief function to convert a std::vector<unsigned char> to a container of strings
|
||||
*
|
||||
* @param data - the container of std::string
|
||||
*
|
||||
* @return the std::vector<unsigned char>
|
||||
*/
|
||||
template<class T>
|
||||
T fromByteArrayToStringContainer(std::vector<unsigned char> &v)
|
||||
{
|
||||
T data;
|
||||
uint32_t size = BC::DataTypes::Convert::fromByteArrayToSimple<uint32_t>(v);
|
||||
v.erase(v.begin(), v.begin()+sizeof(size));
|
||||
|
||||
for(uint32_t i=0; i<size; i++)
|
||||
{
|
||||
std::string convert = BC::DataTypes::Convert::fromByteArrayToString(v);
|
||||
data.push_back(convert);
|
||||
}
|
||||
|
||||
return std::move(data);
|
||||
}
|
||||
|
||||
} // namespace Convert
|
||||
|
||||
|
||||
|
||||
/// type of the clock used by BC
|
||||
using BCClockType = std::chrono::system_clock;
|
||||
|
||||
/// type of all time attributes throughout BC BCClockType::period
|
||||
using BCTimeType = uint64_t;
|
||||
|
||||
/// the period of the clock within BC, can be different from the actual used clock
|
||||
using BCPeriod = std::chrono::nanoseconds;
|
||||
|
||||
/// variable type for device/endpoint ids within libcms++
|
||||
using deviceIdType = uint32_t;
|
||||
|
||||
/// enumeration variable for identifying major device/endpoint types.
|
||||
enum deviceMajorType : uint32_t
|
||||
{
|
||||
/// device/endpoint is a radar
|
||||
RADAR,
|
||||
/// device/endpoint is a sonar
|
||||
SONAR,
|
||||
/// device/endpoint is a lidar
|
||||
LIDAR,
|
||||
/// device/endpoint is a camera
|
||||
CAMERA,
|
||||
/// device/endpoint is a threat avaluation process/device/software
|
||||
THREAT_EVALUATION_MANAGER,
|
||||
/// device/endpoint is a FLOATS Receiver
|
||||
FLOATS_RECEIVER,
|
||||
/// device/endpoint is a display
|
||||
DISPLAY,
|
||||
/// device/endpoint is a history server
|
||||
HISTORY_SERVER,
|
||||
/// device/endpoint is a threat consolidation application
|
||||
THREAT_CONSOLIDATION,
|
||||
/// device/endpoint is an own track generator
|
||||
OWN_TRACK_GENERATOR,
|
||||
/// device/endpoint is a data fusion application
|
||||
DATA_FUSION,
|
||||
/// device/endpoint is an identification process application
|
||||
ID_PROCESS,
|
||||
/// device/endpoint type is unknown
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief map converting from BC::DataTypes::deviceMajorType to string
|
||||
*/
|
||||
static std::map<BC::DataTypes::deviceMajorType, std::string>deviceMojorTypeMap =
|
||||
{
|
||||
{BC::DataTypes::deviceMajorType::UNKNOWN, "Unknown"},
|
||||
{BC::DataTypes::deviceMajorType::DATA_FUSION, "Data Fusion"},
|
||||
{BC::DataTypes::deviceMajorType::CAMERA, "Camera"},
|
||||
{BC::DataTypes::deviceMajorType::DISPLAY, "Display"},
|
||||
{BC::DataTypes::deviceMajorType::FLOATS_RECEIVER, "FLOATS Receiver"},
|
||||
{BC::DataTypes::deviceMajorType::HISTORY_SERVER, "History Server"},
|
||||
{BC::DataTypes::deviceMajorType::ID_PROCESS, "Identification Process"},
|
||||
{BC::DataTypes::deviceMajorType::LIDAR, "Lidar"},
|
||||
{BC::DataTypes::deviceMajorType::OWN_TRACK_GENERATOR, "Own Track Generator"},
|
||||
{BC::DataTypes::deviceMajorType::RADAR, "Radar"},
|
||||
{BC::DataTypes::deviceMajorType::SONAR, "Sonar"},
|
||||
{BC::DataTypes::deviceMajorType::THREAT_EVALUATION_MANAGER, "Threat Evaluation"},
|
||||
{BC::DataTypes::deviceMajorType::THREAT_CONSOLIDATION, "Threat Consolidation"}
|
||||
};
|
||||
|
||||
} // namespace DataTypes
|
||||
|
||||
|
||||
/**
|
||||
* @brief function to get the current time in every BC implementation
|
||||
*/
|
||||
inline BC::DataTypes::BCTimeType getCurrentTime()
|
||||
{
|
||||
std::chrono::time_point<BC::DataTypes::BCClockType> now = BC::DataTypes::BCClockType::now();
|
||||
|
||||
return std::chrono::duration_cast<BC::DataTypes::BCPeriod>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Class/Namespace for BC related constants
|
||||
*/
|
||||
class Constants
|
||||
{
|
||||
public:
|
||||
|
||||
/// the epoch starting date used throughout BC, used to abstract from the epoch used
|
||||
/// in different operating systems and standards
|
||||
static constexpr const char *cEpochDateTime = "1970-01-01 00:00";
|
||||
|
||||
///@name constants related to devices
|
||||
///@{
|
||||
|
||||
/// constants identifying that we want to select/address all devices in the CMS, required for publish/subscribe
|
||||
static const BC::DataTypes::deviceIdType allDevices = 0;
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
///@name PubSub Domain related constants
|
||||
///@{
|
||||
|
||||
/// constant identifying the real world domain
|
||||
static constexpr const char *cRealWorldDomain = "REALWORLD";
|
||||
|
||||
/// constant identifying the default simulation domain
|
||||
static constexpr const char *cSimWorldDomain = "SIMULATION";
|
||||
|
||||
/// constant identifying the Management domain
|
||||
static constexpr const char *cManagementDomain = "_MANAGEMENT_";
|
||||
|
||||
/// constant identifying all domains
|
||||
static constexpr const char *cAllDomains = "_DOMAIN_ALL_";
|
||||
|
||||
///@}
|
||||
|
||||
///@name PubSub Topic related constants
|
||||
///@{
|
||||
|
||||
/// constant identifying that the subscriber is interested in all topics
|
||||
static constexpr const char *cAllTopics = "_TOPIC_ALL_";
|
||||
|
||||
/// constant identifying the PING topic, for pinging subscribers
|
||||
static constexpr const char *cPingTopic = "_TOPIC_PING_";
|
||||
|
||||
/// constant identifying the PONG topic, for answering a PING
|
||||
static constexpr const char *cPongTopic = "_TOPIC_PONG_";
|
||||
|
||||
/// constant identifying the HOTPLUG JOIN message topic
|
||||
static constexpr const char *cHotplugJoin = "_HOTPLUG_JOIN_";
|
||||
|
||||
/// constant identifying the HOTPLUG LEAVE message topic
|
||||
static constexpr const char *cHotplugLeave = "_HOTPLUG_LEAVE_";
|
||||
|
||||
/// constant identifying the PING message topic
|
||||
static constexpr const char *cPing = "_PING_";
|
||||
|
||||
/// constant identifying the PONG message topic
|
||||
static constexpr const char *cPong = "_PONG_";
|
||||
};
|
||||
|
||||
} // namespace BC
|
||||
|
||||
80
libs/libbattle-com/include/BC/BasicMessageQueue.hpp
Normal file
80
libs/libbattle-com/include/BC/BasicMessageQueue.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @copyright MPLv2
|
||||
*/
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
#include <condition_variable>
|
||||
#include <BC/Message.hpp>
|
||||
|
||||
namespace BC{
|
||||
/**
|
||||
* @class BasicMessageQueue
|
||||
*
|
||||
* This class encapsulates shared storage which is a queue and protect it
|
||||
* with a mutex. In Addition there is a condition variable to notify other
|
||||
* threads if there is new data in the queue.
|
||||
*/
|
||||
class BasicMessageQueue
|
||||
{
|
||||
private:
|
||||
std::queue<std::unique_ptr<BC::Message>> q;
|
||||
std::mutex mx;
|
||||
std::condition_variable condVar;
|
||||
public:
|
||||
/**
|
||||
* @brief default constructor for class BasicMessageQueue
|
||||
*/
|
||||
BasicMessageQueue();
|
||||
|
||||
/**
|
||||
* @brief appends given message to queue
|
||||
*
|
||||
* The storage is protected by a mutex. Makes a notify_one call to inform
|
||||
* in waiting thread that there is a new message in the queue.
|
||||
*
|
||||
* @param msg - incoming message
|
||||
*/
|
||||
void appendMessage( std::unique_ptr<BC::Message> msg );
|
||||
|
||||
/**
|
||||
* @brief gets the fron message from the queue
|
||||
*
|
||||
* This method gets the front message in the queue and deletes it from the
|
||||
* queue. The storage is protected by a mutex. If the queue is empty the
|
||||
* function throws an exception.
|
||||
*
|
||||
* @result msg - returns the front message from the queue
|
||||
* @throws length_error - if queue is empty this method throws length_error exception
|
||||
*/
|
||||
std::unique_ptr<BC::Message> getMessage();
|
||||
|
||||
/**
|
||||
* @brief waits for new message to be added
|
||||
*
|
||||
* If the queue is empty this method waits for a notfication on the condition variable.
|
||||
* It returns the front message and deletes it from the queue. This action is protected
|
||||
* by a mutex.
|
||||
*
|
||||
* @result msg - returns the first/front message in the queue
|
||||
* @throws length_error - if queue is empty this method throws length_error exception
|
||||
*/
|
||||
std::unique_ptr<BC::Message> waitForNewMessage();
|
||||
|
||||
/**
|
||||
* @brief method size
|
||||
*
|
||||
* @result size - current size of the message queue
|
||||
*/
|
||||
unsigned int size();
|
||||
|
||||
}; //BasicMessageQueue
|
||||
|
||||
}; // namespace BC
|
||||
150
libs/libbattle-com/include/BC/BasicQueueReceiver.hpp
Normal file
150
libs/libbattle-com/include/BC/BasicQueueReceiver.hpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @copyright MPLv2
|
||||
*/
|
||||
#include <BC/receiveable.hpp>
|
||||
#include <BC/BasicMessageQueue.hpp>
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
/**
|
||||
* @brief class BasicQueueReceiver
|
||||
*
|
||||
* Derived class from receiveable (libbattle-com++) to receive messages
|
||||
* published in the battle-com network.
|
||||
*
|
||||
* This class is a basic component for applications that need to connect to a
|
||||
* battle-com network, like e.g. the prototype CMS.
|
||||
* The receiver will be moved to a thread by the service it is used from. If
|
||||
* the receive method gets called and it is still busy with the previous
|
||||
* message, the new message will get lost.
|
||||
*
|
||||
* Therefor messages that are received by this BasicQueueReceiver are pushed
|
||||
* to a message queue (short receive method). From there the other components
|
||||
* of the application can take the messages as needed. This implementation
|
||||
* ensures that the receive method is short so no information get lost.
|
||||
*/
|
||||
class BasicQueueReceiver : public BC::receiveable
|
||||
{
|
||||
private:
|
||||
/// threadsafe queue to store received messages
|
||||
BC::BasicMessageQueue messages;
|
||||
public:
|
||||
/**
|
||||
* @brief default constructor for class Receiver
|
||||
*/
|
||||
BasicQueueReceiver();
|
||||
|
||||
/**
|
||||
* @brief tryGetMessage
|
||||
*
|
||||
* This method tries to get a message from the message queue.
|
||||
* Calles getMessage from message queue. This method rethrows the exception
|
||||
* that can be trown by called method.
|
||||
*
|
||||
* @result msg - raw pointer to new message from the network
|
||||
* @throws length_error - if queue is empty this method throws length_error exception
|
||||
*/
|
||||
[[deprecated("Replaced by bool tryGetMessage(BC::Message **msg)")]]
|
||||
BC::Message * tryGetMessage();
|
||||
|
||||
/**
|
||||
* @brief tryGetMessage
|
||||
*
|
||||
* This method tries to get a message from the message queue.
|
||||
* Calles getMessage from message queue. This method rethrows the exception
|
||||
* that can be trown by called method.
|
||||
*
|
||||
* @TODO: change param msg to smart pointer (when switching from raw to smart pointer in this project)
|
||||
*
|
||||
* @result true - a message was get successfully
|
||||
* @return false - there was no message in the queue, the pointer is invalid and equals nullptr
|
||||
* @param msg - raw pointer to new message from the network that should be get from the queue
|
||||
*/
|
||||
[[deprecated("Replaced by function that uses unique_ptr")]]
|
||||
bool tryGetMessage(BC::Message **msg);
|
||||
|
||||
/**
|
||||
* @brief waitForNewMessage
|
||||
*
|
||||
* Calles waitForNewMessage method from corresponding message queue. After
|
||||
* notification the new message will be returned.
|
||||
* This method catches the exception: empty queue.
|
||||
*
|
||||
* @result msg - raw pointer to new message from the network
|
||||
* @rethrow - rethrows an exception that is not empty queue exception
|
||||
*/
|
||||
[[deprecated("Replaced by function that uses unique_ptr")]]
|
||||
BC::Message * waitForNewMessage();
|
||||
|
||||
/**
|
||||
* @brief getMessage
|
||||
*
|
||||
* This method gets a message form the message queue if there is a message
|
||||
* in the queue. If the message queue is empty this method throw an
|
||||
* exception
|
||||
*
|
||||
* @result - unique pointer to received message
|
||||
* @throws length_error - if queue is empty this method throws length_error exception
|
||||
*/
|
||||
std::unique_ptr<BC::Message> getMessage();
|
||||
|
||||
/**
|
||||
* @brief waits given time in seconds for new message to be recieved
|
||||
*
|
||||
* This method tries to get one BC::Message from the receiver for a
|
||||
* specific time. If no message can be taken after this time the class
|
||||
* function returns a nullpointer.
|
||||
*
|
||||
* @param time - time duration in seconds the method tries to get a message from the queue
|
||||
* @result - unique pointer to BC::Message from message queue
|
||||
* @result nullptr - returns nullptr if message queue stays empty
|
||||
*/
|
||||
std::unique_ptr<BC::Message> waitSecondsForNewMessage(std::uint16_t time);
|
||||
|
||||
/**
|
||||
* @brief waits given time in milliseconds for new message to be recieved
|
||||
*
|
||||
* This method tries to get one BC::Message from the receiver for a
|
||||
* specific time. If no message can be taken after this time the class
|
||||
* function returns a nullpointer.
|
||||
*
|
||||
* @param time - time duration in milliseconds the method tries to get a message from the queue
|
||||
* @result - unique pointer to BC::Message from message queue
|
||||
* @result nullptr - returns nullptr if message queue stays empty
|
||||
*/
|
||||
std::unique_ptr<BC::Message> waitMillisecondsForNewMessage(std::uint16_t time);
|
||||
|
||||
/**
|
||||
* @brief gets number of messages in the queue
|
||||
*
|
||||
* This method returns the queue size which means the number of messages
|
||||
* stored at the queue.
|
||||
*
|
||||
* @result size - size of message queue
|
||||
*/
|
||||
unsigned int getQueueSize();
|
||||
|
||||
/**
|
||||
* @brief virtual function receive
|
||||
*
|
||||
* This function is called if there are new messages published.
|
||||
* These messages are pushed to the message queue.
|
||||
*
|
||||
* @param m - raw pointer to the received message
|
||||
*/
|
||||
virtual void receive(BC::Message *m) override;
|
||||
|
||||
}; // class BasicQueueReceiver
|
||||
|
||||
}; // namespace BC
|
||||
283
libs/libbattle-com/include/BC/BasicService.hpp
Normal file
283
libs/libbattle-com/include/BC/BasicService.hpp
Normal file
@@ -0,0 +1,283 @@
|
||||
#ifndef __LIBBC_BC_BASICSERVICE_HPP__
|
||||
#define __LIBBC_BC_BASICSERVICE_HPP__
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the BasicService class
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2018-11-23
|
||||
* @copyright 2018 no yet defined
|
||||
*/
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/Message.hpp>
|
||||
#include <BC/receiveable.hpp>
|
||||
|
||||
namespace BC {
|
||||
/**
|
||||
* @brief base class for all battle-com services
|
||||
*
|
||||
* This class is the interface for all battle-com services. It enforces all
|
||||
* the required methods and provides essential data types.
|
||||
*/
|
||||
class BasicService
|
||||
{
|
||||
private:
|
||||
|
||||
/// the network id of the device using this service
|
||||
BC::DataTypes::deviceIdType id;
|
||||
|
||||
/// The major type of the id of the device using this service
|
||||
BC::DataTypes::deviceMajorType majorType;
|
||||
|
||||
/// The minor type of the device, like a string with vendor/device string
|
||||
std::string minorType;
|
||||
|
||||
/// variable for holding the receive thread identifier
|
||||
std::thread receiveThread;
|
||||
|
||||
/// variable indicating if the receiveThread should be stopped
|
||||
std::atomic<bool> stopReceiveThread;
|
||||
|
||||
/// list holding all the subscribers of this service
|
||||
std::map<std::string, std::map<std::string,std::vector<BC::receiveable *>>> subscribers;
|
||||
|
||||
/// mutex protecting the subscrivers list in a multithread context
|
||||
std::mutex subscribersMutex;
|
||||
|
||||
/// show if the service is connected or not
|
||||
std::atomic<bool> connected;
|
||||
|
||||
std::mutex mutex;
|
||||
|
||||
/// attribute identifying this service as a gateway and all packets should be forwarded
|
||||
bool gateway = false;
|
||||
|
||||
|
||||
/**
|
||||
* @brief method called by the receive thread.
|
||||
*
|
||||
* This method is called inside the receiveThread
|
||||
* It calls the derivedReceive method in an endless loop.
|
||||
*/
|
||||
void receive();
|
||||
|
||||
/**
|
||||
* @brief method to process basic received messages
|
||||
*
|
||||
* example messages processed in this method are
|
||||
* PING and Control messages.
|
||||
*
|
||||
* @param m - the message to process
|
||||
*
|
||||
* @return true - the message has been processed by the method
|
||||
* @return false - the message has not been processes by the method
|
||||
*/
|
||||
bool basicProcess(const BC::Message *m);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief called by the connect method after basic initializing
|
||||
*
|
||||
* This method has to be implemented by every child class. It is responsible
|
||||
* for connecting to the underlying transport layer protocol like UDP/TCP.
|
||||
*
|
||||
*/
|
||||
virtual void derivedConnect()=0;
|
||||
|
||||
/**
|
||||
* @brief called by the disconnect method before closing everything down
|
||||
*
|
||||
* This method has to be implemented by every child class. It is responsible
|
||||
* for disconnecting from the underlying transport layer protocol like UDP/TCP.
|
||||
*
|
||||
*/
|
||||
virtual void derivedDisconnect()=0;
|
||||
|
||||
/**
|
||||
* @brief called from the receive thread to receive a message in a *neverending loop*
|
||||
*
|
||||
* This method has to be implemented by every child class. It is responsible
|
||||
* for receiving data from the used transport layer protocol, like UDP/TCP .
|
||||
*
|
||||
* It has to be implemented that it receives one data frame. It is called repeatedly from
|
||||
* the receive thread. It may block but eventually the method has to return control
|
||||
* to the receive thread.
|
||||
*
|
||||
* The last action of this method has to be calling the process(std::vector<unsigned char> v) method
|
||||
*/
|
||||
virtual void derivedReceive()=0;
|
||||
|
||||
/**
|
||||
* @brief process an received data vector, called from the derivedReceive method
|
||||
*
|
||||
* Method converts the vector to a CMS::PubSub::Message and calls
|
||||
* the basicProcess and the process(CMS::PubSub::Message *m) method
|
||||
*
|
||||
* if the message is not processed by one of these methods it searches for subscribers
|
||||
* to call
|
||||
*
|
||||
* @param v - the vector to process and convert to a CMS::PubSub::Message
|
||||
*/
|
||||
void process(std::vector<unsigned char> &v);
|
||||
|
||||
/**
|
||||
* @brief called from the publish method inside the child class
|
||||
*
|
||||
* In this method the transmission of the message through the
|
||||
* used transport layer is implemented.
|
||||
*
|
||||
* The BasicService is publishing a HOTPLUG JOIN after connecting and
|
||||
* a HOTPLUG LEAVE message before disconnecting. The child class is
|
||||
* responsible to add a CMS::PubSub::Payloads::HotPlugJoin payload to
|
||||
* the first and a CMS::PubSub::Payloads::HotPlugLeave payload to the
|
||||
* later in this method before transmitting it.
|
||||
*
|
||||
* @param m - the message to publish/transmit
|
||||
*/
|
||||
virtual void derivedPublish(BC::Message &m)=0;
|
||||
|
||||
/**
|
||||
* @brief method to process certain messages inside the child class
|
||||
*
|
||||
* Method is called after converting the char vector to a CMS::PubSub::Message
|
||||
* and calling basicProcess. The child class can process some required
|
||||
* special messages in this method.
|
||||
*
|
||||
* @param m - the message to process
|
||||
*
|
||||
* @return true - the message has been processed by the method
|
||||
* @return false - the message has not been processes by the method
|
||||
*/
|
||||
virtual bool process(const BC::Message *m)=0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief main constructor for the BasicService class
|
||||
*
|
||||
* This constructor just initializes the attributes to the given parameter values.
|
||||
* receiveThread is initialized to a thread but without a call function.
|
||||
* This is required to just initialize the class without starting a thread.
|
||||
*/
|
||||
BasicService(const BC::DataTypes::deviceIdType &myID, const BC::DataTypes::deviceMajorType &majorT,
|
||||
const std::string &minorT) : id(myID), majorType(majorT), minorType(minorT), receiveThread(),
|
||||
stopReceiveThread(false), connected(false)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* @brief destructor the the BasicService. if necessary stop the receiveThread
|
||||
*
|
||||
*/
|
||||
virtual ~BasicService();
|
||||
|
||||
|
||||
/**
|
||||
* @brief set if we are a gateay or not
|
||||
*
|
||||
*/
|
||||
void setGateway(const bool v){gateway=v;}
|
||||
|
||||
/**
|
||||
* @brief check if we are a gateway or not
|
||||
*
|
||||
*/
|
||||
bool isGateway() const {return gateway;}
|
||||
|
||||
/**
|
||||
* @brief check if the service is already connected
|
||||
*
|
||||
*/
|
||||
bool isConnected() const {return connected;}
|
||||
/**
|
||||
* @brief just return the id
|
||||
*/
|
||||
BC::DataTypes::deviceIdType getId() const {return id;}
|
||||
|
||||
/**
|
||||
* @brief method to connect the service to the underlying network and start receiving
|
||||
*
|
||||
* this method also calls the derivedConnect method of the child class
|
||||
*/
|
||||
void connect();
|
||||
|
||||
/**
|
||||
* @brief method to disconnect the service from the underlying network
|
||||
*
|
||||
* this method also calls the derivedDisconnect method of the child class
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* @brief method to publish a message through the service
|
||||
*
|
||||
* this method calls the derivedPublish method of the child class
|
||||
*
|
||||
* @param m - the message to publish
|
||||
*/
|
||||
void publish(BC::Message &m);
|
||||
|
||||
/**
|
||||
* @brief subscribe a CMS::PubSub::receiveable class to the list of domains and the list of topics
|
||||
*
|
||||
* @param r - the class to subscribe
|
||||
* @param domains the list of domains to subscribe to
|
||||
* @param topics the list of topics to subscribe to
|
||||
*/
|
||||
void subscribe(BC::receiveable *r, std::list<std::string> domains, std::list<std::string> topics);
|
||||
|
||||
/**
|
||||
* @brief subscribe a CMS::PubSub::receiveable class to the domain and the list of topics
|
||||
*
|
||||
* @param r - the class to subscribe
|
||||
* @param domains the domain to subscribe to
|
||||
* @param topics the list of topics to subscribe to
|
||||
*/
|
||||
void subscribe(BC::receiveable *r, std::string domain, std::list<std::string> topics);
|
||||
|
||||
/**
|
||||
* @brief subscribe a CMS::PubSub::receiveable class to the list of domains and the topic
|
||||
*
|
||||
* @param r - the class to subscribe
|
||||
* @param domains the list of domains to subscribe to
|
||||
* @param topics the topic to subscribe to
|
||||
*/
|
||||
void subscribe(BC::receiveable *r, std::string domain, std::string topic);
|
||||
|
||||
/**
|
||||
* @brief Return the id of the service in the network.
|
||||
*
|
||||
*/
|
||||
BC::DataTypes::deviceIdType getID() const { return id;}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the Major Type of the Service.
|
||||
*
|
||||
* @return BC::DataTypes::deviceMajorType
|
||||
*/
|
||||
BC::DataTypes::deviceMajorType getMajorType() const { return majorType;}
|
||||
|
||||
/**
|
||||
* @brief Get the Minor Type of the Service.
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
std::string getMinorType() const { return minorType;}
|
||||
|
||||
};
|
||||
}; // namespace BC
|
||||
|
||||
#endif
|
||||
134
libs/libbattle-com/include/BC/Message.hpp
Normal file
134
libs/libbattle-com/include/BC/Message.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#ifndef __LIBBC_BC_MESSAGE_HPP__
|
||||
#define __LIBBC_BC_MESSAGE_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief header file for the battle-com message class
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2018-11-23
|
||||
* @copyright 2018 no yet defined
|
||||
*/
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/transmittable.hpp>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
/**
|
||||
* @brief simple datatype to combine all information of a message distributed through the publish subscriber system of libbattle-com++
|
||||
*/
|
||||
class Message : public BC::transmittable
|
||||
{
|
||||
private:
|
||||
/// vector representing the object to transmit
|
||||
std::vector<unsigned char> data;
|
||||
|
||||
public:
|
||||
|
||||
/// the device id of the device/endpoint sending this Message
|
||||
BC::DataTypes::deviceIdType sourceID;
|
||||
|
||||
/// the device id of the device/endpoint which should receive this Message BC::Constants::allDevices for broadcast
|
||||
BC::DataTypes::deviceIdType destinationID = BC::Constants::allDevices;
|
||||
|
||||
/// the major type of the device/endpoint transmitting this message
|
||||
BC::DataTypes::deviceMajorType srcMajorType;
|
||||
|
||||
/// the minor type of the device/endpoint transmitting this message
|
||||
std::string srcMinorType;
|
||||
|
||||
/// the time this Message was transmitted by calling the publish method of the PubSubService
|
||||
BC::DataTypes::BCTimeType transmissionTime;
|
||||
|
||||
/// the time this Message was received by calling the subscribed method
|
||||
BC::DataTypes::BCTimeType receptionTime;
|
||||
|
||||
/// the domain this message resides in
|
||||
std::string domain;
|
||||
|
||||
/// which topic does this message have ? helps identifying the transmitted datatype
|
||||
std::string topic;
|
||||
|
||||
/**
|
||||
* @brief set the data object to transmit through the battle-com service
|
||||
*
|
||||
* @prarma d - an object implementing the transmittable interface
|
||||
*/
|
||||
void setData(const BC::transmittable &d){data=d.toByteVector();}
|
||||
|
||||
/**
|
||||
* @brief set the data object to transmit through the battle-com service
|
||||
*
|
||||
* @param d - the object already converted to a byte vector
|
||||
*/
|
||||
void setData(const std::vector<unsigned char> &d){data=d;}
|
||||
|
||||
/**
|
||||
* @brief return the raw byte vector of the data object, required for data reception
|
||||
*
|
||||
* @return the std::vector<unsigned char>
|
||||
*/
|
||||
std::vector<unsigned char> getRawData() const {return data;}
|
||||
|
||||
Message() : sourceID(0), destinationID(0), srcMajorType(BC::DataTypes::UNKNOWN), srcMinorType(""),
|
||||
transmissionTime(0), receptionTime(0), domain(""), topic(""){}
|
||||
|
||||
virtual ~Message()=default;
|
||||
|
||||
/**
|
||||
* @brief Constructor for generationg a Message object from a received std::vector<unsiged char>
|
||||
*
|
||||
* @param v - the std::vector<unsigned char> representing a message object
|
||||
*/
|
||||
explicit Message(std::vector<unsigned char>);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor of the Message class
|
||||
*
|
||||
* creates a copy of the object, including copies of all data
|
||||
*
|
||||
* @param obj - the object from which to copy everything
|
||||
*/
|
||||
Message(const Message &obj);
|
||||
|
||||
/**
|
||||
* @brief returns the size in bytes of the whole message
|
||||
*
|
||||
*/
|
||||
const uint64_t size() const;
|
||||
|
||||
/**
|
||||
* @brief converts the whole message information into a byte vector
|
||||
*
|
||||
* all information of the message class is converted into a byte vector for transmission
|
||||
* through any kind of network.
|
||||
*
|
||||
* @param payload - returns the byte vector by call by reference
|
||||
*/
|
||||
std::vector<unsigned char> toByteVector() const override;
|
||||
|
||||
/**
|
||||
* @brief fills the message class with information from the given byte vector
|
||||
*
|
||||
* the message is filled with all the information from the provided
|
||||
* byte vector, except the data attribute. The byte vector identifying the
|
||||
* data is returned to the caller. The caller has to call the appropriate
|
||||
* factory to generate the right object
|
||||
*
|
||||
* @param payload - provides the byte vector representing the message
|
||||
* @param data - returns the byte vector representing the data attribute by call by reference
|
||||
*/
|
||||
void fromByteVector(std::vector<unsigned char> &payload, std::vector<unsigned char> &data);
|
||||
|
||||
};
|
||||
|
||||
}; // namespace BC
|
||||
|
||||
|
||||
#endif
|
||||
63
libs/libbattle-com/include/BC/Payloads/HotPlugJoin.hpp
Normal file
63
libs/libbattle-com/include/BC/Payloads/HotPlugJoin.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __LIBBC_BC_PAYLOADS_HOTPLUGJOIN_HPP__
|
||||
#define __LIBBC_BC_PAYLOADS_HOTPLUGJOIN_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the BC::Payloads::HotPlugJoin payload
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-03
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/transmittable.hpp>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
namespace Payloads
|
||||
{
|
||||
/**
|
||||
* @brief class representing the payload of a HotPlugJoin message
|
||||
*
|
||||
* the HotPlugJoin messages is transmitted by every PubSub Service after connection
|
||||
* has been established to the underlying network/transport layer.
|
||||
* It provides information about the type of service, the id and the underlying
|
||||
* network/transport layer addresses.
|
||||
*
|
||||
*/
|
||||
class HotPlugJoin : public BC::transmittable
|
||||
{
|
||||
public:
|
||||
HotPlugJoin()=default;
|
||||
/**
|
||||
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
|
||||
*/
|
||||
explicit HotPlugJoin(std::vector<unsigned char> v);
|
||||
|
||||
/// the address of the underlying network layer used to join the network
|
||||
unsigned char networkLayerAddress[16];
|
||||
|
||||
/// the address of the underlying transport layer used to join the network
|
||||
uint32_t transportLayerAddress;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief converts the information of the class (the attributes) to a byte vector
|
||||
*
|
||||
* @param byteVector - returns a std::vector of bytes representing the class
|
||||
*/
|
||||
std::vector<unsigned char> toByteVector() const override;
|
||||
};
|
||||
}; //namespace Payloads
|
||||
}; //namespace BC
|
||||
|
||||
#endif
|
||||
63
libs/libbattle-com/include/BC/Payloads/HotPlugLeave.hpp
Normal file
63
libs/libbattle-com/include/BC/Payloads/HotPlugLeave.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __LIBBC_BC_PAYLOADS_HOTPLUGLEAVE_HPP__
|
||||
#define __LIBBC_BC_PAYLOADS_HOTPLUGLEAVE_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the BC::Payloads::HotPlugLeave payload
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-05
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/transmittable.hpp>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
namespace Payloads
|
||||
{
|
||||
/**
|
||||
* @brief class representing the payload of a HotPlugLeave message
|
||||
*
|
||||
* the HotPlugLeave messages is transmitted by every PubSub Service before disconnecting
|
||||
* from the network.
|
||||
* It provides information about the type of service, the id and the underlying
|
||||
* network/transport layer addresses.
|
||||
*
|
||||
*/
|
||||
class HotPlugLeave : public BC::transmittable
|
||||
{
|
||||
public:
|
||||
HotPlugLeave()=default;
|
||||
/**
|
||||
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
|
||||
*/
|
||||
explicit HotPlugLeave(std::vector<unsigned char> v);
|
||||
|
||||
/// the address of the underlying network layer used to join the network
|
||||
unsigned char networkLayerAddress[16];
|
||||
|
||||
/// the address of the underlying transport layer used to join the network
|
||||
uint32_t transportLayerAddress;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief converts the information of the class (the attributes) to a byte vector
|
||||
*
|
||||
* @param byteVector - returns a std::vector of bytes representing the class
|
||||
*/
|
||||
std::vector<unsigned char> toByteVector() const override;
|
||||
};
|
||||
}; //namespace Payloads
|
||||
}; //namespace BC
|
||||
|
||||
#endif
|
||||
63
libs/libbattle-com/include/BC/Payloads/Ping.hpp
Normal file
63
libs/libbattle-com/include/BC/Payloads/Ping.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __LIBBC_BC_PAYLOADS_PING_HPP__
|
||||
#define __LIBBC_BC_PAYLOADS_PING_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the BC::Payloads::Ping payload
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-06
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/transmittable.hpp>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
|
||||
namespace Payloads
|
||||
{
|
||||
/**
|
||||
* @brief class representing the payload of a Ping message
|
||||
*
|
||||
* the Ping messages is transmitted can be published to all or individual nodes.
|
||||
* these nodes will answer with a Pong message
|
||||
*
|
||||
*/
|
||||
class Ping : public BC::transmittable
|
||||
{
|
||||
public:
|
||||
Ping();
|
||||
/**
|
||||
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
|
||||
*/
|
||||
explicit Ping(std::vector<unsigned char> v);
|
||||
|
||||
/// message id uniqly identifying one ping message
|
||||
uint64_t messageID;
|
||||
|
||||
/// the sequence number of the ping
|
||||
uint64_t sequenceNr;
|
||||
|
||||
/// the local clock ticks
|
||||
uint64_t pingTime;
|
||||
|
||||
/**
|
||||
* @brief converts the information of the class (the attributes) to a byte vector
|
||||
*
|
||||
* @param byteVector - returns a std::vector of bytes representing the class
|
||||
*/
|
||||
std::vector<unsigned char> toByteVector() const override;
|
||||
};
|
||||
}; //namespace Payloads
|
||||
}; //namespace BC
|
||||
|
||||
#endif
|
||||
60
libs/libbattle-com/include/BC/Payloads/Pong.hpp
Normal file
60
libs/libbattle-com/include/BC/Payloads/Pong.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef __LIBBC_BC_PAYLOADS_PONG_HPP__
|
||||
#define __LIBBC_BC_PAYLOADS_PONG_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the BC::Payloads::Pong payload
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-06
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/transmittable.hpp>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
namespace Payloads
|
||||
{
|
||||
/**
|
||||
* @brief class representing the payload of a Pong message
|
||||
*
|
||||
* the Pong messages is the reply to a ping message.
|
||||
*
|
||||
*/
|
||||
class Pong : public BC::transmittable
|
||||
{
|
||||
public:
|
||||
Pong()=default;
|
||||
/**
|
||||
* @brief constructor to recreate the HotPlugJoin payload from a a std::vector<unsigned char>
|
||||
*/
|
||||
explicit Pong(std::vector<unsigned char> v);
|
||||
|
||||
/// message id uniqly identifying one ping message
|
||||
uint64_t pingMessageID;
|
||||
|
||||
/// ping transmission time
|
||||
BC::DataTypes::BCTimeType pingTransmissionTime;
|
||||
|
||||
/// the sequence number of the ping
|
||||
uint64_t sequenceNr;
|
||||
|
||||
/**
|
||||
* @brief converts the information of the class (the attributes) to a byte vector
|
||||
*
|
||||
* @param byteVector - returns a std::vector of bytes representing the class
|
||||
*/
|
||||
std::vector<unsigned char> toByteVector() const override;
|
||||
};
|
||||
}; //namespace Payloads
|
||||
}; //namespace BC
|
||||
|
||||
#endif
|
||||
137
libs/libbattle-com/include/BC/SimpleServiceUDP.hpp
Normal file
137
libs/libbattle-com/include/BC/SimpleServiceUDP.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#ifndef __LIBBC_BC_SIMPLESERVICE_UDP_HPP__
|
||||
#define __LIBBC_BC_SIMPLESERVICE_UDP_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the simpleservice udp class
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-02-01
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <BC/BC.hpp>
|
||||
#include <BC/BasicService.hpp>
|
||||
#include <BC/Message.hpp>
|
||||
|
||||
|
||||
namespace BC {
|
||||
class SimpleServiceUDPremoteClient
|
||||
{
|
||||
public:
|
||||
unsigned short port;
|
||||
BC::DataTypes::deviceIdType id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SimpleServiceUDP uses simple UDP broadcasts for distributing messages
|
||||
*
|
||||
* The SimpleServiceUDP is an implementation of a PubSub Service. It extends the BasicService
|
||||
* and uses UDP broadcasts to distribute data. The constructor of the class
|
||||
*
|
||||
* This Service is only useful for debugging purposes running your network in a local LAN.
|
||||
*/
|
||||
class SimpleServiceUDP : public BC::BasicService
|
||||
{
|
||||
private:
|
||||
/// the IP Address to send messages to
|
||||
std::string dstIp;
|
||||
|
||||
/// the local source IP Address
|
||||
std::string srcIp;
|
||||
|
||||
/// the udp port on which to broadcast and receive messages
|
||||
unsigned short broadcastPort = 0;
|
||||
|
||||
/// the port we are listing on for messages, should normally be broadcastPort, but...
|
||||
unsigned short localPort = 0;
|
||||
|
||||
/// the network socket to work on
|
||||
int inetSocket = -1;
|
||||
|
||||
/// vector of local client ports we forward messages to
|
||||
std::vector<SimpleServiceUDPremoteClient> clients;
|
||||
|
||||
/// mutex for exclusive access to the clients vector
|
||||
std::mutex mutexClients;
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief called from the parent class when the connect method is called
|
||||
*
|
||||
* Method is responsible for setting up the connection to the underlying
|
||||
* transport layer protocol
|
||||
*
|
||||
*/
|
||||
void derivedConnect() override;
|
||||
|
||||
/**
|
||||
* @brief called from the parent class when the disconnect method is called
|
||||
*
|
||||
* Method is responsible for tearing down the connection to the underlying
|
||||
* transport layer protocol
|
||||
*
|
||||
*/
|
||||
void derivedDisconnect() override;
|
||||
|
||||
/**
|
||||
* @brief called from the parent class in the receive thread
|
||||
*
|
||||
* Method is responsible for receiving data frames from the transport layer
|
||||
*
|
||||
* @see BasicService::receive
|
||||
*/
|
||||
void derivedReceive() override;
|
||||
|
||||
/**
|
||||
* @brief called from the parent class after constructing a correct CMS::PubSub::Message
|
||||
*
|
||||
* Method is responsible for processing Service specific messages
|
||||
*
|
||||
* @param m - the received message
|
||||
*
|
||||
* @return true|false true = message has been processed, false = message has not been processed
|
||||
*/
|
||||
bool process(const BC::Message *m) override;
|
||||
|
||||
/**
|
||||
* @brief called from the parent class to actually publish the message
|
||||
*
|
||||
* @param m - the messahe to publish
|
||||
*/
|
||||
void derivedPublish(BC::Message &m) override;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief constructor for the SimpleServiceUDP class
|
||||
*
|
||||
* Constructor initializes the class
|
||||
*
|
||||
* @param myID - the id of the device connected to the network
|
||||
* @param majorT - the majorType of device
|
||||
* @param minorT - the minorType of the device
|
||||
* @param port - the UDP port on which to transmit and receive broadcast messages
|
||||
* @param dst - the broadcast IP address to send messages to
|
||||
* @param src - the local IP Address we listen on, has to be on the same network of the broadcast address
|
||||
*/
|
||||
SimpleServiceUDP(const BC::DataTypes::deviceIdType &myID, const BC::DataTypes::deviceMajorType &majorT,
|
||||
const std::string &minorT, const unsigned short &port, const std::string &dst,
|
||||
const std::string &src) : BasicService(myID,majorT,minorT),
|
||||
dstIp(dst), srcIp(src), broadcastPort(port){}
|
||||
};
|
||||
}; // namespace BC
|
||||
|
||||
#endif
|
||||
13
libs/libbattle-com/include/BC/endianess.hpp.in
Normal file
13
libs/libbattle-com/include/BC/endianess.hpp.in
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef __LIBBC_BC_ENDIANESS_HPP__
|
||||
#define __LIBBC_BC_ENDIANESS_HPP__
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* if we have big or little endian
|
||||
*/
|
||||
#cmakedefine IS_BIG_ENDIAN @IS_BIG_ENDIAN@
|
||||
|
||||
#endif
|
||||
40
libs/libbattle-com/include/BC/receiveable.hpp
Normal file
40
libs/libbattle-com/include/BC/receiveable.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef __LIBBC_BC_RECEIVEABLE_HPP__
|
||||
#define __LIBBC_BC_RECEIVEABLE_HPP__
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the receiveable interface
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-01-08
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
#include <BC/Message.hpp>
|
||||
|
||||
namespace BC {
|
||||
/**
|
||||
* @brief interface for a class which is able to receive messages via a battle-com service
|
||||
*
|
||||
*/
|
||||
class receiveable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief method called by the battle-com service after registering this class via the subscribe method
|
||||
*
|
||||
* Please make sure this method is finished as fast as possible. New messages can only be
|
||||
* processes by the battle-com service after this method has finished!!!!
|
||||
*
|
||||
* @param m - pointer to the message received by the service, this class has to make
|
||||
* sure that the message is deleted/freed after usage
|
||||
*/
|
||||
virtual void receive(BC::Message *m)=0;
|
||||
};
|
||||
}; // namespace BC
|
||||
|
||||
#endif
|
||||
44
libs/libbattle-com/include/BC/transmittable.hpp
Normal file
44
libs/libbattle-com/include/BC/transmittable.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef __LIBBC_BC_TRANSMITTABLE_HPP__
|
||||
#define __LIBBC_BC_TRANSMITTABLE_HPP__
|
||||
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief main header file for the transmittable interface
|
||||
* @author Dominik Meyer <dmeyer@hsu-hh.de>
|
||||
* @date 2019-01-08
|
||||
* @copyright 2019 no yet defined
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace BC
|
||||
{
|
||||
/**
|
||||
* @brief abstract class providing the interface for classes being transmittable through a network
|
||||
*
|
||||
* the developer has to make sure that the correct endianess is used in the toByteVector function
|
||||
* and in the Factory for each Class
|
||||
*/
|
||||
class transmittable
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief converts the information of the class (the attributes) to a byte vector
|
||||
*
|
||||
* @param byteVector - returns a std::vector of bytes representing the class
|
||||
*/
|
||||
virtual std::vector<unsigned char> toByteVector() const = 0;
|
||||
};
|
||||
|
||||
}; //namespace BC
|
||||
|
||||
|
||||
#endif
|
||||
30
libs/libbattle-com/libs/CLI11/.appveyor.yml
Normal file
30
libs/libbattle-com/libs/CLI11/.appveyor.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
- set PATH=C:\Python36;%PATH%
|
||||
- cmake --version
|
||||
- pip install conan
|
||||
- conan user
|
||||
- conan --version
|
||||
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ps: cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_GENERATOR="Visual Studio 14 2015"
|
||||
- ps: cmake --build .
|
||||
- cd ..
|
||||
- conan create . CLIUtils/CLI11
|
||||
|
||||
test_script:
|
||||
- cd build
|
||||
- ps: ctest --output-on-failure -C Debug
|
||||
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://webhooks.gitter.im/e/0185e91c5d989a476d7b
|
||||
on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_status_changed: true
|
||||
11
libs/libbattle-com/libs/CLI11/.ci/azure-build.yml
Normal file
11
libs/libbattle-com/libs/CLI11/.ci/azure-build.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
steps:
|
||||
|
||||
- task: CMake@1
|
||||
inputs:
|
||||
cmakeArgs: .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=$(cli11.single) -DCLI11_CXX_STD=$(cli11.std) -DCLI11_SINGLE_FILE_TESTS=$(cli11.single) -DCMAKE_BUILD_TYPE=$(cli11.build_type) $(cli11.options)
|
||||
displayName: 'Configure'
|
||||
|
||||
- script: cmake --build .
|
||||
displayName: 'Build'
|
||||
workingDirectory: build
|
||||
|
||||
16
libs/libbattle-com/libs/CLI11/.ci/azure-cmake.yml
Normal file
16
libs/libbattle-com/libs/CLI11/.ci/azure-cmake.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
steps:
|
||||
|
||||
# Note that silkeh/clang does not include ca-certificates, so check the shasum for verification
|
||||
- bash: |
|
||||
wget --no-check-certificate "https://cmake.org/files/v3.14/cmake-3.14.3-Linux-x86_64.tar.gz"
|
||||
echo "29faa62fb3a0b6323caa3d9557e1a5f1205614c0d4c5c2a9917f16a74f7eff68 cmake-3.14.3-Linux-x86_64.tar.gz" | shasum -sca 256
|
||||
displayName: Download CMake
|
||||
|
||||
- task: ExtractFiles@1
|
||||
inputs:
|
||||
archiveFilePatterns: 'cmake*.tar.gz'
|
||||
destinationFolder: 'cmake_program'
|
||||
displayName: Extract CMake
|
||||
|
||||
- bash: echo "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.14.3-Linux-x86_64/bin"
|
||||
displayName: Add CMake to PATH
|
||||
12
libs/libbattle-com/libs/CLI11/.ci/azure-test.yml
Normal file
12
libs/libbattle-com/libs/CLI11/.ci/azure-test.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
steps:
|
||||
|
||||
- script: ctest --output-on-failure -C $(cli11.build_type) -T test
|
||||
displayName: 'Test'
|
||||
workingDirectory: build
|
||||
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testResultsFormat: 'cTest'
|
||||
testResultsFiles: '**/Test.xml'
|
||||
|
||||
|
||||
106
libs/libbattle-com/libs/CLI11/.ci/build_docs.sh
Executable file
106
libs/libbattle-com/libs/CLI11/.ci/build_docs.sh
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/sh
|
||||
################################################################################
|
||||
# Title : generateDocumentationAndDeploy.sh
|
||||
# Date created : 2016/02/22
|
||||
# Notes :
|
||||
# Author : Jeroen de Bruijn
|
||||
# Preconditions:
|
||||
# - Packages doxygen doxygen-doc doxygen-latex doxygen-gui graphviz
|
||||
# must be installed.
|
||||
# - Doxygen configuration file must have the destination directory empty and
|
||||
# source code directory with a $(TRAVIS_BUILD_DIR) prefix.
|
||||
# - An gh-pages branch should already exist. See below for mor info on hoe to
|
||||
# create a gh-pages branch.
|
||||
#
|
||||
# Required global variables:
|
||||
# - TRAVIS_BUILD_NUMBER : The number of the current build.
|
||||
# - TRAVIS_COMMIT : The commit that the current build is testing.
|
||||
# - DOXYFILE : The Doxygen configuration file.
|
||||
# - TRAVIS_REPO_SLUG : The username / reponame for the repository.
|
||||
# - GH_REPO_TOKEN : Secure token to the github repository.
|
||||
#
|
||||
# For information on how to encrypt variables for Travis CI please go to
|
||||
# https://docs.travis-ci.com/user/environment-variables/#Encrypted-Variables
|
||||
# or https://gist.github.com/vidavidorra/7ed6166a46c537d3cbd2
|
||||
# For information on how to create a clean gh-pages branch from the master
|
||||
# branch, please go to https://gist.github.com/vidavidorra/846a2fc7dd51f4fe56a0
|
||||
#
|
||||
# This script will generate Doxygen documentation and push the documentation to
|
||||
# the gh-pages branch of a repository specified by GH_REPO_REF.
|
||||
# Before this script is used there should already be a gh-pages branch in the
|
||||
# repository.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
##### Setup this script and get the current gh-pages branch. #####
|
||||
echo 'Setting up the script...'
|
||||
# Exit with nonzero exit code if anything fails
|
||||
set -e
|
||||
|
||||
GH_REPO_ORG=$(echo $TRAVIS_REPO_SLUG | cut -d "/" -f 1)
|
||||
GH_REPO_NAME=$(echo $TRAVIS_REPO_SLUG | cut -d "/" -f 2)
|
||||
GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git"
|
||||
|
||||
# Create a clean working directory for this script.
|
||||
# Get the current gh-pages branch
|
||||
cd docs
|
||||
git clone -b gh-pages https://git@$GH_REPO_REF html
|
||||
cd html
|
||||
|
||||
##### Configure git.
|
||||
# Set the push default to simple i.e. push only the current branch.
|
||||
git config --global push.default simple
|
||||
# Pretend to be an user called Travis CI.
|
||||
git config user.name "Travis CI"
|
||||
git config user.email "travis@travis-ci.org"
|
||||
|
||||
# Remove everything currently in the gh-pages branch.
|
||||
# GitHub is smart enough to know which files have changed and which files have
|
||||
# stayed the same and will only update the changed files. So the gh-pages branch
|
||||
# can be safely cleaned, and it is sure that everything pushed later is the new
|
||||
# documentation.
|
||||
rm -rf *
|
||||
|
||||
# Need to create a .nojekyll file to allow filenames starting with an underscore
|
||||
# to be seen on the gh-pages site. Therefore creating an empty .nojekyll file.
|
||||
# Presumably this is only needed when the SHORT_NAMES option in Doxygen is set
|
||||
# to NO, which it is by default. So creating the file just in case.
|
||||
echo "" > .nojekyll
|
||||
|
||||
################################################################################
|
||||
##### Generate the Doxygen code documentation and log the output. #####
|
||||
echo 'Generating Doxygen code documentation...'
|
||||
# Redirect both stderr and stdout to the log file AND the console.
|
||||
cd ..
|
||||
doxygen $DOXYFILE 2>&1 | tee doxygen.log
|
||||
|
||||
################################################################################
|
||||
##### Upload the documentation to the gh-pages branch of the repository. #####
|
||||
# Only upload if Doxygen successfully created the documentation.
|
||||
# Check this by verifying that the html directory and the file html/index.html
|
||||
# both exist. This is a good indication that Doxygen did it's work.
|
||||
if [ -d "html" ] && [ -f "html/index.html" ]; then
|
||||
|
||||
cd html
|
||||
echo 'Uploading documentation to the gh-pages branch...'
|
||||
# Add everything in this directory (the Doxygen code documentation) to the
|
||||
# gh-pages branch.
|
||||
# GitHub is smart enough to know which files have changed and which files have
|
||||
# stayed the same and will only update the changed files.
|
||||
git add --all
|
||||
|
||||
# Commit the added files with a title and description containing the Travis CI
|
||||
# build number and the GitHub commit reference that issued this build.
|
||||
git commit -m "Deploy code docs to GitHub Pages Travis build: ${TRAVIS_BUILD_NUMBER}" -m "Commit: ${TRAVIS_COMMIT}"
|
||||
|
||||
# Force push to the remote gh-pages branch.
|
||||
# The ouput is redirected to /dev/null to hide any sensitive credential data
|
||||
# that might otherwise be exposed.
|
||||
git push --force "https://${GH_REPO_TOKEN}@${GH_REPO_REF}" > /dev/null 2>&1
|
||||
else
|
||||
echo '' >&2
|
||||
echo 'Warning: No documentation (html) files have been found!' >&2
|
||||
echo 'Warning: Not going to push the documentation to GitHub!' >&2
|
||||
exit 1
|
||||
fi
|
||||
25
libs/libbattle-com/libs/CLI11/.ci/build_doxygen.sh
Normal file
25
libs/libbattle-com/libs/CLI11/.ci/build_doxygen.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/bin/env sh
|
||||
# (Source me)
|
||||
|
||||
set -evx
|
||||
|
||||
DOXYGEN_URL="http://doxygen.nl/files/doxygen-1.8.15.src.tar.gz"
|
||||
cd "${DEPS_DIR}"
|
||||
|
||||
if [[ ! -f "${DEPS_DIR}/doxygen/build/bin/doxygen" ]] ; then
|
||||
echo "Downloading Doxygen"
|
||||
mkdir -p doxygen
|
||||
travis_retry wget --no-check-certificate --quiet -O - "${DOXYGEN_URL}" | tar --strip-components=1 -xz -C doxygen
|
||||
cd doxygen
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j2
|
||||
fi
|
||||
|
||||
export PATH="${DEPS_DIR}/doxygen/build/bin:${PATH}"
|
||||
|
||||
cd "${TRAVIS_BUILD_DIR}"
|
||||
|
||||
set +evx
|
||||
|
||||
17
libs/libbattle-com/libs/CLI11/.ci/build_lcov.sh
Normal file
17
libs/libbattle-com/libs/CLI11/.ci/build_lcov.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/env sh
|
||||
# (Source me)
|
||||
set -evx
|
||||
|
||||
LCOV_URL="http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.13.orig.tar.gz"
|
||||
cd "${DEPS_DIR}"
|
||||
|
||||
if [[ ! -f "${DEPS_DIR}/lcov/bin/lcov" ]] ; then
|
||||
echo "Downloading lcov"
|
||||
mkdir -p lcov
|
||||
travis_retry wget --no-check-certificate --quiet -O - "${LCOV_URL}" | tar --strip-components=1 -xz -C lcov
|
||||
fi
|
||||
|
||||
export PATH="${DEPS_DIR}/lcov/bin:${PATH}"
|
||||
cd "${TRAVIS_BUILD_DIR}"
|
||||
|
||||
set +evx
|
||||
23
libs/libbattle-com/libs/CLI11/.ci/make_and_test.sh
Executable file
23
libs/libbattle-com/libs/CLI11/.ci/make_and_test.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
echo -en "travis_fold:start:script.build\\r"
|
||||
echo "Building..."
|
||||
STD=$1
|
||||
shift
|
||||
set -evx
|
||||
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=ON -DCLI11_CXX_STD=$STD -DCLI11_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER_LAUNCHER=ccache $@
|
||||
cmake --build . -- -j2
|
||||
|
||||
set +evx
|
||||
echo -en "travis_fold:end:script.build\\r"
|
||||
echo -en "travis_fold:start:script.test\\r"
|
||||
echo "Testing..."
|
||||
set -evx
|
||||
|
||||
ctest --output-on-failure
|
||||
|
||||
set +evx
|
||||
echo -en "travis_fold:end:script.test\\r"
|
||||
27
libs/libbattle-com/libs/CLI11/.ci/run_codecov.sh
Executable file
27
libs/libbattle-com/libs/CLI11/.ci/run_codecov.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo -en "travis_fold:start:script.build\\r"
|
||||
echo "Building..."
|
||||
set -evx
|
||||
|
||||
cd ${TRAVIS_BUILD_DIR}
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DCLI11_SINGLE_FILE_TESTS=OFF -DCLI11_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Coverage
|
||||
cmake --build . -- -j2
|
||||
cmake --build . --target CLI11_coverage
|
||||
|
||||
set +evx
|
||||
echo -en "travis_fold:end:script.build\\r"
|
||||
echo -en "travis_fold:start:script.lcov\\r"
|
||||
echo "Capturing and uploading LCov..."
|
||||
set -evx
|
||||
|
||||
lcov --directory . --capture --output-file coverage.info # capture coverage info
|
||||
lcov --remove coverage.info '*/tests/*' '*/examples/*' '*gtest*' '*gmock*' '/usr/*' --output-file coverage.info # filter out system
|
||||
lcov --list coverage.info #debug info
|
||||
# Uploading report to CodeCov
|
||||
bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports"
|
||||
|
||||
set +evx
|
||||
echo -en "travis_fold:end:script.lcov\\r"
|
||||
86
libs/libbattle-com/libs/CLI11/.clang-format
Normal file
86
libs/libbattle-com/libs/CLI11/.clang-format
Normal file
@@ -0,0 +1,86 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
# AccessModifierOffset: -2
|
||||
# AlignAfterOpenBracket: Align
|
||||
# AlignConsecutiveAssignments: false
|
||||
# AlignConsecutiveDeclarations: false
|
||||
# AlignEscapedNewlinesLeft: false
|
||||
# AlignOperands: true
|
||||
# AlignTrailingComments: true
|
||||
# AllowAllParametersOfDeclarationOnNextLine: true
|
||||
# AllowShortBlocksOnASingleLine: false
|
||||
# AllowShortCaseLabelsOnASingleLine: false
|
||||
# AllowShortFunctionsOnASingleLine: All
|
||||
# AllowShortIfStatementsOnASingleLine: false
|
||||
# AllowShortLoopsOnASingleLine: false
|
||||
# AlwaysBreakAfterDefinitionReturnType: None
|
||||
# AlwaysBreakAfterReturnType: None
|
||||
# AlwaysBreakBeforeMultilineStrings: false
|
||||
# AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
# BraceWrapping:
|
||||
# AfterClass: false
|
||||
# AfterControlStatement: false
|
||||
# AfterEnum: false
|
||||
# AfterFunction: false
|
||||
# AfterNamespace: false
|
||||
# AfterObjCDeclaration: false
|
||||
# AfterStruct: false
|
||||
# AfterUnion: false
|
||||
# BeforeCatch: false
|
||||
# BeforeElse: false
|
||||
# IndentBraces: false
|
||||
# BreakBeforeBinaryOperators: None
|
||||
# BreakBeforeBraces: Attach
|
||||
# BreakBeforeTernaryOperators: true
|
||||
# BreakConstructorInitializersBeforeComma: false
|
||||
# BreakAfterJavaFieldAnnotations: false
|
||||
# BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
# ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
# ConstructorInitializerIndentWidth: 4
|
||||
# ContinuationIndentWidth: 4
|
||||
# Cpp11BracedListStyle: true
|
||||
# DerivePointerAlignment: false
|
||||
# DisableFormat: false
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
# IncludeIsMainRegex: '$'
|
||||
# IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# JavaScriptQuotes: Leave
|
||||
# JavaScriptWrapImports: true
|
||||
# KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
# MacroBlockBegin: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
# NamespaceIndentation: None
|
||||
# ObjCBlockIndentWidth: 2
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PointerAlignment: Right
|
||||
# ReflowComments: true
|
||||
SortIncludes: false
|
||||
# SpaceAfterCStyleCast: false
|
||||
# SpaceAfterTemplateKeyword: true
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: Never
|
||||
# SpaceInEmptyParentheses: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
# SpacesInAngles: false
|
||||
# SpacesInContainerLiterals: true
|
||||
# SpacesInCStyleCastParentheses: false
|
||||
# SpacesInParentheses: false
|
||||
# SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
8
libs/libbattle-com/libs/CLI11/.clang-tidy
Normal file
8
libs/libbattle-com/libs/CLI11/.clang-tidy
Normal file
@@ -0,0 +1,8 @@
|
||||
#Checks: '*,-clang-analyzer-alpha.*'
|
||||
#Checks: '-*,google-readability-casting,llvm-namespace-comment,performance-unnecessary-value-param,llvm-include-order,misc-throw-by-value-catch-by-reference,readability-container-size-empty,google-runtime-references,modernize*'
|
||||
Checks: '-*,llvm-namespace-comment,readability-container-size-empty,misc-throw-by-value-catch-by-reference,modernize*,google-readability-casting'
|
||||
HeaderFilterRegex: '.*hpp'
|
||||
CheckOptions:
|
||||
- key: readability-braces-around-statements.ShortStatementLines
|
||||
value: '1'
|
||||
|
||||
4
libs/libbattle-com/libs/CLI11/.codecov.yml
Normal file
4
libs/libbattle-com/libs/CLI11/.codecov.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
ignore:
|
||||
- "tests"
|
||||
- "examples"
|
||||
11
libs/libbattle-com/libs/CLI11/.editorconfig
Normal file
11
libs/libbattle-com/libs/CLI11/.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
40
libs/libbattle-com/libs/CLI11/.github/CONTRIBUTING.md
vendored
Normal file
40
libs/libbattle-com/libs/CLI11/.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
Thanks for considering to write a Pull Request (PR) for CLI11! Here are a few guidelines to get you started:
|
||||
|
||||
Make sure you are comfortable with the license; all contributions are licensed under the original license.
|
||||
|
||||
## Adding functionality
|
||||
Make sure any new functions you add are are:
|
||||
|
||||
* Documented by `///` documentation for Doxygen
|
||||
* Mentioned in the instructions in the README, though brief mentions are okay
|
||||
* Explained in your PR (or previously explained in an Issue mentioned in the PR)
|
||||
* Completely covered by tests
|
||||
|
||||
In general, make sure the addition is well thought out and does not increase the complexity of CLI11 needlessly.
|
||||
|
||||
## Things you should know:
|
||||
|
||||
* Once you make the PR, tests will run to make sure your code works on all supported platforms
|
||||
* The test coverage is also measured, and that should remain 100%
|
||||
* Formatting should be done with clang-format, otherwise the format check will not pass. However, it is trivial to apply this to your PR, so don't worry about this check. If you do have clang-format, just run `scripts/check_style.sh`
|
||||
* Everything must pass clang-tidy as well, run with `-DCLANG_TIDY_FIX-ON` (make sure you use a single threaded build process!)
|
||||
|
||||
Note that the style check is really just:
|
||||
|
||||
```bash
|
||||
git ls-files -- '.cpp' '.hpp' | xargs clang-format -i -style=file
|
||||
```
|
||||
|
||||
And, if you want to always use it, feel free to install the git hook provided in scripts.
|
||||
|
||||
## For developers releasing to Conan.io
|
||||
|
||||
This is now done by the CI system on tagged releases. Previously, the steps to make a Conan.io release were:
|
||||
|
||||
```bash
|
||||
conan remove '*' # optional, I like to be clean
|
||||
conan create . cliutils/stable
|
||||
conan upload "*" -r cli11 --all
|
||||
```
|
||||
|
||||
Here I've assumed that the remote is `cli11`.
|
||||
7
libs/libbattle-com/libs/CLI11/.gitignore
vendored
Normal file
7
libs/libbattle-com/libs/CLI11/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
a.out*
|
||||
*.swp
|
||||
/*build*
|
||||
/test_package/build
|
||||
/Makefile
|
||||
/CMakeFiles/*
|
||||
/cmake_install.cmake
|
||||
9
libs/libbattle-com/libs/CLI11/.gitmodules
vendored
Normal file
9
libs/libbattle-com/libs/CLI11/.gitmodules
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
[submodule "extern/googletest"]
|
||||
path = extern/googletest
|
||||
url = ../../google/googletest.git
|
||||
[submodule "extern/sanitizers"]
|
||||
path = extern/sanitizers
|
||||
url = ../../arsenm/sanitizers-cmake
|
||||
[submodule "extern/json"]
|
||||
path = extern/json
|
||||
url = ../../nlohmann/json.git
|
||||
140
libs/libbattle-com/libs/CLI11/.travis.yml
Normal file
140
libs/libbattle-com/libs/CLI11/.travis.yml
Normal file
@@ -0,0 +1,140 @@
|
||||
language: cpp
|
||||
dist: trusty
|
||||
|
||||
# Exclude ghpages,
|
||||
# but even better, don't build branch and PR, just PR
|
||||
# Include tags starting with v and a digit
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^v\d/
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
- "${TRAVIS_BUILD_DIR}/deps/doxygen"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Default clang
|
||||
- compiler: clang
|
||||
script:
|
||||
- .ci/make_and_test.sh 11
|
||||
- .ci/make_and_test.sh 14
|
||||
- .ci/make_and_test.sh 17
|
||||
|
||||
# Docs and clang 3.5
|
||||
- compiler: clang
|
||||
env:
|
||||
- DEPLOY_MAT=yes
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
install:
|
||||
- export CC=clang-3.5
|
||||
- export CXX=clang++-3.5
|
||||
script:
|
||||
- .ci/make_and_test.sh 11
|
||||
after_success:
|
||||
- export DOXYFILE=$TRAVIS_BUILD_DIR/docs/Doxyfile
|
||||
- export DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- |
|
||||
if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ]
|
||||
then
|
||||
. .ci/build_doxygen.sh
|
||||
.ci/build_docs.sh
|
||||
fi
|
||||
|
||||
# GCC 7 and coverage (8 does not support lcov, wait till 9 and new lcov)
|
||||
- compiler: gcc
|
||||
env:
|
||||
- GCC_VER=7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
- curl
|
||||
- lcov
|
||||
install:
|
||||
- export CC=gcc-7
|
||||
- export CXX=g++-7
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- ". .ci/build_lcov.sh"
|
||||
- ".ci/run_codecov.sh"
|
||||
script:
|
||||
- .ci/make_and_test.sh 11 -DCLI11_EXAMPLE_JSON=ON
|
||||
- .ci/make_and_test.sh 14 -DCLI11_EXAMPLE_JSON=ON
|
||||
- .ci/make_and_test.sh 17 -DCLI11_EXAMPLE_JSON=ON
|
||||
|
||||
# GCC 4.7 and Conan
|
||||
- compiler: gcc
|
||||
env:
|
||||
- GCC_VER=4.7
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.7
|
||||
install:
|
||||
- export CC=gcc-4.7
|
||||
- export CXX=g++-4.7
|
||||
- python -m pip install --user conan
|
||||
- conan user
|
||||
script:
|
||||
- .ci/make_and_test.sh 11
|
||||
after_success:
|
||||
- conan create . cliutils/stable
|
||||
- |
|
||||
if [ "${TRAVIS_TAG}" ]
|
||||
then
|
||||
conan remote add origin https://api.bintray.com/conan/cliutils/CLI11
|
||||
conan user -p ${BINFROG_API_KEY} -r origin henryiii
|
||||
conan upload "*" -c -r origin --all
|
||||
fi
|
||||
|
||||
# GCC 4.8
|
||||
- compiler: gcc
|
||||
env:
|
||||
- GCC_VER=4.8
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.8
|
||||
install:
|
||||
- export CC=gcc-4.8
|
||||
- export CXX=g++-4.8
|
||||
script:
|
||||
- .ci/make_and_test.sh 11
|
||||
|
||||
install: skip
|
||||
|
||||
script:
|
||||
- .ci/make_and_test.sh 11
|
||||
- .ci/make_and_test.sh 14
|
||||
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: L1svZ5J+RiR67dj1fNk/XiZRvYfGJC4c5/dKSvDH+yuKSzZ6ODaTiVmYF8NtMJ7/3AQenEa0OuRBVQ0YpngFz3ugIcRsGCDUHtCMK/Bti0+6ZFdICbqcv6W3BlRIM8s7EOBPhjfbCV+ae7xep9B24HmwBPKukMFjDIj4nwBsmwCHZK9iNFtfaW2J2cr2TJo7QPY01J0W1k/boaj91KzHf9UuhEH8KYqp7szv+6kV00W8bRBtugw419dIm25eXFXgXDT9s/OA7qXV7o5FXWWpkyJ5AINVbY9DerkYag5TStrdOyKk+S1FexRG6TMG4L4Jyu/QxQGhMdu0m1yRCLvIekGtWLDnjNrI2SZrd5HbKprQ0O8j1770Is4q5blVPqAZ6O9jVMJRtVEaYbsJwItz1BJWkPT4S9GFbDL1dq2Z5jR2f5gd/cz2yYH56b47iYHWtzSqEfVhsXiN+atD+tWyQFA4Q/av0bGHwJ6LX0A1q0OCHruUMoxcw1QKfYtV1bkf/folL4Z4Hx3CL+NB0Lkqs8LFsQHxODP4a26I5DS/kaDHofotho8wsWlKFDtonZa+CExORGFFMPnGRz2qX5tMgGoo84wcqrprfoQv2llqeUr3gISPl2qxrljAhj3/Dcl7iI7k0Er7Ji8ENpgjSec4aqnBx8Ke2yaDEmBvwbouFCM=
|
||||
skip_cleanup: true
|
||||
file: build/include/CLI11.hpp
|
||||
on:
|
||||
repo: CLIUtils/CLI11
|
||||
tags: true
|
||||
condition: "$DEPLOY_MAT = yes"
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/bbdb3befce4c00448d24
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: never
|
||||
env:
|
||||
global:
|
||||
- secure: cY0OI609iTAxLRYuYQnNMi+H6n0dBwioTAoFXGGRTnngw2V9om3UmY5eUu4HQEQsQZovHdYpNhlSgRmdwQ4UqSp3FGyrwobf0kzacV4bVnMDeXDmHt8RzE5wP/LwDd8elNF6RRYjElY99f0k0FyXVd0fIvuVkGKQECNLOtEk0jQo+4YTh7dhuCxRhBYgTbNiRL6UJynfrcK0YN+DQ+8CJNupu2VxgaEpCSngTfvDHLcddcrXwpvn3MPc3FsDUbtN389ZCIe41qqIL0ATv46DQaTw4FOevyVfRyrBOznONoGCVeAYKL6VBdrk01Fh6aytF5zgI3hKaKobgEn+QFfzR6l68c6APvqA0Qv39iLjuh6KbdIV2YsqXfyt6FBgqP2xZuNEZW1jZ8LxUOLl2I40UEh87nFutvnSbfIzN+FcLrajm2H2jV2kZGNKAMx+4qxkZuXSre4JPkENfJm2WNFAKlqPt4ZSEQarkDYzZPcEr2I9fbGjQYVJICoN4LikCv9K5z7ujpTxCTNbVpQWZcEOT6QQBc6Vml/N/NKAIl9o2OeTLiXCmT31+KQMeO492KYNQ6VmkeqrVhGExOUcJdNyDJV9C+3mSekb3Sq78SneYRKDechkWbMl0ol07wGTdBwQQwgaorjRyn07x1rDxpPr3z19/+eubnpPUW4UQ5MYsjs=
|
||||
- secure: G6H5HA9pPUgsd96A+uvTxbLjR1rcT9NtxsknIkFDfzGDpffn6wVX+kCIQLf9zFDnQnsfYA/4piiuoBN5U5C7HQrh9UCvBVptXjWviea0Y7CRbMJZpw2rPvXWQtrFNzYkaV7kdJ5B0Mmvh6rcH/I8gKFrkdjF7i7sfzWdFWRU5QXfxXOk2n+xCXX6uFemxHH9850XEjVtnU7YYUebQFaoTYLLy05nlt9JaEF84wfJljY/SJX7I9gpNLtizE9MpJylnrwUeL66OqFievmjL3/bWpPUBjUF0WdtXYlVDja7O582FQDs94ofgqeGieGIMQ0VuovpbQOJSdjs5XHZwu2ce6HZxtOhJJqw6xEwbq43ZdofAlJ5GUEOgrr+j25zIDkdzOhliDKJtw5ysmmTUKEcZ36iWbCE0YP/IC42yOV9oOP6UkgbuwpVDdxAFRgLZLahW9Ok+c1PlzIauPxv+jIEI4rSEEJRKZG2JK3TXUdhd58mHBfQMNjKQMF+Y2wCCGjfMO0q4SgvBhYyb4oBTxEqnc2Pzh2DJdNzRFsV7ktsQSRglHGVI+1XTmQ+2kbBzNOQBLjOuRvDZENUhyxPKGZDHyAOMlVvYm8vvWebM1/F3YgDb/tPh33+EGSvpKkCZ5nUxB5e605H6gdYlNKNhuWKlEKTo2/kF0D39gAUCIcGbzw=
|
||||
- CCACHE_CPP2: yes
|
||||
492
libs/libbattle-com/libs/CLI11/CHANGELOG.md
Normal file
492
libs/libbattle-com/libs/CLI11/CHANGELOG.md
Normal file
@@ -0,0 +1,492 @@
|
||||
## Version 1.8: Transformers, default strings, and flags
|
||||
|
||||
Set handling has been completely replaced by a new backend that works as a Validator or Transformer. This provides a single interface instead of the 16 different functions in App. It also allows ordered collections to be used, custom functions for filtering, and better help and error messages. You can also use a collection of pairs (like `std::map`) to transform the match into an output. Also new are inverted flags, which can cancel or reduce the count of flags, and can also support general flag types. A new `add_option_fn` lets you more easily program CLI11 options with the types you choose. Vector options now support a custom separator. Apps can now be composed with unnamed subcommand support. The final bool "defaults" flag when creating options has been replaced by `->capture_default_str()` (ending an old limitation in construction made this possible); the old method is still available but may be removed in future versions.
|
||||
|
||||
* Replaced default help capture: `.add_option("name", value, "", True)` becomes `.add_option("name", value)->capture_default_str()` [#242]
|
||||
* Added `.always_capture_default()` [#242]
|
||||
* New `CLI::IsMember` validator replaces set validation [#222]
|
||||
* IsMember also supports container of pairs, transform allows modification of result [#228]
|
||||
* Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue` [#253]
|
||||
* Much more powerful flags with different values [#211], general types [#235]
|
||||
* `add_option` now supports bool due to unified bool handling [#211]
|
||||
* Support for composable unnamed subcommands [#216]
|
||||
* Reparsing is better supported with `.remaining_for_passthrough()` [#265]
|
||||
* Custom vector separator using `->delimiter(char)` [#209], [#221], [#240]
|
||||
* Validators added for IP4 addresses and positive numbers [#210] and numbers [#262]
|
||||
* Minimum required Boost for optional Optionals has been corrected to 1.61 [#226]
|
||||
* Positionals can stop options from being parsed with `app.positionals_at_end()` [#223]
|
||||
* Added `validate_positionals` [#262]
|
||||
* Positional parsing is much more powerful [#251], duplicates supported []#247]
|
||||
* Validators can be negated with `!` [#230], and now handle tname functions [#228]
|
||||
* Better enum support and streaming helper [#233] and [#228]
|
||||
* Cleanup for shadow warnings [#232]
|
||||
* Better alignment on multiline descriptions [#269]
|
||||
* Better support for aarch64 [#266]
|
||||
* Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise, `CLI11_TESTING` must be used [#277]
|
||||
* Drop auto-detection of experimental optional and boost::optional; must be enabled explicitly (too fragile) [#277] [#279]
|
||||
|
||||
> ### Converting from CLI11 1.7:
|
||||
>
|
||||
> * `.add_option(..., true)` should be replaced by `.add_option(...)->capture_default_str()` or `app.option_defaults()->always_capture_default()` can be used
|
||||
> * `app.add_set("--name", value, {"choice1", "choice2"})` should become `app.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))`
|
||||
> * The `_ignore_case` version of this can be replaced by adding `CLI::ignore_case` to the argument list in `IsMember`
|
||||
> * The `_ignore_underscore` version of this can be replaced by adding `CLI::ignore_underscore` to the argument list in `IsMember`
|
||||
> * The `_ignore_case_underscore` version of this can be replaced by adding both functions listed above to the argument list in `IsMember`
|
||||
> * If you want an exact match to the original choice after one of the modifier functions matches, use `->transform` instead of `->check`
|
||||
> * The `_mutable` versions of this can be replaced by passing a pointer or shared pointer into `IsMember`
|
||||
> * An error with sets now produces a `ValidationError` instead of a `ConversionError`
|
||||
|
||||
[#209]: https://github.com/CLIUtils/CLI11/pull/209
|
||||
[#210]: https://github.com/CLIUtils/CLI11/pull/210
|
||||
[#211]: https://github.com/CLIUtils/CLI11/pull/211
|
||||
[#216]: https://github.com/CLIUtils/CLI11/pull/216
|
||||
[#221]: https://github.com/CLIUtils/CLI11/pull/221
|
||||
[#222]: https://github.com/CLIUtils/CLI11/pull/222
|
||||
[#223]: https://github.com/CLIUtils/CLI11/pull/223
|
||||
[#226]: https://github.com/CLIUtils/CLI11/pull/226
|
||||
[#228]: https://github.com/CLIUtils/CLI11/pull/228
|
||||
[#230]: https://github.com/CLIUtils/CLI11/pull/230
|
||||
[#232]: https://github.com/CLIUtils/CLI11/pull/232
|
||||
[#233]: https://github.com/CLIUtils/CLI11/pull/233
|
||||
[#235]: https://github.com/CLIUtils/CLI11/pull/235
|
||||
[#240]: https://github.com/CLIUtils/CLI11/pull/240
|
||||
[#242]: https://github.com/CLIUtils/CLI11/pull/242
|
||||
[#247]: https://github.com/CLIUtils/CLI11/pull/247
|
||||
[#251]: https://github.com/CLIUtils/CLI11/pull/251
|
||||
[#253]: https://github.com/CLIUtils/CLI11/pull/253
|
||||
[#262]: https://github.com/CLIUtils/CLI11/pull/262
|
||||
[#265]: https://github.com/CLIUtils/CLI11/pull/265
|
||||
[#266]: https://github.com/CLIUtils/CLI11/pull/266
|
||||
[#269]: https://github.com/CLIUtils/CLI11/pull/269
|
||||
[#277]: https://github.com/CLIUtils/CLI11/pull/277
|
||||
[#279]: https://github.com/CLIUtils/CLI11/pull/279
|
||||
|
||||
|
||||
## Version 1.7.1: Quick patch
|
||||
|
||||
This version provides a quick patch for a (correct) warning from GCC 8 for the windows options code.
|
||||
|
||||
|
||||
* Fix for Windows style option parsing [#201]
|
||||
* Improve `add_subcommand` when throwing an exception [#204]
|
||||
* Better metadata for Conan package [#202]
|
||||
|
||||
[#201]: https://github.com/CLIUtils/CLI11/pull/201
|
||||
[#202]: https://github.com/CLIUtils/CLI11/pull/202
|
||||
[#204]: https://github.com/CLIUtils/CLI11/pull/204
|
||||
|
||||
## Version 1.7: Parse breakup
|
||||
|
||||
The parsing procedure now maps much more sensibly to complex, nested subcommand structures. Each phase of the parsing happens on all subcommands before moving on with the next phase of the parse. This allows several features, like required environment variables, to work properly even through subcommand boundaries.
|
||||
Passing the same subcommand multiple times is better supported. Several new features were added as well, including Windows style option support, parsing strings directly, and ignoring underscores in names. Adding a set that you plan to change later must now be done with `add_mutable_set`.
|
||||
|
||||
* Support Windows style options with `->allow_windows_style_options`. [#187] On by default on Windows. [#190]
|
||||
* Added `parse(string)` to split up and parse a command-line style string directly. [#186]
|
||||
* Added `ignore_underscore` and related functions, to ignore underscores when matching names. [#185]
|
||||
* The default INI Config will now add quotes to strings with spaces [#195]
|
||||
* The default message now will mention the help-all flag also if present [#197]
|
||||
* Added `->description` to set Option descriptions [#199]
|
||||
* Mutating sets (introduced in Version 1.6) now have a clear add method, `add_mutable_set*`, since the set reference should not expire [#200]
|
||||
* Subcommands now track how many times they were parsed in a parsing process. `count()` with no arguments will return the number of times a subcommand was encountered. [#179]
|
||||
* Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and `requirements`; all subcommands complete a phase before moving on. [#179]
|
||||
* Calling parse multiple times is now officially supported without `clear` (automatic). [#179]
|
||||
* Dropped the mostly undocumented `short_circuit` property, as help flag parsing is a bit more complex, and the default callback behavior of options now works properly. [#179]
|
||||
* Use the standard `BUILD_TESTING` over `CLI11_TESTING` if defined [#183]
|
||||
* Cleanup warnings [#191]
|
||||
* Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and `set_type_name`. Use without the `set_` instead. [#192]
|
||||
|
||||
> ### Converting from CLI11 1.6:
|
||||
>
|
||||
> * `->short_circuit()` is no longer needed, just remove it if you were using it - raising an exception will happen in the proper place now without it.
|
||||
> * `->add_set*` becomes `->add_mutable_set*` if you were using the editable set feature
|
||||
> * `footer`, `name`, `callback`, and `type_name` must be used instead of the `set_*` versions (deprecated previously).
|
||||
|
||||
[#179]: https://github.com/CLIUtils/CLI11/pull/179
|
||||
[#183]: https://github.com/CLIUtils/CLI11/pull/183
|
||||
[#185]: https://github.com/CLIUtils/CLI11/pull/185
|
||||
[#186]: https://github.com/CLIUtils/CLI11/pull/186
|
||||
[#187]: https://github.com/CLIUtils/CLI11/pull/187
|
||||
[#190]: https://github.com/CLIUtils/CLI11/pull/190
|
||||
[#191]: https://github.com/CLIUtils/CLI11/pull/191
|
||||
[#192]: https://github.com/CLIUtils/CLI11/pull/192
|
||||
[#197]: https://github.com/CLIUtils/CLI11/pull/197
|
||||
[#195]: https://github.com/CLIUtils/CLI11/issues/195
|
||||
[#199]: https://github.com/CLIUtils/CLI11/pull/199
|
||||
[#200]: https://github.com/CLIUtils/CLI11/pull/200
|
||||
|
||||
## Version 1.6.2: Help-all
|
||||
|
||||
This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. Several smaller fixes.
|
||||
|
||||
* Fixed help-all formatting [#163]
|
||||
* Printing help-all on nested command now fixed (App)
|
||||
* Missing space after help-all restored (Default formatter)
|
||||
* More detail printed on help all (Default formatter)
|
||||
* Help-all subcommands get indented with inner blank lines removed (Default formatter)
|
||||
* `detail::find_and_replace` added to utilities
|
||||
* Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156]
|
||||
* Fixed warning about local variable hiding class member with MSVC [#157]
|
||||
* Fixed compile error with default settings on Clang 7 and libc++ [#158]
|
||||
* Fixed special case of `--help` on subcommands (general fix planned for 1.7) [#168]
|
||||
* Removing an option with links [#179]
|
||||
|
||||
[#156]: https://github.com/CLIUtils/CLI11/issues/156
|
||||
[#157]: https://github.com/CLIUtils/CLI11/issues/157
|
||||
[#158]: https://github.com/CLIUtils/CLI11/issues/158
|
||||
[#163]: https://github.com/CLIUtils/CLI11/pull/163
|
||||
[#168]: https://github.com/CLIUtils/CLI11/issues/168
|
||||
[#179]: https://github.com/CLIUtils/CLI11/pull/179
|
||||
|
||||
|
||||
## Version 1.6.1: Platform fixes
|
||||
|
||||
This version provides a few fixes for special cases, such as mixing with `Windows.h` and better defaults
|
||||
for systems like Hunter. The one new feature is the ability to produce "branded" single file output for
|
||||
providing custom namespaces or custom macro names.
|
||||
|
||||
* Added fix and test for including Windows.h [#145]
|
||||
* No longer build single file by default if main project, supports systems stuck on Python 2.6 [#149], [#151]
|
||||
* Branding support for single file output [#150]
|
||||
|
||||
[#145]: https://github.com/CLIUtils/CLI11/pull/145
|
||||
[#149]: https://github.com/CLIUtils/CLI11/pull/149
|
||||
[#150]: https://github.com/CLIUtils/CLI11/pull/150
|
||||
[#151]: https://github.com/CLIUtils/CLI11/pull/151
|
||||
|
||||
## Version 1.6: Formatting help
|
||||
|
||||
Added a new formatting system [#109]. You can now set the formatter on Apps. This has also simplified the internals of Apps and Options a bit by separating most formatting code.
|
||||
|
||||
* Added `CLI::Formatter` and `formatter` slot for apps, inherited.
|
||||
* `FormatterBase` is the minimum required.
|
||||
* `FormatterLambda` provides for the easy addition of an arbitrary function.
|
||||
* Added `help_all` support (not added by default).
|
||||
|
||||
Changes to the help system (most normal users will not notice this):
|
||||
|
||||
* Renamed `single_name` to `get_name(false, false)` (the default).
|
||||
* The old `get_name()` is now `get_name(false, true)`.
|
||||
* The old `get_pname()` is now `get_name(true, false)`.
|
||||
* Removed `help_*` functions.
|
||||
* Protected function `_has_help_positional` removed.
|
||||
* `format_help` can now be chained.
|
||||
* Added getters for the missing parts of options (help no longer uses any private parts).
|
||||
* Help flags now use new `short_circuit` property to simplify parsing. [#121]
|
||||
|
||||
|
||||
New for Config file reading and writing [#121]:
|
||||
|
||||
* Overridable, bidirectional Config.
|
||||
* ConfigINI provided and used by default.
|
||||
* Renamed ini to config in many places.
|
||||
* Has `config_formatter()` and `get_config_formatter()`.
|
||||
* Dropped prefix argument from `config_to_str`.
|
||||
* Added `ConfigItem`.
|
||||
* Added an example of a custom config format using [nlohmann/json]. [#138]
|
||||
|
||||
|
||||
Validators are now much more powerful [#118], all built in validators upgraded to the new form:
|
||||
|
||||
* A subclass of `CLI::Validator` is now also accepted.
|
||||
* They now can set the type name to things like `PATH` and `INT in [1-4]`.
|
||||
* Validators can be combined with `&` and `|`.
|
||||
* Old form simple validators are still accepted.
|
||||
|
||||
Other changes:
|
||||
|
||||
* Fixing `parse(args)`'s `args` setting and ordering after parse. [#141]
|
||||
* Replaced `set_custom_option` with `type_name` and `type_size` instead of `set_custom_option`. Methods return `this`. [#136]
|
||||
* Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`. [#136]
|
||||
* Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`. [#136]
|
||||
* Fixed support `N<-1` for `type_size`. [#140]
|
||||
* Added `->each()` to make adding custom callbacks easier. [#126]
|
||||
* Allow empty options `add_option("-n",{})` to be edited later with `each` [#142]
|
||||
* Added filter argument to `get_subcommands`, `get_options`; use empty filter `{}` to avoid filtering.
|
||||
* Added `get_groups()` to get groups.
|
||||
* Better support for manual options with `get_option`, `set_results`, and `empty`. [#119]
|
||||
* `lname` and `sname` have getters, added `const get_parent`. [#120]
|
||||
* Using `add_set` will now capture L-values for sets, allowing further modification. [#113]
|
||||
* Dropped duplicate way to run `get_type_name` (`get_typeval`).
|
||||
* Removed `requires` in favor of `needs` (deprecated in last version). [#112]
|
||||
* Const added to argv. [#126]
|
||||
|
||||
Backend and testing changes:
|
||||
|
||||
* Internally, `type_name` is now a lambda function; for sets, this reads the set live. [#116]
|
||||
* Cleaner tests without `app.reset()` (and `reset` is now `clear`). [#141]
|
||||
* Better CMake policy handling. [#110]
|
||||
* Includes are properly sorted. [#120]
|
||||
* Testing (only) now uses submodules. [#111]
|
||||
|
||||
[#109]: https://github.com/CLIUtils/CLI11/pull/109
|
||||
[#110]: https://github.com/CLIUtils/CLI11/pull/110
|
||||
[#111]: https://github.com/CLIUtils/CLI11/pull/111
|
||||
[#112]: https://github.com/CLIUtils/CLI11/pull/112
|
||||
[#113]: https://github.com/CLIUtils/CLI11/issues/113
|
||||
[#116]: https://github.com/CLIUtils/CLI11/pull/116
|
||||
[#118]: https://github.com/CLIUtils/CLI11/pull/118
|
||||
[#119]: https://github.com/CLIUtils/CLI11/pull/119
|
||||
[#120]: https://github.com/CLIUtils/CLI11/pull/120
|
||||
[#121]: https://github.com/CLIUtils/CLI11/pull/121
|
||||
[#126]: https://github.com/CLIUtils/CLI11/pull/126
|
||||
[#127]: https://github.com/CLIUtils/CLI11/pull/127
|
||||
[#138]: https://github.com/CLIUtils/CLI11/pull/138
|
||||
[#140]: https://github.com/CLIUtils/CLI11/pull/140
|
||||
[#141]: https://github.com/CLIUtils/CLI11/pull/141
|
||||
[#142]: https://github.com/CLIUtils/CLI11/pull/142
|
||||
|
||||
[nlohmann/json]: https://github.com/nlohmann/json
|
||||
|
||||
### Version 1.5.4: Optionals
|
||||
This version fixes the optional search in the single file version; some macros were not yet defined when it did the search. You can define the `CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search.
|
||||
|
||||
### Version 1.5.3: Compiler compatibility
|
||||
This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.
|
||||
|
||||
### Version 1.5.2: LICENSE in single header mode
|
||||
|
||||
This is a quick patch release that makes LICENSE part of the single header file, making it easier to include. Minor cleanup from codacy. No significant code changes from 1.5.1.
|
||||
|
||||
### Version 1.5.1: Access
|
||||
|
||||
This patch release adds better access to the App progromatically, to assist with writing custom converters to other formats. It also improves the help output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way unlimited options and positionals interact.
|
||||
|
||||
* Make mixing unlimited positionals and options more intuitive [#102]
|
||||
* Add missing getters `get_options` and `get_description` to App [#105]
|
||||
* The app name now can be set, and will override the auto name if present [#105]
|
||||
* Add `(REQUIRED)` for required options [#104]
|
||||
* Print simple name for Needs/Excludes [#104]
|
||||
* Use Needs instead of Requires in help print [#104]
|
||||
* Groups now are listed in the original definition order [#106]
|
||||
|
||||
[#102]: https://github.com/CLIUtils/CLI11/issues/102
|
||||
[#104]: https://github.com/CLIUtils/CLI11/pull/104
|
||||
[#105]: https://github.com/CLIUtils/CLI11/pull/105
|
||||
[#106]: https://github.com/CLIUtils/CLI11/pull/106
|
||||
|
||||
|
||||
## Version 1.5: Optionals
|
||||
|
||||
This version introduced support for optionals, along with clarification and examples of custom conversion overloads. Enums now have been dropped from the automatic conversion system, allowing explicit protection for out-of-range ints (or a completely custom conversion). This version has some internal cleanup and improved support for the newest compilers. Several bugs were fixed, as well.
|
||||
|
||||
Note: This is the final release with `requires`, please switch to `needs`.
|
||||
|
||||
* Fix unlimited short options eating two values before checking for positionals when no space present [#90]
|
||||
* Symmetric exclude text when excluding options, exclude can be called multiple times [#64]
|
||||
* Support for `std::optional`, `std::experimental::optional`, and `boost::optional` added if `__has_include` is supported [#95]
|
||||
* All macros/CMake variables now start with `CLI11_` instead of just `CLI_` [#95]
|
||||
* The internal stream was not being cleared before use in some cases. Fixed. [#95]
|
||||
* Using an emum now requires explicit conversion overload [#97]
|
||||
* The separator `--` now is removed when it ends unlimited arguments [#100]
|
||||
|
||||
Other, non-user facing changes:
|
||||
|
||||
* Added `Macros.hpp` with better C++ mode discovery [#95]
|
||||
* Deprecated macros added for all platforms
|
||||
* C++17 is now tested on supported platforms [#95]
|
||||
* Informational printout now added to CTest [#95]
|
||||
* Better single file generation [#95]
|
||||
* Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next version of GTest)
|
||||
* Types now have a specific size, separate from the expected number - cleaner and more powerful internally [#92]
|
||||
* Examples now run as part of testing [#99]
|
||||
|
||||
[#64]: https://github.com/CLIUtils/CLI11/issues/64
|
||||
[#90]: https://github.com/CLIUtils/CLI11/issues/90
|
||||
[#92]: https://github.com/CLIUtils/CLI11/issues/92
|
||||
[#95]: https://github.com/CLIUtils/CLI11/pull/95
|
||||
[#97]: https://github.com/CLIUtils/CLI11/pull/97
|
||||
[#99]: https://github.com/CLIUtils/CLI11/pull/99
|
||||
[#100]: https://github.com/CLIUtils/CLI11/pull/100
|
||||
|
||||
|
||||
## Version 1.4: More feedback
|
||||
|
||||
This version adds lots of smaller fixes and additions after the refactor in version 1.3. More ways to download and use CLI11 in CMake have been added. INI files have improved support.
|
||||
|
||||
* Lexical cast is now more strict than before [#68] and fails on overflow [#84]
|
||||
* Added `get_parent()` to access the parent from a subcommand
|
||||
* Added `ExistingPath` validator [#73]
|
||||
* `app.allow_ini_extras()` added to allow extras in INI files [#70]
|
||||
* Multiline INI comments now supported
|
||||
* Descriptions can now be written with `config_to_str` [#66]
|
||||
* Double printing of error message fixed [#77]
|
||||
* Renamed `requires` to `needs` to avoid C++20 keyword [#75], [#82]
|
||||
* MakeSingleHeader now works if outside of git [#78]
|
||||
* Adding install support for CMake [#79], improved support for `find_package` [#83], [#84]
|
||||
* Added support for Conan.io [#83]
|
||||
|
||||
[#70]: https://github.com/CLIUtils/CLI11/issues/70
|
||||
[#75]: https://github.com/CLIUtils/CLI11/issues/75
|
||||
|
||||
[#84]: https://github.com/CLIUtils/CLI11/pull/84
|
||||
[#83]: https://github.com/CLIUtils/CLI11/pull/83
|
||||
[#82]: https://github.com/CLIUtils/CLI11/pull/82
|
||||
[#79]: https://github.com/CLIUtils/CLI11/pull/79
|
||||
[#78]: https://github.com/CLIUtils/CLI11/pull/78
|
||||
[#77]: https://github.com/CLIUtils/CLI11/pull/77
|
||||
[#73]: https://github.com/CLIUtils/CLI11/pull/73
|
||||
[#68]: https://github.com/CLIUtils/CLI11/pull/68
|
||||
[#66]: https://github.com/CLIUtils/CLI11/pull/66
|
||||
|
||||
## Version 1.3: Refactor
|
||||
|
||||
This version focused on refactoring several key systems to ensure correct behavior in the interaction of different settings. Most caveats about
|
||||
features only working on the main App have been addressed, and extra arguments have been reworked. Inheritance
|
||||
of defaults makes configuring CLI11 much easier without having to subclass. Policies add new ways to handle multiple arguments to match your
|
||||
favorite CLI programs. Error messages and help messages are better and more flexible. Several bugs and odd behaviors in the parser have been fixed.
|
||||
|
||||
* Added a version macro, `CLI11_VERSION`, along with `*_MAJOR`, `*_MINOR`, and `*_PATCH`, for programmatic access to the version.
|
||||
* Reworked the way defaults are set and inherited; explicit control given to user with `->option_defaults()` [#48](https://github.com/CLIUtils/CLI11/pull/48)
|
||||
* Hidden options now are based on an empty group name, instead of special "hidden" keyword [#48](https://github.com/CLIUtils/CLI11/pull/48)
|
||||
* `parse` no longer returns (so `CLI11_PARSE` is always usable) [#37](https://github.com/CLIUtils/CLI11/pull/37)
|
||||
* Added `remaining()` and `remaining_size()` [#37](https://github.com/CLIUtils/CLI11/pull/37)
|
||||
* `allow_extras` and `prefix_command` are now valid on subcommands [#37](https://github.com/CLIUtils/CLI11/pull/37)
|
||||
* Added `take_last` to only take last value passed [#40](https://github.com/CLIUtils/CLI11/pull/40)
|
||||
* Added `multi_option_policy` and shortcuts to provide more control than just a take last policy [#59](https://github.com/CLIUtils/CLI11/pull/59)
|
||||
* More detailed error messages in a few cases [#41](https://github.com/CLIUtils/CLI11/pull/41)
|
||||
* Footers can be added to help [#42](https://github.com/CLIUtils/CLI11/pull/42)
|
||||
* Help flags are easier to customize [#43](https://github.com/CLIUtils/CLI11/pull/43)
|
||||
* Subcommand now support groups [#46](https://github.com/CLIUtils/CLI11/pull/46)
|
||||
* `CLI::RuntimeError` added, for easy exit with error codes [#45](https://github.com/CLIUtils/CLI11/pull/45)
|
||||
* The clang-format script is now no longer "hidden" [#48](https://github.com/CLIUtils/CLI11/pull/48)
|
||||
* The order is now preserved for subcommands (list and callbacks) [#49](https://github.com/CLIUtils/CLI11/pull/49)
|
||||
* Tests now run individually, utilizing CMake 3.10 additions if possible [#50](https://github.com/CLIUtils/CLI11/pull/50)
|
||||
* Failure messages are now customizable, with a shorter default [#52](https://github.com/CLIUtils/CLI11/pull/52)
|
||||
* Some improvements to error codes [#53](https://github.com/CLIUtils/CLI11/pull/53)
|
||||
* `require_subcommand` now offers a two-argument form and negative values on the one-argument form are more useful [#51](https://github.com/CLIUtils/CLI11/pull/51)
|
||||
* Subcommands no longer match after the max required number is obtained [#51](https://github.com/CLIUtils/CLI11/pull/51)
|
||||
* Unlimited options no longer prioritize over remaining/unlimited positionals [#51](https://github.com/CLIUtils/CLI11/pull/51)
|
||||
* Added `->transform` which modifies the string parsed [#54](https://github.com/CLIUtils/CLI11/pull/54)
|
||||
* Changed of API in validators to `void(std::string &)` (const for users), throwing providing nicer errors [#54](https://github.com/CLIUtils/CLI11/pull/54)
|
||||
* Added `CLI::ArgumentMismatch` [#56](https://github.com/CLIUtils/CLI11/pull/56) and fixed missing failure if one arg expected [#55](https://github.com/CLIUtils/CLI11/issues/55)
|
||||
* Support for minimum unlimited expected arguments [#56](https://github.com/CLIUtils/CLI11/pull/56)
|
||||
* Single internal arg parse function [#56](https://github.com/CLIUtils/CLI11/pull/56)
|
||||
* Allow options to be disabled from INI file, rename `add_config` to `set_config` [#60](https://github.com/CLIUtils/CLI11/pull/60)
|
||||
|
||||
> ### Converting from CLI11 1.2:
|
||||
>
|
||||
> * `app.parse` no longer returns a vector. Instead, use `app.remaining(true)`.
|
||||
> * `"hidden"` is no longer a special group name, instead use `""`
|
||||
> * Validators API has changed to return an error string; use `.empty()` to get the old bool back
|
||||
> * Use `.set_help_flag` instead of accessing the help pointer directly (discouraged, but not removed yet)
|
||||
> * `add_config` has been renamed to `set_config`
|
||||
> * Errors thrown in some cases are slightly more specific
|
||||
|
||||
## Version 1.2: Stability
|
||||
|
||||
This release focuses on making CLI11 behave properly in corner cases, and with config files on the command line. This includes fixes for a variety of reported issues. A few features were added to make life easier, as well; such as a new flag callback and a macro for the parse command.
|
||||
|
||||
* Added functional form of flag [#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14
|
||||
* Fixed Config file search if passed on command line [#30](https://github.com/CLIUtils/CLI11/issues/30)
|
||||
* Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not support returning arg)
|
||||
* The name string can now contain spaces around commas [#29](https://github.com/CLIUtils/CLI11/pull/29)
|
||||
* `set_default_str` now only sets string, and `set_default_val` will evaluate the default string given [#26](https://github.com/CLIUtils/CLI11/issues/26)
|
||||
* Required positionals now take priority over subcommands [#23](https://github.com/CLIUtils/CLI11/issues/23)
|
||||
* Extra requirements enforced by Travis
|
||||
|
||||
## Version 1.1: Feedback
|
||||
|
||||
This release incorporates feedback from the release announcement. The examples are slowly being expanded, some corner cases improved, and some new functionality for tricky parsing situations.
|
||||
|
||||
* Added simple support for enumerations, allow non-printable objects [#12](https://github.com/CLIUtils/CLI11/issues/12)
|
||||
* Added `app.parse_order()` with original parse order ([#13](https://github.com/CLIUtils/CLI11/issues/13), [#16](https://github.com/CLIUtils/CLI11/pull/16))
|
||||
* Added `prefix_command()`, which is like `allow_extras` but instantly stops and returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8), [#17](https://github.com/CLIUtils/CLI11/pull/17))
|
||||
* Removed Windows warning ([#10](https://github.com/CLIUtils/CLI11/issues/10), [#20](https://github.com/CLIUtils/CLI11/pull/20))
|
||||
* Some improvements to CMake, detect Python and no dependencies on Python 2 (like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18), [#21](https://github.com/CLIUtils/CLI11/pull/21))
|
||||
|
||||
## Version 1.0: Official release
|
||||
|
||||
This is the first stable release for CLI11. Future releases will try to remain backward compatible and will follow semantic versioning if possible. There were a few small changes since version 0.9:
|
||||
|
||||
* Cleanup using `clang-tidy` and `clang-format`
|
||||
* Small improvements to Timers, easier to subclass Error
|
||||
* Move to 3-Clause BSD license
|
||||
|
||||
## Version 0.9: Polish
|
||||
|
||||
This release focused on cleaning up the most exotic compiler warnings, fixing a few oddities of the config parser, and added a more natural method to check subcommands.
|
||||
|
||||
* Better CMake named target (CLI11)
|
||||
* More warnings added, fixed
|
||||
* Ini output now includes `=false` when `default_also` is true
|
||||
* Ini no longer lists the help pointer
|
||||
* Added test for inclusion in multiple files and linking, fixed issues (rarely needed for CLI, but nice for tools)
|
||||
* Support for complex numbers
|
||||
* Subcommands now test true/false directly or with `->parsed()`, cleaner parse
|
||||
|
||||
## Version 0.8: CLIUtils
|
||||
|
||||
This release moved the repository to the CLIUtils master organization.
|
||||
|
||||
* Moved to CLIUtils on GitHub
|
||||
* Fixed docs build and a few links
|
||||
|
||||
## Version 0.7: Code coverage 100%
|
||||
|
||||
Lots of small bugs fixed when adding code coverage, better in edge cases. Much more powerful ini support.
|
||||
|
||||
* Allow comments in ini files (lines starting with `;`)
|
||||
* Ini files support flags, vectors, subcommands
|
||||
* Added CodeCov code coverage reports
|
||||
* Lots of small bugfixes related to adding tests to increase coverage to 100%
|
||||
* Error handling now uses scoped enum in errors
|
||||
* Reparsing rules changed a little to accommodate Ini files. Callbacks are now called when parsing INI, and reset any time results are added.
|
||||
* Adding extra utilities in full version only, `Timer` (not needed for parsing, but useful for general CLI applications).
|
||||
* Better support for custom `add_options` like functions.
|
||||
|
||||
## Version 0.6: Cleanup
|
||||
|
||||
Lots of cleanup and docs additions made it into this release. Parsing is simpler and more robust; fall through option added and works as expected; much more consistent variable names internally.
|
||||
|
||||
* Simplified parsing to use `vector<string>` only
|
||||
* Fixed fallthrough, made it optional as well (default: off): `.fallthrough()`.
|
||||
* Added string versions of `->requires()` and `->excludes()` for consistency.
|
||||
* Renamed protected members for internal consistency, grouped docs.
|
||||
* Added the ability to add a number to `.require_subcommand()`.
|
||||
|
||||
## Version 0.5: Windows support
|
||||
|
||||
* Allow `Hidden` options.
|
||||
* Throw `OptionAlreadyAdded` errors for matching subcommands or options, with ignore-case included, tests
|
||||
* `->ignore_case()` added to subcommands, options, and `add_set_ignore_case`. Subcommands inherit setting from parent App on creation.
|
||||
* Subcommands now can be "chained", that is, left over arguments can now include subcommands that then get parsed. Subcommands are now a list (`get_subcommands`). Added `got_subcommand(App_or_name)` to check for subcommands.
|
||||
* Added `.allow_extras()` to disable error on failure. Parse returns a vector of leftover options. Renamed error to `ExtrasError`, and now triggers on extra options too.
|
||||
* Added `require_subcommand` to `App`, to simplify forcing subcommands. Do **not** do `add_subcommand()->require_subcommand`, since that is the subcommand, not the master `App`.
|
||||
* Added printout of ini file text given parsed options, skips flags.
|
||||
* Support for quotes and spaces in ini files
|
||||
* Fixes to allow support for Windows (added Appveyor) (Uses `-`, not `/` syntax)
|
||||
|
||||
## Version 0.4: Ini support
|
||||
|
||||
* Updates to help print
|
||||
* Removed `run`, please use `parse` unless you subclass and add it
|
||||
* Supports ini files mixed with command line, tested
|
||||
* Added Range for further Plumbum compatibility
|
||||
* Added function to print out ini file
|
||||
|
||||
## Version 0.3: Plumbum compatibility
|
||||
|
||||
* Added `->requires`, `->excludes`, and `->envname` from [Plumbum](http://plumbum.readthedocs.io/en/latest/)
|
||||
* Supports `->mandatory` from Plubmum
|
||||
* More tests for help strings, improvements in formatting
|
||||
* Support type and set syntax in positionals help strings
|
||||
* Added help groups, with `->group("name")` syntax
|
||||
* Added initial support for ini file reading with `add_config` option.
|
||||
* Supports GCC 4.7 again
|
||||
* Clang 3.5 now required for tests due to googlemock usage, 3.4 should still work otherwise
|
||||
* Changes `setup` for an explicit help bool in constructor/`add_subcommand`
|
||||
|
||||
## Version 0.2: Leaner and meaner
|
||||
|
||||
* Moved to simpler syntax, where `Option` pointers are returned and operated on
|
||||
* Removed `make_` style options
|
||||
* Simplified Validators, now only requires `->check(function)`
|
||||
* Removed Combiners
|
||||
* Fixed pointers to Options, stored in `unique_ptr` now
|
||||
* Added `Option_p` and `App_p`, mostly for internal use
|
||||
* Startup sequence, including help flag, can be modified by subclasses
|
||||
|
||||
## Version 0.1: First release
|
||||
|
||||
First release before major cleanup. Still has make syntax and combiners; very clever syntax but not the best or most commonly expected way to work.
|
||||
|
||||
219
libs/libbattle-com/libs/CLI11/CMakeLists.txt
Normal file
219
libs/libbattle-com/libs/CLI11/CMakeLists.txt
Normal file
@@ -0,0 +1,219 @@
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
# Note: this is a header only library. If you have an older CMake than 3.4,
|
||||
# just add the CLI11/include directory and that's all you need to do.
|
||||
|
||||
# Make sure users don't get warnings on a tested (3.4 to 3.14) version
|
||||
# of CMake. For most of the policies, the new version is better (hence the change).
|
||||
# We don't use the 3.4...3.14 syntax because of a bug in a version of MSVC
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.14)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.14)
|
||||
endif()
|
||||
|
||||
set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"")
|
||||
|
||||
# Read in the line containing the version
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/Version.hpp"
|
||||
VERSION_STRING REGEX ${VERSION_REGEX})
|
||||
|
||||
# Pick out just the version
|
||||
string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}")
|
||||
|
||||
# Add the project
|
||||
project(CLI11 LANGUAGES CXX VERSION ${VERSION_STRING})
|
||||
|
||||
# Special target that adds warnings. Is not exported.
|
||||
add_library(CLI11_warnings INTERFACE)
|
||||
|
||||
# Only if built as the main project
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
# User settable
|
||||
set(CLI11_CXX_STD "11" CACHE STRING "The CMake standard to require")
|
||||
|
||||
# Special override for Clang on Linux (useful with an old stdlibc++ and a newer clang)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
option(CLI11_FORCE_LIBCXX "Force Clang to use libc++ instead of libstdc++ (Linux only)" OFF)
|
||||
if(CLI11_FORCE_LIBCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CUR_PROJ ON)
|
||||
set(CMAKE_CXX_STANDARD ${CLI11_CXX_STD})
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
option(CLI11_WARNINGS_AS_ERRORS "Turn all warnings into errors (for CI)")
|
||||
|
||||
# Be moderately paranoid with flags
|
||||
if(MSVC)
|
||||
target_compile_options(CLI11_warnings INTERFACE "/W4")
|
||||
if(CLI11_WARNINGS_AS_ERRORS)
|
||||
target_compile_options(CLI11_warnings INTERFACE "/WX")
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(CLI11_warnings INTERFACE -Wall -Wextra -pedantic -Wshadow)
|
||||
if(CLI11_WARNINGS_AS_ERRORS)
|
||||
target_compile_options(CLI11_warnings INTERFACE -Werror)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.6)
|
||||
# Add clang-tidy if available
|
||||
option(CLANG_TIDY_FIX "Perform fixes for Clang-Tidy" OFF)
|
||||
find_program(
|
||||
CLANG_TIDY_EXE
|
||||
NAMES "clang-tidy"
|
||||
DOC "Path to clang-tidy executable"
|
||||
)
|
||||
|
||||
if(CLANG_TIDY_EXE)
|
||||
if(CLANG_TIDY_FIX)
|
||||
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-fix")
|
||||
else()
|
||||
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(CUR_PROJ OFF)
|
||||
endif()
|
||||
|
||||
# Allow dependent options
|
||||
include(CMakeDependentOption)
|
||||
|
||||
# Allow IDE's to group targets into folders
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
file(GLOB CLI11_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/*")
|
||||
# To see in IDE, must be listed for target
|
||||
|
||||
add_library(CLI11 INTERFACE)
|
||||
|
||||
# Duplicated because CMake adds the current source dir if you don't.
|
||||
target_include_directories(CLI11 INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
# Make add_subdirectory work like find_package
|
||||
add_library(CLI11::CLI11 ALIAS CLI11)
|
||||
|
||||
option(CLI11_INSTALL "Install the CLI11 folder to include during install process" ${CUR_PROJ})
|
||||
|
||||
# This folder should be installed
|
||||
if(CLI11_INSTALL)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include)
|
||||
|
||||
# Make an export target
|
||||
install(TARGETS CLI11
|
||||
EXPORT CLI11Targets)
|
||||
endif()
|
||||
|
||||
# Use find_package on the installed package
|
||||
# Since we have no custom code, we can directly write this
|
||||
# to Config.cmake (otherwise we'd have a custom config and would
|
||||
# import Targets.cmake
|
||||
|
||||
# Add the version in a CMake readable way
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CLI11ConfigVersion.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CLI11ConfigVersion.cmake" @ONLY)
|
||||
|
||||
# These installs only make sense for a local project
|
||||
if(CUR_PROJ)
|
||||
# Make version available in the install
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/CLI11ConfigVersion.cmake"
|
||||
DESTINATION lib/cmake/CLI11)
|
||||
|
||||
# Install the export target as a file
|
||||
install(EXPORT CLI11Targets
|
||||
FILE CLI11Config.cmake
|
||||
NAMESPACE CLI11::
|
||||
DESTINATION lib/cmake/CLI11)
|
||||
|
||||
# Use find_package on the installed package
|
||||
export(TARGETS CLI11
|
||||
NAMESPACE CLI11::
|
||||
FILE CLI11Targets.cmake)
|
||||
|
||||
# Register in the user cmake package registry
|
||||
export(PACKAGE CLI11)
|
||||
endif()
|
||||
|
||||
option(CLI11_SINGLE_FILE "Generate a single header file" OFF)
|
||||
|
||||
if(CLI11_SINGLE_FILE)
|
||||
# Single file test
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
set(Python_VERSION ${PYTHON_VERSION_STRING})
|
||||
set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
|
||||
else()
|
||||
find_package(Python REQUIRED)
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp"
|
||||
COMMAND "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/MakeSingleHeader.py" "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/CLI.hpp" ${CLI11_headers}
|
||||
)
|
||||
add_custom_target(generate_cli_single_file ALL
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp")
|
||||
set_target_properties(generate_cli_single_file
|
||||
PROPERTIES FOLDER "Scripts")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp DESTINATION include)
|
||||
add_library(CLI11_SINGLE INTERFACE)
|
||||
target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
|
||||
add_dependencies(CLI11_SINGLE generate_cli_single_file)
|
||||
target_compile_definitions(CLI11_SINGLE INTERFACE -DCLI11_SINGLE_FILE)
|
||||
target_include_directories(CLI11_SINGLE INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/include/")
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(CLI11_SINGLE_FILE_TESTS
|
||||
"Duplicate all the tests for a single file build"
|
||||
OFF
|
||||
"CLI11_SINGLE_FILE"
|
||||
OFF)
|
||||
|
||||
|
||||
if(DEFINED CLI11_TESTING)
|
||||
set(CLI11_TESTING_INTERNAL "${CLI11_TESTING}")
|
||||
elseif(CUR_PROJ)
|
||||
option(BUILD_TESTING "Build the tests" ON)
|
||||
set(CLI11_TESTING_INTERNAL "${BUILD_TESTING}")
|
||||
else()
|
||||
set(CLI11_TESTING_INTERNAL OFF)
|
||||
endif()
|
||||
|
||||
if(CLI11_TESTING_INTERNAL)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(CLI11_EXAMPLES "Build the examples" ON "CUR_PROJ" OFF)
|
||||
if(CLI11_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# Packaging support
|
||||
set(CPACK_PACKAGE_VENDOR "github.com/CLIUtils/CLI11")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Command line interface")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${CLI11_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${CLI11_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${CLI11_VERSION_PATCH})
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
|
||||
# CPack collects *everything* except what's listed here.
|
||||
set(CPACK_SOURCE_IGNORE_FILES
|
||||
/.git
|
||||
/dist
|
||||
/.*build.*
|
||||
/\\\\.DS_Store
|
||||
/.*\\\\.egg-info
|
||||
/var
|
||||
/Pipfile.*$
|
||||
)
|
||||
include(CPack)
|
||||
|
||||
25
libs/libbattle-com/libs/CLI11/LICENSE
Normal file
25
libs/libbattle-com/libs/CLI11/LICENSE
Normal file
@@ -0,0 +1,25 @@
|
||||
CLI11 1.8 Copyright (c) 2017-2019 University of Cincinnati, developed by Henry
|
||||
Schreiner under NSF AWARD 1414736. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms of CLI11, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. 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.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
|
||||
874
libs/libbattle-com/libs/CLI11/README.md
Normal file
874
libs/libbattle-com/libs/CLI11/README.md
Normal file
@@ -0,0 +1,874 @@
|
||||
# CLI11: Command line parser for C++11
|
||||
|
||||

|
||||
|
||||
[![Build Status Linux and macOS][travis-badge]][travis]
|
||||
[![Build Status Windows][appveyor-badge]][appveyor]
|
||||
[![Build Status Azure][azure-badge]][azure]
|
||||
[![Code Coverage][codecov-badge]][codecov]
|
||||
[![Codacy Badge][codacy-badge]][codacy-link]
|
||||
[![Join the chat at https://gitter.im/CLI11gitter/Lobby][gitter-badge]][gitter]
|
||||
[![License: BSD][license-badge]](./LICENSE)
|
||||
[![Latest release][releases-badge]][github releases]
|
||||
[![DOI][doi-badge]][doi-link]
|
||||
[![Conan.io][conan-badge]][conan-link]
|
||||
[![Try CLI11 1.7 online][wandbox-badge]][wandbox-link]
|
||||
|
||||
[What's new](./CHANGELOG.md) •
|
||||
[Documentation][gitbook] •
|
||||
[API Reference][api-docs]
|
||||
|
||||
CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Background](#background)
|
||||
- [Introduction](#introduction)
|
||||
- [Why write another CLI parser?](#why-write-another-cli-parser)
|
||||
- [Other parsers](#other-parsers)
|
||||
- [Features not supported by this library](#features-not-supported-by-this-library)
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Adding options](#adding-options)
|
||||
- [Option types](#option-types)
|
||||
- [Example](#example)
|
||||
- [Option options](#option-options)
|
||||
- [Validators](#validators) 🆕
|
||||
- [Transforming Validators](#transforming-validators) 🆕
|
||||
- [Validator operations](#validator-operations) 🆕
|
||||
- [Custom Validators](#custom-validators) 🆕
|
||||
- [Querying Validators](#querying-validators) 🆕
|
||||
- [Getting Results](#getting-results) 🆕
|
||||
- [Subcommands](#subcommands)
|
||||
- [Subcommand options](#subcommand-options)
|
||||
- [Option groups](#option-groups) 🆕
|
||||
- [Callbacks](#callbacks)
|
||||
- [Configuration file](#configuration-file)
|
||||
- [Inheriting defaults](#inheriting-defaults)
|
||||
- [Formatting](#formatting)
|
||||
- [Subclassing](#subclassing)
|
||||
- [How it works](#how-it-works)
|
||||
- [Utilities](#utilities)
|
||||
- [Other libraries](#other-libraries)
|
||||
- [API](#api)
|
||||
- [Examples](#Examples)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
Features that were added in the last released major version are marked with "🆕". Features only available in master are marked with "🆕".
|
||||
|
||||
## Background
|
||||
|
||||
### Introduction
|
||||
|
||||
CLI11 provides all the features you expect in a powerful command line parser, with a beautiful, minimal syntax and no dependencies beyond C++11. It is header only, and comes in a single file form for easy inclusion in projects. It is easy to use for small projects, but powerful enough for complex command line projects, and can be customized for frameworks.
|
||||
It is tested on [Travis][], [AppVeyor][], and [Azure][], and is being included in the [GooFit GPU fitting framework][goofit]. It was inspired by [`plumbum.cli`][plumbum] for Python. CLI11 has a user friendly introduction in this README, a more in-depth tutorial [GitBook][], as well as [API documentation][api-docs] generated by Travis.
|
||||
See the [changelog](./CHANGELOG.md) or [GitHub Releases][] for details for current and past releases. Also see the [Version 1.0 post][], [Version 1.3 post][], or [Version 1.6 post][] for more information.
|
||||
|
||||
You can be notified when new releases are made by subscribing to <https://github.com/CLIUtils/CLI11/releases.atom> on an RSS reader, like Feedly, or use the releases mode of the github watching tool.
|
||||
|
||||
### Why write another CLI parser?
|
||||
|
||||
An acceptable CLI parser library should be all of the following:
|
||||
|
||||
- Easy to include (i.e., header only, one file if possible, **no external requirements**).
|
||||
- Short, simple syntax: This is one of the main reasons to use a CLI parser, it should make variables from the command line nearly as easy to define as any other variables. If most of your program is hidden in CLI parsing, this is a problem for readability.
|
||||
- C++11 or better: Should work with GCC 4.8+ (default on CentOS/RHEL 7), Clang 3.4+, AppleClang 7+, NVCC 7.0+, or MSVC 2015+.
|
||||
- Work on Linux, macOS, and Windows.
|
||||
- Well tested using [Travis][] (Linux) and [AppVeyor][] (Windows) or [Azure][] (all three). "Well" is defined as having good coverage measured by [CodeCov][].
|
||||
- Clear help printing.
|
||||
- Nice error messages.
|
||||
- Standard shell idioms supported naturally, like grouping flags, a positional separator, etc.
|
||||
- Easy to execute, with help, parse errors, etc. providing correct exit and details.
|
||||
- Easy to extend as part of a framework that provides "applications" to users.
|
||||
- Usable subcommand syntax, with support for multiple subcommands, nested subcommands, option groups, and optional fallthrough (explained later).
|
||||
- Ability to add a configuration file (`ini` format), and produce it as well.
|
||||
- Produce real values that can be used directly in code, not something you have pay compute time to look up, for HPC applications.
|
||||
- Work with standard types, simple custom types, and extensible to exotic types.
|
||||
- Permissively licensed.
|
||||
|
||||
### Other parsers
|
||||
|
||||
<details><summary>The major CLI parsers for C++ include, with my biased opinions: (click to expand)</summary><p>
|
||||
|
||||
| Library | My biased opinion |
|
||||
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Boost Program Options][] | A great library if you already depend on Boost, but its pre-C++11 syntax is really odd and setting up the correct call in the main function is poorly documented (and is nearly a page of code). A simple wrapper for the Boost library was originally developed, but was discarded as CLI11 became more powerful. The idea of capturing a value and setting it originated with Boost PO. [See this comparison.][cli11-po-compare] |
|
||||
| [The Lean Mean C++ Option Parser][] | One header file is great, but the syntax is atrocious, in my opinion. It was quite impractical to wrap the syntax or to use in a complex project. It seems to handle standard parsing quite well. |
|
||||
| [TCLAP][] | The not-quite-standard command line parsing causes common shortcuts to fail. It also seems to be poorly supported, with only minimal bugfixes accepted. Header only, but in quite a few files. Has not managed to get enough support to move to GitHub yet. No subcommands. Produces wrapped values. |
|
||||
| [Cxxopts][] | C++11, single file, and nice CMake support, but requires regex, therefore GCC 4.8 (CentOS 7 default) does not work. Syntax closely based on Boost PO, so not ideal but familiar. |
|
||||
| [DocOpt][] | Completely different approach to program options in C++11, you write the docs and the interface is generated. Too fragile and specialized. |
|
||||
|
||||
After I wrote this, I also found the following libraries:
|
||||
|
||||
| Library | My biased opinion |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| [GFlags][] | The Google Commandline Flags library. Uses macros heavily, and is limited in scope, missing things like subcommands. It provides a simple syntax and supports config files/env vars. |
|
||||
| [GetOpt][] | Very limited C solution with long, convoluted syntax. Does not support much of anything, like help generation. Always available on UNIX, though (but in different flavors). |
|
||||
| [ProgramOptions.hxx][] | Interesting library, less powerful and no subcommands. Nice callback system. |
|
||||
| [Args][] | Also interesting, and supports subcommands. I like the optional-like design, but CLI11 is cleaner and provides direct value access, and is less verbose. |
|
||||
| [Argument Aggregator][] | I'm a big fan of the [fmt][] library, and the try-catch statement looks familiar. :thumbsup: Doesn't seem to support subcommands. |
|
||||
| [Clara][] | Simple library built for the excellent [Catch][] testing framework. Unique syntax, limited scope. |
|
||||
| [Argh!][] | Very minimalistic C++11 parser, single header. Don't have many features. No help generation?!?! At least it's exception-free. |
|
||||
| [CLI][] | Custom language and parser. Huge build-system overkill for very little benefit. Last release in 2009, but still occasionally active. |
|
||||
|[argparse][] | C++17 single file argument parser. Design seems similar to CLI11 in some ways. |
|
||||
|
||||
See [Awesome C++][] for a less-biased list of parsers. You can also find other single file libraries at [Single file libs][].
|
||||
|
||||
</p></details>
|
||||
<br/>
|
||||
|
||||
None of these libraries fulfill all the above requirements, or really even come close. As you probably have already guessed, CLI11 does.
|
||||
So, this library was designed to provide a great syntax, good compiler compatibility, and minimal installation fuss.
|
||||
|
||||
### Features not supported by this library
|
||||
|
||||
There are some other possible "features" that are intentionally not supported by this library:
|
||||
|
||||
- Non-standard variations on syntax, like `-long` options. This is non-standard and should be avoided, so that is enforced by this library.
|
||||
- Completion of partial options, such as Python's `argparse` supplies for incomplete arguments. It's better not to guess. Most third party command line parsers for python actually reimplement command line parsing rather than using argparse because of this perceived design flaw.
|
||||
- Autocomplete: This might eventually be added to both Plumbum and CLI11, but it is not supported yet.
|
||||
- Wide strings / unicode: Since this uses the standard library only, it might be hard to properly implement, but I would be open to suggestions in how to do this.
|
||||
|
||||
## Install
|
||||
|
||||
To use, there are two methods:
|
||||
|
||||
1. Copy `CLI11.hpp` from the [most recent release][github releases] into your include directory, and you are set. This is combined from the source files for every release. This includes the entire command parser library, but does not include separate utilities (like `Timer`, `AutoTimer`). The utilities are completely self contained and can be copied separately.
|
||||
2. Use `CLI/*.hpp` files. You could check out the repository as a submodule, for example. You can use the `CLI11::CLI11` interface target when linking from `add_subdirectory`.
|
||||
You can also configure and optionally install the project, and then use `find_package(CLI11 CONFIG)` to get the `CLI11::CLI11` target. You can also use [Conan.io][conan-link] or [Hunter][].
|
||||
(These are just conveniences to allow you to use your favorite method of managing packages; it's just header only so including the correct path and
|
||||
using C++11 is all you really need.)
|
||||
|
||||
To build the tests, checkout the repository and use CMake:
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
GTEST_COLOR=1 CTEST_OUTPUT_ON_FAILURE=1 make test
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Adding options
|
||||
|
||||
To set up, add options, and run, your main function will look something like this:
|
||||
|
||||
```cpp
|
||||
int main(int charc, char** argv) {
|
||||
CLI::App app{"App description"};
|
||||
|
||||
std::string filename = "default";
|
||||
app.add_option("-f,--file", filename, "A help string");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
<details><summary>Note: If you don't like macros, this is what that macro expands to: (click to expand)</summary><p>
|
||||
|
||||
```cpp
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch (const CLI::ParseError &e) {
|
||||
return app.exit(e);
|
||||
}
|
||||
```
|
||||
|
||||
The try/catch block ensures that `-h,--help` or a parse error will exit with the correct return code (selected from `CLI::ExitCodes`). (The return here should be inside `main`). You should not assume that the option values have been set inside the catch block; for example, help flags intentionally short-circuit all other processing for speed and to ensure required options and the like do not interfere.
|
||||
|
||||
</p></details>
|
||||
</br>
|
||||
|
||||
The initialization is just one line, adding options is just two each. The parse macro is just one line (or 5 for the contents of the macro). After the app runs, the filename will be set to the correct value if it was passed, otherwise it will be set to the default. You can check to see if this was passed on the command line with `app.count("--file")`.
|
||||
|
||||
#### Option types
|
||||
|
||||
While all options internally are the same type, there are several ways to add an option depending on what you need. The supported values are:
|
||||
|
||||
```cpp
|
||||
// Add options
|
||||
app.add_option(option_name, help_str="") // 🆕
|
||||
|
||||
app.add_option(option_name,
|
||||
variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string
|
||||
help_string="")
|
||||
|
||||
app.add_option_function<type>(option_name,
|
||||
function <void(const type &value)>, // 🆕 int, bool, float, enum, vector, or string-like, or anything with a defined conversion from a string
|
||||
help_string="")
|
||||
|
||||
app.add_complex(... // Special case: support for complex numbers
|
||||
|
||||
// Add flags
|
||||
app.add_flag(option_name,
|
||||
help_string="")
|
||||
|
||||
app.add_flag(option_name,
|
||||
variable_to_bind_to, // bool, int, 🆕 float, 🆕 vector, 🆕 enum, or 🆕 string-like, or 🆕 anything with a defined conversion from a string
|
||||
help_string="")
|
||||
|
||||
app.add_flag_function(option_name, // 🆕
|
||||
function <void(int64_t count)>,
|
||||
help_string="")
|
||||
|
||||
app.add_flag_callback(option_name,function<void(void)>,help_string="") // 🆕
|
||||
|
||||
// Add subcommands
|
||||
App* subcom = app.add_subcommand(name, description);
|
||||
|
||||
Option_group *app.add_option_group(name,description); // 🆕
|
||||
|
||||
// ⚠️ All add_*set* methods deprecated in CLI11 1.8 - use ->transform(CLI::IsMember) instead
|
||||
-app.add_set(option_name,
|
||||
- variable_to_bind_to, // Same type as stored by set
|
||||
- set_of_possible_options, // Set will be copied, ignores changes
|
||||
- help_string="")
|
||||
-app.add_mutable_set(... // Set can change later, keeps reference
|
||||
-app.add_set_ignore_case(... // String only
|
||||
-app.add_mutable_set_ignore_case(... // String only
|
||||
-app.add_set_ignore_underscore(... // String only
|
||||
-app.add_mutable_set_ignore_underscore(... // String only
|
||||
-app.add_set_ignore_case_underscore(... // String only
|
||||
-app.add_mutable_set_ignore_case_underscore(... // String only
|
||||
```
|
||||
|
||||
An option name must start with a alphabetic character, underscore, a number 🆕, '?' 🆕, or '@' 🆕. For long options, after the first character '.', and '-' are also valid characters. For the `add_flag*` functions '{' has special meaning. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on the help line for its positional form.
|
||||
|
||||
The `add_option_function<type>(...` function will typically require the template parameter be given unless a `std::function` object with an exact match is passed. The type can be any type supported by the `add_option` function. The function should throw an error (`CLI::ConversionError` or `CLI::ValidationError` possibly) if the value is not valid.
|
||||
|
||||
🆕 Flag options specified through the `add_flag*` functions allow a syntax for the option names to default particular options to a false value or any other value if some flags are passed. For example:
|
||||
|
||||
```cpp
|
||||
app.add_flag("--flag,!--no-flag",result,"help for flag"); // 🆕
|
||||
```
|
||||
|
||||
specifies that if `--flag` is passed on the command line result will be true or contain a value of 1. If `--no-flag` is
|
||||
passed `result` will contain false or -1 if `result` is a signed integer type, or 0 if it is an unsigned type. An
|
||||
alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`; this is equivalent to the previous
|
||||
example. This also works for short form options `"-f,!-n"` or `"-f,-n{false}"`. If `variable_to_bind_to` is anything but an integer value the
|
||||
default behavior is to take the last value given, while if `variable_to_bind_to` is an integer type the behavior will be to sum
|
||||
all the given arguments and return the result. This can be modified if needed by changing the `multi_option_policy` on each flag (this is not inherited).
|
||||
The default value can be any value. For example if you wished to define a numerical flag:
|
||||
|
||||
```cpp
|
||||
app.add_flag("-1{1},-2{2},-3{3}",result,"numerical flag") // 🆕
|
||||
```
|
||||
|
||||
using any of those flags on the command line will result in the specified number in the output. Similar things can be done for string values, and enumerations, as long as the default value can be converted to the given type.
|
||||
|
||||
|
||||
On a `C++14` compiler, you can pass a callback function directly to `.add_flag`, while in C++11 mode you'll need to use `.add_flag_function` if you want a callback function. The function will be given the number of times the flag was passed. You can throw a relevant `CLI::ParseError` to signal a failure.
|
||||
|
||||
On a compiler that supports C++17's `__has_include`, you can also use `std::optional`, `std::experimental::optional`, and `boost::optional` directly in an `add_option` call. If you don't have `__has_include`, you can define `CLI11_BOOST_OPTIONAL 1` before including CLI11 to manually add support (or 0 to remove) for `boost::optional`. See [CLI11 Internals][] for information on how this was done and how you can add your own converters. Optional values are only supported for types that support the `>>` operator.
|
||||
|
||||
#### Example
|
||||
|
||||
- `"one,-o,--one"`: Valid as long as not a flag, would create an option that can be specified positionally, or with `-o` or `--one`
|
||||
- `"this"` Can only be passed positionally
|
||||
- `"-a,-b,-c"` No limit to the number of non-positional option names
|
||||
|
||||
The add commands return a pointer to an internally stored `Option`.
|
||||
This option can be used directly to check for the count (`->count()`) after parsing to avoid a string based lookup.
|
||||
⚠️ Deprecated: The `add_*` commands have a final argument than can be set to true, which causes the default value to be captured and printed on the command line with the help flag. Since CLI11 1.8, you can simply add `->capture_default_str()`.
|
||||
|
||||
#### Option options
|
||||
|
||||
Before parsing, you can set the following options:
|
||||
|
||||
- `->required()`: The program will quit if this option is not present. This is `mandatory` in Plumbum, but required options seems to be a more standard term. For compatibility, `->mandatory()` also works.
|
||||
- `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`; end with `--` or another recognized option or subcommand.
|
||||
- `->type_name(typename)`: Set the name of an Option's type (`type_name_fn` allows a function instead)
|
||||
- `->type_size(N)`: Set the intrinsic size of an option. The parser will require multiples of this number if negative.
|
||||
- `->needs(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
|
||||
- `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer.
|
||||
- `->envname(name)`: Gets the value from the environment if present and not passed on the command line.
|
||||
- `->group(name)`: The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `""` will not show up in the help print (hidden).
|
||||
- `->ignore_case()`: Ignore the case on the command line (also works on subcommands, does not affect arguments).
|
||||
- `->ignore_underscore()`: Ignore any underscores in the options names (also works on subcommands, does not affect arguments). For example "option_one" will match with "optionone". This does not apply to short form options since they only have one character
|
||||
- `->disable_flag_override()`: 🆕 From the command line long form flag options can be assigned a value on the command line using the `=` notation `--flag=value`. If this behavior is not desired, the `disable_flag_override()` disables it and will generate an exception if it is done on the command line. The `=` does not work with short form flag options.
|
||||
- `->delimiter(char)`: 🆕 allows specification of a custom delimiter for separating single arguments into vector arguments, for example specifying `->delimiter(',')` on an option would result in `--opt=1,2,3` producing 3 elements of a vector and the equivalent of --opt 1 2 3 assuming opt is a vector value.
|
||||
- `->description(str)`: Set/change the description.
|
||||
- `->multi_option_policy(CLI::MultiOptionPolicy::Throw)`: Set the multi-option policy. Shortcuts available: `->take_last()`, `->take_first()`, and `->join()`. This will only affect options expecting 1 argument or bool flags (which do not inherit their default but always start with a specific policy).
|
||||
- `->check(std::string(const std::string &), validator_name="",validator_description="")`: 🆕 Define a check function. The function should return a non empty string with the error message if the check fails
|
||||
- `->check(Validator)`:🆕 Use a Validator object to do the check see [Validators](#validators) for a description of available Validators and how to create new ones.
|
||||
- `->transform(std::string(std::string &), validator_name="",validator_description=")`: Converts the input string into the output string, in-place in the parsed options.
|
||||
- `->transform(Validator)`: uses a Validator object to do the transformation see [Validators](#validators) for a description of available Validators and how to create new ones.
|
||||
- `->each(void(const std::string &)>`: Run this function on each value received, as it is received. It should throw a `ValidationError` if an error is encountered.
|
||||
- `->configurable(false)`: Disable this option from being in a configuration file.
|
||||
`->capture_default_str()`: 🆕 Store the current value attached and display it in the help string.
|
||||
`->default_function(std::string())`: 🆕 Advanced: Change the function that `capture_default_str()` uses.
|
||||
`->always_capture_default()`: 🆕 Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.
|
||||
|
||||
|
||||
These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. The `each` function takes any function that has the signature `void(const std::string&)`; it should throw a `ValidationError` when validation fails. The help message will have the name of the parent option prepended. Since `each`, `check` and `transform` use the same underlying mechanism, you can chain as many as you want, and they will be executed in order. Operations added through `transform` are executed first in reverse order of addition, and `check` and `each` are run following the transform functions in order of addition. If you just want to see the unconverted values, use `.results()` to get the `std::vector<std::string>` of results.
|
||||
|
||||
On the command line, options can be given as:
|
||||
|
||||
- `-a` (flag)
|
||||
- `-abc` (flags can be combined)
|
||||
- `-f filename` (option)
|
||||
- `-ffilename` (no space required)
|
||||
- `-abcf filename` (flags and option can be combined)
|
||||
- `--long` (long flag)
|
||||
- `--long_flag=true` (long flag with equals to override default value) 🆕
|
||||
- `--file filename` (space)
|
||||
- `--file=filename` (equals)
|
||||
|
||||
If `allow_windows_style_options()` is specified in the application or subcommand options can also be given as:
|
||||
- `/a` (flag)
|
||||
- `/f filename` (option)
|
||||
- `/long` (long flag)
|
||||
- `/file filename` (space)
|
||||
- `/file:filename` (colon)
|
||||
- `/long_flag:false` (long flag with : to override the default value) 🆕
|
||||
= Windows style options do not allow combining short options or values not separated from the short option like with `-` options
|
||||
|
||||
🆕 Long flag options may be given with an `=<value>` to allow specifying a false value, or some other value to the flag. See [config files](#configuration-file) for details on the values supported. NOTE: only the `=` or `:` for windows-style options may be used for this, using a space will result in the argument being interpreted as a positional argument. This syntax can override the default values, and can be disabled by using `disable_flag_override()`.
|
||||
|
||||
Extra positional arguments will cause the program to exit, so at least one positional option with a vector is recommended if you want to allow extraneous arguments.
|
||||
If you set `.allow_extras()` on the main `App`, you will not get an error. You can access the missing options using `remaining` (if you have subcommands, `app.remaining(true)` will get all remaining options, subcommands included).
|
||||
If the remaining arguments are to processed by another `App` then the function `remaining_for_passthrough()` 🆕 can be used to get the remaining arguments in reverse order such that `app.parse(vector)` works directly and could even be used inside a subcommand callback.
|
||||
|
||||
You can access a vector of pointers to the parsed options in the original order using `parse_order()`.
|
||||
If `--` is present in the command line that does not end an unlimited option, then
|
||||
everything after that is positional only.
|
||||
|
||||
#### Validators
|
||||
Validators are structures to check or modify inputs, they can be used to verify that an input meets certain criteria or transform it into another value. They are added through the `check` or `transform` functions. The differences between the two function are that checks do not modify the input whereas transforms can and are executed before any Validators added through `check`.
|
||||
|
||||
CLI11 has several Validators built-in that perform some common checks
|
||||
|
||||
- `CLI::IsMember(...)`: 🆕 Require an option be a member of a given set. See [Transforming Validators](#transforming-validators) for more details.
|
||||
- `CLI::Transformer(...)`: 🆕 Modify the input using a map. See [Transforming Validators](#transforming-validators) for more details.
|
||||
- `CLI::CheckedTransformer(...)`: 🆕 Modify the input using a map, and require that the input is either in the set or already one of the outputs of the set. See [Transforming Validators](#transforming-validators) for more details.
|
||||
- `CLI::AsNumberWithUnit(...)`:🆕 Modify the `<NUMBER> <UNIT>` pair by matching the unit and multiplying the number by the corresponding factor. It can be used as a base for transformers, that accept things like size values (`1 KB`) or durations (`0.33 ms`).
|
||||
- `CLI::AsSizeValue(...)`: 🆕 Convert inputs like `100b`, `42 KB`, `101 Mb`, `11 Mib` to absolute values. `KB` can be configured to be interpreted as 10^3 or 2^10.
|
||||
- `CLI::ExistingFile`: Requires that the file exists if given.
|
||||
- `CLI::ExistingDirectory`: Requires that the directory exists.
|
||||
- `CLI::ExistingPath`: Requires that the path (file or directory) exists.
|
||||
- `CLI::NonexistentPath`: Requires that the path does not exist.
|
||||
- `CLI::Range(min,max)`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0.
|
||||
- `CLI::Bounded(min,max)`: 🆕 Modify the input such that it is always between min and max (make sure to use floating point if needed). Min defaults to 0. Will produce an error if conversion is not possible.
|
||||
- `CLI::PositiveNumber`: 🆕 Requires the number be greater or equal to 0
|
||||
- `CLI::Number`: 🆕 Requires the input be a number.
|
||||
- `CLI::ValidIPV4`: 🆕 Requires that the option be a valid IPv4 string e.g. `'255.255.255.255'`, `'10.1.1.7'`.
|
||||
|
||||
These Validators can be used by simply passing the name into the `check` or `transform` methods on an option
|
||||
|
||||
```cpp
|
||||
->check(CLI::ExistingFile);
|
||||
->check(CLI::Range(0,10));
|
||||
```
|
||||
|
||||
Validators can be merged using `&` and `|` and inverted using `!` 🆕. For example:
|
||||
|
||||
```cpp
|
||||
->check(CLI::Range(0,10)|CLI::Range(20,30));
|
||||
```
|
||||
|
||||
will produce a check to ensure a value is between 0 and 10 or 20 and 30.
|
||||
|
||||
```cpp
|
||||
->check(!CLI::PositiveNumber);
|
||||
```
|
||||
|
||||
will produce a check for a number less than 0.
|
||||
|
||||
##### Transforming Validators
|
||||
There are a few built in Validators that let you transform values if used with the `transform` function. If they also do some checks then they can be used `check` but some may do nothing in that case.
|
||||
* 🆕 `CLI::Bounded(min,max)` will bound values between min and max and values outside of that range are limited to min or max, it will fail if the value cannot be converted and produce a `ValidationError`
|
||||
* 🆕 The `IsMember` Validator lets you specify a set of predefined options. You can pass any container or copyable pointer (including `std::shared_ptr`) to a container to this validator; the container just needs to be iterable and have a `::value_type`. The key type should be convertible from a string, You can use an initializer list directly if you like. If you need to modify the set later, the pointer form lets you do that; the type message and check will correctly refer to the current version of the set. The container passed in can be a set, vector, or a map like structure. If used in the `transform` method the output value will be the matching key as it could be modified by filters.
|
||||
After specifying a set of options, you can also specify "filter" functions of the form `T(T)`, where `T` is the type of the values. The most common choices probably will be `CLI::ignore_case` an `CLI::ignore_underscore`, and `CLI::ignore_space`. These all work on strings but it is possible to define functions that work on other types.
|
||||
Here are some examples
|
||||
of `IsMember`:
|
||||
|
||||
* `CLI::IsMember({"choice1", "choice2"})`: Select from exact match to choices.
|
||||
* `CLI::IsMember({"choice1", "choice2"}, CLI::ignore_case, CLI::ignore_underscore)`: Match things like `Choice_1`, too.
|
||||
* `CLI::IsMember(std::set<int>({2,3,4}))`: Most containers and types work; you just need `std::begin`, `std::end`, and `::value_type`.
|
||||
* `CLI::IsMember(std::map<std::string, TYPE>({{"one", 1}, {"two", 2}}))`: You can use maps; in `->transform()` these replace the matched value with the matched key. The value member of the map is not used in `IsMember`, so it can be any type.
|
||||
* `auto p = std::make_shared<std::vector<std::string>>(std::initializer_list<std::string>("one", "two")); CLI::IsMember(p)`: You can modify `p` later.
|
||||
* 🆕 The `Transformer` and `CheckedTransformer` Validators transform one value into another. Any container or copyable pointer (including `std::shared_ptr`) to a container that generates pairs of values can be passed to these `Validator's`; the container just needs to be iterable and have a `::value_type` that consists of pairs. The key type should be convertible from a string, and the value type should be convertible to a string You can use an initializer list directly if you like. If you need to modify the map later, the pointer form lets you do that; the description message will correctly refer to the current version of the map. `Transformer` does not do any checking so values not in the map are ignored. `CheckedTransformer` takes an extra step of verifying that the value is either one of the map key values, in which case it is transformed, or one of the expected output values, and if not will generate a `ValidationError`. A Transformer placed using `check` will not do anything.
|
||||
After specifying a map of options, you can also specify "filter" just like in `CLI::IsMember`.
|
||||
Here are some examples (`Transformer` and `CheckedTransformer` are interchangeable in the examples)
|
||||
of `Transformer`:
|
||||
|
||||
* `CLI::Transformer({{"key1", "map1"},{"key2","map2"}})`: Select from key values and produce map values.
|
||||
|
||||
* `CLI::Transformer(std::map<std::string,int>({"two",2},{"three",3},{"four",4}}))`: most maplike containers work, the `::value_type` needs to produce a pair of some kind.
|
||||
* `CLI::CheckedTransformer(std::map<std::string, int>({{"one", 1}, {"two", 2}}))`: You can use maps; in `->transform()` these replace the matched key with the value. `CheckedTransformer` also requires that the value either match one of the keys or match one of known outputs.
|
||||
* `auto p = std::make_shared<CLI::TransformPairs<std::string>>(std::initializer_list<std::pair<std::string,std::string>>({"key1", "map1"},{"key2","map2"})); CLI::Transformer(p)`: You can modify `p` later. `TransformPairs<T>` is an alias for `std::vector<std::pair<<std::string,T>>`
|
||||
|
||||
NOTES: If the container used in `IsMember`, `Transformer`, or `CheckedTransformer` has a `find` function like `std::unordered_map` or `std::map` then that function is used to do the searching. If it does not have a `find` function a linear search is performed. If there are filters present, the fast search is performed first, and if that fails a linear search with the filters on the key values is performed.
|
||||
|
||||
##### Validator operations 🆕
|
||||
Validators are copyable and have a few operations that can be performed on them to alter settings. Most of the built in Validators have a default description that is displayed in the help. This can be altered via `.description(validator_description)`.
|
||||
The name of a Validator, which is useful for later reference from the `get_validator(name)` method of an `Option` can be set via `.name(validator_name)`
|
||||
The operation function of a Validator can be set via
|
||||
`.operation(std::function<std::string(std::string &>)`. The `.active()` function can activate or deactivate a Validator from the operation.
|
||||
All the functions return a Validator reference allowing them to be chained. For example
|
||||
|
||||
```cpp
|
||||
opt->check(CLI::Range(10,20).description("range is limited to sensible values").active(false).name("range"));
|
||||
```
|
||||
|
||||
will specify a check on an option with a name "range", but deactivate it for the time being.
|
||||
The check can later be activated through
|
||||
|
||||
```cpp
|
||||
opt->get_validator("range")->active();
|
||||
```
|
||||
|
||||
##### Custom Validators 🆕
|
||||
|
||||
A validator object with a custom function can be created via
|
||||
|
||||
```cpp
|
||||
CLI::Validator(std::function<std::string(std::string &)>,validator_description,validator_name="");
|
||||
```
|
||||
|
||||
or if the operation function is set later they can be created with
|
||||
|
||||
```cpp
|
||||
CLI::Validator(validator_description);
|
||||
```
|
||||
|
||||
It is also possible to create a subclass of `CLI::Validator`, in which case it can also set a custom description function, and operation function.
|
||||
|
||||
##### Querying Validators 🆕
|
||||
|
||||
Once loaded into an Option, a pointer to a named Validator can be retrieved via
|
||||
|
||||
```cpp
|
||||
opt->get_validator(name);
|
||||
```
|
||||
|
||||
This will retrieve a Validator with the given name or throw a `CLI::OptionNotFound` error. If no name is given or name is empty the first unnamed Validator will be returned or the first Validator if there is only one.
|
||||
|
||||
Validators have a few functions to query the current values
|
||||
* `get_description()`: 🆕 Will return a description string
|
||||
* `get_name()`: 🆕 Will return the Validator name
|
||||
* `get_active()`: 🆕 Will return the current active state, true if the Validator is active.
|
||||
* `get_modifying()`: 🆕 Will return true if the Validator is allowed to modify the input, this can be controlled via the `non_modifying()` 🆕 method, though it is recommended to let `check` and `transform` option methods manipulate it if needed.
|
||||
|
||||
#### Getting results
|
||||
|
||||
In most cases, the fastest and easiest way is to return the results through a callback or variable specified in one of the `add_*` functions. But there are situations where this is not possible or desired. For these cases the results may be obtained through one of the following functions. Please note that these functions will do any type conversions and processing during the call so should not used in performance critical code:
|
||||
|
||||
- `results()`: Retrieves a vector of strings with all the results in the order they were given.
|
||||
- `results(variable_to_bind_to)`: 🆕 Gets the results according to the MultiOptionPolicy and converts them just like the `add_option_function` with a variable.
|
||||
- `Value=as<type>()`: 🆕 Returns the result or default value directly as the specified type if possible, can be vector to return all results, and a non-vector to get the result according to the MultiOptionPolicy in place.
|
||||
|
||||
### Subcommands
|
||||
|
||||
Subcommands are supported, and can be nested infinitely. To add a subcommand, call the `add_subcommand` method with a name and an optional description. This gives a pointer to an `App` that behaves just like the main app, and can take options or further subcommands. Add `->ignore_case()` to a subcommand to allow any variation of caps to also be accepted. `->ignore_underscore()` is similar, but for underscores. Children inherit the current setting from the parent. You cannot add multiple matching subcommand names at the same level (including `ignore_case` and `ignore_underscore`).
|
||||
|
||||
If you want to require that at least one subcommand is given, use `.require_subcommand()` on the parent app. You can optionally give an exact number of subcommands to require, as well. If you give two arguments, that sets the min and max number allowed.
|
||||
0 for the max number allowed will allow an unlimited number of subcommands. As a handy shortcut, a single negative value N will set "up to N" values. Limiting the maximum number allows you to keep arguments that match a previous
|
||||
subcommand name from matching.
|
||||
|
||||
If an `App` (main or subcommand) has been parsed on the command line, `->parsed` will be true (or convert directly to bool).
|
||||
All `App`s have a `get_subcommands()` method, which returns a list of pointers to the subcommands passed on the command line. A `got_subcommand(App_or_name)` method is also provided that will check to see if an `App` pointer or a string name was collected on the command line.
|
||||
|
||||
For many cases, however, using an app's callback may be easier. Every app executes a callback function after it parses; just use a lambda function (with capture to get parsed values) to `.callback`. If you throw `CLI::Success` or `CLI::RuntimeError(return_value)`, you can
|
||||
even exit the program through the callback. The main `App` has a callback slot, as well, but it is generally not as useful.
|
||||
You are allowed to throw `CLI::Success` in the callbacks.
|
||||
Multiple subcommands are allowed, to allow [`Click`][click] like series of commands (order is preserved). 🆕 The same subcommand can be triggered multiple times but all positional arguments will take precedence over the second and future calls of the subcommand. `->count()` on the subcommand will return the number of times the subcommand was called. The subcommand callback will only be triggered once unless the `.immediate_callback()` 🆕 flag is set. In which case the callback executes on completion of the subcommand arguments but after the arguments for that subcommand have been parsed, and can be triggered multiple times.
|
||||
|
||||
🆕 Subcommands may also have an empty name either by calling `add_subcommand` with an empty string for the name or with no arguments.
|
||||
Nameless subcommands function a similarly to groups in the main `App`. See [Option groups](#option-groups) to see how this might work. If an option is not defined in the main App, all nameless subcommands are checked as well. This allows for the options to be defined in a composable group. The `add_subcommand` function has an overload for adding a `shared_ptr<App>` so the subcommand(s) could be defined in different components and merged into a main `App`, or possibly multiple `Apps`. Multiple nameless subcommands are allowed. Callbacks for nameless subcommands are only triggered if any options from the subcommand were parsed.
|
||||
|
||||
#### Subcommand options
|
||||
|
||||
There are several options that are supported on the main app and subcommands and option_groups. These are:
|
||||
|
||||
- `.ignore_case()`: Ignore the case of this subcommand. Inherited by added subcommands, so is usually used on the main `App`.
|
||||
- `.ignore_underscore()`: Ignore any underscores in the subcommand name. Inherited by added subcommands, so is usually used on the main `App`.
|
||||
- `.allow_windows_style_options()`: Allow command line options to be parsed in the form of `/s /long /file:file_name.ext` This option does not change how options are specified in the `add_option` calls or the ability to process options in the form of `-s --long --file=file_name.ext`.
|
||||
- `.fallthrough()`: Allow extra unmatched options and positionals to "fall through" and be matched on a parent command. Subcommands always are allowed to fall through.
|
||||
- `.disable()`: 🆕 Specify that the subcommand is disabled, if given with a bool value it will enable or disable the subcommand or option group.
|
||||
- `.disabled_by_default()`: 🆕 Specify that at the start of parsing the subcommand/option_group should be disabled. This is useful for allowing some Subcommands to trigger others.
|
||||
- `.enabled_by_default()`: 🆕 Specify that at the start of each parse the subcommand/option_group should be enabled. This is useful for allowing some Subcommands to disable others.
|
||||
- `.validate_positionals()`: 🆕 Specify that positionals should pass validation before matching. Validation is specified through `transform`, `check`, and `each` for an option. If an argument fails validation it is not an error and matching proceeds to the next available positional or extra arguments.
|
||||
- `.excludes(option_or_subcommand)`: 🆕 If given an option pointer or pointer to another subcommand, these subcommands cannot be given together. In the case of options, if the option is passed the subcommand cannot be used and will generate an error.
|
||||
- `.require_option()`: 🆕 Require 1 or more options or option groups be used.
|
||||
- `.require_option(N)`: 🆕 Require `N` options or option groups, if `N>0`, or up to `N` if `N<0`. `N=0` resets to the default to 0 or more.
|
||||
- `.require_option(min, max)`: 🆕 Explicitly set min and max allowed options or option groups. Setting `max` to 0 implies unlimited options.
|
||||
- `.require_subcommand()`: Require 1 or more subcommands.
|
||||
- `.require_subcommand(N)`: Require `N` subcommands if `N>0`, or up to `N` if `N<0`. `N=0` resets to the default to 0 or more.
|
||||
- `.require_subcommand(min, max)`: Explicitly set min and max allowed subcommands. Setting `max` to 0 is unlimited.
|
||||
- `.add_subcommand(name="", description="")`: Add a subcommand, returns a pointer to the internally stored subcommand.
|
||||
- `.add_subcommand(shared_ptr<App>)`: 🆕 Add a subcommand by shared_ptr, returns a pointer to the internally stored subcommand.
|
||||
- `.remove_subcommand(App)`: 🆕 Remove a subcommand from the app or subcommand.
|
||||
- `.got_subcommand(App_or_name)`: Check to see if a subcommand was received on the command line.
|
||||
- `.get_subcommands(filter)`: The list of subcommands that match a particular filter function.
|
||||
- `.add_option_group(name="", description="")`: 🆕 Add an [option group](#option-groups) to an App, an option group is specialized subcommand intended for containing groups of options or other groups for controlling how options interact.
|
||||
- `.get_parent()`: Get the parent App or `nullptr` if called on master App.
|
||||
- `.get_option(name)`: Get an option pointer by option name will throw if the specified option is not available, nameless subcommands are also searched
|
||||
- `.get_option_no_throw(name)`: 🆕 Get an option pointer by option name. This function will return a `nullptr` instead of throwing if the option is not available.
|
||||
- `.get_options(filter)`: Get the list of all defined option pointers (useful for processing the app for custom output formats).
|
||||
- `.parse_order()`: Get the list of option pointers in the order they were parsed (including duplicates).
|
||||
- `.formatter(fmt)`: Set a formatter, with signature `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more details.
|
||||
- `.description(str)`: Set/change the description.
|
||||
- `.get_description()`: Access the description.
|
||||
- `.parsed()`: True if this subcommand was given on the command line.
|
||||
- `.count()`: Returns the number of times the subcommand was called.
|
||||
- `.count(option_name)`: Returns the number of times a particular option was called.
|
||||
- `.count_all()`: 🆕 Returns the total number of arguments a particular subcommand processed, on the master App it returns the total number of processed commands.
|
||||
- `.name(name)`: Add or change the name.
|
||||
- `.callback(void() function)`: Set the callback that runs at the end of parsing. The options have already run at this point. See [Subcommand callbacks](#callbacks) for some additional details.
|
||||
- `.immediate_callback()`: 🆕 Specify that the callback for a subcommand should run immediately on completion of a subcommand vs at the completion of all parsing if this option is not used.
|
||||
- `.pre_parse_callback(void(size_t) function)`: 🆕 Set a callback that executes after the first argument of an application is processed. See [Subcommand callbacks](#callbacks) for some additional details.
|
||||
- `.allow_extras()`: Do not throw an error if extra arguments are left over.
|
||||
- `.positionals_at_end()`: 🆕 Specify that positional arguments occur as the last arguments and throw an error if an unexpected positional is encountered.
|
||||
- `.prefix_command()`: Like `allow_extras`, but stop immediately on the first unrecognized item. It is ideal for allowing your app or subcommand to be a "prefix" to calling another app.
|
||||
- `.footer(message)`: Set text to appear at the bottom of the help string.
|
||||
- `.set_help_flag(name, message)`: Set the help flag name and message, returns a pointer to the created option.
|
||||
- `.set_help_all_flag(name, message)`: Set the help all flag name and message, returns a pointer to the created option. Expands subcommands.
|
||||
- `.failure_message(func)`: Set the failure message function. Two provided: `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default).
|
||||
- `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""` will be hide the subcommand.
|
||||
- `[option_name]`: 🆕 retrieve a const pointer to an option given by `option_name` for Example `app["--flag1"]` will get a pointer to the option for the "--flag1" value, `app["--flag1"]->as<bool>()` will get the results of the command line for a flag. The operation will throw an exception if the option name is not valid.
|
||||
|
||||
> Note: if you have a fixed number of required positional options, that will match before subcommand names. `{}` is an empty filter function, and any positional argument will match before repeated subcommand names.
|
||||
|
||||
|
||||
#### Callbacks
|
||||
A subcommand has two optional callbacks that are executed at different stages of processing. The `preparse_callback` 🆕 is executed once after the first argument of a subcommand or application is processed and gives an argument for the number of remaining arguments to process. For the main app the first argument is considered the program name, for subcommands the first argument is the subcommand name. For Option groups and nameless subcommands the first argument is after the first argument or subcommand is processed from that group.
|
||||
The second callback is executed after parsing. The behavior depends on the status of the `immediate_callback` flag 🆕. If true, this runs immediately after the parsing of the subcommand. Or if the flag is false, once after parsing of all arguments. If the `immediate_callback` is set then the callback can be executed multiple times if the subcommand list given multiple times. If the main app or subcommand has a config file, no data from the config file will be reflected in immediate_callback. `immediate_callback()` has no effect on the main app, though it can be inherited. For option_groups `immediate_callback` causes the callback to be run prior to other option groups and options in the main app, effectively giving the options in the group priority.
|
||||
|
||||
For example say an application was set up like
|
||||
|
||||
```cpp
|
||||
app.callback(ac);
|
||||
sub1=app.add_subcommand("sub1")->callback(c1)->preparse_callback(pc1)->immediate_callback();
|
||||
sub2=app.add_subcommand("sub2")->callback(c2)->preparse_callback(pc2);
|
||||
app.preparse_callback( pa);
|
||||
|
||||
... A bunch of other options
|
||||
|
||||
```
|
||||
|
||||
Then the command line is given as
|
||||
|
||||
```
|
||||
program --opt1 opt1_val sub1 --sub1opt --sub1optb val sub2 --sub2opt sub1 --sub1opt2 sub2 --sub2opt2 val
|
||||
```
|
||||
|
||||
* pa will be called prior to parsing any values with an argument of 13.
|
||||
* pc1 will be called immediately after processing the sub1 command with a value of 10.
|
||||
* c1 will be called when the `sub2` command is encountered.
|
||||
* pc2 will be called with value of 6 after the sub2 command is encountered.
|
||||
* c1 will be called again after the second sub2 command is encountered.
|
||||
* c2 will be called once after processing all arguments.
|
||||
* ac will be called after completing the parse and all lower level callbacks have been executed.
|
||||
|
||||
A subcommand is considered terminated when one of the following conditions are met.
|
||||
1. There are no more arguments to process
|
||||
2. Another subcommand is encountered that would not fit in an optional slot of the subcommand
|
||||
3. The positional_mark(`--`) is encountered and there are no available positional slots in the subcommand.
|
||||
4. The subcommand_terminator mark(`++`) is encountered
|
||||
|
||||
If the `immediate_callback` flag is set then all contained options are processed and the callback is triggered. If a subcommand with an `immediate_callback` flag is called again, then the contained options are reset, and can be triggered again.
|
||||
|
||||
|
||||
|
||||
#### Option groups 🆕
|
||||
|
||||
The subcommand method
|
||||
|
||||
```cpp
|
||||
.add_option_group(name,description)
|
||||
```
|
||||
|
||||
Will create an option group, and return a pointer to it. An option group allows creation of a collection of options, similar to the groups function on options, but with additional controls and requirements. They allow specific sets of options to be composed and controlled as a collective. For an example see [range test](./tests/ranges.cpp). Option groups are a specialization of an App so all [functions](#subcommand-options) that work with an App or subcommand also work on option groups. Options can be created as part of an option group using the add functions just like a subcommand, or previously created options can be added through
|
||||
|
||||
```cpp
|
||||
ogroup->add_option(option_pointer);
|
||||
ogroup->add_options(option_pointer);
|
||||
ogroup->add_options(option1,option2,option3,...);
|
||||
```
|
||||
|
||||
The option pointers used in this function must be options defined in the parent application of the option group otherwise an error will be generated. Subcommands can also be added via
|
||||
|
||||
```cpp
|
||||
ogroup->add_subcommand(subcom_pointer);
|
||||
```
|
||||
|
||||
This results in the subcommand being moved from its parent into the option group.
|
||||
|
||||
Options in an option group are searched for a command line match after any options in the main app, so any positionals in the main app would be matched first. So care must be taken to make sure of the order when using positional arguments and option groups.
|
||||
Option groups work well with `excludes` and `require_options` methods, as an application will treat an option group as a single option for the purpose of counting and requirements, and an option group will be considered used if any of the options or subcommands contained in it are used. Option groups allow specifying requirements such as requiring 1 of 3 options in one group and 1 of 3 options in a different group. Option groups can contain other groups as well. Disabling an option group will turn off all options within the group.
|
||||
|
||||
The `CLI::TriggerOn` 🆕 and `CLI::TriggerOff` 🆕 methods are helper methods to allow the use of options/subcommands from one group to trigger another group on or off.
|
||||
|
||||
```cpp
|
||||
CLI::TriggerOn(group1_pointer, triggered_group);
|
||||
CLI::TriggerOff(group2_pointer, disabled_group);
|
||||
```
|
||||
|
||||
These functions make use of `preparse_callback`, `enabled_by_default()` and `disabled_by_default`. The triggered group may be a vector of group pointers. These methods should only be used once per group and will override any previous use of the underlying functions. More complex arrangements can be accomplished using similar methodology with a custom preparse_callback function that does more.
|
||||
|
||||
|
||||
### Configuration file
|
||||
|
||||
```cpp
|
||||
app.set_config(option_name="",
|
||||
default_file_name="",
|
||||
help_string="Read an ini file",
|
||||
required=false)
|
||||
```
|
||||
|
||||
If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in `ini` format by default (other formats can be added by an adept user). An example of a file:
|
||||
|
||||
```ini
|
||||
; Comments are supported, using a ;
|
||||
; The default section is [default], case insensitive
|
||||
|
||||
value = 1
|
||||
str = "A string"
|
||||
vector = 1 2 3
|
||||
str_vector = "one" "two" "and three"
|
||||
|
||||
; Sections map to subcommands
|
||||
[subcommand]
|
||||
in_subcommand = Wow
|
||||
sub.subcommand = true
|
||||
```
|
||||
|
||||
Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `yes`, 🆕 `enable`; or `false`, `off`, `0`, `no`, 🆕 `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not mean that subcommand was passed, it just sets the "defaults". You cannot set positional-only arguments or force subcommands to be present in the command line.
|
||||
|
||||
To print a configuration file from the passed
|
||||
arguments, use `.config_to_str(default_also=false, prefix="", write_description=false)`, where `default_also` will also show any defaulted arguments, `prefix` will add a prefix, and `write_description` will include option descriptions.
|
||||
|
||||
### Inheriting defaults
|
||||
|
||||
Many of the defaults for subcommands and even options are inherited from their creators. The inherited default values for subcommands are `allow_extras`, `prefix_command`, `ignore_case`, `ignore_underscore`, `fallthrough`, `group`, `footer`,`immediate_callback` and maximum number of required subcommands. The help flag existence, name, and description are inherited, as well.
|
||||
|
||||
Options have defaults for `group`, `required`, `multi_option_policy`, `ignore_case`, `ignore_underscore`, 🆕 `delimiter`, and 🆕 `disable_flag_override`. To set these defaults, you should set the `option_defaults()` object, for example:
|
||||
|
||||
```cpp
|
||||
app.option_defaults()->required();
|
||||
// All future options will be required
|
||||
```
|
||||
|
||||
The default settings for options are inherited to subcommands, as well.
|
||||
|
||||
### Formatting
|
||||
|
||||
The job of formatting help printouts is delegated to a formatter callable object on Apps and Options. You are free to replace either formatter by calling `formatter(fmt)` on an `App`, where fmt is any copyable callable with the correct signature.
|
||||
CLI11 comes with a default App formatter functional, `Formatter`. It is customizable; you can set `label(key, value)` to replace the default labels like `REQUIRED`, and `column_width(n)` to set the width of the columns before you add the functional to the app or option. You can also override almost any stage of the formatting process in a subclass of either formatter. If you want to make a new formatter from scratch, you can do
|
||||
that too; you just need to implement the correct signature. The first argument is a const pointer to the in question. The formatter will get a `std::string` usage name as the second option, and a `AppFormatMode` mode for the final option. It should return a `std::string`.
|
||||
|
||||
The `AppFormatMode` can be `Normal`, `All`, or `Sub`, and it indicates the situation the help was called in. `Sub` is optional, but the default formatter uses it to make sure expanded subcommands are called with
|
||||
their own formatter since you can't access anything but the call operator once a formatter has been set.
|
||||
|
||||
### Subclassing
|
||||
|
||||
The App class was designed allow toolkits to subclass it, to provide preset default options (see above) and setup/teardown code. Subcommands remain an unsubclassed `App`, since those are not expected to need setup and teardown. The default `App` only adds a help flag, `-h,--help`, than can removed/replaced using `.set_help_flag(name, help_string)`. You can also set a help-all flag with `.set_help_all_flag(name, help_string)`; this will expand the subcommands (one level only). You can remove options if you have pointers to them using `.remove_option(opt)`. You can add a `pre_callback` override to customize the after parse
|
||||
but before run behavior, while
|
||||
still giving the user freedom to `callback` on the main app.
|
||||
|
||||
The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a string; the optional bool should be set to true if you are
|
||||
including the program name in the string, and false otherwise.
|
||||
|
||||
Also, in a related note, the `App` you get a pointer to is stored in the parent `App` in a `shared_ptr`s (similar to `Option`s) and are deleted when the main `App` goes out of scope unless the object has another owner.
|
||||
|
||||
### How it works
|
||||
|
||||
Every `add_` option you have seen so far depends on one method that takes a lambda function. Each of these methods is just making a different lambda function with capture to populate the option. The function has full access to the vector of strings, so it knows how many times an option was passed or how many arguments it received. The lambda returns `true` if it could validate the option strings, and
|
||||
`false` if it failed.
|
||||
|
||||
Other values can be added as long as they support `operator>>` (and defaults can be printed if they support `operator<<`). To add a new type, for example, provide a custom `operator>>` with an `istream` (inside the CLI namespace is fine if you don't want to interfere with an existing `operator>>`).
|
||||
|
||||
If you wanted to extend this to support a completely new type, use a lambda or add a specialization of the `lexical_cast` function template in the namespace `CLI::detail` with the type you need to convert to. Some examples of some new parsers for `complex<double>` that support all of the features of a standard `add_options` call are in [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
|
||||
|
||||
#### Example
|
||||
|
||||
```cpp
|
||||
app.add_option("--fancy-count", [](std::vector<std::string> val){
|
||||
std::cout << "This option was given " << val.size() << " times." << std::endl;
|
||||
return true;
|
||||
});
|
||||
```
|
||||
|
||||
### Utilities
|
||||
|
||||
There are a few other utilities that are often useful in CLI programming. These are in separate headers, and do not appear in `CLI11.hpp`, but are completely independent and can be used as needed. The `Timer`/`AutoTimer` class allows you to easily time a block of code, with custom print output.
|
||||
|
||||
```cpp
|
||||
{
|
||||
CLI::AutoTimer timer {"My Long Process", CLI::Timer::Big};
|
||||
some_long_running_process();
|
||||
}
|
||||
```
|
||||
|
||||
This will create a timer with a title (default: `Timer`), and will customize the output using the predefined `Big` output (default: `Simple`). Because it is an `AutoTimer`, it will print out the time elapsed when the timer is destroyed at the end of the block. If you use `Timer` instead, you can use `to_string` or `std::cout << timer << std::endl;` to print the time. The print function can be any function that takes two strings, the title and the time, and returns a formatted
|
||||
string for printing.
|
||||
|
||||
### Other libraries
|
||||
|
||||
If you use the excellent [Rang][] library to add color to your terminal in a safe, multi-platform way, you can combine it with CLI11 nicely:
|
||||
|
||||
```cpp
|
||||
std::atexit([](){std::cout << rang::style::reset;});
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch (const CLI::ParseError &e) {
|
||||
std::cout << (e.get_exit_code()==0 ? rang::fg::blue : rang::fg::red);
|
||||
return app.exit(e);
|
||||
}
|
||||
```
|
||||
|
||||
This will print help in blue, errors in red, and will reset before returning the terminal to the user.
|
||||
|
||||
If you are on a Unix-like system, and you'd like to handle control-c and color, you can add:
|
||||
|
||||
```cpp
|
||||
#include <csignal>
|
||||
void signal_handler(int s) {
|
||||
std::cout << std::endl << rang::style::reset << rang::fg::red << rang::fg::bold;
|
||||
std::cout << "Control-C detected, exiting..." << rang::style::reset << std::endl;
|
||||
std::exit(1); // will call the correct exit func, no unwinding of the stack though
|
||||
}
|
||||
```
|
||||
|
||||
And, in your main function:
|
||||
|
||||
```cpp
|
||||
// Nice Control-C
|
||||
struct sigaction sigIntHandler;
|
||||
sigIntHandler.sa_handler = signal_handler;
|
||||
sigemptyset(&sigIntHandler.sa_mask);
|
||||
sigIntHandler.sa_flags = 0;
|
||||
sigaction(SIGINT, &sigIntHandler, nullptr);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
The API is [documented here][api-docs]. Also see the [CLI11 tutorial GitBook][gitbook].
|
||||
|
||||
## Examples
|
||||
|
||||
Several short examples of different features are included in the repository. A brief description of each is included here
|
||||
|
||||
- [callback_passthrough](https://github.com/CLIUtils/CLI11/blob/master/examples/callback_passthrough.cpp): Example of directly passing remaining arguments through to a callback function which generates a CLI11 application based on existing arguments.
|
||||
- [digit_args](https://github.com/CLIUtils/CLI11/blob/master/examples/digit_args.cpp): Based on [Issue #123](https://github.com/CLIUtils/CLI11/issues/123), uses digit flags to pass a value
|
||||
- [enum](https://github.com/CLIUtils/CLI11/blob/master/examples/enum.cpp): Using enumerations in an option, and the use of [CheckedTransformer](#transforming-validators)
|
||||
- [formatter](https://github.com/CLIUtils/CLI11/blob/master/examples/formatter.cpp): Illustrating usage of a custom formatter
|
||||
- [groups](https://github.com/CLIUtils/CLI11/blob/master/examples/groups.cpp): Example using groups of options for help grouping and a the timer helper class
|
||||
- [inter_argument_order](https://github.com/CLIUtils/CLI11/blob/master/examples/inter_argument_order.cpp): An app to practice mixing unlimited arguments, but still recover the original order.
|
||||
- [json](https://github.com/CLIUtils/CLI11/blob/master/examples/json.cpp): Using JSON as a config file parser
|
||||
- [modhelp](https://github.com/CLIUtils/CLI11/blob/master/examples/modhelp.cpp): How to modify the help flag to do something other than default
|
||||
- [nested](https://github.com/CLIUtils/CLI11/blob/master/examples/nested.cpp): Nested subcommands
|
||||
- [option_groups](https://github.com/CLIUtils/CLI11/blob/master/examples/option_groups.cpp): illustrating the use of option groups and a required number of options.
|
||||
based on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88) to set interacting groups of options
|
||||
- [positional_arity](https://github.com/CLIUtils/CLI11/blob/master/examples/positional_arity.cpp): Illustrating use of `preparse_callback` to handle situations where the number of arguments can determine which should get parsed, Based on [Issue #166](https://github.com/CLIUtils/CLI11/issues/166)
|
||||
- [positional_validation](https://github.com/CLIUtils/CLI11/blob/master/examples/positional_validation.cpp): Example of how positional arguments are validated using the `validate_positional` flag, also based on [Issue #166](https://github.com/CLIUtils/CLI11/issues/166)
|
||||
- [prefix_command](https://github.com/CLIUtils/CLI11/blob/master/examples/prefix_command.cpp): illustrating use of the `prefix_command` flag.
|
||||
- [ranges](https://github.com/CLIUtils/CLI11/blob/master/examples/ranges.cpp): App to demonstrate exclusionary option groups based on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88)
|
||||
- [shapes](https://github.com/CLIUtils/CLI11/blob/master/examples/shapes.cpp): illustrating how to set up repeated subcommands Based on [gitter discussion](https://gitter.im/CLI11gitter/Lobby?at=5c7af6b965ffa019ea788cd5)
|
||||
- [simple](https://github.com/CLIUtils/CLI11/blob/master/examples/simple.cpp): a simple example of how to set up a CLI11 Application with different flags and options
|
||||
- [subcom_help](https://github.com/CLIUtils/CLI11/blob/master/examples/subcom_help.cpp): configuring help for subcommands
|
||||
- [subcom_partitioned](https://github.com/CLIUtils/CLI11/blob/master/examples/subcom_partitioned.cpp): Example with a timer and subcommands generated separately and added to the main app later.
|
||||
- [subcommands](https://github.com/CLIUtils/CLI11/blob/master/examples/subcommands.cpp): Short example of subcommands
|
||||
- [validators](https://github.com/CLIUtils/CLI11/blob/master/examples/validators.cpp): Example illustrating use of validators
|
||||
|
||||
## Contribute
|
||||
|
||||
To contribute, open an [issue][github issues] or [pull request][github pull requests] on GitHub, or ask a question on [gitter][]. The is also a short note to contributors [here](./.github/CONTRIBUTING.md).
|
||||
This readme roughly follows the [Standard Readme Style][] and includes a mention of almost every feature of the library. More complex features are documented in more detail in the [CLI11 tutorial GitBook][gitbook].
|
||||
|
||||
This project was created by [Henry Schreiner](https://github.com/henryiii).
|
||||
Significant features and/or improvements to the code were contributed by:
|
||||
|
||||
- [Anton](https://github.com/SX91)
|
||||
- [Doug Johnston](https://github.com/dvj)
|
||||
- [Jonas Nilsson](https://github.com/SkyToGround)
|
||||
- [Lucas Czech](https://github.com/lczech)
|
||||
- [Marcus Brinkmann](https://github.com/lambdafu)
|
||||
- [Mathias Soeken](https://github.com/msoeken)
|
||||
- [Nathan Hourt](https://github.com/nathanhourt)
|
||||
- [Sean Fisk](https://github.com/seanfisk)
|
||||
- [Stéphane Del Pino](https://github.com/delpinux)
|
||||
- [Mak Kolybabi](https://github.com/mogigoma)
|
||||
- [Paweł Bylica](https://github.com/chfast)
|
||||
- [Philip Top](https://github.com/phlptp) <!-- Major features in 1.7 and 1.8 -->
|
||||
- [almikhayl](https://github.com/almikhayl)
|
||||
- [nurelin](https://github.com/nurelin) <!-- help_all in message -->
|
||||
- [ncihneg](https://github.com/ncihneg) <!-- Quoting strings in INI generation -->
|
||||
- [Fred Helmesjö](https://github.com/helmesjo) <!-- `->description()` -->
|
||||
- [Rafi Wiener](https://github.com/rafiw) <!-- INI, +ive validators and vector separators -->
|
||||
[elszon](https://github.com/elszon) <!-- Formatting in multiline string -->
|
||||
[ryan4729](https://github.com/ryan4729) <!-- AArch64 support -->
|
||||
[Andrew Hardin](https://github.com/andrew-hardin) <!-- Fixing two warnings -->
|
||||
[Paul le Roux](https://github.com/pleroux0) <!-- Arch independent CMake Config -->
|
||||
- [Viacheslav Kroilov](https://github.com/metopa) <!-- AsNumberWithUnit and AsSizeValue -->
|
||||
|
||||
|
||||
## License
|
||||
|
||||
As of version 1.0, this library is available under a 3-Clause BSD license. See the [LICENSE](./LICENSE) file for details.
|
||||
|
||||
CLI11 was developed at the [University of Cincinnati][] to support of the [GooFit][] library under [NSF Award 1414736][]. Version 0.9 was featured in a [DIANA/HEP][] meeting at CERN ([see the slides][diana slides]). Please give it a try! Feedback is always welcome.
|
||||
|
||||
[doi-badge]: https://zenodo.org/badge/80064252.svg
|
||||
[doi-link]: https://zenodo.org/badge/latestdoi/80064252
|
||||
[azure-badge]: https://dev.azure.com/CLIUtils/CLI11/_apis/build/status/CLIUtils.CLI11?branchName=master
|
||||
[azure]: https://dev.azure.com/CLIUtils/CLI11/_build/|latest?definitionId=1&branchName=master
|
||||
[travis-badge]: https://img.shields.io/travis/CLIUtils/CLI11/master.svg?label=Linux/macOS
|
||||
[travis]: https://travis-ci.org/CLIUtils/CLI11
|
||||
[appveyor-badge]: https://img.shields.io/appveyor/ci/HenrySchreiner/cli11/master.svg?label=Windows
|
||||
[appveyor]: https://ci.appveyor.com/project/HenrySchreiner/cli11
|
||||
[codecov-badge]: https://codecov.io/gh/CLIUtils/CLI11/branch/master/graph/badge.svg
|
||||
[codecov]: https://codecov.io/gh/CLIUtils/CLI11
|
||||
[gitter-badge]: https://badges.gitter.im/CLI11gitter/Lobby.svg
|
||||
[gitter]: https://gitter.im/CLI11gitter/Lobby
|
||||
[license-badge]: https://img.shields.io/badge/License-BSD-blue.svg
|
||||
[conan-badge]: https://api.bintray.com/packages/cliutils/CLI11/CLI11%3Acliutils/images/download.svg
|
||||
[conan-link]: https://bintray.com/cliutils/CLI11/CLI11%3Acliutils/_latestVersion
|
||||
[github releases]: https://github.com/CLIUtils/CLI11/releases
|
||||
[github issues]: https://github.com/CLIUtils/CLI11/issues
|
||||
[github pull requests]: https://github.com/CLIUtils/CLI11/pulls
|
||||
[goofit]: https://GooFit.github.io
|
||||
[plumbum]: https://plumbum.readthedocs.io/en/latest/
|
||||
[click]: http://click.pocoo.org
|
||||
[api-docs]: https://CLIUtils.github.io/CLI11/index.html
|
||||
[rang]: https://github.com/agauniyal/rang
|
||||
[boost program options]: http://www.boost.org/doc/libs/1_63_0/doc/html/program_options.html
|
||||
[the lean mean c++ option parser]: http://optionparser.sourceforge.net
|
||||
[tclap]: http://tclap.sourceforge.net
|
||||
[cxxopts]: https://github.com/jarro2783/cxxopts
|
||||
[docopt]: https://github.com/docopt/docopt.cpp
|
||||
[gflags]: https://gflags.github.io/gflags
|
||||
[getopt]: https://www.gnu.org/software/libc/manual/html_node/Getopt.html
|
||||
[diana/hep]: http://diana-hep.org
|
||||
[nsf award 1414736]: https://nsf.gov/awardsearch/showAward?AWD_ID=1414736
|
||||
[university of cincinnati]: http://www.uc.edu
|
||||
[gitbook]: https://cliutils.gitlab.io/CLI11Tutorial
|
||||
[cli11 internals]: https://cliutils.gitlab.io/CLI11Tutorial/chapters/internals.html
|
||||
[programoptions.hxx]: https://github.com/Fytch/ProgramOptions.hxx
|
||||
[argument aggregator]: https://github.com/vietjtnguyen/argagg
|
||||
[args]: https://github.com/Taywee/args
|
||||
[argh!]: https://github.com/adishavit/argh
|
||||
[fmt]: https://github.com/fmtlib/fmt
|
||||
[catch]: https://github.com/philsquared/Catch
|
||||
[clara]: https://github.com/philsquared/Clara
|
||||
[version 1.0 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-10/
|
||||
[version 1.3 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-13/
|
||||
[version 1.6 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-16/
|
||||
[wandbox-badge]: https://img.shields.io/badge/try_1.7-online-blue.svg
|
||||
[wandbox-link]: https://wandbox.org/permlink/k1BzlRwOZ07ieEuD
|
||||
[releases-badge]: https://img.shields.io/github/release/CLIUtils/CLI11.svg
|
||||
[cli11-po-compare]: https://iscinumpy.gitlab.io/post/comparing-cli11-and-boostpo/
|
||||
[diana slides]: https://indico.cern.ch/event/619465/contributions/2507949/attachments/1448567/2232649/20170424-diana-2.pdf
|
||||
[awesome c++]: https://github.com/fffaraz/awesome-cpp/blob/master/README.md#cli
|
||||
[cli]: https://codesynthesis.com/projects/cli/
|
||||
[single file libs]: https://github.com/nothings/single_file_libs/blob/master/README.md
|
||||
[codacy-badge]: https://api.codacy.com/project/badge/Grade/ac0df3aead2a4421b02070c3f324a0b9
|
||||
[codacy-link]: https://www.codacy.com/app/henryiii/CLI11?utm_source=github.com&utm_medium=referral&utm_content=CLIUtils/CLI11&utm_campaign=Badge_Grade
|
||||
[hunter]: https://docs.hunter.sh/en/latest/packages/pkg/CLI11.html
|
||||
[standard readme style]: https://github.com/RichardLitt/standard-readme
|
||||
[argparse]: https://github.com/p-ranav/argparse
|
||||
76
libs/libbattle-com/libs/CLI11/azure-pipelines.yml
Normal file
76
libs/libbattle-com/libs/CLI11/azure-pipelines.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
# C/C++ with GCC
|
||||
# Build your C/C++ project with GCC using make.
|
||||
# Add steps that publish test results, save build artifacts, deploy, and more:
|
||||
# https://docs.microsoft.com/azure/devops/pipelines/apps/c-cpp/gcc
|
||||
|
||||
trigger:
|
||||
- master
|
||||
|
||||
variables:
|
||||
cli11.single: ON
|
||||
cli11.std: 14
|
||||
cli11.build_type: Debug
|
||||
cli11.options:
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 4
|
||||
|
||||
jobs:
|
||||
|
||||
- job: ClangFormatTidy
|
||||
variables:
|
||||
CXX_FLAGS: "-Werror -Wcast-align -Wfloat-equal -Wimplicit-atomic-properties -Wmissing-declarations -Woverlength-strings -Wshadow -Wstrict-selector-match -Wundeclared-selector -Wunreachable-code -std=c++11"
|
||||
cli11.options: -DCLANG_TIDY_FIX=ON
|
||||
cli11.std: 11
|
||||
cli11.single: OFF
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 1
|
||||
pool:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
container: silkeh/clang:5
|
||||
steps:
|
||||
- script: scripts/check_style.sh
|
||||
displayName: Check format
|
||||
- template: .ci/azure-cmake.yml
|
||||
- template: .ci/azure-build.yml
|
||||
- script: git diff --exit-code --color
|
||||
displayName: Check tidy
|
||||
|
||||
- job: Native
|
||||
strategy:
|
||||
matrix:
|
||||
Linux:
|
||||
vmImage: 'ubuntu-latest'
|
||||
macOS:
|
||||
vmImage: 'macOS-latest'
|
||||
Windows:
|
||||
vmImage: 'vs2017-win2016'
|
||||
pool:
|
||||
vmImage: $(vmImage)
|
||||
steps:
|
||||
- template: .ci/azure-build.yml
|
||||
- template: .ci/azure-test.yml
|
||||
|
||||
- job: Docker
|
||||
variables:
|
||||
cli11.single: OFF
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
strategy:
|
||||
matrix:
|
||||
gcc9:
|
||||
containerImage: gcc:9
|
||||
cli11.std: 17
|
||||
gcc4.7:
|
||||
containerImage: gcc:4.7
|
||||
cli11.std: 11
|
||||
clang3.4:
|
||||
containerImage: silkeh/clang:3.4
|
||||
cli11.std: 11
|
||||
clang8:
|
||||
containerImage: silkeh/clang:8
|
||||
cli11.std: 14
|
||||
cli11.options: -DCLI11_FORCE_LIBCXX=ON
|
||||
container: $[ variables['containerImage'] ]
|
||||
steps:
|
||||
- template: .ci/azure-cmake.yml
|
||||
- template: .ci/azure-build.yml
|
||||
- template: .ci/azure-test.yml
|
||||
|
||||
76
libs/libbattle-com/libs/CLI11/cmake/AddGoogletest.cmake
Normal file
76
libs/libbattle-com/libs/CLI11/cmake/AddGoogletest.cmake
Normal file
@@ -0,0 +1,76 @@
|
||||
#
|
||||
#
|
||||
# Downloads GTest and provides a helper macro to add tests. Add make check, as well, which
|
||||
# gives output on failed tests without having to set an environment variable.
|
||||
#
|
||||
#
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
# older version of google tests doesn't support MSYS so needs this flag to compile
|
||||
if (MSYS)
|
||||
set(gtest_disable_pthreads ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "")
|
||||
add_subdirectory("${CLI11_SOURCE_DIR}/extern/googletest" "${CLI11_BINARY_DIR}/extern/googletest" EXCLUDE_FROM_ALL)
|
||||
|
||||
|
||||
if(GOOGLE_TEST_INDIVIDUAL)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.9)
|
||||
include(GoogleTest)
|
||||
else()
|
||||
set(GOOGLE_TEST_INDIVIDUAL OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Target must already exist
|
||||
macro(add_gtest TESTNAME)
|
||||
target_link_libraries(${TESTNAME} PUBLIC gtest gmock gtest_main)
|
||||
|
||||
if(GOOGLE_TEST_INDIVIDUAL)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.10)
|
||||
gtest_add_tests(TARGET ${TESTNAME}
|
||||
TEST_PREFIX "${TESTNAME}."
|
||||
TEST_LIST TmpTestList)
|
||||
set_tests_properties(${TmpTestList} PROPERTIES FOLDER "Tests")
|
||||
else()
|
||||
gtest_discover_tests(${TESTNAME}
|
||||
TEST_PREFIX "${TESTNAME}."
|
||||
PROPERTIES FOLDER "Tests")
|
||||
|
||||
endif()
|
||||
else()
|
||||
add_test(${TESTNAME} ${TESTNAME})
|
||||
set_target_properties(${TESTNAME} PROPERTIES FOLDER "Tests")
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
mark_as_advanced(
|
||||
gmock_build_tests
|
||||
gtest_build_samples
|
||||
gtest_build_tests
|
||||
gtest_disable_pthreads
|
||||
gtest_force_shared_crt
|
||||
gtest_hide_internal_symbols
|
||||
BUILD_GMOCK
|
||||
BUILD_GTEST
|
||||
)
|
||||
|
||||
set_target_properties(gtest gtest_main gmock gmock_main
|
||||
PROPERTIES FOLDER "Extern")
|
||||
|
||||
foreach(TGT IN ITEMS gtest gtest_main gmock gmock_main)
|
||||
get_property(DIR_LIST TARGET ${TGT} PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
foreach(ITEM IN LISTS DIR_LIST)
|
||||
set_property(TARGET ${TGT} APPEND PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${ITEM}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(MSVC)
|
||||
if (MSVC_VERSION GREATER_EQUAL 1900)
|
||||
target_compile_definitions(gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
target_compile_definitions(gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
target_compile_definitions(gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
target_compile_definitions(gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,13 @@
|
||||
# Adapted from write_basic_package_version_file(... COMPATIBILITY AnyNewerVersion) output
|
||||
# ARCH_INDEPENDENT is only present in cmake 3.14 and onwards
|
||||
|
||||
set(PACKAGE_VERSION "@VERSION_STRING@")
|
||||
|
||||
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
244
libs/libbattle-com/libs/CLI11/cmake/CodeCoverage.cmake
Normal file
244
libs/libbattle-com/libs/CLI11/cmake/CodeCoverage.cmake
Normal file
@@ -0,0 +1,244 @@
|
||||
# Copyright (c) 2012 - 2017, Lars Bilke
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. 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.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
|
||||
#
|
||||
# CHANGES:
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# 2016-02-03, Lars Bilke
|
||||
# - Refactored functions to use named parameters
|
||||
#
|
||||
# 2017-06-02, Lars Bilke
|
||||
# - Merged with modified version from github.com/ufz/ogs
|
||||
#
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt:
|
||||
# include(CodeCoverage)
|
||||
#
|
||||
# 3. Append necessary compiler flags:
|
||||
# APPEND_COVERAGE_COMPILER_FLAGS()
|
||||
#
|
||||
# 4. If you need to exclude additional directories from the report, specify them
|
||||
# using the COVERAGE_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE.
|
||||
# Example:
|
||||
# set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*')
|
||||
#
|
||||
# 5. Use the functions described below to create a custom make target which
|
||||
# runs your test executable and produces a code coverage report.
|
||||
#
|
||||
# 6. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Check prereqs
|
||||
find_program( GCOV_PATH gcov )
|
||||
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
||||
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
||||
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
||||
find_program( SIMPLE_PYTHON_EXECUTABLE python )
|
||||
|
||||
if(NOT GCOV_PATH)
|
||||
message(FATAL_ERROR "gcov not found! Aborting...")
|
||||
endif() # NOT GCOV_PATH
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
|
||||
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
||||
endif()
|
||||
elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||
message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
|
||||
endif()
|
||||
|
||||
set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE INTERNAL "")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
mark_as_advanced(
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||
endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||
endif()
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# SETUP_TARGET_FOR_COVERAGE(
|
||||
# NAME testrunner_coverage # New target name
|
||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES testrunner # Dependencies to build first
|
||||
# )
|
||||
function(SETUP_TARGET_FOR_COVERAGE)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT LCOV_PATH)
|
||||
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||
endif() # NOT LCOV_PATH
|
||||
|
||||
if(NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif() # NOT GENHTML_PATH
|
||||
|
||||
# Setup target
|
||||
add_custom_target(${Coverage_NAME}
|
||||
|
||||
# Cleanup lcov
|
||||
COMMAND ${LCOV_PATH} --directory . --zerocounters
|
||||
# Create baseline to make sure untouched files show up in the report
|
||||
COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base
|
||||
|
||||
# Run tests
|
||||
COMMAND ${Coverage_EXECUTABLE}
|
||||
|
||||
# Capturing lcov counters and generating report
|
||||
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info
|
||||
# add baseline counters
|
||||
COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total
|
||||
COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
|
||||
COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
# Show where to find the lcov info report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # SETUP_TARGET_FOR_COVERAGE
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# SETUP_TARGET_FOR_COVERAGE_COBERTURA(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# )
|
||||
function(SETUP_TARGET_FOR_COVERAGE_COBERTURA)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT SIMPLE_PYTHON_EXECUTABLE)
|
||||
message(FATAL_ERROR "python not found! Aborting...")
|
||||
endif() # NOT SIMPLE_PYTHON_EXECUTABLE
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(COBERTURA_EXCLUDES "")
|
||||
foreach(EXCLUDE ${COVERAGE_EXCLUDES})
|
||||
set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}")
|
||||
endforeach()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
|
||||
# Run tests
|
||||
${Coverage_EXECUTABLE}
|
||||
|
||||
# Running gcovr
|
||||
COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES}
|
||||
-o ${Coverage_NAME}.xml
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
|
||||
)
|
||||
|
||||
endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
|
||||
|
||||
function(APPEND_COVERAGE_COMPILER_FLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||
endfunction() # APPEND_COVERAGE_COMPILER_FLAGS
|
||||
36
libs/libbattle-com/libs/CLI11/conanfile.py
Normal file
36
libs/libbattle-com/libs/CLI11/conanfile.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from conans import ConanFile, CMake
|
||||
from conans.tools import load
|
||||
import re
|
||||
|
||||
def get_version():
|
||||
try:
|
||||
content = load("include/CLI/Version.hpp")
|
||||
version = re.search(r'#define CLI11_VERSION "(.*)"', content).group(1)
|
||||
return version
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
class CLI11Conan(ConanFile):
|
||||
name = "CLI11"
|
||||
version = get_version()
|
||||
description = "Command Line Interface toolkit for C++11"
|
||||
topics = ("cli", "c++11", "parser", "cli11")
|
||||
url = "https://github.com/CLIUtils/CLI11"
|
||||
homepage = "https://github.com/CLIUtils/CLI11"
|
||||
author = "Henry Schreiner <hschrein@cern.ch>"
|
||||
license = "BSD-3-Clause"
|
||||
|
||||
settings = "os", "compiler", "arch", "build_type"
|
||||
exports_sources = "LICENSE", "README.md", "include/*", "extern/*", "cmake/*", "CMakeLists.txt", "tests/*"
|
||||
|
||||
def build(self): # this is not building a library, just tests
|
||||
cmake = CMake(self)
|
||||
cmake.definitions["CLI11_EXAMPLES"] = "OFF"
|
||||
cmake.definitions["CLI11_SINGLE_FILE"] = "OFF"
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
cmake.test()
|
||||
cmake.install()
|
||||
|
||||
def package_id(self):
|
||||
self.info.header_only()
|
||||
2
libs/libbattle-com/libs/CLI11/docs/.gitignore
vendored
Normal file
2
libs/libbattle-com/libs/CLI11/docs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/html/*
|
||||
/latex/*
|
||||
114
libs/libbattle-com/libs/CLI11/docs/CLI11.svg
Normal file
114
libs/libbattle-com/libs/CLI11/docs/CLI11.svg
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="34.342606mm"
|
||||
height="15.300875mm"
|
||||
viewBox="0 0 34.342606 15.300875"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 (unknown)"
|
||||
sodipodi:docname="CLI11.svg"
|
||||
inkscape:export-filename="/data/CLI11_300.png"
|
||||
inkscape:export-xdpi="222.62143"
|
||||
inkscape:export-ydpi="222.62143">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.206433"
|
||||
inkscape:cx="93.996945"
|
||||
inkscape:cy="15.843961"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1347"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-53.018986,-23.9019)">
|
||||
<g
|
||||
id="g4602"
|
||||
transform="rotate(-0.28559572,70.190289,31.552338)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3732"
|
||||
transform="scale(0.26458333)"
|
||||
d="m 233.33789,90.337891 -32.95117,28.619139 31.94726,28.91406 64.9004,0.29688 32.95117,-28.61914 -31.94727,-28.914064 z"
|
||||
style="fill:#008080;stroke-width:0.54128456" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:0.3148967;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 62.120274,24.413292 -8.32335,7.065988 8.069765,7.138804 16.393615,0.0733 8.32335,-7.065988 -8.069768,-7.138806 z"
|
||||
id="path3774" />
|
||||
</g>
|
||||
<g
|
||||
id="g4609"
|
||||
transform="translate(-0.43472687)">
|
||||
<path
|
||||
inkscape:transform-center-y="0.00020894337"
|
||||
inkscape:transform-center-x="0.0229185"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3730"
|
||||
d="m 60.964519,27.804182 c 0.886395,-0.348655 1.859691,-0.390207 2.74248,-0.111952 0.651274,0.210103 1.042699,0.454066 1.576252,0.972044 l -1.506657,0.592635 c -0.744252,-0.446473 -1.423964,-0.497745 -2.270962,-0.164583 -0.738662,0.290549 -1.26082,0.814436 -1.498695,1.510755 -0.203801,0.580557 -0.182185,1.300104 0.05025,1.891033 0.534609,1.359137 2.079298,2.048044 3.418738,1.521183 0.699266,-0.275052 1.11846,-0.713017 1.465328,-1.565931 l 1.585527,-0.623658 c -0.04824,1.554281 -1.023053,2.892949 -2.510224,3.47792 -2.127345,0.836779 -4.497206,-0.187252 -5.322363,-2.28505 -0.809661,-2.058401 0.211919,-4.404734 2.270322,-5.214396 z"
|
||||
style="fill:#ffffff;stroke-width:0.14321487" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3728"
|
||||
transform="scale(0.26458333)"
|
||||
d="m 253.49609,104.47266 h 5.48047 v 24.32031 h 9.03906 v 5.24023 h -14.51953 z"
|
||||
style="fill:#ffffff;stroke-width:0.54128456" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3726"
|
||||
transform="scale(0.26458333)"
|
||||
d="m 271.07422,104.47266 h 5.48047 v 29.56054 h -5.48047 z"
|
||||
style="fill:#ffffff;stroke-width:0.54128456" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3724"
|
||||
transform="scale(0.26458333)"
|
||||
d="m 294.68555,104.47266 v 29.56054 h -5.32032 v -24.56054 h -3.71875 z"
|
||||
style="fill:#ffffff;stroke-width:0.54128456" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3705"
|
||||
transform="scale(0.26458333)"
|
||||
d="m 305.76758,104.47266 v 29.56054 h -5.32031 v -24.56054 h -3.71875 z"
|
||||
style="fill:#ffffff;stroke-width:0.54128456" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
BIN
libs/libbattle-com/libs/CLI11/docs/CLI11_100.png
Normal file
BIN
libs/libbattle-com/libs/CLI11/docs/CLI11_100.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
libs/libbattle-com/libs/CLI11/docs/CLI11_300.png
Normal file
BIN
libs/libbattle-com/libs/CLI11/docs/CLI11_300.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
2473
libs/libbattle-com/libs/CLI11/docs/Doxyfile
Normal file
2473
libs/libbattle-com/libs/CLI11/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
26
libs/libbattle-com/libs/CLI11/docs/mainpage.md
Normal file
26
libs/libbattle-com/libs/CLI11/docs/mainpage.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Introduction
|
||||
|
||||
This is the Doxygen API documentation for CLI11 parser. There is a friendly introduction to CLI11 on the [Github page](https://github.com/CLIUtils/CLI11).
|
||||
|
||||
The main classes are:
|
||||
|
||||
| Name | Where used |
|
||||
|---------------|-------------------------------------|
|
||||
|CLI::Option | Options, stored in the app |
|
||||
|CLI::App | The main application or subcommands |
|
||||
|CLI::Validator | A check that can affect the type name |
|
||||
|CLI::Formatter | A subclassable formatter for help printing |
|
||||
|CLI::ExitCode | A scoped enum with exit codes |
|
||||
|CLI::Timer | A timer class, only in CLI/Timer.hpp (not in `CLI11.hpp`) |
|
||||
|CLI::AutoTimer | A timer that prints on deletion |
|
||||
|
||||
|
||||
Groups of related topics:
|
||||
|
||||
| Name | Description |
|
||||
|----------------------|------------------------------------------------|
|
||||
| @ref error_group | Errors that can be thrown |
|
||||
| @ref validator_group | Common validators used in CLI::Option::check() |
|
||||
|
||||
|
||||
|
||||
228
libs/libbattle-com/libs/CLI11/examples/CMakeLists.txt
Normal file
228
libs/libbattle-com/libs/CLI11/examples/CMakeLists.txt
Normal file
@@ -0,0 +1,228 @@
|
||||
function(add_cli_exe T)
|
||||
add_executable(${T} ${ARGN} ${CLI11_headers})
|
||||
target_link_libraries(${T} PUBLIC CLI11)
|
||||
set_target_properties(
|
||||
${T} PROPERTIES
|
||||
FOLDER "Examples"
|
||||
)
|
||||
|
||||
if(CLANG_TIDY_EXE)
|
||||
set_target_properties(
|
||||
${T} PROPERTIES
|
||||
CXX_CLANG_TIDY "${DO_CLANG_TIDY}"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
option(CLI11_EXAMPLE_JSON OFF)
|
||||
if(CLI11_EXAMPLE_JSON)
|
||||
if(NOT EXISTS "${CLI11_SOURCE_DIR}/extern/json/single_include/nlohmann/json.hpp")
|
||||
message(ERROR "You are missing the json package for CLI11_EXAMPLE_JSON. Please update your submodules (git submodule update --init)")
|
||||
endif()
|
||||
if(CMAKE_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
|
||||
message(WARNING "The json example requires GCC 4.8+ (requirement on json library)")
|
||||
endif()
|
||||
add_cli_exe(json json.cpp)
|
||||
target_include_directories(json PUBLIC SYSTEM "${CLI11_SOURCE_DIR}/extern/json/single_include")
|
||||
|
||||
add_test(NAME json_config_out COMMAND json --item 2)
|
||||
set_property(TEST json_config_out PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"{"
|
||||
"\"item\": \"2\""
|
||||
"\"simple\": false"
|
||||
"}")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/input.json" [=[{"item":3,"simple":false}]=])
|
||||
add_test(NAME json_config_in COMMAND json --config "${CMAKE_CURRENT_BINARY_DIR}/input.json")
|
||||
set_property(TEST json_config_in PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"{"
|
||||
"\"item\": \"3\""
|
||||
"\"simple\": false"
|
||||
"}")
|
||||
endif()
|
||||
|
||||
add_cli_exe(simple simple.cpp)
|
||||
add_test(NAME simple_basic COMMAND simple)
|
||||
add_test(NAME simple_all COMMAND simple -f filename.txt -c 12 --flag --flag -d 1.2)
|
||||
set_property(TEST simple_all PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Working on file: filename.txt, direct count: 1, opt count: 1"
|
||||
"Working on count: 12, direct count: 1, opt count: 1"
|
||||
"Received flag: 2 (2) times"
|
||||
"Some value: 1.2")
|
||||
|
||||
|
||||
add_cli_exe(subcommands subcommands.cpp)
|
||||
add_test(NAME subcommands_none COMMAND subcommands)
|
||||
set_property(TEST subcommands_none PROPERTY
|
||||
PASS_REGULAR_EXPRESSION "A subcommand is required")
|
||||
add_test(NAME subcommands_all COMMAND subcommands --random start --file name stop --count)
|
||||
set_property(TEST subcommands_all PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Working on --file from start: name"
|
||||
"Working on --count from stop: 1, direct count: 1"
|
||||
"Count of --random flag: 1"
|
||||
"Subcommand: start"
|
||||
"Subcommand: stop")
|
||||
|
||||
add_cli_exe(subcom_partitioned subcom_partitioned.cpp)
|
||||
add_test(NAME subcom_partitioned_none COMMAND subcom_partitioned)
|
||||
set_property(TEST subcom_partitioned_none PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"This is a timer:"
|
||||
"--file is required"
|
||||
"Run with --help for more information.")
|
||||
|
||||
add_test(NAME subcom_partitioned_all COMMAND subcom_partitioned --file this --count --count -d 1.2)
|
||||
set_property(TEST subcom_partitioned_all PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"This is a timer:"
|
||||
"Working on file: this, direct count: 1, opt count: 1"
|
||||
"Working on count: 2, direct count: 2, opt count: 2"
|
||||
"Some value: 1.2")
|
||||
# test shows that the help prints out for unnamed subcommands
|
||||
add_test(NAME subcom_partitioned_help COMMAND subcom_partitioned --help)
|
||||
set_property(TEST subcom_partitioned_help PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"-f,--file TEXT REQUIRED"
|
||||
"-d,--double FLOAT")
|
||||
|
||||
add_cli_exe(option_groups option_groups.cpp)
|
||||
add_test(NAME option_groups_missing COMMAND option_groups )
|
||||
set_property(TEST option_groups_missing PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Exactly 1 option from"
|
||||
"is required")
|
||||
add_test(NAME option_groups_extra COMMAND option_groups --csv --binary)
|
||||
set_property(TEST option_groups_extra PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"and 2 were given")
|
||||
add_test(NAME option_groups_extra2 COMMAND option_groups --csv --address "192.168.1.1" -o "test.out")
|
||||
set_property(TEST option_groups_extra2 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"at most 1")
|
||||
|
||||
add_cli_exe(positional_arity positional_arity.cpp)
|
||||
add_test(NAME positional_arity1 COMMAND positional_arity one )
|
||||
set_property(TEST positional_arity1 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one")
|
||||
add_test(NAME positional_arity2 COMMAND positional_arity one two )
|
||||
set_property(TEST positional_arity2 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one"
|
||||
"File 2 = two")
|
||||
add_test(NAME positional_arity3 COMMAND positional_arity 1 2 one)
|
||||
set_property(TEST positional_arity3 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one")
|
||||
add_test(NAME positional_arity_fail COMMAND positional_arity 1 one two)
|
||||
set_property(TEST positional_arity_fail PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Could not convert")
|
||||
|
||||
add_cli_exe(positional_validation positional_validation.cpp)
|
||||
add_test(NAME positional_validation1 COMMAND positional_validation one )
|
||||
set_property(TEST positional_validation1 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one")
|
||||
add_test(NAME positional_validation2 COMMAND positional_validation one 1 2 two )
|
||||
set_property(TEST positional_validation2 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one"
|
||||
"File 2 = two")
|
||||
add_test(NAME positional_validation3 COMMAND positional_validation 1 2 one)
|
||||
set_property(TEST positional_validation3 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one")
|
||||
add_test(NAME positional_validation4 COMMAND positional_validation 1 one two 2)
|
||||
set_property(TEST positional_validation4 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"File 1 = one"
|
||||
"File 2 = two")
|
||||
|
||||
add_cli_exe(shapes shapes.cpp)
|
||||
add_test(NAME shapes_all COMMAND shapes circle 4.4 circle 10.7 rectangle 4 4 circle 2.3 triangle 4.5 ++ rectangle 2.1 ++ circle 234.675)
|
||||
set_property(TEST shapes_all PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"circle2"
|
||||
"circle4"
|
||||
"rectangle2 with edges [2.1,2.1]"
|
||||
"triangel1 with sides [4.5]")
|
||||
|
||||
add_cli_exe(ranges ranges.cpp)
|
||||
add_test(NAME ranges_range COMMAND ranges --range 1 2 3)
|
||||
set_property(TEST ranges_range PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"[2:1:3]")
|
||||
add_test(NAME ranges_minmax COMMAND ranges --min 2 --max 3)
|
||||
set_property(TEST ranges_minmax PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"[2:1:3]")
|
||||
add_test(NAME ranges_error COMMAND ranges --min 2 --max 3 --step 1 --range 1 2 3)
|
||||
set_property(TEST ranges_error PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Exactly 1 option from")
|
||||
|
||||
add_cli_exe(validators validators.cpp)
|
||||
add_test(NAME validators_help COMMAND validators --help)
|
||||
set_property(TEST validators_help PROPERTY PASS_REGULAR_EXPRESSION
|
||||
" -f,--file TEXT:FILE[\\r\\n\\t ]+File name"
|
||||
" -v,--value INT:INT in [3 - 6][\\r\\n\\t ]+Value in range")
|
||||
add_test(NAME validators_file COMMAND validators --file nonex.xxx)
|
||||
set_property(TEST validators_file PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"--file: File does not exist: nonex.xxx"
|
||||
"Run with --help for more information.")
|
||||
add_test(NAME validators_plain COMMAND validators --value 9)
|
||||
set_property(TEST validators_plain PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"--value: Value 9 not in range 3 to 6"
|
||||
"Run with --help for more information.")
|
||||
|
||||
add_cli_exe(groups groups.cpp)
|
||||
add_test(NAME groups_none COMMAND groups)
|
||||
set_property(TEST groups_none PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"This is a timer:"
|
||||
"--file is required"
|
||||
"Run with --help for more information.")
|
||||
add_test(NAME groups_all COMMAND groups --file this --count --count -d 1.2)
|
||||
set_property(TEST groups_all PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"This is a timer:"
|
||||
"Working on file: this, direct count: 1, opt count: 1"
|
||||
"Working on count: 2, direct count: 2, opt count: 2"
|
||||
"Some value: 1.2")
|
||||
|
||||
add_cli_exe(inter_argument_order inter_argument_order.cpp)
|
||||
add_test(NAME inter_argument_order COMMAND inter_argument_order --foo 1 2 3 --x --bar 4 5 6 --z --foo 7 8)
|
||||
set_property(TEST inter_argument_order PROPERTY PASS_REGULAR_EXPRESSION
|
||||
[=[foo : 1
|
||||
foo : 2
|
||||
foo : 3
|
||||
bar : 4
|
||||
bar : 5
|
||||
bar : 6
|
||||
foo : 7
|
||||
foo : 8]=])
|
||||
|
||||
add_cli_exe(prefix_command prefix_command.cpp)
|
||||
add_test(NAME prefix_command COMMAND prefix_command -v 3 2 1 -- other one two 3)
|
||||
set_property(TEST prefix_command PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Prefix: 3 : 2 : 1"
|
||||
"Remaining commands: other one two 3")
|
||||
|
||||
add_cli_exe(callback_passthrough callback_passthrough.cpp)
|
||||
add_test(NAME callback_passthrough1 COMMAND callback_passthrough --argname t2 --t2 test)
|
||||
set_property(TEST callback_passthrough1 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"the value is now test")
|
||||
add_test(NAME callback_passthrough2 COMMAND callback_passthrough --arg EEEK --argname arg)
|
||||
set_property(TEST callback_passthrough2 PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"the value is now EEEK")
|
||||
|
||||
add_cli_exe(enum enum.cpp)
|
||||
add_test(NAME enum_pass COMMAND enum -l 1)
|
||||
add_test(NAME enum_fail COMMAND enum -l 4)
|
||||
set_property(TEST enum_fail PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"--level: Check 4 value in {" "FAILED")
|
||||
|
||||
add_cli_exe(digit_args digit_args.cpp)
|
||||
add_test(NAME digit_args COMMAND digit_args -h)
|
||||
set_property(TEST digit_args PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"-3{3}")
|
||||
|
||||
add_cli_exe(modhelp modhelp.cpp)
|
||||
add_test(NAME modhelp COMMAND modhelp -a test -h)
|
||||
set_property(TEST modhelp PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Option -a string in help: test")
|
||||
|
||||
add_subdirectory(subcom_in_files)
|
||||
add_test(NAME subcom_in_files COMMAND subcommand_main subcommand_a -f this.txt --with-foo)
|
||||
set_property(TEST subcom_in_files PROPERTY PASS_REGULAR_EXPRESSION
|
||||
"Working on file: this\.txt"
|
||||
"Using foo!")
|
||||
|
||||
add_cli_exe(formatter formatter.cpp)
|
||||
|
||||
add_cli_exe(nested nested.cpp)
|
||||
|
||||
add_cli_exe(subcom_help subcom_help.cpp)
|
||||
add_test(NAME subcom_help_normal COMMAND subcom_help sub --help)
|
||||
add_test(NAME subcom_help_reversed COMMAND subcom_help --help sub)
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("callback_passthrough");
|
||||
app.allow_extras();
|
||||
std::string argName;
|
||||
std::string val;
|
||||
app.add_option("--argname", argName, "the name of the custom command line argument");
|
||||
app.callback([&app, &val, &argName]() {
|
||||
if(!argName.empty()) {
|
||||
CLI::App subApp;
|
||||
subApp.add_option("--" + argName, val, "custom argument option");
|
||||
subApp.parse(app.remaining_for_passthrough());
|
||||
}
|
||||
});
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
std::cout << "the value is now " << val << '\n';
|
||||
}
|
||||
15
libs/libbattle-com/libs/CLI11/examples/digit_args.cpp
Normal file
15
libs/libbattle-com/libs/CLI11/examples/digit_args.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App app;
|
||||
|
||||
int val;
|
||||
// add a set of flags with default values associate with them
|
||||
app.add_flag("-1{1},-2{2},-3{3},-4{4},-5{5},-6{6}, -7{7}, -8{8}, -9{9}", val, "compression level");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::cout << "value = " << val << std::endl;
|
||||
return 0;
|
||||
}
|
||||
25
libs/libbattle-com/libs/CLI11/examples/enum.cpp
Normal file
25
libs/libbattle-com/libs/CLI11/examples/enum.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
enum class Level : int { High, Medium, Low };
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App app;
|
||||
|
||||
Level level;
|
||||
// specify string->value mappings
|
||||
std::vector<std::pair<std::string, Level>> map{
|
||||
{"high", Level::High}, {"medium", Level::Medium}, {"low", Level::Low}};
|
||||
// checked Transform does the translation and checks the results are either in one of the strings or one of the
|
||||
// translations already
|
||||
app.add_option("-l,--level", level, "Level settings")
|
||||
->required()
|
||||
->transform(CLI::CheckedTransformer(map, CLI::ignore_case));
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
// CLI11's built in enum streaming can be used outside CLI11 like this:
|
||||
using namespace CLI::enums;
|
||||
std::cout << "Enum received: " << level << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
29
libs/libbattle-com/libs/CLI11/examples/formatter.cpp
Normal file
29
libs/libbattle-com/libs/CLI11/examples/formatter.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
class MyFormatter : public CLI::Formatter {
|
||||
public:
|
||||
MyFormatter() : Formatter() {}
|
||||
std::string make_option_opts(const CLI::Option *) const override { return " OPTION"; }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App app;
|
||||
app.set_help_all_flag("--help-all", "Show all help");
|
||||
|
||||
auto fmt = std::make_shared<MyFormatter>();
|
||||
fmt->column_width(15);
|
||||
app.formatter(fmt);
|
||||
|
||||
app.add_flag("--flag", "This is a flag");
|
||||
|
||||
auto sub1 = app.add_subcommand("one", "Description One");
|
||||
sub1->add_flag("--oneflag", "Some flag");
|
||||
auto sub2 = app.add_subcommand("two", "Description Two");
|
||||
sub2->add_flag("--twoflag", "Some other flag");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::cout << "This app was meant to show off the formatter, run with -h" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
31
libs/libbattle-com/libs/CLI11/examples/groups.cpp
Normal file
31
libs/libbattle-com/libs/CLI11/examples/groups.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
#include "CLI/Timer.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::AutoTimer("This is a timer");
|
||||
|
||||
CLI::App app("K3Pi goofit fitter");
|
||||
|
||||
std::string file;
|
||||
CLI::Option *opt = app.add_option("-f,--file,file", file, "File name")->required()->group("Important");
|
||||
|
||||
int count;
|
||||
CLI::Option *copt = app.add_flag("-c,--count", count, "Counter")->required()->group("Important");
|
||||
|
||||
double value; // = 3.14;
|
||||
app.add_option("-d,--double", value, "Some Value")->group("Other");
|
||||
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch(const CLI::ParseError &e) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
|
||||
<< ", opt count: " << opt->count() << std::endl;
|
||||
std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
|
||||
<< ", opt count: " << copt->count() << std::endl;
|
||||
std::cout << "Some value: " << value << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App app{"An app to practice mixing unlimited arguments, but still recover the original order."};
|
||||
|
||||
std::vector<int> foos;
|
||||
auto foo = app.add_option("--foo,-f", foos, "Some unlimited argument");
|
||||
|
||||
std::vector<int> bars;
|
||||
auto bar = app.add_option("--bar", bars, "Some unlimited arggument");
|
||||
|
||||
app.add_flag("--z,--x", "Random other flags");
|
||||
|
||||
// Standard parsing lines (copy and paste in, or use CLI11_PARSE)
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch(const CLI::ParseError &e) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
// I prefer using the back and popping
|
||||
std::reverse(std::begin(foos), std::end(foos));
|
||||
std::reverse(std::begin(bars), std::end(bars));
|
||||
|
||||
std::vector<std::pair<std::string, int>> keyval;
|
||||
for(auto option : app.parse_order()) {
|
||||
if(option == foo) {
|
||||
keyval.emplace_back("foo", foos.back());
|
||||
foos.pop_back();
|
||||
}
|
||||
if(option == bar) {
|
||||
keyval.emplace_back("bar", bars.back());
|
||||
bars.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Prove the vector is correct
|
||||
for(auto &pair : keyval) {
|
||||
std::cout << pair.first << " : " << pair.second << std::endl;
|
||||
}
|
||||
}
|
||||
113
libs/libbattle-com/libs/CLI11/examples/json.cpp
Normal file
113
libs/libbattle-com/libs/CLI11/examples/json.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// This example is only built on GCC 7 on Travis due to mismatch in stdlib
|
||||
// for clang (CLI11 is forgiving about mismatches, json.hpp is not)
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
class ConfigJSON : public CLI::Config {
|
||||
public:
|
||||
std::string to_config(const CLI::App *app, bool default_also, bool, std::string) const override {
|
||||
|
||||
json j;
|
||||
|
||||
for(const CLI::Option *opt : app->get_options({})) {
|
||||
|
||||
// Only process option with a long-name and configurable
|
||||
if(!opt->get_lnames().empty() && opt->get_configurable()) {
|
||||
std::string name = opt->get_lnames()[0];
|
||||
|
||||
// Non-flags
|
||||
if(opt->get_type_size() != 0) {
|
||||
|
||||
// If the option was found on command line
|
||||
if(opt->count() == 1)
|
||||
j[name] = opt->results().at(0);
|
||||
else if(opt->count() > 1)
|
||||
j[name] = opt->results();
|
||||
|
||||
// If the option has a default and is requested by optional argument
|
||||
else if(default_also && !opt->get_default_str().empty())
|
||||
j[name] = opt->get_default_str();
|
||||
|
||||
// Flag, one passed
|
||||
} else if(opt->count() == 1) {
|
||||
j[name] = true;
|
||||
|
||||
// Flag, multiple passed
|
||||
} else if(opt->count() > 1) {
|
||||
j[name] = opt->count();
|
||||
|
||||
// Flag, not present
|
||||
} else if(opt->count() == 0 && default_also) {
|
||||
j[name] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const CLI::App *subcom : app->get_subcommands({}))
|
||||
j[subcom->get_name()] = json(to_config(subcom, default_also, false, ""));
|
||||
|
||||
return j.dump(4);
|
||||
}
|
||||
|
||||
std::vector<CLI::ConfigItem> from_config(std::istream &input) const override {
|
||||
json j;
|
||||
input >> j;
|
||||
return _from_config(j);
|
||||
}
|
||||
|
||||
std::vector<CLI::ConfigItem>
|
||||
_from_config(json j, std::string name = "", std::vector<std::string> prefix = {}) const {
|
||||
std::vector<CLI::ConfigItem> results;
|
||||
|
||||
if(j.is_object()) {
|
||||
for(json::iterator item = j.begin(); item != j.end(); ++item) {
|
||||
auto copy_prefix = prefix;
|
||||
if(!name.empty())
|
||||
copy_prefix.push_back(name);
|
||||
auto sub_results = _from_config(*item, item.key(), copy_prefix);
|
||||
results.insert(results.end(), sub_results.begin(), sub_results.end());
|
||||
}
|
||||
} else if(!name.empty()) {
|
||||
results.emplace_back();
|
||||
CLI::ConfigItem &res = results.back();
|
||||
res.name = name;
|
||||
res.parents = prefix;
|
||||
if(j.is_boolean()) {
|
||||
res.inputs = {j.get<bool>() ? "true" : "false"};
|
||||
} else if(j.is_number()) {
|
||||
std::stringstream ss;
|
||||
ss << j.get<double>();
|
||||
res.inputs = {ss.str()};
|
||||
} else if(j.is_string()) {
|
||||
res.inputs = {j.get<std::string>()};
|
||||
} else if(j.is_array()) {
|
||||
for(std::string ival : j)
|
||||
res.inputs.push_back(ival);
|
||||
} else {
|
||||
throw CLI::ConversionError("Failed to convert " + name);
|
||||
}
|
||||
} else {
|
||||
throw CLI::ConversionError("You must make all top level values objects in json!");
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App app;
|
||||
app.config_formatter(std::make_shared<ConfigJSON>());
|
||||
|
||||
int item;
|
||||
|
||||
app.add_flag("--simple");
|
||||
app.add_option("--item", item);
|
||||
app.set_config("--config");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::cout << app.config_to_str(true, true) << std::endl;
|
||||
}
|
||||
30
libs/libbattle-com/libs/CLI11/examples/modhelp.cpp
Normal file
30
libs/libbattle-com/libs/CLI11/examples/modhelp.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App test{R"raw(Modify the help print so that argument values are accessible.
|
||||
Note that this will not shortcut `->required` and other similar options.)raw"};
|
||||
|
||||
// Remove help flag because it shortcuts all processing
|
||||
test.set_help_flag();
|
||||
|
||||
// Add custom flag that activates help
|
||||
auto help = test.add_flag("-h,--help", "Request help");
|
||||
|
||||
std::string some_option;
|
||||
test.add_option("-a", some_option, "Some description");
|
||||
|
||||
try {
|
||||
test.parse(argc, argv);
|
||||
if(*help)
|
||||
throw CLI::CallForHelp();
|
||||
} catch(const CLI::Error &e) {
|
||||
std::cout << "Option -a string in help: " << some_option << std::endl;
|
||||
return test.exit(e);
|
||||
}
|
||||
|
||||
std::cout << "Option -a string: " << some_option << std::endl;
|
||||
return 0;
|
||||
}
|
||||
22
libs/libbattle-com/libs/CLI11/examples/nested.cpp
Normal file
22
libs/libbattle-com/libs/CLI11/examples/nested.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <string>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("Vision Application");
|
||||
app.set_help_all_flag("--help-all", "Expand all help");
|
||||
app.add_flag("--version", "Get version");
|
||||
|
||||
CLI::App *cameraApp = app.add_subcommand("camera", "Configure the app camera");
|
||||
cameraApp->require_subcommand(0, 1); // 0 (default) or 1 camera
|
||||
|
||||
std::string mvcamera_config_file = "mvcamera_config.json";
|
||||
CLI::App *mvcameraApp = cameraApp->add_subcommand("mvcamera", "MatrixVision Camera Configuration");
|
||||
mvcameraApp->add_option("-c,--config", mvcamera_config_file, "Config filename", true)->check(CLI::ExistingFile);
|
||||
|
||||
std::string mock_camera_path;
|
||||
CLI::App *mockcameraApp = cameraApp->add_subcommand("mock", "Mock Camera Configuration");
|
||||
mockcameraApp->add_option("-p,--path", mock_camera_path, "Path")->required()->check(CLI::ExistingPath);
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
}
|
||||
38
libs/libbattle-com/libs/CLI11/examples/option_groups.cpp
Normal file
38
libs/libbattle-com/libs/CLI11/examples/option_groups.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("data output specification");
|
||||
app.set_help_all_flag("--help-all", "Expand all help");
|
||||
|
||||
auto format = app.add_option_group("output_format", "formatting type for output");
|
||||
auto target = app.add_option_group("output target", "target location for the output");
|
||||
bool csv = false;
|
||||
bool human = false;
|
||||
bool binary = false;
|
||||
format->add_flag("--csv", csv, "specify the output in csv format");
|
||||
format->add_flag("--human", human, "specify the output in human readable text format");
|
||||
format->add_flag("--binary", binary, "specify the output in binary format");
|
||||
// require one of the options to be selected
|
||||
format->require_option(1);
|
||||
std::string fileLoc;
|
||||
std::string networkAddress;
|
||||
target->add_option("-o,--file", fileLoc, "specify the file location of the output");
|
||||
target->add_option("--address", networkAddress, "specify a network address to send the file");
|
||||
|
||||
// require at most one of the target options
|
||||
target->require_option(0, 1);
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::string format_type = (csv) ? std::string("CSV") : ((human) ? "human readable" : "binary");
|
||||
std::cout << "Selected " << format_type << "format" << std::endl;
|
||||
if(fileLoc.empty()) {
|
||||
std::cout << " sent to file " << fileLoc << std::endl;
|
||||
} else if(networkAddress.empty()) {
|
||||
std::cout << " sent over network to " << networkAddress << std::endl;
|
||||
} else {
|
||||
std::cout << " sent to std::cout" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
38
libs/libbattle-com/libs/CLI11/examples/positional_arity.cpp
Normal file
38
libs/libbattle-com/libs/CLI11/examples/positional_arity.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("test for positional arity");
|
||||
|
||||
auto numbers = app.add_option_group("numbers", "specify key numbers");
|
||||
auto files = app.add_option_group("files", "specify files");
|
||||
int num1 = -1, num2 = -1;
|
||||
numbers->add_option("num1", num1, "first number");
|
||||
numbers->add_option("num2", num2, "second number");
|
||||
std::string file1, file2;
|
||||
files->add_option("file1", file1, "first file")->required();
|
||||
files->add_option("file2", file2, "second file");
|
||||
// set a pre parse callback that turns the numbers group on or off depending on the number of arguments
|
||||
app.preparse_callback([numbers](size_t arity) {
|
||||
if(arity <= 2) {
|
||||
numbers->disabled();
|
||||
} else {
|
||||
numbers->disabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
if(num1 != -1)
|
||||
std::cout << "Num1 = " << num1 << '\n';
|
||||
|
||||
if(num2 != -1)
|
||||
std::cout << "Num2 = " << num2 << '\n';
|
||||
|
||||
std::cout << "File 1 = " << file1 << '\n';
|
||||
if(!file2.empty()) {
|
||||
std::cout << "File 2 = " << file2 << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("test for positional validation");
|
||||
|
||||
int num1 = -1, num2 = -1;
|
||||
app.add_option("num1", num1, "first number")->check(CLI::Number);
|
||||
app.add_option("num2", num2, "second number")->check(CLI::Number);
|
||||
std::string file1, file2;
|
||||
app.add_option("file1", file1, "first file")->required();
|
||||
app.add_option("file2", file2, "second file");
|
||||
app.validate_positionals();
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
if(num1 != -1)
|
||||
std::cout << "Num1 = " << num1 << '\n';
|
||||
|
||||
if(num2 != -1)
|
||||
std::cout << "Num2 = " << num2 << '\n';
|
||||
|
||||
std::cout << "File 1 = " << file1 << '\n';
|
||||
if(!file2.empty()) {
|
||||
std::cout << "File 2 = " << file2 << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
libs/libbattle-com/libs/CLI11/examples/prefix_command.cpp
Normal file
26
libs/libbattle-com/libs/CLI11/examples/prefix_command.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("Prefix command app");
|
||||
app.prefix_command();
|
||||
|
||||
std::vector<int> vals;
|
||||
app.add_option("--vals,-v", vals)->expected(-1);
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::vector<std::string> more_comms = app.remaining();
|
||||
|
||||
std::cout << "Prefix";
|
||||
for(int v : vals)
|
||||
std::cout << ": " << v << " ";
|
||||
|
||||
std::cout << std::endl << "Remaining commands: ";
|
||||
|
||||
for(auto com : more_comms)
|
||||
std::cout << com << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
33
libs/libbattle-com/libs/CLI11/examples/ranges.cpp
Normal file
33
libs/libbattle-com/libs/CLI11/examples/ranges.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app{"App to demonstrate exclusionary option groups."};
|
||||
|
||||
std::vector<int> range;
|
||||
app.add_option("--range,-R", range, "A range")->expected(-2);
|
||||
|
||||
auto ogroup = app.add_option_group("min_max_step", "set the min max and step");
|
||||
int min, max, step = 1;
|
||||
ogroup->add_option("--min,-m", min, "The minimum")->required();
|
||||
ogroup->add_option("--max,-M", max, "The maximum")->required();
|
||||
ogroup->add_option("--step,-s", step, "The step", true);
|
||||
|
||||
app.require_option(1);
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
if(!range.empty()) {
|
||||
if(range.size() == 2) {
|
||||
min = range[0];
|
||||
max = range[1];
|
||||
}
|
||||
if(range.size() >= 3) {
|
||||
step = range[0];
|
||||
min = range[1];
|
||||
max = range[2];
|
||||
}
|
||||
}
|
||||
std::cout << "range is [" << min << ':' << step << ':' << max << "]\n";
|
||||
return 0;
|
||||
}
|
||||
48
libs/libbattle-com/libs/CLI11/examples/shapes.cpp
Normal file
48
libs/libbattle-com/libs/CLI11/examples/shapes.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("load shapes");
|
||||
|
||||
app.set_help_all_flag("--help-all");
|
||||
auto circle = app.add_subcommand("circle", "draw a circle")->immediate_callback();
|
||||
double radius{0.0};
|
||||
int circle_counter = 0;
|
||||
circle->callback([&radius, &circle_counter] {
|
||||
++circle_counter;
|
||||
std::cout << "circle" << circle_counter << " with radius " << radius << std::endl;
|
||||
});
|
||||
|
||||
circle->add_option("radius", radius, "the radius of the circle")->required();
|
||||
|
||||
auto rect = app.add_subcommand("rectangle", "draw a rectangle")->immediate_callback();
|
||||
double edge1{0.0};
|
||||
double edge2{0.0};
|
||||
int rect_counter = 0;
|
||||
rect->callback([&edge1, &edge2, &rect_counter] {
|
||||
++rect_counter;
|
||||
if(edge2 == 0) {
|
||||
edge2 = edge1;
|
||||
}
|
||||
std::cout << "rectangle" << rect_counter << " with edges [" << edge1 << ',' << edge2 << "]" << std::endl;
|
||||
edge2 = 0;
|
||||
});
|
||||
|
||||
rect->add_option("edge1", edge1, "the first edge length of the rectangle")->required();
|
||||
rect->add_option("edge2", edge2, "the second edge length of the rectangle");
|
||||
|
||||
auto tri = app.add_subcommand("triangle", "draw a rectangle")->immediate_callback();
|
||||
std::vector<double> sides;
|
||||
int tri_counter = 0;
|
||||
tri->callback([&sides, &tri_counter] {
|
||||
++tri_counter;
|
||||
|
||||
std::cout << "triangle" << tri_counter << " with sides [" << CLI::detail::join(sides) << "]" << std::endl;
|
||||
});
|
||||
|
||||
tri->add_option("sides", sides, "the side lengths of the triangle");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
29
libs/libbattle-com/libs/CLI11/examples/simple.cpp
Normal file
29
libs/libbattle-com/libs/CLI11/examples/simple.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "CLI/CLI.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
CLI::App app("K3Pi goofit fitter");
|
||||
|
||||
std::string file;
|
||||
CLI::Option *opt = app.add_option("-f,--file,file", file, "File name");
|
||||
|
||||
int count;
|
||||
CLI::Option *copt = app.add_option("-c,--count", count, "Counter");
|
||||
|
||||
int v;
|
||||
CLI::Option *flag = app.add_flag("--flag", v, "Some flag that can be passed multiple times");
|
||||
|
||||
double value; // = 3.14;
|
||||
app.add_option("-d,--double", value, "Some Value");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
|
||||
<< ", opt count: " << opt->count() << std::endl;
|
||||
std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
|
||||
<< ", opt count: " << copt->count() << std::endl;
|
||||
std::cout << "Received flag: " << v << " (" << flag->count() << ") times\n";
|
||||
std::cout << "Some value: " << value << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
14
libs/libbattle-com/libs/CLI11/examples/subcom_help.cpp
Normal file
14
libs/libbattle-com/libs/CLI11/examples/subcom_help.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CLI::App cli_global{"Demo app"};
|
||||
auto &cli_sub = *cli_global.add_subcommand("sub", "Some subcommand");
|
||||
std::string sub_arg;
|
||||
cli_sub.add_option("sub_arg", sub_arg, "Argument for subcommand")->required();
|
||||
CLI11_PARSE(cli_global, argc, argv);
|
||||
if(cli_sub) {
|
||||
std::cout << "Got: " << sub_arg << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
add_cli_exe(subcommand_main subcommand_main.cpp subcommand_a.cpp subcommand_a.hpp)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user