Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@

# Development stuff
.direnv

# Vim
*.swp
37 changes: 36 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,39 @@ cpp-parselglossy
:target: https://travis-ci.org/dev-cafe/cpp-parselglossy
:alt: Linux build status

Example of using parselglossy with a C++ project
This repo contains a simple example of how to use ``parselglossy`` in a C++
project using two different CMake setups: externalproject and fetchcontent.
The code example is identical in the two setups.

To install ``parselglossy`` through pipenv using the provided Pipfile:

.. code:: bash

$ cd cpp-parselglossy
$ pipenv install
$ pipenv shell

To configure and build the ``fetchcontent`` example (identical for ``externalproject``):

.. code:: bash

$ cd fetchcontent
$ mkdir build
$ cmake -H. -Bbuild
$ cd build
$ make

To run the test suite:

.. code:: bash

$ cd build
$ ctest

To run example:

.. code:: bash

$ cd examples
$ parselglossy parse --outfile=throw_darts.json --template=../build/share/template.yml --grammar=getkw throw_darts.inp
$ ../build/bin/pi throw_darts.json
36 changes: 36 additions & 0 deletions fetchcontent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,40 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(${PROJECT_SOURCE_DIR}/external/upstream/fetch_nlohmann_json.cmake)

message(STATUS "Project will be installed to ${CMAKE_INSTALL_PREFIX}")

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

message(STATUS "Build type set to ${CMAKE_BUILD_TYPE}")

include(GNUInstallDirs)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})

# Offer the user the choice of overriding the installation directories
set(INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Installation directory for libraries")
set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Installation directory for executables")
set(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Installation directory for header files")
if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKEDIR CMake)
else()
set(DEF_INSTALL_CMAKEDIR share/cmake/${PROJECT_NAME})
endif()
set(INSTALL_CMAKEDIR ${DEF_INSTALL_CMAKEDIR} CACHE PATH "Installation directory for CMake files")

# Report to user
foreach(p LIB BIN INCLUDE CMAKE)
file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALL_${p}DIR} _path )
message(STATUS "Installing ${p} components to ${_path}")
unset(_path)
endforeach()

add_subdirectory(src)

enable_testing()
include(CTest)
add_subdirectory(tests)
7 changes: 7 additions & 0 deletions fetchcontent/examples/integration.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
title = "This program computes Pi"
method = integration

Integration {
n_steps = 10**4
}

8 changes: 8 additions & 0 deletions fetchcontent/examples/throw_darts.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title = "This program computes Pi"
method = darts

Darts {
n_darts = 10**4
random_seed = 1
}

1 change: 0 additions & 1 deletion fetchcontent/external/upstream/CMakeLists.txt

This file was deleted.

2 changes: 1 addition & 1 deletion fetchcontent/external/upstream/fetch_nlohmann_json.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
find_package(nlohmann_json 3.5.0 CONFIG QUIET)

if(TARGET nlohmann_json::nlhomann_json)
if(TARGET nlohmann_json::nlohmann_json)
get_target_property(
_loc
nlohmann_json::nlohmann_json
Expand Down
26 changes: 0 additions & 26 deletions fetchcontent/external/upstream/nlohmann_json/CMakeLists.txt

This file was deleted.

46 changes: 44 additions & 2 deletions fetchcontent/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,48 @@
add_executable(example example.cpp)
add_executable(pi pi.cpp)

target_link_libraries(example
target_link_libraries(pi
PRIVATE
nlohmann_json::nlohmann_json
)

# RPATH fixing
file(RELATIVE_PATH _rel ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR} ${CMAKE_INSTALL_PREFIX})
if(APPLE)
set(_rpath "@loader_path/${_rel}")
else()
set(_rpath "\$ORIGIN/${_rel}")
endif()
file(TO_NATIVE_PATH "${_rpath}/${CMAKE_INSTALL_LIBDIR}" Pi_RPATH)

set_target_properties(pi
PROPERTIES
MACOSX_RPATH ON
SKIP_BUILD_RPATH OFF
BUILD_WITH_INSTALL_RPATH OFF
INSTALL_RPATH "${Pi_RPATH}"
INSTALL_RPATH_USE_LINK_PATH ON
)

install(
TARGETS
pi
RUNTIME
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT bin
)


file(
COPY
template.yml
DESTINATION
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}
)

install(
FILES
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/template.yml
DESTINATION
${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}
)

103 changes: 103 additions & 0 deletions fetchcontent/src/pi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <random>

#include "nlohmann/json.hpp"

using json = nlohmann::json;

int fetch_input(int argc, char **argv, json &input);
void integration(const json &input, json &output);
void throw_darts(const json &input, json &output);

int main(int argc, char **argv) {
// Read JSON input
json inp_json;
if (fetch_input(argc, argv, inp_json)) return EXIT_FAILURE;

// Prepare JSON output
json out_json;
out_json["title"] = inp_json["title"];

// Fetch computation method from input
auto method = inp_json["method"].get<std::string>();
if (method == "integration") {
const auto &int_json = inp_json["Integration"].get<json>();
integration(int_json, out_json);
}
if (method == "darts") {
const auto &dart_json = inp_json["Darts"].get<json>();
throw_darts(dart_json, out_json);
}

// Dump JSON input
std::cout << "\n-------------- JSON input -----------------\n";
std::cout << inp_json.dump(2) << std::endl;
std::cout << "-------------------------------------------\n";

// Dump JSON output
std::cout << "\n-------------- JSON output ----------------\n";
std::cout << out_json.dump(2) << std::endl;
std::cout << "-------------------------------------------\n\n";

return EXIT_SUCCESS;
}

int fetch_input(int argc, char **argv, json &input) {
if (argc != 2) {
std::cout << "Wrong number of arguments!" << std::endl;
return 1;
}

std::ifstream ifs(argv[1], std::ios_base::in);
if (ifs.fail()) {
std::cout << "Failed to open file!" << std::endl;
return 1;
}

ifs >> input;
ifs.close();

return 0;
}

void integration(const json &input, json &output) {
auto n_steps = input["n_steps"].get<int>();
auto step = 1.0 / n_steps;

auto sum = 0.0;
for (auto i = 0; i < n_steps; i++) {
auto x = (i + 0.5) * step;
auto f_x = 1.0 / (1.0 + x * x);
sum += step * f_x;
}

output["method"] = "Numerical integration";
output["pi"] = 4.0 * sum;
}

void throw_darts(const json &input, json &output) {
auto n_darts = input["n_darts"].get<int>();
auto seed = input["random_seed"].get<int>();

// Seed the random number generator
std::mt19937 rand_en(seed);
std::uniform_real_distribution<> uniform_dist(0.0, 1.0);

auto n_hits = 0;
for (auto i = 0; i < n_darts; i++) {
//creates 2 random numbers between 0 and 1
auto x = uniform_dist(rand_en);
auto y = uniform_dist(rand_en);
auto r = std::sqrt(x*x + y*y);

//counts how often the dart hits the circle
if (r <= 1.0) n_hits++;
}

output["method"] = "Throwing darts";
output["pi"] = 4.0 * n_hits / n_darts;
}

44 changes: 44 additions & 0 deletions fetchcontent/src/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
keywords:
- name: title
type: str
docstring: |
Please provide a title of the calculation to display in the beginning.
- name: method
type: str
predicates:
- "value == 'integration' or value == 'darts'"
docstring: |
Choose which method to use, numerical integration or throwing darts.
sections:
- name: Integration
docstring: |
Section giving details on the numerical integration method.
keywords:
- name: n_steps
type: int
default: 1000
predicates:
- 'value > 0'
- 'value < 1000000'
docstring: |
Number of intervals in the numerical integration. Larger number means higher accuracy.
- name: Darts
docstring: |
Section giving details on the dart throwing method.
keywords:
- name: n_darts
type: int
default: 1000
predicates:
- 'value > 0'
- 'value < 1000000'
docstring: |
Number of darts to throw. Larger number means higher accuracy.
- name: random_seed
type: int
default: 0
predicates:
- 'value >= 0'
- 'value < 2**32'
docstring: |
Number used as seed in the pseudo-random number generator.
5 changes: 5 additions & 0 deletions fetchcontent/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Integration tests
add_subdirectory(darts)
add_subdirectory(darts_default)
add_subdirectory(integration)
add_subdirectory(integration_default)
25 changes: 25 additions & 0 deletions fetchcontent/tests/darts/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
execute_process(
COMMAND
cmake -E create_symlink
"${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/template.yml" # Old name
"${CMAKE_CURRENT_BINARY_DIR}/template.yml" # New name
)

file(
COPY
pi.inp
DESTINATION
${CMAKE_CURRENT_BINARY_DIR}
)

add_test(
NAME
darts
COMMAND
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test
--binary=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
--work-dir=${CMAKE_CURRENT_BINARY_DIR}
--verbose
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
)
8 changes: 8 additions & 0 deletions fetchcontent/tests/darts/pi.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title = "This program computes Pi"
method = darts

Darts {
n_darts = 100000
random_seed = 225512
}

Loading