Thanks to visit codestin.com
Credit goes to github.com

Skip to content

doc: how-to guide on using legacy code #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ci/build-examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,16 @@ steps:
'hello-world-rooted',
]

- name: 'pack'
waitFor: ['gcf-builder-ready']
id: 'howto-use-legacy-code'
args: ['build',
'--env', 'FUNCTION_SIGNATURE_TYPE=http',
'--env', 'TARGET_FUNCTION=HowtoUseLegacyCode',
'--path', 'examples/howto_use_legacy_code',
'howto-use-legacy-code',
]

# Build the cloud site examples.
- name: 'pack'
waitFor: ['gcf-builder-ready']
Expand Down
1 change: 1 addition & 0 deletions ci/generate-build-examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ generic_example hello_gcs HelloGcs http
generic_example hello_with_third_party HelloWithThirdParty http
generic_example hello_world HelloWorld http
generic_example hello_world ::HelloWorld http hello-world-rooted
generic_example howto_use_legacy_code HowtoUseLegacyCode http howto-use-legacy-code

cat <<_EOF_
# Build the cloud site examples.
Expand Down
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ add_library(
hello_multiple_sources/hello_multiple_sources.cc
hello_with_third_party/hello_with_third_party.cc
hello_world/hello_world.cc
howto_use_legacy_code/howto_use_legacy_code.cc
howto_use_legacy_code/legacy/legacy.cc
site/bearer_token/bearer_token.cc
site/concepts_after_response/concepts_after_response.cc
site/concepts_after_timeout/concepts_after_timeout.cc
Expand Down
45 changes: 45 additions & 0 deletions examples/howto_use_legacy_code/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# ~~~
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ~~~

cmake_minimum_required(VERSION 3.5)
project(functions-framework-cpp-howto-local-development CXX C)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Threads REQUIRED)
find_package(functions_framework_cpp REQUIRED)

include(ExternalProject)
externalproject_add(
legacy
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/legacy"
DEPENDS "" SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/legacy"
CONFIGURE_COMMAND ""
BUILD_COMMAND "make" "CXX=${CMAKE_CXX_COMPILER}" "default" BUILD_IN_SOURCE
ON
BUILD_BYPRODUCTS "<SOURCE_DIR>/liblegacy.a"
INSTALL_COMMAND "")
ExternalProject_Get_Property(legacy SOURCE_DIR)

add_library(functions_framework_cpp_function howto_use_legacy_code.cc)
add_dependencies(functions_framework_cpp_function legacy)
target_link_libraries(
functions_framework_cpp_function PUBLIC "${SOURCE_DIR}/liblegacy.a"
functions-framework-cpp::framework)

add_executable(main main.cc)
target_link_libraries(main PRIVATE functions_framework_cpp_function)
148 changes: 148 additions & 0 deletions examples/howto_use_legacy_code/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# How-to Guide: use functions with legacy code

This guide shows you how to use legacy code with the C++ Functions Framework.

This guide shows how to create a CMake file that invokes an external build tool
to compile some legacy code. This is a complex subject, with a lot of nuances
depending on the nature of the legacy code and the build system used to compile
it. We hope this guide can give you starting pointers to learn more about the
topic.

We recommend you use [ExternalProject_Add] facility in CMake to compile any
pre-existing code. This is a general-purpose function in CMake that invokes
any external tool to compile some code. Often this function also downloads
the code from some external repository, but it can use code in your source
tree.

[ExternalProject_Add]: https://cmake.org/cmake/help/latest/module/ExternalProject.html

## Installing Dependencies

Because the Functions Framework for C++ uses C++17, you will need a working C++
compiler with support for C++17. If you are a GCC user, any version after 8.0
should work. For Clang any version after 6.0 should work. We have not tested
these instructions with MSVC.

This guide uses [CMake (>= 3.5)][cmake] as a build tool. There are detailed
[install instructions][cmake-install], but many system package managers have
packages for it. Verify your CMake tool version:

```shell
cmake --version
# Output: cmake version X.Y.Z ... verify this is >= 3.5
```

The Functions Framework for C++ recommends using [vcpkg][vcpkg-gh] to manage
dependencies. This is how dependencies will be installed and compiled in the
production environment, so you probably want to use the same approach in
development. Follow the [vcpkg install instructions][vcpkg-install] to get
vcpkg installed on your development environment. For example, on Linux you
would use:

```shell
cd $HOME
git clone -q https://github.com/microsoft/vcpkg
# Expected output: none
./vcpkg/bootstrap-vcpkg.sh --disableMetrics
```

You should see output like this:

```console
Downloading cmake...
...
Downloading ninja...
...
Downloading vcpkg tool sources
...
..
Building vcpkg-tool...
...
..
[88/88] Linking CXX executable vcpkg
```

This will create a `vcpkg` executable in the `$HOME/vcpkg` directory.

## Compiling a function

Once vcpkg is compiled you can build the example. If you have not cloned
the `functions-framework-cpp` repository yet, you need to do so now:

```shell
cd $HOME
git clone -q https://github.com/GoogleCloudPlatform/functions-framework-cpp.git
# Expected output: none
```

Then go to the directory hosting this example and use CMake to build
the example:

```shell
cd functions-framework-cpp/examples/howto_use_legacy_code
```

Run the CMake configure step. If needed, this will download and build any
dependencies for your function:

```shell
cmake -H. -B.build -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake
```

You should see output like this:

> :warning: the first time you use or build the framework it might take several
> minutes, maybe as much as 1/2 hour, depending on your workstation
> performance. Future builds, even in different directories, should be faster
> as `vcpkg` caches binary artifacts in `$HOME/.cache/vcpkg`.

```console
-- Running vcpkg install
...
-- Running vcpkg install - done
-- Configuring done
-- Generating done
-- Build files have been written to: .../howto_use_legacy_code/.build
```

If you have previously built the dependencies with `vcpkg` the output may include
informational messages about reusing these binary artifacts. With some versions
of CMake you may see a warning about your version of Boost, something like:

```console
CMake Warning at /usr/share/cmake-3.16/Modules/FindBoost.cmake:1161 (message):
New Boost version may have incorrect or missing dependencies and imported
targets
```

You can safely ignore this warning.

With the dependencies built and CMake configured you can now build the code:

```shell
cmake --build .build
```

This will output some informational messages about the build progress, and will
create a binary called `local_server` in the .build subdirectory.

## Running the function locally

This will produce a standalone HTTP server, which you can run locally using:

```shell
.build/main --port 8080
```

Test this program using `curl`. In a separate terminal window run:

```shell
curl http://localhost:8080
```

You can just interrupt (`Ctrl-C`) the program to terminate it.

[vcpkg-gh]: https://github.com/microsoft/vcpkg
[vcpkg-install]: https://github.com/microsoft/vcpkg#getting-started
[cmake]: https://cmake.org
[cmake-install]: https://cmake.org/install/
28 changes: 28 additions & 0 deletions examples/howto_use_legacy_code/howto_use_legacy_code.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "legacy/legacy.h"
#include <google/cloud/functions/http_request.h>
#include <google/cloud/functions/http_response.h>

using ::google::cloud::functions::HttpRequest;
using ::google::cloud::functions::HttpResponse;

// Though not used in this example, the request is passed by value to support
// applications that move-out its data.
HttpResponse HowtoUseLegacyCode(HttpRequest) { // NOLINT
return HttpResponse{}
.set_header("Content-Type", "text/plain")
.set_payload(legacy::LegacyMessage());
}
2 changes: 2 additions & 0 deletions examples/howto_use_legacy_code/legacy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
liblegacy.a
legacy.o
23 changes: 23 additions & 0 deletions examples/howto_use_legacy_code/legacy/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ~~~
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ~~~

default: liblegacy.a

liblegacy.a: legacy.o
$(AR) r $@ $<

legacy.o: legacy.cc legacy.h
$(CXX) $(CXXFLAGS) -c -o $@ $<
22 changes: 22 additions & 0 deletions examples/howto_use_legacy_code/legacy/legacy.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "legacy.h"
#include <string>

namespace legacy {
std::string LegacyMessage() {
return "C++ version is " + std::to_string(__cplusplus) + "\n";
}
} // namespace legacy
24 changes: 24 additions & 0 deletions examples/howto_use_legacy_code/legacy/legacy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef FUNCTIONS_FRAMEWORK_CPP_EXAMPLES_HOWTO_USE_LEGACY_CODE_LEGACY_LEGACY_H
#define FUNCTIONS_FRAMEWORK_CPP_EXAMPLES_HOWTO_USE_LEGACY_CODE_LEGACY_LEGACY_H

#include <string>

namespace legacy {
std::string LegacyMessage();
} // namespace legacy

#endif // FUNCTIONS_FRAMEWORK_CPP_EXAMPLES_HOWTO_USE_LEGACY_CODE_LEGACY_LEGACY_H
24 changes: 24 additions & 0 deletions examples/howto_use_legacy_code/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <google/cloud/functions/framework.h>
#include <cstdlib>

namespace gcf = ::google::cloud::functions;

gcf::HttpResponse HowtoUseLegacyCode(gcf::HttpRequest);

int main(int argc, char* argv[]) {
return ::google::cloud::functions::Run(argc, argv, HowtoUseLegacyCode);
}
8 changes: 8 additions & 0 deletions examples/howto_use_legacy_code/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "hello-with-third-party",
"version-string": "unversioned",
"dependencies": [
"fmt",
"functions-framework-cpp"
]
}
6 changes: 6 additions & 0 deletions examples/http_examples_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ gcf::HttpResponse HelloGcs(gcf::HttpRequest);
gcf::HttpResponse HelloMultipleSources(gcf::HttpRequest);
gcf::HttpResponse HelloWithThirdParty(gcf::HttpRequest request);
gcf::HttpResponse HelloWorld(gcf::HttpRequest);
gcf::HttpResponse HowtoUseLegacyCode(gcf::HttpRequest);

namespace hello_from_namespace {
gcf::HttpResponse HelloWorld(gcf::HttpRequest);
Expand Down Expand Up @@ -67,4 +68,9 @@ TEST(HttpExamplesTest, HelloFromNestedNamespace) {
EXPECT_THAT(actual.payload(), HasSubstr("C++ namespace"));
}

TEST(HttpExampleTest, HowtoUseLegacyCode) {
auto const actual = HowtoUseLegacyCode(gcf::HttpRequest{});
EXPECT_THAT(actual.payload(), HasSubstr("C++"));
}

} // namespace