Posted on

Accessing AWS (S3) from C++ under CMake

I wanted to start using the AWS SDK from a native app with the least amount of friction to simplify porting it to other platforms and thought about sharing it in case it’s of use to others.

Rationale

Whilst Amazon provide a CMake find module to locate the AWS SDK’s libs and headers those libs and headers need to be installed on the system and platform-specific steps to do that are described (at the time of writing) in the AWS docs as a precursor to finding it using CMake. The process however could be simplified by instead performing the SDK build and installation within CMake itself as part of your app’s project using CMake’s ExternalProject support. By performing the initial SDK fetch and install in CMake you can trivialise the move to other platforms given the entire app build (app + SDK) is now managed by CMake. Potentially the Amazon provided CMake find module could also be discarded (as we control what we are building and where we are building it to – i.e. a project specific build directory that we control as part of our project’s CMake file vs. the entire system).

Integrating the AWS SDK with CMake

The snippet below will download, build and then link in the minimum required AWS SDK libraries to perform S3 access in C++ from an app using this approach. The CMake code below describes an app (example_AWS) that has a single source file (example.cpp) the source code of which is left as an exercise for the reader (there are plenty of s3 examples in Amazon’s SDK documentation linked to below).

Include(ExternalProject)

# Build AWS SDK for s3
ExternalProject_Add(aws-sdk
    PREFIX              ${CMAKE_BINARY_DIR}/aws-sdk
    GIT_REPOSITORY      https://github.com/aws/aws-sdk-cpp.git
    UPDATE_COMMAND      ""
    CONFIGURE_COMMAND ${CMAKE_COMMAND} "-G${CMAKE_GENERATOR}" 
    -DBUILD_ONLY=s3
    -DBUILD_SHARED_LIBS=ON
    -DCMAKE_SOURCE_DIR:PATH=<SOURCE_DIR>
    -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
    -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
    -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
    -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
    -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
)
ExternalProject_Get_Property(aws-sdk INSTALL_DIR)
add_library(aws-sdk::core SHARED IMPORTED)
add_library(aws-sdk::s3   SHARED IMPORTED)
set_target_properties(aws-sdk::core PROPERTIES IMPORTED_LOCATION ${INSTALL_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}aws-cpp-sdk-core${CMAKE_SHARED_LIBRARY_SUFFIX})
set_target_properties(aws-sdk::s3   PROPERTIES IMPORTED_LOCATION ${INSTALL_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}aws-cpp-sdk-s3${CMAKE_SHARED_LIBRARY_SUFFIX})
set(AWS_INCLUDE_DIRS ${INSTALL_DIR}/include)
set(AWS_LIBS         aws-sdk::s3 aws-sdk::core)
include_directories(SYSTEM ${AWS_INCLUDE_DIRS})

# Build our project (that uses s3)
SET(SOURCES
    example.cpp
)

SET(HEADERS
)

set(PROJECT_NAME example_AWS)
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
add_dependencies(${PROJECT_NAME} aws-sdk)
target_link_libraries(${PROJECT_NAME} ${AWS_LIBS})
if(APPLE)
    set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "@executable_path")
endif()

NB. If you’re cross-compiling then you’ll need to provide the CMAKE_TOOLCHAIN_FILE and any toolchain specific arguments to the CONFIGURE_COMMAND above (i.e. CMAKE_TOOLCHAIN_FILE=path/to/my/tool_chain_file.cmake). 

Accessing S3

From here you can now follow the S3 examples provided by Amazon:

Amazon S3 code examples

 

Leave a Reply

Your email address will not be published. Required fields are marked *