├── README.md ├── basics └── exercises │ └── swap │ ├── CMakeLists.txt │ └── swap.cpp ├── cgal └── exercises │ ├── convex_hull.cpp │ ├── convex_hull.dat │ ├── triangle_mesh_rasterize_1.dat │ ├── triangulation_output_1.dat │ ├── triangulation_statistics_1.dat │ └── triangulation_statistics_2.dat ├── cmake ├── examples │ ├── assert │ │ ├── CMakeLists.txt │ │ └── assert.cpp │ ├── boost_1 │ │ ├── CMakeLists.txt │ │ ├── month_later.cpp │ │ └── time.cpp │ ├── hello │ │ ├── CMakeLists.txt │ │ └── hello.cpp │ ├── libfoo │ │ ├── CMakeLists.txt │ │ ├── app │ │ │ └── demo.cpp │ │ ├── include │ │ │ └── foo │ │ │ │ ├── gadget.hpp │ │ │ │ ├── other.hpp │ │ │ │ └── widget.hpp │ │ └── lib │ │ │ ├── gadget.cpp │ │ │ └── widget.cpp │ ├── multilingual_hello │ │ ├── CMakeLists.txt │ │ ├── README │ │ ├── hello.c │ │ ├── hello.cpp │ │ ├── hello.f │ │ └── hello.java │ └── simple │ │ ├── CMakeLists.txt │ │ ├── app.cpp │ │ └── util.hpp └── exercises │ ├── assertions │ └── assert_false.cpp │ ├── basic │ ├── math.cpp │ ├── math.hpp │ ├── sinc.cpp │ └── unit_step.cpp │ ├── boost_timer │ ├── fibonacci.cpp │ ├── fibonacci.hpp │ └── timer.cpp │ ├── buggy │ └── buggy.cpp │ ├── cgal_in_circle │ ├── in_circle.cpp │ ├── in_sphere.cpp │ ├── utility.cpp │ └── utility.hpp │ ├── coverage │ ├── CodeCoverage.cmake │ ├── random.cpp │ └── run_tests │ ├── fibonacci │ ├── fibonacci.cpp │ ├── fibonacci.hpp │ └── main.cpp │ ├── hello │ └── hello.cpp │ ├── hg2g │ ├── include │ │ └── hg2g │ │ │ └── hg2g.hpp │ ├── lib │ │ ├── answer.cpp │ │ └── question.cpp │ └── src │ │ └── answer.cpp │ ├── sanitizers │ ├── asan_fail.cpp │ └── ubsan_fail.cpp │ └── spl │ └── demo.cpp ├── lcov └── examples │ └── bqueue │ ├── CMakeLists.txt │ ├── CodeCoverage.cmake │ ├── bqueue.hpp │ └── test_bqueue.cpp ├── miscellany ├── buggy │ ├── CMakeLists.txt │ └── app.cpp ├── data_race │ ├── CMakeLists.txt │ └── app.cpp ├── deadlock │ ├── CMakeLists.txt │ └── app.cpp └── factorial │ ├── CMakeLists.txt │ └── factorial.cpp ├── slides ├── catch2 │ ├── CMakeLists.txt │ ├── benchmark_fibonacci.cpp │ ├── bubble_sort.hpp │ ├── counter.hpp │ ├── fibonacci.hpp │ ├── fixture.cpp │ ├── section.cpp │ ├── stack.hpp │ ├── test_bubble_sort.cpp │ ├── test_counter.cpp │ ├── test_math.cpp │ └── test_stack.cpp ├── clang_tidy │ ├── CMakeLists.txt │ ├── app.cpp │ └── lib.cpp ├── helgrind │ ├── CMakeLists.txt │ ├── clipboard.txt │ ├── data_race_1_0.cpp │ └── data_race_1_1.cpp ├── lcov │ ├── CMakeLists.txt │ ├── CodeCoverage.cmake │ ├── app.cpp │ ├── run_tests │ ├── signum.cpp │ └── utility.hpp ├── modules │ ├── Makefile │ ├── export_1 │ │ ├── CMakeLists.txt │ │ ├── hg2g-m.cpp │ │ └── main.cpp │ ├── greet_1 │ │ ├── CMakeLists.txt │ │ ├── greet.cpp │ │ └── greetings.cpp │ ├── greet_2 │ │ ├── CMakeLists.txt │ │ ├── greet.cpp │ │ ├── greetings-m.cpp │ │ └── greetings.cpp │ ├── greet_3 │ │ ├── CMakeLists.txt │ │ ├── greet.cpp │ │ ├── greetings-m.cpp │ │ ├── greetings_en.cpp │ │ └── greetings_fr.cpp │ ├── linkage_1 │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ ├── sol-m.cpp │ │ └── sol.cpp │ ├── math_1 │ │ ├── CMakeLists.txt │ │ ├── app.cpp │ │ └── math-m.cpp │ ├── math_2 │ │ ├── CMakeLists.txt │ │ ├── app.cpp │ │ ├── math-m.cpp │ │ └── math.cpp │ └── reachability_2 │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ └── zeus-m.cpp └── tsan │ ├── CMakeLists.txt │ ├── clipboard.txt │ ├── data_race.cpp │ ├── data_race_1.cpp │ ├── data_race_2.cpp │ └── deadlock.cpp ├── vim_lsp └── examples │ └── example_1 │ ├── CMakeLists.txt │ ├── app │ └── main.cpp │ ├── util │ ├── util.cpp │ └── util.hpp │ ├── vimlsp.vim │ └── vimrc └── ycm └── examples └── example_1 ├── CMakeLists.txt ├── app.cpp ├── util.hpp ├── vimrc └── ycm.vim /README.md: -------------------------------------------------------------------------------- 1 | Companion Git Repository for "Programming in C++" 2 | ================================================= 3 | 4 | This repository contains some examples and exercises that are associated 5 | with the following textbook and lecture slides: 6 | 7 | - Michael D. Adams. 8 | Exercises for Programming in C++, 9 | Version 2021-04-01, 10 | Apr. 2021, 11 | xxii + 136 pages, 12 | ISBN 978-0-9879197-5-5 ([PDF](https://www.ece.uvic.ca/~mdadams/cppbook/downloads/exercises_for_programming_in_cpp-2021-04-01.pdf)). 13 | 14 | - Michael D. Adams. 15 | Lecture Slides for Programming in C++ --- The C++ Language, Libraries, 16 | Tools, and Other Topics, 17 | Version 2021-04-01, 18 | Apr. 2021, 19 | xxiii + 2901 slides, 20 | ISBN 978-0-9879197-4-8 ([PDF](https://www.ece.uvic.ca/~mdadams/cppbook/downloads/lecture_slides_for_programming_in_cpp-2021-04-01.pdf)). 21 | 22 | Obtaining the Lecture Slides 23 | ---------------------------- 24 | 25 | The most recent version of each of the textbook and lecture slides 26 | (in PDF format) can be found at: 27 | 28 | - 29 | 30 | Video Lectures 31 | -------------- 32 | 33 | Video lectures for some of the material associated with the textbook 34 | and lecture slides can be found at: 35 | 36 | - 37 | -------------------------------------------------------------------------------- /basics/exercises/swap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | 3 | project(swap LANGUAGES CXX) 4 | 5 | add_executable(swap swap.cpp) 6 | -------------------------------------------------------------------------------- /basics/exercises/swap/swap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // This function swaps the values of "x" and "y". 4 | void swap(int x, int y) 5 | { 6 | int tmp = x; 7 | x = y; 8 | y = tmp; 9 | } 10 | 11 | int main(int argc, char** argv) 12 | { 13 | int first = 10; 14 | int second = 20; 15 | 16 | std::cout << "The numbers before swapping are:\n" 17 | << first << ", " << second << "\n"; 18 | 19 | swap(first, second); 20 | 21 | std::cout << "The numbers after swapping are:\n" 22 | << first << ", " << second << "\n"; 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /cgal/exercises/convex_hull.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) 6 | { 7 | using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; 8 | using Triangulation = CGAL::Triangulation_2; 9 | using Vertex_circulator = Triangulation::Vertex_circulator; 10 | using Point = Triangulation::Point; 11 | 12 | Triangulation tri; 13 | 14 | // Read points from standard input and insert them into the triangulation. 15 | Point point; 16 | while (std::cin >> point) { 17 | tri.insert(point); 18 | } 19 | 20 | // Loop over all of the vertices incident to the infinite vertex. 21 | // These are the vertices on the convex hull. 22 | std::cout << "Vertices on convex hull:\n"; 23 | Vertex_circulator vertexCircStart = 24 | tri.incident_vertices(tri.infinite_vertex()); 25 | if (vertexCircStart != 0) { 26 | Vertex_circulator vertexCirc = vertexCircStart; 27 | do { 28 | std::cout << vertexCirc->point() << "\n"; 29 | ++vertexCirc; 30 | } while (vertexCirc != vertexCircStart); 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /cgal/exercises/convex_hull.dat: -------------------------------------------------------------------------------- 1 | 0 0 2 | 5 0 3 | 100 0 4 | 100 100 5 | 0 100 6 | 25 34 7 | 75 23 8 | 88 23 9 | 99 1 10 | 5 3 11 | 44 62 12 | -------------------------------------------------------------------------------- /cgal/exercises/triangulation_statistics_1.dat: -------------------------------------------------------------------------------- 1 | 0 15 2 | 0 44 3 | 0 45 4 | 0 6 5 | 0 60 6 | 0 67 7 | 0 68 8 | 0 91 9 | 1 2 10 | 1 22 11 | 1 24 12 | 1 31 13 | 1 38 14 | 1 42 15 | 1 66 16 | 1 68 17 | 1 70 18 | 1 74 19 | 1 77 20 | 1 97 21 | 2 11 22 | 2 2 23 | 2 25 24 | 2 47 25 | 2 51 26 | 2 84 27 | 2 87 28 | 3 10 29 | 3 11 30 | 3 12 31 | 3 17 32 | 3 46 33 | 3 56 34 | 3 61 35 | 3 64 36 | 3 95 37 | 4 0 38 | 4 1 39 | 4 10 40 | 4 21 41 | 4 51 42 | 4 52 43 | 4 55 44 | 4 61 45 | 4 64 46 | 4 65 47 | 4 75 48 | 4 96 49 | 5 11 50 | 5 3 51 | 5 36 52 | 5 46 53 | 5 47 54 | 5 59 55 | 5 80 56 | 5 96 57 | 6 27 58 | 6 63 59 | 6 77 60 | 6 87 61 | 7 27 62 | 7 37 63 | 7 41 64 | 7 45 65 | 7 75 66 | 7 76 67 | 7 92 68 | 7 93 69 | 8 25 70 | 8 28 71 | 8 45 72 | 8 47 73 | 8 52 74 | 8 73 75 | 8 74 76 | 8 87 77 | 8 93 78 | 8 99 79 | 9 11 80 | 9 14 81 | 9 16 82 | 9 17 83 | 9 36 84 | 9 43 85 | 9 6 86 | 9 63 87 | 9 79 88 | 9 8 89 | 9 92 90 | 9 95 91 | 10 0 92 | 10 34 93 | 10 57 94 | 10 62 95 | 10 90 96 | 10 94 97 | 11 13 98 | 11 16 99 | 11 31 100 | 11 42 101 | 11 50 102 | 11 52 103 | 11 61 104 | 11 82 105 | 11 90 106 | 11 96 107 | 12 1 108 | 12 10 109 | 12 14 110 | 12 22 111 | 12 35 112 | 12 4 113 | 12 68 114 | 12 73 115 | 12 79 116 | 12 89 117 | 13 10 118 | 13 12 119 | 13 2 120 | 13 23 121 | 13 26 122 | 13 27 123 | 13 41 124 | 13 48 125 | 13 51 126 | 13 57 127 | 13 66 128 | 13 74 129 | 13 75 130 | 13 77 131 | 14 0 132 | 14 15 133 | 14 19 134 | 14 37 135 | 14 61 136 | 14 80 137 | 14 85 138 | 14 95 139 | 15 12 140 | 15 32 141 | 15 4 142 | 15 40 143 | 15 44 144 | 15 45 145 | 15 48 146 | 15 52 147 | 15 58 148 | 15 71 149 | 16 2 150 | 16 21 151 | 16 24 152 | 16 36 153 | 16 47 154 | 16 48 155 | 16 80 156 | 16 86 157 | 17 28 158 | 17 6 159 | 17 64 160 | 17 68 161 | 17 81 162 | 17 83 163 | 17 84 164 | 17 90 165 | 18 1 166 | 18 12 167 | 18 17 168 | 18 32 169 | 18 39 170 | 18 5 171 | 18 55 172 | 18 56 173 | 18 60 174 | 18 62 175 | 18 70 176 | 18 75 177 | 18 85 178 | 18 88 179 | 18 89 180 | 18 99 181 | 19 15 182 | 19 37 183 | 19 46 184 | 19 67 185 | 19 71 186 | 19 82 187 | 19 84 188 | 19 87 189 | 19 88 190 | 19 91 191 | 20 15 192 | 20 16 193 | 20 19 194 | 20 2 195 | 20 53 196 | 20 56 197 | 20 59 198 | 20 64 199 | 20 81 200 | 21 21 201 | 21 25 202 | 21 33 203 | 21 43 204 | 21 49 205 | 21 52 206 | 21 60 207 | 21 70 208 | 21 98 209 | 22 12 210 | 22 22 211 | 22 29 212 | 22 3 213 | 22 34 214 | 22 48 215 | 22 53 216 | 22 72 217 | 22 78 218 | 22 83 219 | 22 9 220 | 22 90 221 | 23 15 222 | 23 16 223 | 23 2 224 | 23 45 225 | 23 49 226 | 23 50 227 | 23 70 228 | 23 77 229 | 23 84 230 | 23 87 231 | 23 97 232 | 23 99 233 | 24 13 234 | 24 14 235 | 24 42 236 | 24 48 237 | 24 70 238 | 25 13 239 | 25 16 240 | 25 22 241 | 25 34 242 | 25 72 243 | 25 80 244 | 25 83 245 | 25 87 246 | 25 99 247 | 26 1 248 | 26 12 249 | 26 14 250 | 26 25 251 | 26 38 252 | 26 4 253 | 26 5 254 | 26 52 255 | 26 7 256 | 26 70 257 | 26 8 258 | 26 96 259 | 27 3 260 | 27 40 261 | 27 56 262 | 27 88 263 | 27 98 264 | 27 99 265 | 28 15 266 | 28 22 267 | 28 30 268 | 28 35 269 | 28 41 270 | 28 44 271 | 28 51 272 | 28 53 273 | 28 54 274 | 28 60 275 | 28 66 276 | 28 83 277 | 28 85 278 | 28 92 279 | 28 93 280 | 29 23 281 | 29 29 282 | 29 30 283 | 29 34 284 | 29 50 285 | 29 57 286 | 29 87 287 | 29 93 288 | 29 96 289 | 30 1 290 | 30 11 291 | 30 18 292 | 30 35 293 | 30 53 294 | 30 64 295 | 30 68 296 | 30 69 297 | 30 7 298 | 30 75 299 | 31 19 300 | 31 4 301 | 31 42 302 | 31 44 303 | 31 56 304 | 31 58 305 | 31 70 306 | 31 74 307 | 31 76 308 | 31 8 309 | 31 94 310 | 32 17 311 | 32 20 312 | 32 26 313 | 32 28 314 | 32 36 315 | 32 48 316 | 32 63 317 | 32 64 318 | 32 79 319 | 32 82 320 | 32 90 321 | 32 99 322 | 33 22 323 | 33 31 324 | 33 33 325 | 33 35 326 | 33 4 327 | 33 58 328 | 33 71 329 | 33 74 330 | 33 78 331 | 33 88 332 | 33 99 333 | 34 15 334 | 34 24 335 | 34 35 336 | 34 39 337 | 34 51 338 | 34 53 339 | 34 56 340 | 34 6 341 | 34 61 342 | 34 63 343 | 34 69 344 | 34 74 345 | 34 76 346 | 34 83 347 | 34 84 348 | 34 87 349 | 35 11 350 | 35 30 351 | 35 50 352 | 35 7 353 | 35 82 354 | 36 3 355 | 36 30 356 | 36 31 357 | 36 38 358 | 36 54 359 | 36 59 360 | 36 60 361 | 36 69 362 | 36 7 363 | 36 75 364 | 36 83 365 | 36 84 366 | 36 86 367 | 37 0 368 | 37 29 369 | 37 37 370 | 37 40 371 | 37 41 372 | 37 44 373 | 37 99 374 | 38 25 375 | 38 33 376 | 38 40 377 | 38 50 378 | 38 74 379 | 38 81 380 | 38 85 381 | 39 23 382 | 39 29 383 | 39 33 384 | 39 39 385 | 39 46 386 | 39 51 387 | 39 6 388 | 39 69 389 | 39 73 390 | 39 76 391 | 39 97 392 | 40 25 393 | 40 29 394 | 40 3 395 | 40 33 396 | 40 4 397 | 40 44 398 | 40 58 399 | 40 78 400 | 40 9 401 | 41 3 402 | 41 52 403 | 41 62 404 | 41 63 405 | 41 65 406 | 41 82 407 | 41 85 408 | 42 16 409 | 42 2 410 | 42 24 411 | 42 49 412 | 42 66 413 | 42 74 414 | 42 85 415 | 42 90 416 | 43 32 417 | 43 44 418 | 43 57 419 | 43 60 420 | 43 66 421 | 43 69 422 | 43 7 423 | 43 77 424 | 43 83 425 | 43 91 426 | 43 99 427 | 44 0 428 | 44 10 429 | 44 14 430 | 44 19 431 | 44 30 432 | 44 41 433 | 44 43 434 | 44 47 435 | 44 62 436 | 44 65 437 | 44 86 438 | 44 88 439 | 44 89 440 | 45 11 441 | 45 13 442 | 45 22 443 | 45 3 444 | 45 60 445 | 45 61 446 | 45 79 447 | 45 97 448 | 46 1 449 | 46 46 450 | 46 56 451 | 46 57 452 | 46 68 453 | 46 79 454 | 46 90 455 | 46 91 456 | 46 93 457 | 46 96 458 | 46 99 459 | 47 13 460 | 47 20 461 | 47 47 462 | 47 51 463 | 47 54 464 | 47 55 465 | 47 57 466 | 47 67 467 | 47 81 468 | 47 93 469 | 47 99 470 | 48 1 471 | 48 20 472 | 48 28 473 | 48 3 474 | 48 43 475 | 48 49 476 | 48 50 477 | 48 52 478 | 48 61 479 | 48 78 480 | 48 81 481 | 48 94 482 | 48 97 483 | 49 41 484 | 49 51 485 | 49 53 486 | 49 74 487 | 49 85 488 | 49 97 489 | 50 23 490 | 50 24 491 | 50 27 492 | 50 34 493 | 50 41 494 | 50 49 495 | 50 66 496 | 50 67 497 | 50 79 498 | 50 87 499 | 50 98 500 | 51 20 501 | 51 25 502 | 51 28 503 | 51 46 504 | 51 50 505 | 51 59 506 | 51 7 507 | 51 72 508 | 51 82 509 | 51 83 510 | 51 87 511 | 52 12 512 | 52 51 513 | 52 62 514 | 52 72 515 | 52 8 516 | 52 86 517 | 52 88 518 | 52 93 519 | 52 96 520 | 52 97 521 | 53 0 522 | 53 1 523 | 53 14 524 | 53 17 525 | 53 23 526 | 53 24 527 | 53 26 528 | 53 29 529 | 53 43 530 | 53 49 531 | 53 57 532 | 53 73 533 | 53 76 534 | 53 78 535 | 53 8 536 | 53 86 537 | 53 90 538 | 54 12 539 | 54 29 540 | 54 49 541 | 54 5 542 | 54 55 543 | 54 95 544 | 55 17 545 | 55 18 546 | 55 2 547 | 55 35 548 | 55 4 549 | 55 44 550 | 55 58 551 | 55 68 552 | 55 69 553 | 55 95 554 | 56 11 555 | 56 15 556 | 56 2 557 | 56 30 558 | 56 33 559 | 56 54 560 | 56 58 561 | 56 64 562 | 56 67 563 | 57 10 564 | 57 30 565 | 57 35 566 | 57 40 567 | 57 45 568 | 57 55 569 | 57 71 570 | 57 74 571 | 57 89 572 | 57 95 573 | 58 11 574 | 58 2 575 | 58 33 576 | 58 42 577 | 58 51 578 | 58 76 579 | 58 92 580 | 59 11 581 | 59 15 582 | 59 20 583 | 59 35 584 | 59 38 585 | 59 40 586 | 59 46 587 | 59 60 588 | 59 7 589 | 59 73 590 | 59 78 591 | 59 83 592 | 59 88 593 | 59 89 594 | 59 93 595 | 59 95 596 | 60 11 597 | 60 18 598 | 60 2 599 | 60 24 600 | 60 29 601 | 60 33 602 | 60 39 603 | 60 5 604 | 60 53 605 | 60 57 606 | 60 61 607 | 60 64 608 | 60 68 609 | 60 70 610 | 60 77 611 | 60 80 612 | 60 83 613 | 60 96 614 | 61 11 615 | 61 13 616 | 61 46 617 | 61 50 618 | 61 73 619 | 61 74 620 | 61 75 621 | 61 76 622 | 61 8 623 | 61 80 624 | 61 90 625 | 62 0 626 | 62 1 627 | 62 3 628 | 62 64 629 | 62 72 630 | 62 85 631 | 62 9 632 | 62 94 633 | 62 98 634 | 63 11 635 | 63 14 636 | 63 24 637 | 63 25 638 | 63 39 639 | 63 62 640 | 63 67 641 | 63 87 642 | 63 9 643 | 63 95 644 | 64 22 645 | 64 53 646 | 65 21 647 | 65 29 648 | 65 59 649 | 65 71 650 | 65 79 651 | 65 8 652 | 65 85 653 | 65 87 654 | 65 9 655 | 66 21 656 | 66 43 657 | 66 55 658 | 66 67 659 | 66 68 660 | 66 71 661 | 67 12 662 | 67 13 663 | 67 2 664 | 67 23 665 | 67 24 666 | 67 35 667 | 67 36 668 | 67 46 669 | 67 86 670 | 67 92 671 | 68 13 672 | 68 25 673 | 68 58 674 | 68 60 675 | 68 71 676 | 68 73 677 | 68 77 678 | 68 85 679 | 68 90 680 | 68 91 681 | 69 20 682 | 69 47 683 | 69 59 684 | 69 74 685 | 69 78 686 | 69 81 687 | 69 82 688 | 69 98 689 | 70 11 690 | 70 18 691 | 70 21 692 | 70 24 693 | 70 30 694 | 70 31 695 | 70 34 696 | 70 42 697 | 70 47 698 | 70 58 699 | 70 66 700 | 70 79 701 | 70 83 702 | 70 93 703 | 71 23 704 | 71 25 705 | 71 59 706 | 71 6 707 | 71 88 708 | 71 98 709 | 72 17 710 | 72 4 711 | 72 45 712 | 72 47 713 | 72 48 714 | 72 60 715 | 72 61 716 | 72 66 717 | 72 68 718 | 72 7 719 | 72 73 720 | 72 74 721 | 72 77 722 | 72 90 723 | 72 91 724 | 73 1 725 | 73 11 726 | 73 18 727 | 73 21 728 | 73 22 729 | 73 23 730 | 73 28 731 | 74 16 732 | 74 24 733 | 74 29 734 | 74 31 735 | 74 36 736 | 74 5 737 | 74 60 738 | 74 68 739 | 74 76 740 | 74 79 741 | 74 86 742 | 74 87 743 | 74 92 744 | 75 15 745 | 75 22 746 | 75 36 747 | 75 53 748 | 75 67 749 | 75 69 750 | 76 16 751 | 76 17 752 | 76 32 753 | 76 46 754 | 76 63 755 | 76 69 756 | 76 80 757 | 77 19 758 | 77 5 759 | 77 6 760 | 77 61 761 | 77 75 762 | 77 80 763 | 77 81 764 | 77 90 765 | 77 92 766 | 77 94 767 | 78 21 768 | 78 3 769 | 78 37 770 | 78 44 771 | 78 50 772 | 78 60 773 | 78 69 774 | 78 90 775 | 78 91 776 | 79 16 777 | 79 20 778 | 79 21 779 | 79 23 780 | 79 26 781 | 79 46 782 | 79 50 783 | 79 87 784 | 79 92 785 | 79 96 786 | 79 99 787 | 80 15 788 | 80 16 789 | 80 18 790 | 80 2 791 | 80 20 792 | 80 23 793 | 80 34 794 | 80 41 795 | 80 45 796 | 80 56 797 | 80 57 798 | 80 6 799 | 80 61 800 | 80 8 801 | 80 83 802 | 80 90 803 | 80 91 804 | 80 99 805 | 81 10 806 | 81 17 807 | 81 2 808 | 81 26 809 | 81 63 810 | 81 7 811 | 81 81 812 | 81 83 813 | 82 12 814 | 82 24 815 | 82 38 816 | 82 40 817 | 82 46 818 | 82 6 819 | 82 60 820 | 82 7 821 | 82 78 822 | 82 80 823 | 82 96 824 | 83 13 825 | 83 30 826 | 83 36 827 | 83 53 828 | 83 54 829 | 83 61 830 | 83 67 831 | 83 74 832 | 83 98 833 | 83 99 834 | 84 11 835 | 84 19 836 | 84 25 837 | 84 43 838 | 84 44 839 | 84 61 840 | 84 88 841 | 85 14 842 | 85 16 843 | 85 36 844 | 85 41 845 | 85 44 846 | 85 51 847 | 85 64 848 | 85 65 849 | 85 7 850 | 85 91 851 | 86 14 852 | 86 20 853 | 86 26 854 | 86 46 855 | 86 65 856 | 86 73 857 | 86 74 858 | 86 94 859 | 86 99 860 | 87 10 861 | 87 19 862 | 87 46 863 | 87 48 864 | 87 50 865 | 87 6 866 | 87 61 867 | 87 71 868 | 87 75 869 | 87 9 870 | 87 92 871 | 88 13 872 | 88 21 873 | 88 36 874 | 88 42 875 | 88 43 876 | 88 63 877 | 88 67 878 | 88 92 879 | 89 17 880 | 89 20 881 | 89 28 882 | 89 29 883 | 89 57 884 | 89 75 885 | 89 90 886 | 90 24 887 | 90 29 888 | 90 30 889 | 90 41 890 | 90 66 891 | 90 70 892 | 90 85 893 | 90 89 894 | 91 12 895 | 91 28 896 | 91 41 897 | 91 59 898 | 91 60 899 | 91 67 900 | 91 68 901 | 91 77 902 | 91 85 903 | 91 87 904 | 91 93 905 | 92 0 906 | 92 12 907 | 92 14 908 | 92 30 909 | 92 31 910 | 92 46 911 | 92 53 912 | 92 96 913 | 93 67 914 | 93 84 915 | 93 94 916 | 94 0 917 | 94 12 918 | 94 2 919 | 94 22 920 | 94 43 921 | 94 50 922 | 94 58 923 | 94 7 924 | 94 75 925 | 94 85 926 | 94 9 927 | 94 94 928 | 95 18 929 | 95 19 930 | 95 2 931 | 95 26 932 | 95 38 933 | 95 40 934 | 95 43 935 | 95 44 936 | 95 47 937 | 95 52 938 | 95 69 939 | 95 89 940 | 95 9 941 | 95 91 942 | 96 0 943 | 96 15 944 | 96 29 945 | 96 30 946 | 96 31 947 | 96 52 948 | 96 53 949 | 96 56 950 | 96 68 951 | 96 80 952 | 96 87 953 | 96 96 954 | 97 19 955 | 97 32 956 | 97 33 957 | 97 38 958 | 97 59 959 | 97 7 960 | 97 77 961 | 97 91 962 | 97 99 963 | 98 1 964 | 98 28 965 | 98 43 966 | 98 61 967 | 98 74 968 | 99 27 969 | 99 31 970 | 99 41 971 | 99 43 972 | 99 47 973 | 99 53 974 | 99 69 975 | 99 7 976 | 99 91 977 | -------------------------------------------------------------------------------- /cgal/exercises/triangulation_statistics_2.dat: -------------------------------------------------------------------------------- 1 | 0 0 2 | 0 100 3 | 100 100 4 | 100 0 5 | 6 | -------------------------------------------------------------------------------- /cmake/examples/assert/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Specify minimum required version of CMake. 2 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 3 | 4 | # Specify project and identify languages used. 5 | project(assert LANGUAGES CXX) 6 | 7 | # Enable verbose makefiles. 8 | set(CMAKE_VERBOSE_MAKEFILE true) 9 | 10 | # Print the value of several key variables. 11 | if((DEFINED CMAKE_BUILD_TYPE) AND (NOT CMAKE_BUILD_TYPE STREQUAL "")) 12 | message("CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 13 | else() 14 | message("CMAKE_BUILD_TYPE is unset/empty") 15 | endif() 16 | message("CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") 17 | message("CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}") 18 | message("CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") 19 | message("CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") 20 | message("CMAKE_CXX_FLAGS_MINSIZEREL: ${CMAKE_CXX_FLAGS_MINSIZEREL}") 21 | 22 | # Add program target called assert. 23 | add_executable(assert assert.cpp) 24 | -------------------------------------------------------------------------------- /cmake/examples/assert/assert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << "About to execute assert(false).\n"; 7 | 8 | assert(false); 9 | 10 | // If assertions are enabled, this line of code should never be reached. 11 | std::cout << "Assertions are disabled.\n"; 12 | 13 | return std::cout ? 0 : 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmake/examples/boost_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(demo LANGUAGES CXX) 3 | set(CMAKE_VERBOSE_MAKEFILE true) 4 | 5 | # Note: Since the specified Boost components are necessary to build the code, 6 | # treat the case of missing components as a fatal error by using the "REQUIRED" 7 | # qualifier. 8 | find_package(Boost REQUIRED COMPONENTS chrono date_time) 9 | 10 | ################################################################################ 11 | # month_later target 12 | ################################################################################ 13 | 14 | add_executable(month_later month_later.cpp) 15 | 16 | # Approach 1: Use include-directories and library variables. 17 | # Note: We need to specify include directories. 18 | target_include_directories(month_later PUBLIC ${Boost_INCLUDE_DIRS}) 19 | target_link_libraries(month_later ${Boost_DATE_TIME_LIBRARY}) 20 | 21 | # Approach 2: Use imported targets 22 | # Note: We do not need to specify include directories. 23 | #target_link_libraries(month_later Boost::date_time) 24 | 25 | ################################################################################ 26 | # time target 27 | ################################################################################ 28 | 29 | add_executable(time time.cpp) 30 | 31 | # Approach 1: Use include-directories and library variables. 32 | # Note: We need to specify include directories. 33 | # Note: We need to specify any depended-upon library (i.e., system). 34 | target_include_directories(time PUBLIC ${Boost_INCLUDE_DIRS}) 35 | target_link_libraries(time ${Boost_CHRONO_LIBRARY} ${Boost_SYSTEM_LIBRARY}) 36 | 37 | # Approach 2: Use imported targets 38 | # Note: We do not need to specify include directories. 39 | # Note: We do not need to specify depended-upon libraries. 40 | #target_link_libraries(time Boost::chrono) 41 | 42 | -------------------------------------------------------------------------------- /cmake/examples/boost_1/month_later.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace bg = boost::gregorian; 6 | 7 | int main() 8 | { 9 | bg::date d = bg::day_clock::local_day(), 10 | prev = d - bg::months(1), 11 | next = d + bg::months(1); 12 | std::cout 13 | << "Today is " 14 | << bg::to_simple_string(d) << ".\n" 15 | << "One month before today was " 16 | << bg::to_simple_string(prev) << ".\n" 17 | << "One month from today will be " 18 | << bg::to_simple_string(next) << ".\n"; 19 | } 20 | -------------------------------------------------------------------------------- /cmake/examples/boost_1/time.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | double get_result() 7 | { 8 | double sum = 0.0; 9 | for (long i = 0L; i < 1000000L; ++i) { 10 | sum += std::sin(i) * std::cos(i); 11 | } 12 | return sum; 13 | } 14 | 15 | namespace bc = boost::chrono; 16 | 17 | int main() { 18 | // Get the start time. 19 | auto start_time = bc::high_resolution_clock::now(); 20 | // Do some computation. 21 | double result = get_result(); 22 | // Get the end time. 23 | auto end_time = bc::high_resolution_clock::now(); 24 | // Compute elapsed time in seconds. 25 | double elapsed_time = bc::duration(end_time - start_time).count(); 26 | // Print result and elapsed time. 27 | std::cout << "result " << result << '\n'; 28 | std::cout << "time (in seconds) " << elapsed_time << '\n'; 29 | } 30 | -------------------------------------------------------------------------------- /cmake/examples/hello/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Specify minimum required version of CMake. 2 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 3 | 4 | # Specify project and identify languages used. 5 | project(hello LANGUAGES CXX) 6 | 7 | # Add program target called hello. 8 | add_executable(hello hello.cpp) 9 | -------------------------------------------------------------------------------- /cmake/examples/hello/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello, World!\n"; 5 | return !std::cout; 6 | } 7 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(libfoo LANGUAGES CXX) 3 | set(CMAKE_VERBOSE_MAKEFILE true) 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS true) 5 | 6 | # Note: This example is only for explanatory purposes. 7 | # It is not intended as a normal use of CMake. 8 | 9 | option(BUILD_WITH_LIBRARY "Build with a library." false) 10 | 11 | if (BUILD_WITH_LIBRARY) 12 | # Build as a library 13 | add_library(foo lib/gadget.cpp lib/widget.cpp) 14 | target_include_directories(foo PUBLIC include) 15 | add_executable(demo app/demo.cpp) 16 | target_link_libraries(demo foo) 17 | else() 18 | # Build without library 19 | add_executable(demo app/demo.cpp lib/gadget.cpp lib/widget.cpp) 20 | target_include_directories(demo PUBLIC include) 21 | endif() 22 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/app/demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | foo::Widget w; 9 | foo::Gadget g; 10 | std::cout << w << '\n'; 11 | std::cout << g << '\n'; 12 | return std::cout ? 0 : 1; 13 | } 14 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/include/foo/gadget.hpp: -------------------------------------------------------------------------------- 1 | #ifndef foo_gadget_hpp 2 | #define foo_gadget_hpp 3 | 4 | #include 5 | 6 | namespace foo { 7 | 8 | class Gadget 9 | { 10 | public: 11 | Gadget(); 12 | std::ostream& output(std::ostream& out) const; 13 | }; 14 | 15 | std::ostream& operator<<(std::ostream& out, const Gadget& g); 16 | 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/include/foo/other.hpp: -------------------------------------------------------------------------------- 1 | #ifndef foo_other_hpp 2 | #define foo_other_hpp 3 | 4 | #include 5 | #include 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/include/foo/widget.hpp: -------------------------------------------------------------------------------- 1 | #ifndef foo_widget_hpp 2 | #define foo_widget_hpp 3 | 4 | #include 5 | 6 | namespace foo { 7 | 8 | class Widget 9 | { 10 | public: 11 | Widget(); 12 | std::ostream& output(std::ostream& out) const; 13 | }; 14 | 15 | std::ostream& operator<<(std::ostream& out, const Widget& w); 16 | 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/lib/gadget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace foo { 5 | 6 | Gadget::Gadget() 7 | { 8 | } 9 | 10 | std::ostream& Gadget::output(std::ostream& out) const 11 | { 12 | out << "Gadget"; 13 | return out; 14 | } 15 | 16 | std::ostream& operator<<(std::ostream& out, const Gadget& g) 17 | { 18 | return g.output(out); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /cmake/examples/libfoo/lib/widget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace foo { 5 | 6 | Widget::Widget() 7 | { 8 | } 9 | 10 | std::ostream& Widget::output(std::ostream& out) const 11 | { 12 | out << "Widget"; 13 | return out; 14 | } 15 | 16 | std::ostream& operator<<(std::ostream& out, const Widget& w) 17 | { 18 | return w.output(out); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /cmake/examples/multilingual_hello/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | 3 | project(hello LANGUAGES CXX C Fortran Java) 4 | 5 | add_executable(hello_c++ hello.cpp) 6 | add_executable(hello_c hello.c) 7 | add_executable(hello_fortran hello.f) 8 | add_library(hello_java hello.java) 9 | -------------------------------------------------------------------------------- /cmake/examples/multilingual_hello/README: -------------------------------------------------------------------------------- 1 | README 2 | 3 | This directory contains the source code for the classic hello-world 4 | program written in several programming languages, including C++, C, 5 | Fortran, and Java. 6 | 7 | hello.c 8 | The source code for the hello-world program written in C. 9 | hello.cpp 10 | The source code for the hello-world program written in C++. 11 | hello.f 12 | The source code for the hello-world program written in Fortran. 13 | hello.java 14 | The source code for the hello-world program written in Java. 15 | 16 | The code in this directory can be built using CMake with the CMakeLists 17 | file provided. 18 | 19 | To run the Java program after building (on a Linux-based system), use a 20 | command like: 21 | 22 | java -cp hello_java.jar hello 23 | 24 | -------------------------------------------------------------------------------- /cmake/examples/multilingual_hello/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Hello, World!\n"); 6 | } 7 | -------------------------------------------------------------------------------- /cmake/examples/multilingual_hello/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello, World!\n"; 6 | } 7 | -------------------------------------------------------------------------------- /cmake/examples/multilingual_hello/hello.f: -------------------------------------------------------------------------------- 1 | program hello 2 | print *, "Hello, World!" 3 | end program hello 4 | -------------------------------------------------------------------------------- /cmake/examples/multilingual_hello/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String[] args) { 3 | System.out.println("Hello, World!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /cmake/examples/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(simple LANGUAGES CXX) 3 | set(CMAKE_VERBOSE_MAKEFILE ON) 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 5 | add_executable(app app.cpp) 6 | -------------------------------------------------------------------------------- /cmake/examples/simple/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.hpp" 3 | 4 | int main() 5 | { 6 | double x; 7 | while (std::cin >> x) { 8 | auto y = square(x); 9 | std::cout << y << '\n'; 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /cmake/examples/simple/util.hpp: -------------------------------------------------------------------------------- 1 | template 2 | inline T square(const T& x) 3 | { 4 | return x * x; 5 | } 6 | -------------------------------------------------------------------------------- /cmake/exercises/assertions/assert_false.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << "About to execute assert(false).\n"; 7 | 8 | assert(false); 9 | 10 | // If assertions are enabled, this line of code should never be reached. 11 | std::cout << "Assertions are disabled.\n"; 12 | 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmake/exercises/basic/math.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double sinc(double x) 4 | { 5 | return (x == 0.0) ? 1.0 : (sin(x) / x); 6 | } 7 | 8 | double unit_step(double x) 9 | { 10 | if (x > 0.0) { 11 | return 1.0; 12 | } else if (x == 0.0) { 13 | return 0.5; 14 | } else { 15 | return 0.0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /cmake/exercises/basic/math.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MATH_HPP 2 | #define MATH_HPP 3 | 4 | double sinc(double); 5 | double unit_step(double); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /cmake/exercises/basic/sinc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "math.hpp" 3 | 4 | int main(int argc, char** argv) 5 | { 6 | double x; 7 | while (std::cin >> x) { 8 | std::cout << sinc(x) << '\n'; 9 | } 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /cmake/exercises/basic/unit_step.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "math.hpp" 3 | 4 | int main(int argc, char** argv) 5 | { 6 | double x; 7 | while (std::cin >> x) { 8 | std::cout << unit_step(x) << '\n'; 9 | } 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /cmake/exercises/boost_timer/fibonacci.cpp: -------------------------------------------------------------------------------- 1 | // A bad way to compute Fibonacci numbers. 2 | // Can you say "stack overflow"? ;) 3 | long fibonacci(long i) 4 | { 5 | if (i == 0 || i == 1) { 6 | return 1; 7 | } else { 8 | return fibonacci(i - 1) + fibonacci(i - 2); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /cmake/exercises/boost_timer/fibonacci.hpp: -------------------------------------------------------------------------------- 1 | long fibonacci(long i); 2 | -------------------------------------------------------------------------------- /cmake/exercises/boost_timer/timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "fibonacci.hpp" 4 | 5 | int main() 6 | { 7 | boost::timer::auto_cpu_timer t; 8 | for (long i = 0; i < 32; ++i) { 9 | std::cout << fibonacci(i) << '\n'; 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /cmake/exercises/buggy/buggy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int values[] = {1, 2, 3, 4, std::numeric_limits::max()}; 7 | int sum = 0; 8 | for (int i = 0; i < 6; ++i) { 9 | sum += values[i]; 10 | } 11 | std::cout << sum << '\n'; 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /cmake/exercises/cgal_in_circle/in_circle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utility.hpp" 5 | 6 | int main() 7 | { 8 | using Kernel = CGAL::Filtered_kernel>; 9 | Kernel::Point_2 a; 10 | Kernel::Point_2 b; 11 | Kernel::Point_2 c; 12 | Kernel::Point_2 q; 13 | Kernel::Side_of_oriented_circle_2 side_of_oriented_circle; 14 | while (std::cin >> a >> b >> c >> q) { 15 | std::cout << to_string(side_of_oriented_circle(a, b, c, q)) << '\n'; 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /cmake/exercises/cgal_in_circle/in_sphere.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utility.hpp" 5 | 6 | int main() 7 | { 8 | using Kernel = CGAL::Filtered_kernel>; 9 | Kernel::Point_3 a; 10 | Kernel::Point_3 b; 11 | Kernel::Point_3 c; 12 | Kernel::Point_3 d; 13 | Kernel::Point_3 q; 14 | Kernel::Side_of_oriented_sphere_3 side_of_oriented_sphere; 15 | while (std::cin >> a >> b >> c >> d >> q) { 16 | std::cout << to_string(side_of_oriented_sphere(a, b, c, d, q)) << '\n'; 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /cmake/exercises/cgal_in_circle/utility.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::string to_string(CGAL::Oriented_side orient) 5 | { 6 | switch (orient) { 7 | case CGAL::ON_NEGATIVE_SIDE: 8 | return "on negative side"; 9 | break; 10 | case CGAL::ON_POSITIVE_SIDE: 11 | return "on positive side"; 12 | break; 13 | case CGAL::ON_ORIENTED_BOUNDARY: 14 | return "on oriented boundary"; 15 | break; 16 | } 17 | std::abort(); 18 | } 19 | -------------------------------------------------------------------------------- /cmake/exercises/cgal_in_circle/utility.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::string to_string(CGAL::Oriented_side orient); 5 | -------------------------------------------------------------------------------- /cmake/exercises/coverage/CodeCoverage.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 - 2017, Lars Bilke 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # CHANGES: 30 | # 31 | # 2012-01-31, Lars Bilke 32 | # - Enable Code Coverage 33 | # 34 | # 2013-09-17, Joakim Söderberg 35 | # - Added support for Clang. 36 | # - Some additional usage instructions. 37 | # 38 | # 2016-02-03, Lars Bilke 39 | # - Refactored functions to use named parameters 40 | # 41 | # 2017-06-02, Lars Bilke 42 | # - Merged with modified version from github.com/ufz/ogs 43 | # 44 | # 45 | # USAGE: 46 | # 47 | # 1. Copy this file into your cmake modules path. 48 | # 49 | # 2. Add the following line to your CMakeLists.txt: 50 | # include(CodeCoverage) 51 | # 52 | # 3. Append necessary compiler flags: 53 | # APPEND_COVERAGE_COMPILER_FLAGS() 54 | # 55 | # 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og 56 | # 57 | # 4. If you need to exclude additional directories from the report, specify them 58 | # using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV. 59 | # Example: 60 | # set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') 61 | # 62 | # 5. Use the functions described below to create a custom make target which 63 | # runs your test executable and produces a code coverage report. 64 | # 65 | # 6. Build a Debug build: 66 | # cmake -DCMAKE_BUILD_TYPE=Debug .. 67 | # make 68 | # make my_coverage_target 69 | # 70 | 71 | include(CMakeParseArguments) 72 | 73 | # Check prereqs 74 | find_program( GCOV_PATH gcov ) 75 | find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) 76 | find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) 77 | find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) 78 | find_package(Python COMPONENTS Interpreter) 79 | 80 | if(NOT GCOV_PATH) 81 | message(FATAL_ERROR "gcov not found! Aborting...") 82 | endif() # NOT GCOV_PATH 83 | 84 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") 85 | if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) 86 | message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") 87 | endif() 88 | elseif(NOT CMAKE_COMPILER_IS_GNUCXX) 89 | message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 90 | endif() 91 | 92 | set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -ftest-coverage" 93 | CACHE INTERNAL "") 94 | 95 | set(CMAKE_CXX_FLAGS_COVERAGE 96 | ${COVERAGE_COMPILER_FLAGS} 97 | CACHE STRING "Flags used by the C++ compiler during coverage builds." 98 | FORCE ) 99 | set(CMAKE_C_FLAGS_COVERAGE 100 | ${COVERAGE_COMPILER_FLAGS} 101 | CACHE STRING "Flags used by the C compiler during coverage builds." 102 | FORCE ) 103 | set(CMAKE_EXE_LINKER_FLAGS_COVERAGE 104 | "" 105 | CACHE STRING "Flags used for linking binaries during coverage builds." 106 | FORCE ) 107 | set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE 108 | "" 109 | CACHE STRING "Flags used by the shared libraries linker during coverage builds." 110 | FORCE ) 111 | mark_as_advanced( 112 | CMAKE_CXX_FLAGS_COVERAGE 113 | CMAKE_C_FLAGS_COVERAGE 114 | CMAKE_EXE_LINKER_FLAGS_COVERAGE 115 | CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) 116 | 117 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 118 | message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") 119 | endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 120 | 121 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 122 | link_libraries(gcov) 123 | else() 124 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") 125 | endif() 126 | 127 | # Defines a target for running and collection code coverage information 128 | # Builds dependencies, runs the given executable and outputs reports. 129 | # NOTE! The executable should always have a ZERO as exit code otherwise 130 | # the coverage generation will not complete. 131 | # 132 | # SETUP_TARGET_FOR_COVERAGE_LCOV( 133 | # NAME testrunner_coverage # New target name 134 | # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 135 | # DEPENDENCIES testrunner # Dependencies to build first 136 | # ) 137 | function(SETUP_TARGET_FOR_COVERAGE_LCOV) 138 | 139 | set(options NONE) 140 | set(oneValueArgs NAME) 141 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) 142 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 143 | 144 | if(NOT LCOV_PATH) 145 | message(FATAL_ERROR "lcov not found! Aborting...") 146 | endif() # NOT LCOV_PATH 147 | 148 | if(NOT GENHTML_PATH) 149 | message(FATAL_ERROR "genhtml not found! Aborting...") 150 | endif() # NOT GENHTML_PATH 151 | 152 | # Setup target 153 | add_custom_target(${Coverage_NAME} 154 | 155 | # Cleanup lcov 156 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . --zerocounters 157 | # Create baseline to make sure untouched files show up in the report 158 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base 159 | 160 | # Run tests 161 | COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 162 | 163 | # Capturing lcov counters and generating report 164 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info 165 | # add baseline counters 166 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total 167 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 168 | COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 169 | COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 170 | 171 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 172 | DEPENDS ${Coverage_DEPENDENCIES} 173 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 174 | ) 175 | 176 | # Show where to find the lcov info report 177 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 178 | COMMAND ; 179 | COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." 180 | ) 181 | 182 | # Show info where to find the report 183 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 184 | COMMAND ; 185 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 186 | ) 187 | 188 | endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV 189 | 190 | # Defines a target for running and collection code coverage information 191 | # Builds dependencies, runs the given executable and outputs reports. 192 | # NOTE! The executable should always have a ZERO as exit code otherwise 193 | # the coverage generation will not complete. 194 | # 195 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML( 196 | # NAME ctest_coverage # New target name 197 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 198 | # DEPENDENCIES executable_target # Dependencies to build first 199 | # ) 200 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) 201 | 202 | set(options NONE) 203 | set(oneValueArgs NAME) 204 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 205 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 206 | 207 | if(NOT Python_FOUND) 208 | message(FATAL_ERROR "python not found! Aborting...") 209 | endif() 210 | 211 | if(NOT GCOVR_PATH) 212 | message(FATAL_ERROR "gcovr not found! Aborting...") 213 | endif() # NOT GCOVR_PATH 214 | 215 | # Combine excludes to several -e arguments 216 | set(GCOVR_EXCLUDES "") 217 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 218 | string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) 219 | list(APPEND GCOVR_EXCLUDES "-e") 220 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") 221 | endforeach() 222 | 223 | add_custom_target(${Coverage_NAME} 224 | # Run tests 225 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 226 | 227 | # Running gcovr 228 | COMMAND ${GCOVR_PATH} --xml 229 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 230 | --object-directory=${PROJECT_BINARY_DIR} 231 | -o ${Coverage_NAME}.xml 232 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 233 | DEPENDS ${Coverage_DEPENDENCIES} 234 | COMMENT "Running gcovr to produce Cobertura code coverage report." 235 | ) 236 | 237 | # Show info where to find the report 238 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 239 | COMMAND ; 240 | COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." 241 | ) 242 | 243 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML 244 | 245 | # Defines a target for running and collection code coverage information 246 | # Builds dependencies, runs the given executable and outputs reports. 247 | # NOTE! The executable should always have a ZERO as exit code otherwise 248 | # the coverage generation will not complete. 249 | # 250 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML( 251 | # NAME ctest_coverage # New target name 252 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 253 | # DEPENDENCIES executable_target # Dependencies to build first 254 | # ) 255 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) 256 | 257 | set(options NONE) 258 | set(oneValueArgs NAME) 259 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 260 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 261 | 262 | if(NOT Python_FOUND) 263 | message(FATAL_ERROR "python not found! Aborting...") 264 | endif() 265 | 266 | if(NOT GCOVR_PATH) 267 | message(FATAL_ERROR "gcovr not found! Aborting...") 268 | endif() # NOT GCOVR_PATH 269 | 270 | # Combine excludes to several -e arguments 271 | set(GCOVR_EXCLUDES "") 272 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 273 | string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) 274 | list(APPEND GCOVR_EXCLUDES "-e") 275 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") 276 | endforeach() 277 | 278 | add_custom_target(${Coverage_NAME} 279 | # Run tests 280 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 281 | 282 | # Create folder 283 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} 284 | 285 | # Running gcovr 286 | COMMAND ${Python_EXECUTABLE} ${GCOVR_PATH} --html --html-details 287 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 288 | --object-directory=${PROJECT_BINARY_DIR} 289 | -o ${Coverage_NAME}/index.html 290 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 291 | DEPENDS ${Coverage_DEPENDENCIES} 292 | COMMENT "Running gcovr to produce HTML code coverage report." 293 | ) 294 | 295 | # Show info where to find the report 296 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 297 | COMMAND ; 298 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 299 | ) 300 | 301 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML 302 | 303 | function(APPEND_COVERAGE_COMPILER_FLAGS) 304 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 305 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 306 | message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") 307 | endfunction() # APPEND_COVERAGE_COMPILER_FLAGS 308 | -------------------------------------------------------------------------------- /cmake/exercises/coverage/random.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char** argv) 7 | { 8 | std::size_t count = 1; 9 | double mu = 0; 10 | double sigma = 1.0; 11 | 12 | int c; 13 | while ((c = getopt(argc, argv, "m:s:n:")) > 0) { 14 | switch (c) { 15 | case 'm': 16 | mu = std::atof(optarg); 17 | break; 18 | case 's': 19 | sigma = std::atof(optarg); 20 | break; 21 | case 'n': 22 | count = std::atoi(optarg);; 23 | break; 24 | default: 25 | std::cerr << "invalid option " << static_cast(c) << '\n'; 26 | break; 27 | } 28 | } 29 | 30 | if (sigma <= 0) { 31 | std::cerr << "bad value\n"; 32 | std::exit(1); 33 | } 34 | 35 | std::random_device rd; 36 | std::mt19937 gen(rd()); 37 | std::normal_distribution<> dist(mu, sigma); 38 | 39 | for (std::size_t i = 0; i < count; ++i) { 40 | std::cout << dist(gen) << '\n'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cmake/exercises/coverage/run_tests: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | if [ $# -ne 1 ]; then 4 | echo "binary directory not specified" 5 | exit 1 6 | fi 7 | 8 | bin_dir="$1" 9 | 10 | program="$bin_dir/random" 11 | 12 | "$program" -n 10 13 | "$program" -s 0.1 14 | -------------------------------------------------------------------------------- /cmake/exercises/fibonacci/fibonacci.cpp: -------------------------------------------------------------------------------- 1 | int fibonacci(int n) 2 | { 3 | if (n == 0) { 4 | return 0; 5 | } else { 6 | int previous = 0; 7 | int current = 1; 8 | int next = 1; 9 | for (int i = 1; i < n; ++i) { 10 | next = current + previous; 11 | previous = current; 12 | current = next; 13 | } 14 | return next; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cmake/exercises/fibonacci/fibonacci.hpp: -------------------------------------------------------------------------------- 1 | int fibonacci(int n); 2 | -------------------------------------------------------------------------------- /cmake/exercises/fibonacci/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fibonacci.hpp" 3 | 4 | int main() 5 | { 6 | int i; 7 | while (std::cin >> i) { 8 | std::cout << fibonacci(i) << '\n'; 9 | } 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /cmake/exercises/hello/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello, World!\n"; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /cmake/exercises/hg2g/include/hg2g/hg2g.hpp: -------------------------------------------------------------------------------- 1 | #ifndef hg2g_hg2g_hpp 2 | #define hg2g_hg2g_hpp 3 | 4 | #include 5 | 6 | namespace hg2g { 7 | 8 | std::string get_answer(); 9 | std::string get_question(); 10 | 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /cmake/exercises/hg2g/lib/answer.cpp: -------------------------------------------------------------------------------- 1 | #include "hg2g/hg2g.hpp" 2 | 3 | namespace hg2g { 4 | 5 | std::string get_answer() 6 | { 7 | return "42"; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /cmake/exercises/hg2g/lib/question.cpp: -------------------------------------------------------------------------------- 1 | #include "hg2g/hg2g.hpp" 2 | #include 3 | 4 | namespace hg2g { 5 | 6 | std::string get_question() 7 | { 8 | throw std::runtime_error("answer cannot be computed"); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /cmake/exercises/hg2g/src/answer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hg2g/hg2g.hpp" 3 | 4 | int main() 5 | try { 6 | std::cout << "The answer to the ultimate question of " 7 | "life, the universe, and everything is:\n" << hg2g::get_answer() << '\n'; 8 | 9 | std::cout << "The ultimate question is:\n" << hg2g::get_question() << '\n'; 10 | return 0; 11 | } catch(...) { 12 | std::cerr << "Exception caught.\n"; 13 | std::cerr << "Program terminating.\n"; 14 | } 15 | -------------------------------------------------------------------------------- /cmake/exercises/sanitizers/asan_fail.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void i_feel_so_dirty() 4 | { 5 | int a[4]; 6 | std::cout << a[5] << '\n'; 7 | int* p = nullptr; 8 | std::cout << (*p) << '\n'; 9 | } 10 | 11 | int main() 12 | { 13 | i_feel_so_dirty(); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /cmake/exercises/sanitizers/ubsan_fail.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int i_feel_so_dirty() 5 | { 6 | int i; 7 | std::cout << i << '\n'; 8 | i = -16; 9 | std::cout << (i << 1) << '\n'; 10 | std::cout << (i >> 1) << '\n'; 11 | std::cout << (i << 128) << '\n'; 12 | i = std::numeric_limits::max(); 13 | ++i; 14 | std::cout << i << '\n'; 15 | } 16 | 17 | int main() 18 | { 19 | i_feel_so_dirty(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /cmake/exercises/spl/demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | SPL::OutputBitStream obs(std::cout); 6 | std::string s("Hello, World!\n"); 7 | for (auto c : s) { 8 | obs.putBits(c, 8); 9 | } 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /lcov/examples/bqueue/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(coverage_example LANGUAGES CXX) 3 | 4 | option(ENABLE_COVERAGE "Enable coverage" FALSE) 5 | set(CMAKE_VERBOSE_MAKEFILE TRUE) 6 | set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) 7 | 8 | find_package(Catch2 3 REQUIRED) 9 | 10 | if (ENABLE_COVERAGE) 11 | set(CMAKE_BUILD_TYPE "Debug" CACHE STRING 12 | "Set the build type." FORCE) 13 | include(CodeCoverage.cmake) 14 | append_coverage_compiler_flags() 15 | endif() 16 | 17 | add_executable(test_bqueue test_bqueue.cpp) 18 | target_link_libraries(test_bqueue PRIVATE Catch2::Catch2WithMain) 19 | 20 | if (ENABLE_COVERAGE) 21 | setup_target_for_coverage_lcov( 22 | NAME coverage 23 | EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_bqueue 24 | LCOV_ARGS --rc lcov_branch_coverage=1 25 | GENHTML_ARGS --legend --branch-coverage 26 | DEPENDENCIES test_bqueue) 27 | endif() 28 | -------------------------------------------------------------------------------- /lcov/examples/bqueue/CodeCoverage.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 - 2017, Lars Bilke 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # CHANGES: 30 | # 31 | # 2012-01-31, Lars Bilke 32 | # - Enable Code Coverage 33 | # 34 | # 2013-09-17, Joakim Söderberg 35 | # - Added support for Clang. 36 | # - Some additional usage instructions. 37 | # 38 | # 2016-02-03, Lars Bilke 39 | # - Refactored functions to use named parameters 40 | # 41 | # 2017-06-02, Lars Bilke 42 | # - Merged with modified version from github.com/ufz/ogs 43 | # 44 | # 45 | # USAGE: 46 | # 47 | # 1. Copy this file into your cmake modules path. 48 | # 49 | # 2. Add the following line to your CMakeLists.txt: 50 | # include(CodeCoverage) 51 | # 52 | # 3. Append necessary compiler flags: 53 | # APPEND_COVERAGE_COMPILER_FLAGS() 54 | # 55 | # 4. If you need to exclude additional directories from the report, specify them 56 | # using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV. 57 | # Example: 58 | # set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') 59 | # 60 | # 5. Use the functions described below to create a custom make target which 61 | # runs your test executable and produces a code coverage report. 62 | # 63 | # 6. Build a Debug build: 64 | # cmake -DCMAKE_BUILD_TYPE=Debug .. 65 | # make 66 | # make my_coverage_target 67 | # 68 | 69 | include(CMakeParseArguments) 70 | 71 | # Check prereqs 72 | find_program( GCOV_PATH gcov ) 73 | find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) 74 | find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) 75 | find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) 76 | find_program( SIMPLE_PYTHON_EXECUTABLE python ) 77 | 78 | if(NOT GCOV_PATH) 79 | message(FATAL_ERROR "gcov not found! Aborting...") 80 | endif() # NOT GCOV_PATH 81 | 82 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") 83 | if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) 84 | message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") 85 | endif() 86 | elseif(NOT CMAKE_COMPILER_IS_GNUCXX) 87 | message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 88 | endif() 89 | 90 | set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage" 91 | CACHE INTERNAL "") 92 | 93 | set(CMAKE_CXX_FLAGS_COVERAGE 94 | ${COVERAGE_COMPILER_FLAGS} 95 | CACHE STRING "Flags used by the C++ compiler during coverage builds." 96 | FORCE ) 97 | set(CMAKE_C_FLAGS_COVERAGE 98 | ${COVERAGE_COMPILER_FLAGS} 99 | CACHE STRING "Flags used by the C compiler during coverage builds." 100 | FORCE ) 101 | set(CMAKE_EXE_LINKER_FLAGS_COVERAGE 102 | "" 103 | CACHE STRING "Flags used for linking binaries during coverage builds." 104 | FORCE ) 105 | set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE 106 | "" 107 | CACHE STRING "Flags used by the shared libraries linker during coverage builds." 108 | FORCE ) 109 | mark_as_advanced( 110 | CMAKE_CXX_FLAGS_COVERAGE 111 | CMAKE_C_FLAGS_COVERAGE 112 | CMAKE_EXE_LINKER_FLAGS_COVERAGE 113 | CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) 114 | 115 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 116 | message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") 117 | endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 118 | 119 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 120 | link_libraries(gcov) 121 | else() 122 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") 123 | endif() 124 | 125 | # Defines a target for running and collection code coverage information 126 | # Builds dependencies, runs the given executable and outputs reports. 127 | # NOTE! The executable should always have a ZERO as exit code otherwise 128 | # the coverage generation will not complete. 129 | # 130 | # SETUP_TARGET_FOR_COVERAGE_LCOV( 131 | # NAME testrunner_coverage # New target name 132 | # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 133 | # DEPENDENCIES testrunner # Dependencies to build first 134 | # ) 135 | function(SETUP_TARGET_FOR_COVERAGE_LCOV) 136 | 137 | set(options NONE) 138 | set(oneValueArgs NAME) 139 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) 140 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 141 | 142 | if(NOT LCOV_PATH) 143 | message(FATAL_ERROR "lcov not found! Aborting...") 144 | endif() # NOT LCOV_PATH 145 | 146 | if(NOT GENHTML_PATH) 147 | message(FATAL_ERROR "genhtml not found! Aborting...") 148 | endif() # NOT GENHTML_PATH 149 | 150 | # Setup target 151 | add_custom_target(${Coverage_NAME} 152 | 153 | # Cleanup lcov 154 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 155 | -directory . --zerocounters 156 | # Create baseline to make sure untouched files show up in the report 157 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 158 | -c -i -d . -o ${Coverage_NAME}.base 159 | 160 | # Run tests 161 | COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 162 | 163 | # Note: Do not use base information from above. 164 | # This causes Lcov to incorrectly consider some functions for static 165 | # initialization not to have been called. 166 | # Capturing lcov counters and generating report 167 | #COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 168 | # --directory . --capture --output-file ${Coverage_NAME}.info 169 | # add baseline counters 170 | #COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 171 | # -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info 172 | # --output-file ${Coverage_NAME}.total 173 | 174 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 175 | --directory . --capture --output-file ${Coverage_NAME}.total 176 | 177 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 178 | --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} 179 | --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 180 | COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} 181 | ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 182 | COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base 183 | ${Coverage_NAME}.total 184 | ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 185 | 186 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 187 | DEPENDS ${Coverage_DEPENDENCIES} 188 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 189 | ) 190 | 191 | # Show where to find the lcov info report 192 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 193 | COMMAND ; 194 | COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." 195 | ) 196 | 197 | # Show info where to find the report 198 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 199 | COMMAND ; 200 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 201 | ) 202 | 203 | endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV 204 | 205 | # Defines a target for running and collection code coverage information 206 | # Builds dependencies, runs the given executable and outputs reports. 207 | # NOTE! The executable should always have a ZERO as exit code otherwise 208 | # the coverage generation will not complete. 209 | # 210 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML( 211 | # NAME ctest_coverage # New target name 212 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 213 | # DEPENDENCIES executable_target # Dependencies to build first 214 | # ) 215 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) 216 | 217 | set(options NONE) 218 | set(oneValueArgs NAME) 219 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 220 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 221 | 222 | if(NOT SIMPLE_PYTHON_EXECUTABLE) 223 | message(FATAL_ERROR "python not found! Aborting...") 224 | endif() # NOT SIMPLE_PYTHON_EXECUTABLE 225 | 226 | if(NOT GCOVR_PATH) 227 | message(FATAL_ERROR "gcovr not found! Aborting...") 228 | endif() # NOT GCOVR_PATH 229 | 230 | # Combine excludes to several -e arguments 231 | set(GCOVR_EXCLUDES "") 232 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 233 | list(APPEND GCOVR_EXCLUDES "-e") 234 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") 235 | endforeach() 236 | 237 | add_custom_target(${Coverage_NAME} 238 | # Run tests 239 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 240 | 241 | # Running gcovr 242 | COMMAND ${GCOVR_PATH} --xml 243 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 244 | --object-directory=${PROJECT_BINARY_DIR} 245 | -o ${Coverage_NAME}.xml 246 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 247 | DEPENDS ${Coverage_DEPENDENCIES} 248 | COMMENT "Running gcovr to produce Cobertura code coverage report." 249 | ) 250 | 251 | # Show info where to find the report 252 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 253 | COMMAND ; 254 | COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." 255 | ) 256 | 257 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML 258 | 259 | # Defines a target for running and collection code coverage information 260 | # Builds dependencies, runs the given executable and outputs reports. 261 | # NOTE! The executable should always have a ZERO as exit code otherwise 262 | # the coverage generation will not complete. 263 | # 264 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML( 265 | # NAME ctest_coverage # New target name 266 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 267 | # DEPENDENCIES executable_target # Dependencies to build first 268 | # ) 269 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) 270 | 271 | set(options NONE) 272 | set(oneValueArgs NAME) 273 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 274 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 275 | 276 | if(NOT SIMPLE_PYTHON_EXECUTABLE) 277 | message(FATAL_ERROR "python not found! Aborting...") 278 | endif() # NOT SIMPLE_PYTHON_EXECUTABLE 279 | 280 | if(NOT GCOVR_PATH) 281 | message(FATAL_ERROR "gcovr not found! Aborting...") 282 | endif() # NOT GCOVR_PATH 283 | 284 | # Combine excludes to several -e arguments 285 | set(GCOVR_EXCLUDES "") 286 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 287 | list(APPEND GCOVR_EXCLUDES "-e") 288 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") 289 | endforeach() 290 | 291 | add_custom_target(${Coverage_NAME} 292 | # Run tests 293 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 294 | 295 | # Create folder 296 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} 297 | 298 | # Running gcovr 299 | COMMAND ${GCOVR_PATH} --html --html-details 300 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 301 | --object-directory=${PROJECT_BINARY_DIR} 302 | -o ${Coverage_NAME}/index.html 303 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 304 | DEPENDS ${Coverage_DEPENDENCIES} 305 | COMMENT "Running gcovr to produce HTML code coverage report." 306 | ) 307 | 308 | # Show info where to find the report 309 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 310 | COMMAND ; 311 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 312 | ) 313 | 314 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML 315 | 316 | function(APPEND_COVERAGE_COMPILER_FLAGS) 317 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 318 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 319 | message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") 320 | endfunction() # APPEND_COVERAGE_COMPILER_FLAGS 321 | -------------------------------------------------------------------------------- /lcov/examples/bqueue/bqueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RA_BQUEUE_HPP 2 | #define RA_BQUEUE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace ra::containers { 11 | 12 | /* 13 | A simple bounded queue container. 14 | */ 15 | template 16 | class bqueue 17 | { 18 | public: 19 | using value_type = T; 20 | bqueue(std::size_t max_size); 21 | std::size_t size() const; 22 | std::size_t max_size() const; 23 | bool empty() const; 24 | void push(const T& item); 25 | void push(T&& item); 26 | void pop(T& item); 27 | private: 28 | std::queue q_; 29 | std::size_t max_size_; 30 | }; 31 | 32 | template 33 | bqueue::bqueue(std::size_t max_size) : max_size_(max_size) 34 | { 35 | } 36 | 37 | template 38 | inline std::size_t bqueue::size() const 39 | { 40 | return q_.size(); 41 | } 42 | 43 | template 44 | inline std::size_t bqueue::max_size() const 45 | { 46 | return max_size_; 47 | } 48 | 49 | template 50 | inline bool bqueue::empty() const 51 | { 52 | return q_.empty(); 53 | } 54 | 55 | template 56 | void bqueue::push(const T& item) 57 | { 58 | if (q_.size() >= max_size_) { 59 | throw std::runtime_error("queue is full"); 60 | } 61 | q_.push(item); 62 | } 63 | 64 | template 65 | void bqueue::push(T&& item) 66 | { 67 | if (q_.size() >= max_size_) { 68 | throw std::runtime_error("queue is full"); 69 | } 70 | q_.push(std::move(item)); 71 | } 72 | 73 | template 74 | void bqueue::pop(T& item) 75 | { 76 | if (q_.size() == 0) { 77 | throw std::runtime_error("queue is empty"); 78 | } 79 | item = q_.front(); 80 | q_.pop(); 81 | } 82 | 83 | template 84 | void pop_into_vector(bqueue& q, std::vector& v) 85 | { 86 | typename bqueue::value_type item; 87 | while (!q.empty()) { 88 | q.pop(item); 89 | v.push_back(std::move(item)); 90 | } 91 | } 92 | 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /lcov/examples/bqueue/test_bqueue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "bqueue.hpp" 5 | 6 | TEMPLATE_TEST_CASE("Check constructor", "[constructors]", 7 | int, double) { 8 | using Queue = ra::containers::bqueue; 9 | constexpr std::size_t max_size = 1024; 10 | Queue s(max_size); 11 | CHECK(s.empty()); 12 | CHECK(s.size() == 0); 13 | CHECK(s.max_size() == max_size); 14 | } 15 | 16 | TEMPLATE_TEST_CASE("Check push and pop", "[modifiers]", 17 | int, double) { 18 | using Queue = ra::containers::bqueue; 19 | Queue s(1024); 20 | TestType pushed_item(0); 21 | s.push(pushed_item); 22 | CHECK(s.size() == 1); 23 | TestType item; 24 | s.pop(item); 25 | CHECK(item == pushed_item); 26 | CHECK(s.size() == 0); 27 | CHECK(s.empty()); 28 | } 29 | 30 | TEMPLATE_TEST_CASE("Check pop_into_vector", "[modifiers]", 31 | int) { 32 | using Queue = ra::containers::bqueue; 33 | Queue q(1024); 34 | for (auto&& i : {1, 2, 3}) { 35 | q.push(i); 36 | } 37 | std::vector v; 38 | pop_into_vector(q, v); 39 | CHECK(v == std::vector{1, 2, 3}); 40 | } 41 | -------------------------------------------------------------------------------- /miscellany/buggy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Specify minimum required version of CMake. 2 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 3 | 4 | # Specify project and identify languages used. 5 | project(app LANGUAGES CXX) 6 | 7 | # Enable verbose makefiles. 8 | set(CMAKE_VERBOSE_MAKEFILE true) 9 | 10 | # Add program target called app. 11 | add_executable(app app.cpp) 12 | -------------------------------------------------------------------------------- /miscellany/buggy/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | std::vector v{1, 2, 3}; 8 | auto two = std::find(v.begin(), v.end(), 2); 9 | for (int i = 0; i < 4096; ++i) { 10 | v.push_back(i); 11 | } 12 | std::cout << *two << '\n'; 13 | } 14 | -------------------------------------------------------------------------------- /miscellany/data_race/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(threads_example LANGUAGES CXX) 3 | 4 | option(ENABLE_TSAN "Enable Thread Sanitizer" false) 5 | 6 | # Require compliance with C++17 standard. 7 | set(CMAKE_CXX_STANDARD 17) 8 | set(CMAKE_CXX_STANDARD_REQUIRED true) 9 | 10 | set(CMAKE_VERBOSE_MAKEFILE true) 11 | 12 | if(ENABLE_TSAN) 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") 14 | endif() 15 | 16 | # Find the threads library, indicating a preference for the 17 | # pthread library. 18 | set(THREADS_PREFER_PTHREAD_FLAG true) 19 | find_package(Threads REQUIRED) 20 | 21 | # Define a program target called app. 22 | add_executable(app app.cpp) 23 | 24 | # Set the libraries for the app target. 25 | target_link_libraries(app Threads::Threads) 26 | -------------------------------------------------------------------------------- /miscellany/data_race/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | constexpr auto num_iterations = 1'000'000; 7 | 8 | void worker(volatile unsigned long long& count) 9 | { 10 | for (auto i = num_iterations; i; --i) { 11 | ++count; 12 | } 13 | } 14 | 15 | int main(int argc, char** argv) 16 | { 17 | int num_threads = 4; 18 | if (argc >= 2) { 19 | num_threads = std::atoi(argv[1]); 20 | } 21 | unsigned long long count = 0; 22 | std::vector threads; 23 | for (int i = 0; i < num_threads; ++i) { 24 | threads.emplace_back(worker, 25 | std::reference_wrapper(count)); 26 | } 27 | for (auto&& t : threads) { 28 | t.join(); 29 | } 30 | std::cout << count << '\n'; 31 | } 32 | -------------------------------------------------------------------------------- /miscellany/deadlock/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(threads_example LANGUAGES CXX) 3 | 4 | option(ENABLE_TSAN "Enable Thread Sanitizer" false) 5 | 6 | # Require compliance with C++17 standard. 7 | set(CMAKE_CXX_STANDARD 17) 8 | set(CMAKE_CXX_STANDARD_REQUIRED true) 9 | 10 | set(CMAKE_VERBOSE_MAKEFILE true) 11 | 12 | if(ENABLE_TSAN) 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") 14 | endif() 15 | 16 | # Find the threads library, indicating a preference for the 17 | # pthread library. 18 | set(THREADS_PREFER_PTHREAD_FLAG true) 19 | find_package(Threads REQUIRED) 20 | 21 | # Define a program target called app. 22 | add_executable(app app.cpp) 23 | 24 | # Set the libraries for the app target. 25 | target_link_libraries(app Threads::Threads) 26 | -------------------------------------------------------------------------------- /miscellany/deadlock/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void worker(std::vector& v1, std::mutex& m1, std::vector& v2, 8 | std::mutex& m2) 9 | { 10 | for (auto i = 1'000'000; i; --i) { 11 | std::scoped_lock l1(m1); 12 | std::scoped_lock l2(m2); 13 | std::swap(v1, v2); 14 | } 15 | } 16 | 17 | int main(int argc, char** argv) 18 | { 19 | bool allow_deadlock = true; 20 | if (argc >= 2) { 21 | allow_deadlock = std::atoi(argv[1]); 22 | } 23 | std::vector va{0, 2, 4, 6}; 24 | std::mutex ma; 25 | std::vector vb{1, 3, 5, 7}; 26 | std::mutex mb; 27 | 28 | std::vector threads; 29 | threads.emplace_back(worker, 30 | std::reference_wrapper>(va), 31 | std::reference_wrapper(ma), 32 | std::reference_wrapper>(vb), 33 | std::reference_wrapper(mb)); 34 | if (allow_deadlock) { 35 | threads.emplace_back(worker, 36 | std::reference_wrapper>(vb), 37 | std::reference_wrapper(mb), 38 | std::reference_wrapper>(va), 39 | std::reference_wrapper(ma)); 40 | } 41 | 42 | for (auto&& t : threads) { 43 | t.join(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /miscellany/factorial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Specify minimum required version of CMake. 2 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 3 | 4 | # Specify project and identify languages used. 5 | project(factorial LANGUAGES CXX) 6 | 7 | # Enable verbose makefiles. 8 | set(CMAKE_VERBOSE_MAKEFILE true) 9 | 10 | # Add program target called factorial. 11 | add_executable(factorial factorial.cpp) 12 | -------------------------------------------------------------------------------- /miscellany/factorial/factorial.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int factorial(int n) 5 | { 6 | int result = 1; 7 | while (n > 1) { 8 | result *= n; 9 | --n; 10 | } 11 | return result; 12 | } 13 | 14 | int main(int argc, char** argv) 15 | { 16 | int n = 13; 17 | if (argc >= 2) { 18 | n = std::atoi(argv[1]); 19 | } 20 | std::cerr << "computing " << n << "!\n"; 21 | std::cout << factorial(n) << '\n'; 22 | return (std::cout) ? 0 : 1; 23 | } 24 | -------------------------------------------------------------------------------- /slides/catch2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(slides_catch LANGUAGES CXX) 3 | 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS true) 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED true) 7 | 8 | include(CTest) 9 | find_package(Catch2 3 REQUIRED) 10 | include(Catch) 11 | 12 | add_executable(fixture fixture.cpp) 13 | target_link_libraries(fixture PRIVATE Catch2::Catch2WithMain) 14 | list(APPEND targets fixture) 15 | 16 | add_executable(section section.cpp) 17 | target_link_libraries(section PRIVATE Catch2::Catch2WithMain) 18 | list(APPEND targets section) 19 | 20 | add_executable(test_counter test_counter.cpp) 21 | target_link_libraries(test_counter PRIVATE Catch2::Catch2WithMain) 22 | list(APPEND targets test_counter) 23 | 24 | add_executable(test_math test_math.cpp) 25 | target_link_libraries(test_math PRIVATE Catch2::Catch2WithMain) 26 | list(APPEND targets test_math) 27 | 28 | add_executable(test_stack test_stack.cpp) 29 | target_link_libraries(test_stack PRIVATE Catch2::Catch2WithMain) 30 | list(APPEND targets test_stack) 31 | 32 | add_executable(test_bubble_sort test_bubble_sort.cpp) 33 | target_link_libraries(test_bubble_sort PRIVATE Catch2::Catch2WithMain) 34 | list(APPEND targets test_bubble_sort) 35 | 36 | add_executable(benchmark_fibonacci benchmark_fibonacci.cpp) 37 | target_link_libraries(benchmark_fibonacci PRIVATE Catch2::Catch2WithMain) 38 | list(APPEND targets benchmark_fibonacci) 39 | 40 | foreach(target ${targets}) 41 | catch_discover_tests(${target}) 42 | endforeach() 43 | -------------------------------------------------------------------------------- /slides/catch2/benchmark_fibonacci.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "fibonacci.hpp" 4 | 5 | // Note: [!benchmark] is special tag indicating test case is benchmark 6 | TEST_CASE("benchmark fibonacci", "[!benchmark]") { 7 | REQUIRE(fibonacci(20) == 6'765); 8 | BENCHMARK("fibonacci(20)") { 9 | return fibonacci(20); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /slides/catch2/bubble_sort.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | void bubble_sort(ForwardIterator first, ForwardIterator last, Compare less) { 7 | for (auto sorted = first; first != last; last = sorted) { 8 | sorted = first; 9 | for (auto cur = first, prev = first; ++cur != last; ++prev) { 10 | if (less(*cur, *prev)) { 11 | std::iter_swap(cur, prev); 12 | sorted = cur; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /slides/catch2/counter.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class counter { 5 | public: 6 | using count_type = std::size_t; 7 | static constexpr count_type max_count() { 8 | return std::numeric_limits::max(); 9 | } 10 | counter(count_type count = 0) : count_(count) {} 11 | count_type get_count() const { 12 | return count_; 13 | } 14 | void increment() { 15 | if (count_ == max_count()) { 16 | throw std::overflow_error("counter overflow"); 17 | } 18 | ++count_; 19 | } 20 | private: 21 | count_type count_; 22 | }; 23 | -------------------------------------------------------------------------------- /slides/catch2/fibonacci.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FIBONACCI_HPP 2 | #define FIBONACCI_HPP 3 | 4 | #include 5 | 6 | constexpr uint64_t fibonacci(uint64_t n) { 7 | if (n >= 2) {return fibonacci(n - 1) + fibonacci(n - 2);} 8 | else if (n == 1) {return 1;} 9 | else {return 0;} 10 | } 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /slides/catch2/fixture.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class TestFixture { 6 | public: 7 | TestFixture() : q0(), q1{1, 2, 3} { 8 | } 9 | protected: 10 | std::deque q0; 11 | std::deque q1; 12 | }; 13 | 14 | TEST_CASE_METHOD(TestFixture, "Check deque at", "[deque]") { 15 | CHECK_THROWS_AS(q0.at(0), std::out_of_range); 16 | CHECK(q1.at(0) == 1); 17 | CHECK_THROWS_AS(q1.at(3), std::out_of_range); 18 | } 19 | 20 | TEST_CASE_METHOD(TestFixture, "Check deque clear", "[deque]") { 21 | q0.clear(); 22 | CHECK(q0.size() == 0); 23 | q1.clear(); 24 | CHECK(q1.size() == 0); 25 | } 26 | -------------------------------------------------------------------------------- /slides/catch2/section.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST_CASE("Check resize", "[vector]") { 6 | constexpr std::size_t size = 128; 7 | std::vector x(size); 8 | REQUIRE(x.size() == size); 9 | REQUIRE(x.capacity() >= size); 10 | SECTION("Increase size") { 11 | std::size_t n = size * 16; 12 | x.resize(n); 13 | CHECK(x.size() == n); 14 | CHECK(x.capacity() >= n); 15 | } 16 | SECTION("Decrease size") { 17 | std::size_t n = size / 16; 18 | x.resize(n); 19 | CHECK(x.size() == n); 20 | CHECK(x.capacity() >= n); 21 | } 22 | SECTION("Zero size") { 23 | x.resize(0); 24 | CHECK(x.size() == 0); 25 | CHECK(x.capacity() >= size); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /slides/catch2/stack.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Note: T is not allowed to be bool. 5 | template 6 | class Stack { 7 | public: 8 | bool empty() const {return s_.empty();} 9 | std::size_t size() const {return s_.size();} 10 | const T& top() const {return s_.back();} 11 | void push(const T& x) {s_.push_back(x);} 12 | void pop() {s_.pop_back();} 13 | private: 14 | std::vector s_; 15 | }; 16 | -------------------------------------------------------------------------------- /slides/catch2/test_bubble_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include "bubble_sort.hpp" 6 | 7 | /* 8 | This needs to be completed. 9 | */ 10 | TEMPLATE_TEST_CASE("test", "[blah]", int, double, short) { 11 | std::forward_list values{7, 0, 6, 1, 5, 2, 4, 3}; 12 | bubble_sort(values.begin(), values.end(), std::less()); 13 | CHECK((values == std::forward_list{0, 1, 2, 3, 4, 5, 6, 7})); 14 | bubble_sort(values.begin(), values.end(), std::greater()); 15 | CHECK((values == std::forward_list{7, 6, 5, 4, 3, 2, 1, 0})); 16 | } 17 | -------------------------------------------------------------------------------- /slides/catch2/test_counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "counter.hpp" 3 | 4 | TEST_CASE("constructor", "[counter][constructor]") { 5 | counter x; 6 | CHECK(x.get_count() == 0); 7 | counter y(1); 8 | CHECK(y.get_count() == 1); 9 | } 10 | 11 | TEST_CASE("maximum count", "[counter][method]") { 12 | CHECK(counter::max_count() == std::numeric_limits< 13 | counter::count_type>::max()); 14 | } 15 | 16 | TEST_CASE("increment (no overflow)", "[counter][method]") { 17 | counter x(0); 18 | REQUIRE(x.get_count() == 0); 19 | x.increment(); 20 | CHECK(x.get_count() == 1); 21 | } 22 | 23 | TEST_CASE("increment (overflow)", "[counter][method]") { 24 | counter x(counter::max_count()); 25 | CHECK_THROWS_AS(x.increment(), std::overflow_error); 26 | } 27 | -------------------------------------------------------------------------------- /slides/catch2/test_math.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | TEST_CASE("check addition") { 5 | float x = 0.0f; 6 | for (int i = 0; i < 10; ++i) {x += 0.1f;} 7 | CHECK_NOFAIL(x == 1.0f); 8 | // condition may be false due to roundoff error 9 | CHECK_THAT(x, Catch::Matchers::WithinAbs(1.0f, 0.01f)); 10 | // should pass (absolute tolerance 0.01) 11 | CHECK_THAT(x, Catch::Matchers::WithinRel(1.0f, 0.01f)); 12 | // should pass (relative tolerance 1%) 13 | float y = std::nextafter(0.0f, 1.0f); 14 | CHECK_THAT(y, Catch::Matchers::WithinULP(0.0f, 1)); 15 | // should pass (y is next representable value greater than 0.0f) 16 | } 17 | -------------------------------------------------------------------------------- /slides/catch2/test_stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack.hpp" 4 | 5 | TEMPLATE_TEST_CASE("Check default constructor", "[stack][constructor]", 6 | int, double, std::complex) { 7 | Stack s; 8 | CHECK(s.empty()); 9 | CHECK(s.size() == 0); 10 | } 11 | 12 | TEMPLATE_TEST_CASE("Check push and pop", "[stack][modifier]", 13 | int, double, std::complex) { 14 | std::size_t size = 0; 15 | Stack s; 16 | REQUIRE(s.size() == size); 17 | while (size < 3) { 18 | ++size; s.push(TestType(size)); 19 | REQUIRE(s.size() == size); 20 | REQUIRE(s.top() == TestType(size)); 21 | } 22 | while (size > 0) { 23 | s.pop(); --size; 24 | REQUIRE(s.size() == size); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /slides/clang_tidy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(clang_tidy LANGUAGES CXX) 3 | 4 | find_program(CLANG_TIDY_PROGRAM NAMES "clang-tidy" 5 | DOC "Path to clang-tidy executable") 6 | if (CLANG_TIDY_PROGRAM) 7 | set(CLANG_TIDY_OPTIONS "-warnings-as-errors=*") 8 | set(RUN_CLANG_TIDY "${CLANG_TIDY_PROGRAM}" "${CLANG_TIDY_OPTIONS}") 9 | endif() 10 | 11 | add_library(lib lib.cpp) 12 | add_executable(app app.cpp lib) 13 | set(targets lib app) 14 | 15 | if (CLANG_TIDY_PROGRAM) 16 | set_target_properties(${targets} PROPERTIES CXX_CLANG_TIDY 17 | "${RUN_CLANG_TIDY}") 18 | endif() 19 | -------------------------------------------------------------------------------- /slides/clang_tidy/app.cpp: -------------------------------------------------------------------------------- 1 | int func(); 2 | char* foobar(); 3 | 4 | int main() { 5 | auto x = 1 / 2; 6 | double y = 1 / x; 7 | char* cp = new char[1024]; 8 | delete cp; 9 | func(); 10 | foobar(); 11 | int i; 12 | return i + 1; 13 | } 14 | -------------------------------------------------------------------------------- /slides/clang_tidy/lib.cpp: -------------------------------------------------------------------------------- 1 | int func() {} 2 | 3 | char* foobar() { 4 | char c; 5 | return &c; 6 | } 7 | -------------------------------------------------------------------------------- /slides/helgrind/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(slides_helgrind LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_STANDARD_REQUIRED true) 6 | 7 | find_package(Threads REQUIRED) 8 | 9 | add_executable(data_race_1_0 data_race_1_0.cpp) 10 | target_link_libraries(data_race_1_0 Threads::Threads) 11 | 12 | add_executable(data_race_1_1 data_race_1_1.cpp) 13 | target_link_libraries(data_race_1_1 Threads::Threads) 14 | -------------------------------------------------------------------------------- /slides/helgrind/clipboard.txt: -------------------------------------------------------------------------------- 1 | cmake -S. -Btmp_cmake 2 | cmake --build tmp_cmake 3 | 4 | # Code has data race. 5 | ./tmp_cmake/data_race_1_0 6 | valgrind --tool=helgrind ./tmp_cmake/data_race_1_0 |& less 7 | 8 | # Code is data-race free. 9 | ./tmp_cmake/data_race_1_1 10 | valgrind --tool=helgrind ./tmp_cmake/data_race_1_1 |& less 11 | -------------------------------------------------------------------------------- /slides/helgrind/data_race_1_0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | unsigned long count = 0; 5 | 6 | void func() { 7 | for (unsigned long i = 0; i < 1'000'000; ++i) { 8 | ++count; 9 | } 10 | } 11 | 12 | int main() { 13 | std::thread t1(func); 14 | std::thread t2(func); 15 | t1.join(); 16 | t2.join(); 17 | std::cout << count << '\n'; 18 | } 19 | -------------------------------------------------------------------------------- /slides/helgrind/data_race_1_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | unsigned long count = 0; 6 | std::mutex m; 7 | 8 | void func() { 9 | for (unsigned long i = 0; i < 1'000'000; ++i) { 10 | std::scoped_lock lock(m); 11 | ++count; 12 | } 13 | } 14 | 15 | int main() { 16 | std::thread t1(func); 17 | std::thread t2(func); 18 | t1.join(); 19 | t2.join(); 20 | std::cout << count << '\n'; 21 | } 22 | -------------------------------------------------------------------------------- /slides/lcov/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(coverage_example LANGUAGES CXX C) 3 | option(ENABLE_COVERAGE "Enable coverage" false) 4 | set(CMAKE_VERBOSE_MAKEFILE true) 5 | set(CMAKE_EXPORT_COMPILE_COMMANDS true) 6 | 7 | if (ENABLE_COVERAGE) 8 | set(CMAKE_BUILD_TYPE "Debug" CACHE STRING 9 | "Set the build type." FORCE) 10 | include(CodeCoverage.cmake) 11 | append_coverage_compiler_flags() 12 | endif() 13 | 14 | add_executable(app app.cpp signum.cpp) 15 | 16 | if (ENABLE_COVERAGE) 17 | setup_target_for_coverage_lcov( 18 | NAME coverage 19 | EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/run_tests 20 | EXECUTABLE_ARGS ${CMAKE_CURRENT_BINARY_DIR} 21 | LCOV_ARGS --rc lcov_branch_coverage=1 22 | GENHTML_ARGS --legend --branch-coverage 23 | DEPENDENCIES app) 24 | endif() 25 | -------------------------------------------------------------------------------- /slides/lcov/CodeCoverage.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 - 2017, Lars Bilke 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | # 29 | # CHANGES: 30 | # 31 | # 2012-01-31, Lars Bilke 32 | # - Enable Code Coverage 33 | # 34 | # 2013-09-17, Joakim Söderberg 35 | # - Added support for Clang. 36 | # - Some additional usage instructions. 37 | # 38 | # 2016-02-03, Lars Bilke 39 | # - Refactored functions to use named parameters 40 | # 41 | # 2017-06-02, Lars Bilke 42 | # - Merged with modified version from github.com/ufz/ogs 43 | # 44 | # 45 | # USAGE: 46 | # 47 | # 1. Copy this file into your cmake modules path. 48 | # 49 | # 2. Add the following line to your CMakeLists.txt: 50 | # include(CodeCoverage) 51 | # 52 | # 3. Append necessary compiler flags: 53 | # APPEND_COVERAGE_COMPILER_FLAGS() 54 | # 55 | # 4. If you need to exclude additional directories from the report, specify them 56 | # using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV. 57 | # Example: 58 | # set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') 59 | # 60 | # 5. Use the functions described below to create a custom make target which 61 | # runs your test executable and produces a code coverage report. 62 | # 63 | # 6. Build a Debug build: 64 | # cmake -DCMAKE_BUILD_TYPE=Debug .. 65 | # make 66 | # make my_coverage_target 67 | # 68 | 69 | include(CMakeParseArguments) 70 | 71 | # Check prereqs 72 | find_program( GCOV_PATH gcov ) 73 | find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) 74 | find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) 75 | find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) 76 | find_program( SIMPLE_PYTHON_EXECUTABLE python ) 77 | 78 | if(NOT GCOV_PATH) 79 | message(FATAL_ERROR "gcov not found! Aborting...") 80 | endif() # NOT GCOV_PATH 81 | 82 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") 83 | if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) 84 | message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") 85 | endif() 86 | elseif(NOT CMAKE_COMPILER_IS_GNUCXX) 87 | message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 88 | endif() 89 | 90 | set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage" 91 | CACHE INTERNAL "") 92 | 93 | set(CMAKE_CXX_FLAGS_COVERAGE 94 | ${COVERAGE_COMPILER_FLAGS} 95 | CACHE STRING "Flags used by the C++ compiler during coverage builds." 96 | FORCE ) 97 | set(CMAKE_C_FLAGS_COVERAGE 98 | ${COVERAGE_COMPILER_FLAGS} 99 | CACHE STRING "Flags used by the C compiler during coverage builds." 100 | FORCE ) 101 | set(CMAKE_EXE_LINKER_FLAGS_COVERAGE 102 | "" 103 | CACHE STRING "Flags used for linking binaries during coverage builds." 104 | FORCE ) 105 | set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE 106 | "" 107 | CACHE STRING "Flags used by the shared libraries linker during coverage builds." 108 | FORCE ) 109 | mark_as_advanced( 110 | CMAKE_CXX_FLAGS_COVERAGE 111 | CMAKE_C_FLAGS_COVERAGE 112 | CMAKE_EXE_LINKER_FLAGS_COVERAGE 113 | CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) 114 | 115 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 116 | message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") 117 | endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 118 | 119 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 120 | link_libraries(gcov) 121 | else() 122 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") 123 | endif() 124 | 125 | # Defines a target for running and collection code coverage information 126 | # Builds dependencies, runs the given executable and outputs reports. 127 | # NOTE! The executable should always have a ZERO as exit code otherwise 128 | # the coverage generation will not complete. 129 | # 130 | # SETUP_TARGET_FOR_COVERAGE_LCOV( 131 | # NAME testrunner_coverage # New target name 132 | # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 133 | # DEPENDENCIES testrunner # Dependencies to build first 134 | # ) 135 | function(SETUP_TARGET_FOR_COVERAGE_LCOV) 136 | 137 | set(options NONE) 138 | set(oneValueArgs NAME) 139 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) 140 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 141 | 142 | if(NOT LCOV_PATH) 143 | message(FATAL_ERROR "lcov not found! Aborting...") 144 | endif() # NOT LCOV_PATH 145 | 146 | if(NOT GENHTML_PATH) 147 | message(FATAL_ERROR "genhtml not found! Aborting...") 148 | endif() # NOT GENHTML_PATH 149 | 150 | # Setup target 151 | add_custom_target(${Coverage_NAME} 152 | 153 | # Cleanup lcov 154 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 155 | -directory . --zerocounters 156 | # Create baseline to make sure untouched files show up in the report 157 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 158 | -c -i -d . -o ${Coverage_NAME}.base 159 | 160 | # Run tests 161 | COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 162 | 163 | # Note: Do not use base information from above. 164 | # This causes Lcov to incorrectly consider some functions for static 165 | # initialization not to have been called. 166 | # Capturing lcov counters and generating report 167 | #COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 168 | # --directory . --capture --output-file ${Coverage_NAME}.info 169 | # add baseline counters 170 | #COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 171 | # -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info 172 | # --output-file ${Coverage_NAME}.total 173 | 174 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 175 | --directory . --capture --output-file ${Coverage_NAME}.total 176 | 177 | COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} 178 | --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} 179 | --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 180 | COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} 181 | ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 182 | COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base 183 | ${Coverage_NAME}.total 184 | ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned 185 | 186 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 187 | DEPENDS ${Coverage_DEPENDENCIES} 188 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 189 | ) 190 | 191 | # Show where to find the lcov info report 192 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 193 | COMMAND ; 194 | COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." 195 | ) 196 | 197 | # Show info where to find the report 198 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 199 | COMMAND ; 200 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 201 | ) 202 | 203 | endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV 204 | 205 | # Defines a target for running and collection code coverage information 206 | # Builds dependencies, runs the given executable and outputs reports. 207 | # NOTE! The executable should always have a ZERO as exit code otherwise 208 | # the coverage generation will not complete. 209 | # 210 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML( 211 | # NAME ctest_coverage # New target name 212 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 213 | # DEPENDENCIES executable_target # Dependencies to build first 214 | # ) 215 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) 216 | 217 | set(options NONE) 218 | set(oneValueArgs NAME) 219 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 220 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 221 | 222 | if(NOT SIMPLE_PYTHON_EXECUTABLE) 223 | message(FATAL_ERROR "python not found! Aborting...") 224 | endif() # NOT SIMPLE_PYTHON_EXECUTABLE 225 | 226 | if(NOT GCOVR_PATH) 227 | message(FATAL_ERROR "gcovr not found! Aborting...") 228 | endif() # NOT GCOVR_PATH 229 | 230 | # Combine excludes to several -e arguments 231 | set(GCOVR_EXCLUDES "") 232 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 233 | list(APPEND GCOVR_EXCLUDES "-e") 234 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") 235 | endforeach() 236 | 237 | add_custom_target(${Coverage_NAME} 238 | # Run tests 239 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 240 | 241 | # Running gcovr 242 | COMMAND ${GCOVR_PATH} --xml 243 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 244 | --object-directory=${PROJECT_BINARY_DIR} 245 | -o ${Coverage_NAME}.xml 246 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 247 | DEPENDS ${Coverage_DEPENDENCIES} 248 | COMMENT "Running gcovr to produce Cobertura code coverage report." 249 | ) 250 | 251 | # Show info where to find the report 252 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 253 | COMMAND ; 254 | COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." 255 | ) 256 | 257 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML 258 | 259 | # Defines a target for running and collection code coverage information 260 | # Builds dependencies, runs the given executable and outputs reports. 261 | # NOTE! The executable should always have a ZERO as exit code otherwise 262 | # the coverage generation will not complete. 263 | # 264 | # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML( 265 | # NAME ctest_coverage # New target name 266 | # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR 267 | # DEPENDENCIES executable_target # Dependencies to build first 268 | # ) 269 | function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) 270 | 271 | set(options NONE) 272 | set(oneValueArgs NAME) 273 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) 274 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 275 | 276 | if(NOT SIMPLE_PYTHON_EXECUTABLE) 277 | message(FATAL_ERROR "python not found! Aborting...") 278 | endif() # NOT SIMPLE_PYTHON_EXECUTABLE 279 | 280 | if(NOT GCOVR_PATH) 281 | message(FATAL_ERROR "gcovr not found! Aborting...") 282 | endif() # NOT GCOVR_PATH 283 | 284 | # Combine excludes to several -e arguments 285 | set(GCOVR_EXCLUDES "") 286 | foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) 287 | list(APPEND GCOVR_EXCLUDES "-e") 288 | list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") 289 | endforeach() 290 | 291 | add_custom_target(${Coverage_NAME} 292 | # Run tests 293 | ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} 294 | 295 | # Create folder 296 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} 297 | 298 | # Running gcovr 299 | COMMAND ${GCOVR_PATH} --html --html-details 300 | -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} 301 | --object-directory=${PROJECT_BINARY_DIR} 302 | -o ${Coverage_NAME}/index.html 303 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} 304 | DEPENDS ${Coverage_DEPENDENCIES} 305 | COMMENT "Running gcovr to produce HTML code coverage report." 306 | ) 307 | 308 | # Show info where to find the report 309 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD 310 | COMMAND ; 311 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." 312 | ) 313 | 314 | endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML 315 | 316 | function(APPEND_COVERAGE_COMPILER_FLAGS) 317 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 318 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) 319 | message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") 320 | endfunction() # APPEND_COVERAGE_COMPILER_FLAGS 321 | -------------------------------------------------------------------------------- /slides/lcov/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utility.hpp" 4 | int main(int argc, char** argv) { 5 | if (argc < 2) { 6 | return 1; 7 | } 8 | double x = std::atof(argv[1]); 9 | std::cout << signum(x) << '\n'; 10 | } 11 | -------------------------------------------------------------------------------- /slides/lcov/run_tests: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | BINARY_DIR="$1" 4 | 5 | $BINARY_DIR/app 6 | $BINARY_DIR/app 0 7 | $BINARY_DIR/app 1 8 | exit 0 9 | 10 | -------------------------------------------------------------------------------- /slides/lcov/signum.cpp: -------------------------------------------------------------------------------- 1 | #include "utility.hpp" 2 | int signum(double x) { 3 | if (x > 0) { 4 | return 1; 5 | } else if (x < 0) { 6 | return -1; 7 | } else { 8 | return 0; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /slides/lcov/utility.hpp: -------------------------------------------------------------------------------- 1 | int signum(double x); 2 | -------------------------------------------------------------------------------- /slides/modules/Makefile: -------------------------------------------------------------------------------- 1 | CMAKE_CONFIG_OPTIONS += -GNinja 2 | 3 | CMAKE_SUBDIRS = \ 4 | export_1 \ 5 | greet_1 \ 6 | greet_2 \ 7 | greet_3 \ 8 | linkage_1 \ 9 | math_1 \ 10 | math_2 \ 11 | module_1 \ 12 | reachability_1 \ 13 | reachability_2 \ 14 | 15 | .PHONY: all 16 | all: 17 | for subdir in $(CMAKE_SUBDIRS); do \ 18 | if [ ! -d $$subdir ]; then continue; fi; \ 19 | echo PROCESSING DIRECTORY: $$subdir; \ 20 | ( cd $$subdir && \ 21 | cmake -H. -Btmp_cmake $(CMAKE_CONFIG_OPTIONS) && \ 22 | cmake --build tmp_cmake \ 23 | ) || exit 1; \ 24 | done 25 | 26 | .PHONY: clean 27 | clean: 28 | for subdir in $(CMAKE_SUBDIRS); do \ 29 | if [ ! -d $$subdir ]; then continue; fi; \ 30 | ( cd $$subdir && rm -rf tmp_cmake ) || exit 1; \ 31 | done 32 | -------------------------------------------------------------------------------- /slides/modules/export_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(export_1 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | hg2g-m.cpp 11 | ) 12 | add_executable(app main.cpp) 13 | target_link_libraries(app lib) 14 | -------------------------------------------------------------------------------- /slides/modules/export_1/hg2g-m.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | export module hg2g; 4 | namespace hg2g { 5 | export using c42_t = char[42]; 6 | c42_t x; 7 | export struct depressed_tag {}; 8 | export template T constexpr forty_two{sizeof(x)}; 9 | export { 10 | std::string marvin{"paranoid"}; 11 | void panic() {throw 42;} 12 | } 13 | } 14 | export namespace hg2g { 15 | int get_answer() {return sizeof(x);} 16 | } 17 | export namespace h2g2 = hg2g; 18 | -------------------------------------------------------------------------------- /slides/modules/export_1/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | import hg2g; 3 | int main() try { 4 | std::cout << hg2g::get_answer() << ' ' << hg2g::marvin << '\n'; 5 | // auto x = hg2g::x[0]; // ERROR: x not visible 6 | if (!std::cout.flush()) {hg2g::panic();} 7 | } catch (...) {std::cerr << "Don't panic!\n";} 8 | -------------------------------------------------------------------------------- /slides/modules/greet_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(greet_1 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | greetings.cpp 11 | ) 12 | add_executable(greet greet.cpp) 13 | target_link_libraries(greet lib) 14 | -------------------------------------------------------------------------------- /slides/modules/greet_1/greet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | import greetings; 3 | 4 | int main() { 5 | std::cout << greetings::get_greeting() << std::endl; 6 | return !std::cout; 7 | } 8 | -------------------------------------------------------------------------------- /slides/modules/greet_1/greetings.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | export module greetings; 4 | 5 | namespace greetings { 6 | export std::string get_greeting() { 7 | return "Hello, World!"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /slides/modules/greet_2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(greet_2 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | greetings-m.cpp 11 | PRIVATE 12 | greetings.cpp 13 | ) 14 | add_executable(greet greet.cpp) 15 | target_link_libraries(greet lib) 16 | -------------------------------------------------------------------------------- /slides/modules/greet_2/greet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | import greetings; 3 | 4 | int main() { 5 | std::cout << greetings::get_greeting() << std::endl; 6 | return !std::cout; 7 | } 8 | -------------------------------------------------------------------------------- /slides/modules/greet_2/greetings-m.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | export module greetings; 4 | namespace greetings { 5 | export std::string get_greeting(); 6 | } 7 | -------------------------------------------------------------------------------- /slides/modules/greet_2/greetings.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | module greetings; 4 | namespace greetings { 5 | std::string get_greeting() { 6 | return "Hello, World!"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/greet_3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(greet_3 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | greetings-m.cpp 11 | greetings_en.cpp 12 | greetings_fr.cpp 13 | ) 14 | add_executable(greet greet.cpp) 15 | target_link_libraries(greet lib) 16 | -------------------------------------------------------------------------------- /slides/modules/greet_3/greet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | import greetings; 3 | 4 | int main() { 5 | std::cout << greetings::get_greeting_en() << '\n'; 6 | std::cout << greetings::get_greeting_fr() << '\n'; 7 | return !std::cout.flush(); 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/greet_3/greetings-m.cpp: -------------------------------------------------------------------------------- 1 | export module greetings; 2 | export import :english; 3 | export import :french; 4 | -------------------------------------------------------------------------------- /slides/modules/greet_3/greetings_en.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | export module greetings:english; 4 | export namespace greetings { 5 | std::string get_greeting_en() { 6 | return "Hello, World!"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/greet_3/greetings_fr.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | export module greetings:french; 4 | export namespace greetings { 5 | std::string get_greeting_fr() { 6 | return "Bonjour, Tout Le Monde!"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/linkage_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(linkage_1 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | sol-m.cpp 11 | PRIVATE 12 | sol.cpp 13 | ) 14 | add_executable(app main.cpp) 15 | target_link_libraries(app lib) 16 | -------------------------------------------------------------------------------- /slides/modules/linkage_1/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | import sol; 4 | 5 | int main() { 6 | std::cout << std::format("{}\n", sol::forty_two()); 7 | } 8 | -------------------------------------------------------------------------------- /slides/modules/linkage_1/sol-m.cpp: -------------------------------------------------------------------------------- 1 | export module sol; 2 | namespace { 3 | int x = 42; // x has internal linkage 4 | bool yes() {return true;} // yes has internal linkage 5 | } 6 | namespace sol { 7 | static int y = 0; // y has internal linkage 8 | int z = -1; // z has module linkage 9 | export inline constexpr int forty_two() {return 42;} 10 | // forty_two has external linkage 11 | int nil() {return 0;} // nil has module linkage 12 | export int value() {return forty_two() + nil();} 13 | // value has external linkage 14 | int foo() // foo has module linkage 15 | { 16 | struct S {}; // S has no linkage 17 | int i = 0; // i has no linkage 18 | return yes() + i + sizeof(S); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /slides/modules/linkage_1/sol.cpp: -------------------------------------------------------------------------------- 1 | module sol; 2 | namespace sol { 3 | inline constexpr int forty_two(); 4 | void blah() { 5 | ++z; 6 | int x = forty_two(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/math_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(math_1 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | math-m.cpp 11 | ) 12 | add_executable(app app.cpp) 13 | target_link_libraries(app lib) 14 | -------------------------------------------------------------------------------- /slides/modules/math_1/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | import zeus.math; 3 | 4 | int main() { 5 | std::cout << zeus::math::square(2.0) 6 | << ' ' << zeus::math::sinc(0.0) 7 | << ' ' << zeus::math::get_answer() << '\n'; 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/math_1/math-m.cpp: -------------------------------------------------------------------------------- 1 | module; // start of global module fragment 2 | #include 3 | export module zeus.math; // start of module unit purview 4 | 5 | namespace zeus::math { 6 | double answer = 42; 7 | export double sinc(double x) 8 | {return (x != 0) ? sin(x) / x : 1.0;} 9 | export double get_answer() {return answer;} 10 | export template T square(const T& x) 11 | {return x * x;} 12 | } 13 | -------------------------------------------------------------------------------- /slides/modules/math_2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(math_2 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | math-m.cpp 11 | PRIVATE 12 | math.cpp 13 | ) 14 | add_executable(app app.cpp) 15 | target_link_libraries(app lib) 16 | -------------------------------------------------------------------------------- /slides/modules/math_2/app.cpp: -------------------------------------------------------------------------------- 1 | // not module unit, since no module declaration 2 | #include 3 | import zeus.math; 4 | int main() { 5 | std::cout << zeus::math::square(2.0) << ' ' << zeus::math::sinc(0.0) 6 | << ' ' << zeus::math::get_answer() << '\n'; 7 | } 8 | -------------------------------------------------------------------------------- /slides/modules/math_2/math-m.cpp: -------------------------------------------------------------------------------- 1 | // no global module fragment 2 | // declare module interface unit 3 | export module zeus.math; // start of module unit purview 4 | namespace zeus::math { 5 | export double sinc(double); 6 | // note: must export template definition, not just declaration 7 | export template T square(const T& x) {return x * x;} 8 | export double get_answer(); 9 | double answer = 42; 10 | } 11 | -------------------------------------------------------------------------------- /slides/modules/math_2/math.cpp: -------------------------------------------------------------------------------- 1 | module; // start of global module fragment 2 | #include 3 | // declare module implementation unit 4 | module zeus.math; // start of module unit purview 5 | namespace zeus::math { 6 | double sinc(double x) {return (x != 0) ? sin(x) / x : 1.0;} 7 | double get_answer() {return answer;} 8 | } 9 | -------------------------------------------------------------------------------- /slides/modules/reachability_2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 2 | project(reachability_2 LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | add_library(lib) 8 | target_sources(lib 9 | PUBLIC FILE_SET CXX_MODULES FILES 10 | zeus-m.cpp 11 | ) 12 | add_executable(app main.cpp) 13 | target_link_libraries(app lib) 14 | -------------------------------------------------------------------------------- /slides/modules/reachability_2/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | import zeus; 3 | 4 | int main() { 5 | // zeus::int_point q; // ERROR: int_point not visible 6 | auto p = zeus::origin(); 7 | assert(p.x == 0 && p.y == 0); 8 | using point = decltype(p); 9 | point q; 10 | } 11 | -------------------------------------------------------------------------------- /slides/modules/reachability_2/zeus-m.cpp: -------------------------------------------------------------------------------- 1 | export module zeus; 2 | namespace zeus { 3 | struct int_point {int x; int y;}; 4 | export int_point origin() {return {0, 0};} 5 | } 6 | -------------------------------------------------------------------------------- /slides/tsan/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(slides_tsan LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED true) 6 | 7 | find_package(Threads REQUIRED) 8 | 9 | add_executable(data_race data_race.cpp) 10 | target_link_libraries(data_race Threads::Threads) 11 | 12 | add_executable(data_race_1 data_race_1.cpp) 13 | target_link_libraries(data_race_1 Threads::Threads) 14 | 15 | add_executable(data_race_2 data_race_2.cpp) 16 | target_link_libraries(data_race_2 Threads::Threads) 17 | 18 | add_executable(deadlock deadlock.cpp) 19 | target_link_libraries(deadlock Threads::Threads) 20 | -------------------------------------------------------------------------------- /slides/tsan/clipboard.txt: -------------------------------------------------------------------------------- 1 | Without TSan 2 | ============ 3 | 4 | cmake -S. -Btmp_cmake 5 | cmake --build tmp_cmake 6 | 7 | tmp_cmake/data_race_2 8 | tmp_cmake/data_race_1 9 | tmp_cmake/data_race 10 | tmp_cmake/deadlock # Note: May or may not actually deadlock. 11 | 12 | With TSan 13 | ========= 14 | 15 | CXX=g++ CXXFLAGS="-fsanitize=thread" cmake -S. -Btmp_cmake 16 | cmake --build tmp_cmake 17 | 18 | tmp_cmake/data_race_2 19 | TSAN_OPTIONS="halt_on_error=1 color=always" tmp_cmake/data_race_2 |& less -r 20 | 21 | tmp_cmake/data_race_1 22 | TSAN_OPTIONS="color=always" tmp_cmake/data_race_1 |& less -r 23 | 24 | tmp_cmake/data_race 25 | 26 | tmp_cmake/deadlock 27 | TSAN_OPTIONS="halt_on_error=1 color=always" tmp_cmake/deadlock |& less -r 28 | -------------------------------------------------------------------------------- /slides/tsan/data_race.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int x = 0; 3 | int main() { 4 | std::thread t([&]{x = 42;}); 5 | x = 43; 6 | t.join(); 7 | } 8 | -------------------------------------------------------------------------------- /slides/tsan/data_race_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int x = 0; 4 | void func() {x = 42;} 5 | int main() { 6 | std::thread t(func); 7 | std::cout << "Hello\n"; 8 | x = 43; 9 | t.join(); 10 | } 11 | -------------------------------------------------------------------------------- /slides/tsan/data_race_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | unsigned long long counter = 0; 5 | 6 | void func() { 7 | for (unsigned long long i = 0; i < 10'000'000; ++i) { 8 | ++counter; 9 | } 10 | } 11 | 12 | int main() { 13 | std::thread t1(func); 14 | std::thread t2(func); 15 | t1.join(); 16 | t2.join(); 17 | std::cout << counter << '\n'; 18 | } 19 | -------------------------------------------------------------------------------- /slides/tsan/deadlock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | std::mutex m0; 5 | std::mutex m1; 6 | void func1(int n) { 7 | for (auto i = n; i > 0; --i) { 8 | std::scoped_lock l0(m0); 9 | std::scoped_lock l1(m1); 10 | std::cout << "a\n"; 11 | } 12 | } 13 | void func2(int n) { 14 | for (auto i = n; i > 0; --i) { 15 | std::scoped_lock l1(m1); 16 | std::scoped_lock l0(m0); 17 | std::cout << "b\n"; 18 | } 19 | } 20 | int main() { 21 | std::thread t1([]{func1(10'000);}); 22 | std::thread t2([]{func2(10'000);}); 23 | t1.join(); t2.join(); 24 | } 25 | -------------------------------------------------------------------------------- /vim_lsp/examples/example_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Specify minimum required version of CMake. 2 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 3 | 4 | # Specify project and identify languages used. 5 | project(hello LANGUAGES CXX) 6 | 7 | # Generate a verbose makefile. 8 | set(CMAKE_VERBOSE_MAKEFILE TRUE) 9 | 10 | # Generate a compilation database file. 11 | set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) 12 | 13 | # Add program target called hello. 14 | add_executable(app app/main.cpp util/util.cpp) 15 | target_include_directories(app PRIVATE util) 16 | -------------------------------------------------------------------------------- /vim_lsp/examples/example_1/app/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.hpp" 3 | 4 | int main() { 5 | Counter c(41); 6 | ++c; 7 | std::cout << c.value() << '\n'; 8 | { 9 | Counter c(40); 10 | ++++c; 11 | std::cout << c.value() << '\n'; 12 | } 13 | int x = get_answer(); 14 | std::cout << x << '\n'; 15 | return !std::cout; 16 | } 17 | -------------------------------------------------------------------------------- /vim_lsp/examples/example_1/util/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | int get_answer() { 4 | return 42; 5 | } 6 | -------------------------------------------------------------------------------- /vim_lsp/examples/example_1/util/util.hpp: -------------------------------------------------------------------------------- 1 | #ifndef util_hpp 2 | #define util_hpp 3 | 4 | class Counter { 5 | public: 6 | using value_type = int; 7 | Counter(value_type value = 0) : value_(value) {} 8 | Counter& operator++() { 9 | ++value_; 10 | return *this; 11 | } 12 | value_type value() const { 13 | return value_; 14 | } 15 | private: 16 | value_type value_; 17 | }; 18 | 19 | int get_answer(); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /vim_lsp/examples/example_1/vimlsp.vim: -------------------------------------------------------------------------------- 1 | " Example Vim LSP user setup file .vimrc-vimlsp 2 | 3 | let g:lsp_diagnostics_signs_enabled = 1 4 | let g:lsp_diagnostics_signs_error = {'text': '🗙'} 5 | let g:lsp_diagnostics_signs_warning = {'text': '⚠️'} 6 | let g:lsp_diagnostics_signs_hint = {'text': '💡'} 7 | let g:lsp_diagnostics_signs_information = {'text': '🛈'} 8 | 9 | let g:lsp_diagnostics_enabled = 1 10 | let g:lsp_diagnostics_echo_cursor = 0 11 | let g:lsp_diagnostics_float_cursor = 1 12 | 13 | let g:lsp_document_code_action_signs_enabled = 1 14 | let g:lsp_document_code_action_signs_hint = {'text': 'Ⓐ'} 15 | 16 | " invoke sde_lsp_cpp_setup for C and C++ source files 17 | autocmd FileType c,cpp call s:sde_lsp_cpp_setup() 18 | 19 | function s:sde_lsp_cpp_setup() 20 | 21 | nmap gd :below LspDefinition 22 | nmap gs :LspDocumentSymbolSearch 23 | nmap gS :LspWorkspaceSymbolSearch 24 | nmap gr :LspReferences 25 | nmap gi :below LspImplementation 26 | nmap gt :below LspTypeDefinition 27 | nmap rn :LspRename 28 | nmap [g :LspPreviousDiagnostic 29 | nmap ]g :LspNextDiagnostic 30 | nmap K :LspHover 31 | nnoremap lsp#scroll(+4) 32 | nnoremap lsp#scroll(-4) 33 | 34 | "inoremap pumvisible() ? "\" : "\" 35 | "inoremap pumvisible() ? "\" : "\" 36 | "inoremap pumvisible() ? "\" : "\" 37 | "imap (asyncomplete_force_refresh) 38 | 39 | endfunction 40 | -------------------------------------------------------------------------------- /vim_lsp/examples/example_1/vimrc: -------------------------------------------------------------------------------- 1 | " Example .vimrc for use with Vim LSP 2 | 3 | :filetype on 4 | au FileType * setl fo-=cro 5 | 6 | " Do not automatically paste text as if in insert mode. 7 | :set t_BE= 8 | 9 | " Uncomment the following line to set the leader key to a comma. 10 | " let mapleader="," 11 | 12 | " Configuration for Vim LSP 13 | let g:system_vimlsp_file = expand('~/.vim/misc/sde/vim-lsp.vim') 14 | let g:user_vimlsp_file = expand('~/.vimrc-vimlsp') 15 | if filereadable(g:system_vimlsp_file) 16 | :execute ':so' g:system_vimlsp_file 17 | let g:lsp_log_verbose = 1 18 | let g:lsp_log_file = expand('~/.vim-lsp.log') 19 | if filereadable(g:user_vimlsp_file) 20 | :execute ':so' g:user_vimlsp_file 21 | endif 22 | endif 23 | -------------------------------------------------------------------------------- /ycm/examples/example_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | 3 | project(simple LANGUAGES CXX) 4 | 5 | # Enable verbose makefiles. 6 | set(CMAKE_VERBOSE_MAKEFILE ON) 7 | 8 | # Generate compilation database file. 9 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 10 | 11 | add_executable(app app.cpp) 12 | -------------------------------------------------------------------------------- /ycm/examples/example_1/app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.hpp" 3 | 4 | int main() 5 | { 6 | double x; 7 | while (std::cin >> x) { 8 | auto y = square(x); 9 | std::cout << y << '\n'; 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /ycm/examples/example_1/util.hpp: -------------------------------------------------------------------------------- 1 | template 2 | inline T square(const T& x) 3 | { 4 | return x * x; 5 | } 6 | -------------------------------------------------------------------------------- /ycm/examples/example_1/vimrc: -------------------------------------------------------------------------------- 1 | :filetype on 2 | 3 | " Do not automatically paste text as if in insert mode. 4 | :set t_BE= 5 | 6 | " Uncomment the following line to set the leader key to a comma. 7 | " let mapleader="," 8 | 9 | " Configuration for YCM 10 | if isdirectory(expand('~/.vim/pack/sde/start/YouCompleteMe')) 11 | :execute ':so' expand('~/.vimrc-ycm') 12 | endif 13 | -------------------------------------------------------------------------------- /ycm/examples/example_1/ycm.vim: -------------------------------------------------------------------------------- 1 | " Example of user YCM setup .vimrc-ycm 2 | 3 | nnoremap :YcmForceCompileAndDiagnostics 4 | 5 | nnoremap dd :YcmDiags GoTo 6 | nnoremap yt :YcmCompleter GetType 7 | nnoremap yg :YcmCompleter GoTo 8 | nnoremap yd :YcmCompleter GoToDeclaration 9 | nnoremap yD :YcmCompleter GoToDefinition 10 | nnoremap yi :YcmCompleter GoToInclude 11 | nnoremap yf :YcmCompleter FixIt 12 | --------------------------------------------------------------------------------