Skip to content

Commit fe35240

Browse files
committed
Update documentation & examples
1 parent 96d7844 commit fe35240

21 files changed

Lines changed: 923 additions & 193 deletions

.clang-format

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ KeepEmptyLinesAtTheStartOfBlocks: true
3333
MacroBlockBegin: ''
3434
MacroBlockEnd: ''
3535
MaxEmptyLinesToKeep: 1
36-
PenaltyBreakAssignment: 2
37-
PenaltyBreakBeforeFirstCallParameter: 19
38-
PenaltyBreakComment: 300
39-
PenaltyBreakFirstLessLess: 120
40-
PenaltyBreakString: 1000
36+
PenaltyBreakComment: 10
37+
PenaltyBreakAssignment: 20
38+
PenaltyBreakString: 30
39+
PenaltyBreakBeforeFirstCallParameter: 35
40+
PenaltyBreakFirstLessLess: 40
4141
PenaltyExcessCharacter: 1000000
4242
PenaltyReturnTypeOnItsOwnLine: 100000
4343
PointerAlignment: Left

.clang-tidy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ HeaderFilterRegex: ''
55
FormatStyle: 'none'
66
CheckOptions:
77
- key: modernize-pass-by-value.ValuesOnly
8-
value: '1',
8+
value: '1'
99
- key: readability-implicit-bool-conversion.AllowPointerConditions
10-
value: '1',
10+
value: '1'
1111
- key: readability-implicit-bool-conversion.AllowIntegerConditions
1212
value: '1'
1313

CMakeLists.txt

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ check_cxx_source_compiles("
1111
#include <execinfo.h>
1212
1313
int main() {
14-
void *buffer[5];
15-
int nptrs = backtrace(buffer, 5);
16-
char **strings = backtrace_symbols(buffer, nptrs);
14+
void *buffer[5];
15+
int nptrs = backtrace(buffer, 5);
16+
char **strings = backtrace_symbols(buffer, nptrs);
1717
18-
return !!strings;
19-
}" HAVE_BACKTRACE)
18+
return !!strings;
19+
}" HAVE_BACKTRACE)
2020

2121

22-
check_cxx_compiler_flag("-flto" LTO_CAPABLE)
22+
check_cxx_compiler_flag("-Wl,-flto" LTO_CAPABLE)
2323

2424
add_library(${PROJECT_NAME}
2525
"src/logging.cpp"
@@ -54,18 +54,28 @@ else ()
5454
target_compile_definitions(${PROJECT_NAME} PRIVATE "-DAWS_LAMBDA_LOG=0")
5555
endif()
5656

57-
if (${LTO_CAPABLE})
57+
if ((BUILD_SHARED_LIBS) AND (LTO_CAPABLE))
5858
target_compile_options(${PROJECT_NAME} PRIVATE "-flto")
5959
target_link_libraries(${PROJECT_NAME} PRIVATE "-flto")
6060
endif()
6161

6262
target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_11")
6363

64+
#tests
65+
if (DISABLE_TESTS)
66+
add_subdirectory(tests/resources)
67+
else()
68+
enable_testing()
69+
add_subdirectory(tests)
70+
endif()
71+
6472
# installation
65-
install(FILES
66-
"include/aws/lambda-runtime/runtime.h"
73+
install(FILES "include/aws/lambda-runtime/runtime.h"
6774
DESTINATION "include/aws/lambda-runtime")
6875

76+
install(FILES "include/aws/logging/logging.h"
77+
DESTINATION "include/aws/logging")
78+
6979
install(TARGETS ${PROJECT_NAME}
7080
EXPORT ${PROJECT_NAME}-targets
7181
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
@@ -74,7 +84,7 @@ install(TARGETS ${PROJECT_NAME}
7484

7585
configure_file("${CMAKE_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake"
7686
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
77-
@ONLY)
87+
@ONLY)
7888

7989
export(EXPORT "${PROJECT_NAME}-targets" NAMESPACE AWS::)
8090

@@ -85,3 +95,6 @@ install(EXPORT "${PROJECT_NAME}-targets"
8595
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
8696
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/${PROJECT_NAME}/cmake/")
8797

98+
install(PROGRAMS "${CMAKE_SOURCE_DIR}/packaging/packager"
99+
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/${PROJECT_NAME}/cmake/")
100+

README.md

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,141 @@
1-
## AWS Lambda Cpp Runtime
1+
## AWS Lambda C++ Runtime
22

33
C++ implementation of the lambda runtime API
44

5-
## License
5+
## Building The Runtime
6+
Since AWS Lambda runs on GNU/Linux, you should build this runtime library and your logic on GNU/Linux as well.
7+
8+
9+
Using CMake, run the following commands:
10+
```cmake
11+
$ git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git
12+
$ cd aws-lambda-cpp-runtime
13+
$ mkdir build
14+
$ cd build
15+
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=~/lambda-install
16+
$ make && make install
17+
```
18+
19+
To consume this library in a project that is also using CMake, you would do:
20+
21+
```cmake
22+
cmake_minimum_required(VERSION 3.5)
23+
set(CMAKE_CXX_STANDARD 11)
24+
project(demo LANGUAGES CXX)
25+
find_package(aws-lambda-runtime)
26+
add_executable(${PROJECT_NAME} "main.cpp")
27+
target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-lambda-runtime)
28+
target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_11")
29+
target_compile_options(${PROJECT_NAME} PRIVATE "-Wall" "-Wextra")
30+
31+
# this line creates a target that packages your binary and zips it up
32+
aws_lambda_package_target(${PROJECT_NAME})
33+
```
34+
35+
And here is how a sample `main.cpp` would look like for example:
36+
```cpp
37+
#include <aws/lambda-runtime/runtime.h>
38+
39+
using namespace aws::lambda_runtime;
40+
41+
static invocation_response my_handler(invocation_request const& req)
42+
{
43+
if (req.payload.length() > 42) {
44+
return invocation_response::failure("error message here"/*error_message*/, "error type here" /*error_type*/);
45+
}
46+
47+
return invocation_response::success("json payload here" /*payload*/, "application/json" /*MIME type*/);
48+
}
49+
50+
int main()
51+
{
52+
run_handler(my_handler);
53+
return 0;
54+
}
55+
```
56+
57+
And finally, here's how you would package it all and send it to AWS Lambda. Run the following commands
58+
from your application's root directory:
59+
60+
```bash
61+
$ mkdir build
62+
$ cd build
63+
$ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=~/lambda-install
64+
$ make
65+
$ make aws-lambda-package-demo
66+
```
67+
The last command above `make aws-lambda-package-demo` will create a zip file called `demo.zip` in the current directory.
68+
69+
Using the aws CLI, create a lambda function that uses that zip file as such:
670

71+
```bash
72+
$ aws lambda create-function --function-name demo \
73+
--role <specify role arn here> \
74+
--runtime provided --timeout 15 --memory-size 128 \
75+
--handler demo --zip-file fileb://demo.zip
76+
```
77+
78+
And to invoke the function:
79+
```bash
80+
$ aws lambda invoke --function-name demo --payload '{"answer":42}' output.txt
81+
```
82+
83+
## Using the C++ SDK for AWS with this runtime
84+
This library is completely independent from the AWS C++ SDK. You should treat the AWS C++ SDK as just another dependency in your application.
85+
This is a [detailed example](https://github.com/awslabs/aws-lambda-cpp-runtime/examples/README.md) of using the AWS C++ SDK with this Lambda runtime.
86+
87+
## Supported Compilers
88+
We've tested with Clang & GCC but in theory any *fully* compliant C++11 compiler targeting GNU/Linux x86-64 should work.
89+
90+
## Packaging, ABI, GNU C Library, Oh My!
91+
Lambda runs your code on some version of Amazon Linux. It would be a less than ideal customer experience if you are forced to build your application on that platform and that platform only.
92+
93+
However, the freedom to build on any linux distro brings a challenge. The GNU C Library ABI. There is no guarantee the platform used to build the Lambda function has the same GLIBC version as the one used by AWS Lambda. In fact, you might not even be using GNU's implementation. For example you could build a C++ Lambda function using musl libc.
94+
95+
To ensure that your application will run correctly on Lambda, , we must package the entire C runtime library with your function.
96+
If you choose to build on the same Amazon Linux version used by lambda, you could avoid packaging the C runtime in your zip file.
97+
This can be done by passing the `NO_LIBC` flag in CMake as follows:
98+
```cmake
99+
aws_lambda_package_target(${PROJECT_NAME} NO_LIBC)
100+
```
101+
### Common Pitfalls with Packaging
102+
103+
* Any library dependency your Lambda function has that is dynamically loaded via `dlopen` will NOT be automatically packaged. You **must** add those dependencies manually to the zip file.
104+
This applies to any configuration or resource files that your code depends on.
105+
106+
* If you are making HTTP calls over TLS (https), keep in mind that the CA bundle location is different between distros.
107+
For example, if you are using the AWS C++ SDK, it's best to set the following configuration options:
108+
109+
```cpp
110+
Aws::Client::ClientConfiguration config;
111+
config.caFile = "/etc/pki/tls/certs/ca-bundle.crt";
112+
```
113+
If you are not using the AWS C++ SDK, but happens to be using libcurl directly, you can set the CA bundle location by doing:
114+
```c
115+
curl_easy_setopt(curl_handle, CURLOPT_CAINFO, "/etc/pki/tls/certs/ca-bundle.crt");
116+
```
117+
118+
## FAQ
119+
* Why is the zip file so large? what are all those files?
120+
Typically, the zip file is large because we have to package the entire C standard library.
121+
You can reduce the size by doing some or all of the following:
122+
1. Ensure you're building in release mode `-DCMAKE_BUILD_TYPE=Release`
123+
1. If possible, build your function using musl libc, it's tiny. The easiest way to do this, assuming your code is portable, is to build on Alpine linux.
124+
* How to upload a zip file that's bigger than 50MB via the CLI?
125+
Upload your zip file to S3 first:
126+
```bash
127+
$ aws s3 cp demo.zip s3://mys3bucket/demo.zip
128+
```
129+
NOTE: you must use the same region for your S3 bucket as the lambda.
130+
131+
Then tell Lambda where to get it from:
132+
```bash
133+
$ aws lambda create-function --function-name demo \
134+
--role <specify role arn here> \
135+
--runtime provided --timeout 15 --memory-size 128 \
136+
--handler demo
137+
--code "S3Bucket=mys3bucket,S3Key=demo.zip"
138+
```
139+
140+
## License
7141
This library is licensed under the Apache 2.0 License.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
11
include(${CMAKE_CURRENT_LIST_DIR}/@CMAKE_PROJECT_NAME@-targets.cmake)
22

3+
set(AWS_LAMBDA_PACKAGING_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/packager)
4+
function(aws_lambda_package_target target)
5+
set(options OPTIONAL NO_LIBC)
6+
cmake_parse_arguments(PACKAGER "${options}" "" "" ${ARGN})
7+
if (${PACKAGER_NO_LIBC})
8+
set (PACKAGER_NO_LIBC "-d")
9+
else()
10+
set (PACKAGER_NO_LIBC "")
11+
endif()
12+
add_custom_target(aws-lambda-package-${target}
13+
COMMAND ${AWS_LAMBDA_PACKAGING_SCRIPT} ${PACKAGER_NO_LIBC} $<TARGET_FILE:${target}>
14+
DEPENDS ${target})
15+
endfunction()
16+

examples/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
set(CMAKE_CXX_STANDARD 11)
3+
project(encoder LANGUAGES CXX)
4+
5+
find_package(aws-lambda-runtime)
6+
find_package(AWSSDK COMPONENTS s3)
7+
8+
add_executable(${PROJECT_NAME} "main.cpp")
9+
10+
target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-lambda-runtime ${AWSSDK_LINK_LIBRARIES})
11+
12+
target_compile_options(${PROJECT_NAME} PRIVATE
13+
"-Wall"
14+
"-Wextra"
15+
"-Wconversion"
16+
"-Wshadow"
17+
"-Wno-sign-conversion")
18+
19+
target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_11")
20+
21+
aws_lambda_package_target(${PROJECT_NAME})
22+

examples/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM alpine:latest
2+
3+
RUN apk update && apk add cmake make git g++ bash curl-dev zlib-dev

examples/README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Example using the AWS C++ SDK with Lambda
2+
3+
We'll build a lambda that downloads an image file from S3 and sends it back in the response as Base64 encoded that can be displayed in a web page for example.
4+
To also show case how this can be done on a Linux distro other than Amazon Linux, you can use the Dockerfile in this directory to create an Alpine Linux environment in which you can run the following instructions.
5+
6+
That being said, the instructions below should work on any Linux distribution.
7+
8+
## Build the AWS C++ SDK
9+
Start by building the SDK from source.
10+
```bash
11+
$ mkdir ~/install
12+
$ git clone https://github.com/aws/aws-sdk-cpp.git
13+
$ cd aws-sdk-cpp
14+
$ mkdir build
15+
$ cd build
16+
$ cmake .. -DBUILD_ONLY="s3" \
17+
-DCMAKE_BUILD_TYPE=Release \
18+
-DBUILD_SHARED_LIBS=OFF \
19+
-DCUSTOM_MEMORY_MANAGEMENT=OFF
20+
-DCMAKE_INSTALL_PREFIX=~/install \
21+
-DENABLE_UNITY_BUILD=ON
22+
23+
$ make
24+
$ make install
25+
```
26+
27+
## Build the Runtime
28+
Now let's build the C++ Lambda runtime, so in a separate directory clone this repository and follow these steps:
29+
30+
```bash
31+
$ git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git
32+
$ cd aws-lambda-cpp-runtime
33+
$ mkdir build
34+
$ cd build
35+
$ cmake .. -DCMAKE_BUILD_TYPE=Release \
36+
-DBUILD_SHARED_LIBS=OFF \
37+
-DCMAKE_INSTALL_PREFIX=~/install \
38+
$ make
39+
$ make install
40+
```
41+
42+
## Build the application
43+
The last step is to build the Lambda function in `main.cpp` and run the packaging command as follows:
44+
45+
```bash
46+
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/install
47+
$ make
48+
$ make aws-lambda-package-encoder
49+
```
50+
51+
You should now have a zip file called `encoder.zip`. Follow the instructions in the main README to upload it and invoke the lambda.

0 commit comments

Comments
 (0)