TurtleSec
@pati_gallardo
Turtle
Sec
@pati_gallardo
TurtleSec
@pati_gallardo
Dependency
Management in C++
TechTown 2021
Patricia Aas
Turtle
Sec
TurtleSec
@pati_gallardo
Patricia Aas - Trainer & Consultant
C++ Programmer, Application Security
Currently : TurtleSec
Previously : Vivaldi, Cisco Systems, Knowit, Opera Software
Master in Computer Science
Pronouns: she/her Turtle
Sec
TurtleSec
@pati_gallardo 4
Which ones?
Conan
Fetch Content
vcpkg
CPM
TurtleSec
@pati_gallardo 5
Why
Dependency
Management?
TurtleSec
@pati_gallardo 6
Heartbleed
TurtleSec
@pati_gallardo
TurtleSec
@pati_gallardo 7
● Do you know which version of OpenSSL is running in
all your products?
● Could you update it if needed?
● Even in products that are deployed?
● What if it is a transitive dependency?
● What if you have multiple versions of it?
● Do you know?
The Problem
TurtleSec
@pati_gallardo 8
TurtleSec
@pati_gallardo
Order
TurtleSec
@pati_gallardo 9
● If you copy a dependency in it is yours now
● All vulnerabilities that are discovered will be in your
fork
● Are you on top of patches?
● How will you upgrade?
Copy Pasting Code
TurtleSec
@pati_gallardo
@pati_gallardo 10
TurtleSec
Demo Project
TurtleSec
@pati_gallardo 11
● Works with CMake
● Can be "easily" replaced
● Has key dependencies
● Can be invoked from CMake
● Is maintained
Requirements for
Dependency Manager
TurtleSec
@pati_gallardo
Package Management
vs
Dependency Management
12
TurtleSec
@pati_gallardo 13
● What is reasonable for you to build from source?
● What is not?
● Is that line at “system SDK”?
● Depends vs Build-depends - build time vs runtime
dependencies
What is a “system SDK”?
TurtleSec
@pati_gallardo 14
The code doesn't really matter, it just needs to be:
● Non-trivial
● Require non-trivial dependencies
● Compile
The code
TurtleSec
@pati_gallardo 15
● Renders a window using SFML
● Logs to the console using fmt
● Has a test using Catch2
The features
TurtleSec
@pati_gallardo 16
Project Structure
📂 project
📂 src
CMakeLists.txt
main.cpp
📂 test
CMakeLists.txt
test.cpp
CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 17
main.cpp
src/main.cpp
1. #include <fmt/format.h>
2. #include <SFML/Graphics.hpp>
3.
4. int main() {
5. fmt::print("Hello {}n", "Project");
6. sf::RenderWindow window(sf::VideoMode(800, 600), "Hello Project");
7. while (window.isOpen()) {
8. sf::Event event;
9. while (window.pollEvent(event)) {
10. if (event.type == sf::Event::Closed)
11. window.close();
12. }
13. window.clear();
14. window.display();
15. }
16. return EXIT_SUCCESS;
17. }
TurtleSec
@pati_gallardo 18
Project Structure
📂 project
📂 src
CMakeLists.txt
main.cpp
📂 test
CMakeLists.txt
test.cpp
CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 19
test.cpp
src/test.cpp
1. #define CATCH_CONFIG_MAIN
2. #include <catch2/catch.hpp>
3.
4. TEST_CASE("tests_conan", "[conan]") {
5. REQUIRE(true);
6. }
TurtleSec
@pati_gallardo 20
Project Structure
📂 project
📂 src
CMakeLists.txt
main.cpp
📂 test
CMakeLists.txt
test.cpp
CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 21
1. cmake_minimum_required(VERSION 3.19.2)
2.
3. project(project_name
4. VERSION "0.1.1"
5. DESCRIPTION "Some description"
6. LANGUAGES CXX)
7. set(CMAKE_CXX_STANDARD 17)
8. set(CMAKE_CXX_STANDARD_REQUIRED ON)
9.
10. enable_testing()
11. add_subdirectory(src)
12. add_subdirectory(test)
CMakeLists.txt
Root CMakeLists.txt
TurtleSec
@pati_gallardo 22
● SFML - version 2.5.1 - GUI
● Catch2 - version 2.13.7 - test framework
● {fmt} - version 8.0.1 - logging
The dependencies
TurtleSec
@pati_gallardo 23
Project Structure
📂 project
📂 src
CMakeLists.txt
main.cpp
📂 test
CMakeLists.txt
test.cpp
CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 24
1. find_package(SFML COMPONENTS
2. audio graphics system window
3. CONFIG REQUIRED)
4. find_package(fmt CONFIG REQUIRED)
5.
6. add_executable(sfml_program main.cpp)
7. target_link_libraries(sfml_program PUBLIC
8. fmt::fmt
9. SFML::audio
10. SFML::graphics
11. SFML::system
12. SFML::window)
CMakeLists.txt
src/CMakeLists.txt
TurtleSec
@pati_gallardo 25
Project Structure
📂 project
📂 src
CMakeLists.txt
main.cpp
📂 test
CMakeLists.txt
test.cpp
CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 26
1. find_package(Catch2 REQUIRED)
2.
3. add_executable(tests test.cpp)
4. target_link_libraries(tests Catch2::Catch2)
5.
6. add_test(NAME tests COMMAND tests)
CMakeLists.txt
test/CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 27
name: CMake
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
build:
name: "${{ matrix.conf.name }} | ${{ matrix.cmake-build-type }}"
runs-on: ${{ matrix.conf.os }}
defaults:
run:
working-directory: <sub_project>
strategy:
fail-fast: false
matrix:
conf:
- name: Ubuntu Latest
os: ubuntu-latest
- name: MacOS Latest
os: macos-latest
- name: Windows Latest
os: windows-latest
cmake-build-type: [ Debug, Release ]
steps:
- uses: actions/checkout@v2
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{ matrix.cmake-build-type }}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{ matrix.cmake-build-type }}
- name: Test
working-directory: ${{github.workspace}}/build
run: ctest -C ${{ matrix.cmake-build-type }}
TurtleSec
GitHub Action
Workflow
Framework
TurtleSec
@pati_gallardo
@pati_gallardo 28
TurtleSec
Meta Project
TurtleSec
@pati_gallardo 29
Meta Project - Depend On Me
📂 depend_on_me
📁 conan_project
📁 cpm_project
📁 fetch_content_project
📁 vcpkg_project
CMakeLists.txt
TurtleSec
TurtleSec
@pati_gallardo 30
Conan - JFrog
● Has a lot of dependencies
● Supports a lot of configuration
● Actively supported
● Recent versions
TurtleSec
@pati_gallardo
@pati_gallardo 31
1. cmake_minimum_required(VERSION 3.19.2)
2.
3. project(depend_on_me_conan
4. VERSION "0.1.1"
5. DESCRIPTION "Some description"
6. LANGUAGES CXX)
7.
8. set(CMAKE_CXX_STANDARD 17)
9. set(CMAKE_CXX_STANDARD_REQUIRED ON)
10.
11. include(setup_conan.cmake)
12.
13. add_subdirectory(src)
14. add_subdirectory(test)
CMakeLists.txt
Conan Root CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 32
1. set(ENV{CONAN_SYSREQUIRES_MODE} enabled)
2. if (NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
3. file(DOWNLOAD
4. "https://github.com/conan-io/cmake-conan/raw/v0.16.1/conan.cmake"
5. "${CMAKE_BINARY_DIR}/conan.cmake")
6. endif ()
7.
8. include(${CMAKE_BINARY_DIR}/conan.cmake)
9.
10. conan_check(REQUIRED)
11. conan_cmake_autodetect(settings)
12. conan_cmake_install(PATH_OR_REFERENCE
13. ${CMAKE_CURRENT_SOURCE_DIR}/conanfile.txt
14. BUILD missing
15. SETTINGS ${settings})
16.
17. set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
setup_conan.cmake
TurtleSec
@pati_gallardo
@pati_gallardo 33
1. [requires]
2. sfml/2.5.1
3. catch2/2.13.7
4. fmt/8.0.1
5.
6. [options]
7. sfml:audio=True
8. sfml:graphics=True
9. sfml:window=True
10.
11. [generators]
12. cmake
13. cmake_multi
14. cmake_paths
15. cmake_find_package
16. cmake_find_package_multi
conanfile.txt
Conan conanfile.txt
TurtleSec
@pati_gallardo
@pati_gallardo 34
1. find_package(SFML COMPONENTS
2. audio graphics system window
3. CONFIG REQUIRED)
4. find_package(fmt CONFIG REQUIRED)
5.
6. add_executable(sfml_program main.cpp)
7. target_link_libraries(sfml_program PUBLIC
8. fmt::fmt
9. SFML::audio
10. SFML::graphics
11. SFML::system
12. SFML::window)
conan_project/src/CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 35
1. jobs:
2. build:
3. env:
4. CONAN_SYSREQUIRES_MODE: enabled
5. CONAN_USER_HOME: "${{ github.workspace }}/CONAN_CACHE"
6. CONAN_USER_HOME_SHORT: "${{ github.workspace }}/CONAN_CACHE/short"
7. # ...
8. - name: Cache Conan
9. uses: actions/cache@v2
10. env:
11. cache-name: conan-modules
12. with:
13. path: ${{ env.CONAN_USER_HOME }}
14. key: ${{ matrix.conf.os }}-${{ matrix.cmake-build-type }}-${{ hashFiles('conan_project/conanfile.txt') }}
15.
16. - name: remove Conan's installation registry
17. run: conan remove --system-reqs '*'
18. # ...
19. - name: remove Conan's installation registry
20. run: conan remove --system-reqs '*'
cmake_conan.yml
Conan GitHub Action Caching
TurtleSec
@pati_gallardo 36
Meta Project - Depend On Me
📂 depend_on_me
📁 conan_project
📁 cpm_project
📁 fetch_content_project
📁 vcpkg_project
CMakeLists.txt
TurtleSec
TurtleSec
@pati_gallardo 37
CPM
● Built on FetchContent
● Can't use find_package
TurtleSec
@pati_gallardo
@pati_gallardo 38
1. cmake_minimum_required(VERSION 3.19.2)
2.
3. project(depend_on_me_cpm
4. VERSION "0.1.1"
5. DESCRIPTION "Some description"
6. LANGUAGES CXX)
7. set(CMAKE_CXX_STANDARD 14) # SFML uses std::auto_ptr
8. set(CMAKE_CXX_STANDARD_REQUIRED ON)
9.
10. include(setup_cpm.cmake)
11.
12. enable_testing()
13. add_subdirectory(src)
14. add_subdirectory(test)
CMakeLists.txt
CPM Root CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo
1. if (NOT EXISTS "${CMAKE_BINARY_DIR}/CPM.cmake")
2. file(DOWNLOAD
3. "https://github.com/cpm-cmake/CPM.cmake/raw/v0.34.0/cmake/CPM.cmake"
4. "${CMAKE_BINARY_DIR}/CPM.cmake")
5. endif ()
6.
7. include(${CMAKE_BINARY_DIR}/CPM.cmake)
8.
9. CPMAddPackage("gh:catchorg/Catch2#v2.13.7")
10. CPMAddPackage("gh:fmtlib/fmt#8.0.1")
11. CPMAddPackage("gh:SFML/SFML#2.5.1")
setup_cpm.cmake
CPM setup_cpm.cmake
39
TurtleSec
@pati_gallardo
@pati_gallardo 40
1. add_executable(sfml_program main.cpp)
2. target_link_libraries(sfml_program PUBLIC
3. fmt::fmt
4. sfml-audio
5. sfml-graphics
6. sfml-system
7. sfml-window)
cpm_project/src/CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 41
1. # ...
2. - name: Cache CPM build folder
3. uses: actions/cache@v2
4. env:
5. cache-name: cpm-modules
6. with:
7. path: ${{runner.workspace}}/depend_on_me/build/_deps
8. key: ${{matrix.conf.os}}-${{matrix.cmake-build-type}}-${{hashFiles('cpm_project/CMakeLists.txt')}}
9. # ...
cmake_cpm.yml
CPM GitHub Action Caching
TurtleSec
@pati_gallardo 42
Meta Project - Depend On Me
📂 depend_on_me
📁 conan_project
📁 cpm_project
📁 fetch_content_project
📁 vcpkg_project
CMakeLists.txt
TurtleSec
TurtleSec
@pati_gallardo 43
Fetch Content - CMake Kitware
● Can't use find_package
TurtleSec
@pati_gallardo
@pati_gallardo 44
1. cmake_minimum_required(VERSION 3.19.2)
2.
3. project(depend_on_me_fetch_content
4. VERSION "0.1.1"
5. DESCRIPTION "Some description"
6. LANGUAGES CXX)
7. set(CMAKE_CXX_STANDARD 14) # SFML uses std::auto_ptr
8. set(CMAKE_CXX_STANDARD_REQUIRED ON)
9.
10. include(setup_fetch_content.cmake)
11.
12. enable_testing()
13. add_subdirectory(src)
14. add_subdirectory(test)
CMakeLists.txt
Fetch Content Root CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 45
1. include(FetchContent)
2.
3. FetchContent_Declare(Catch2
4. GIT_REPOSITORY https://github.com/catchorg/Catch2.git
5. GIT_TAG v2.13.7)
6. FetchContent_MakeAvailable(Catch2)
7.
8. FetchContent_Declare(fmt
9. GIT_REPOSITORY https://github.com/fmtlib/fmt.git
10. GIT_TAG 8.0.1)
11. FetchContent_MakeAvailable(fmt)
12.
13. FetchContent_Declare(SFML
14. GIT_REPOSITORY https://github.com/SFML/SFML.git
15. GIT_TAG 2.5.1)
16. FetchContent_MakeAvailable(SFML)
setup_fetch_content.cmake
TurtleSec
@pati_gallardo
@pati_gallardo 46
1. add_executable(sfml_program main.cpp)
2. target_link_libraries(sfml_program PUBLIC
3. fmt::fmt
4. sfml-audio
5. sfml-graphics
6. sfml-system
7. sfml-window)
fetch_content_project/src/CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 47
1. # ...
2. - name: Cache FetchContent build folder
3. uses: actions/cache@v2
4. env:
5. cache-name: fetch-content-modules
6. with:
7. path: ${{runner.workspace}}/depend_on_me/build/_deps
8. key: ${{matrix.conf.os}}-${{matrix.cmake-build-type}}-${{hashFiles('fetch_content_project/CMakeLists.txt')}}
9. # ...
cmake_fetch_content.yml
Fetch Content
GitHub Action Caching
TurtleSec
@pati_gallardo 48
Meta Project - Depend On Me
📂 depend_on_me
📁 conan_project
📁 cpm_project
📁 fetch_content_project
📁 vcpkg_project
CMakeLists.txt
TurtleSec
TurtleSec
@pati_gallardo 49
vcpkg - Microsoft
● We're using FetchConent to get vcpkg
● We're not specifying version
● Upcoming feature?
TurtleSec
@pati_gallardo
@pati_gallardo 50
1. cmake_minimum_required(VERSION 3.19.2)
2.
3. include(setup_vcpkg.cmake)
4.
5. project(depend_on_me_vcpkg
6. VERSION "0.1.1"
7. DESCRIPTION "Some description"
8. LANGUAGES CXX)
9. set(CMAKE_CXX_STANDARD 17)
10. set(CMAKE_CXX_STANDARD_REQUIRED ON)
11.
12. enable_testing()
13. add_subdirectory(src)
14. add_subdirectory(test)
CMakeLists.txt
vcpkg Root CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 51
1. include(FetchContent)
2. FetchContent_Declare(
3. vcpkg
4. GIT_REPOSITORY https://github.com/microsoft/vcpkg
5. GIT_TAG 5568f110b509a9fd90711978a7cb76bae75bb092 # 2021.05.12
6. )
7.
8. if (NOT DEFINED CMAKE_TOOLCHAIN_FILE)
9. FetchContent_GetProperties(vcpkg
10. POPULATED vcpkg_POPULATED
11. SOURCE_DIR vcpkg_SOURCE_DIR)
12. if (NOT vcpkg_POPULATED)
13. FetchContent_Populate(vcpkg)
14. endif ()
15.
16. set(CMAKE_TOOLCHAIN_FILE
17. "${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake")
18. endif ()
setup_vcpkg.cmake
TurtleSec
@pati_gallardo
@pati_gallardo 52
1. {
2. "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
3. "name": "depend-on-me",
4. "version": "0.1",
5. "dependencies": [
6. "sfml",
7. "fmt",
8. "catch2"
9. ]
10. }
vcpkg.json
vcpkg vcpkg.json
TurtleSec
@pati_gallardo
@pati_gallardo 53
1. find_package(SFML COMPONENTS audio graphics system window CONFIG REQUIRED)
2. find_package(fmt CONFIG REQUIRED)
3.
4. if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
5. find_package(OpenGL REQUIRED COMPONENTS OpenGL GLX)
6. endif ()
7.
8. add_executable(sfml_program main.cpp)
9. target_link_libraries(sfml_program PUBLIC
10. fmt::fmt
11. sfml-audio
12. sfml-graphics
13. sfml-system
14. sfml-window)
15.
16. if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
17. target_link_libraries(sfml_program PUBLIC OpenGL::OpenGL OpenGL::GLX)
18. endif ()
vcpkg_project/src/CMakeLists.txt
TurtleSec
@pati_gallardo
@pati_gallardo 54
1. # ...
2. - name: Cache vcpkg
3. uses: actions/cache@v2
4. env:
5. cache-name: vcpkg-modules
6. with:
7. path: |
8. ${{runner.workspace}}/depend_on_me/build/vcpkg_installed
9. ${{runner.workspace}}/depend_on_me/build/_deps
10. key: ${{matrix.conf.os}}-${{matrix.cmake-build-type}}-${{hashFiles('vcpkg_project/vcpkg.json')}}
11. # ...
cmake_vcpkg.yml
vcpkg GitHub Action Caching
TurtleSec
@pati_gallardo 55
Meta Project - Future Work
📂 depend_on_me/unfinished
📁 conda_project
📁 external_project
📁 hunter_project
📁 ???
TurtleSec
TurtleSec
@pati_gallardo 56
Upgrading
is not
enough
TurtleSec
@pati_gallardo 57
● Do you know all of your dependencies?
● Do you know their versions?
● Do you know if they have known vulnerabilities?
● Can you rebuild everything you support?
● Can you ship to all your users?
Problems
TurtleSec
@pati_gallardo 58
We need
integration with
dependency scanners
TurtleSec
@pati_gallardo 59
TurtleSec
@pati_gallardo
"Order"
TurtleSec
@pati_gallardo
Turtle
Sec
@pati_gallardo

Dependency Management in C++ (NDC TechTown 2021)