Skip to content

Application build error with AWS SDK/Curl as static libraries on Windows #2502

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

Open
Shempp opened this issue May 23, 2023 · 3 comments
Open
Labels
bug This issue is a bug. Cmake Cmake related submissions p3 This is a minor priority issue

Comments

@Shempp
Copy link

Shempp commented May 23, 2023

Describe the bug

An application that uses the static libraries of AWS and Curl is built with errors on Windows.

Expected Behavior

An application that uses the static libraries of AWS and Curl is built without errors on Windows.

Current Behavior

If you try to use the static versions of AWS/Curl we get numerous errors at the linking stage, for example:

1>aws-cpp-sdk-core.lib(CurlHttpClient.obj) : error LNK2019: unresolved external symbol __imp__curl_global_init in function "public: static void __cdecl Aws::Http::CurlHttpClient::InitGlobalState(void)" (?InitGlobalState@CurlHttpClient@Http@Aws@@SAXXZ).

Reproduction Steps

  1. Build Curl as static library
  2. Build AWS as static library
    CMake command:
cmake -A Win32 -DCMAKE_INSTALL_PREFIX="C:/aws-sdk-cpp" -DBUILD_ONLY="s3" -DFORCE_CURL=ON -DCURL_INCLUDE_DIR="C:/curl/include" -DCURL_LIBRARY="C:/curl/lib/libcurl.lib" -DBUILD_SHARED_LIBS=OFF -DCPP_STANDARD=14 -DENABLE_TESTING=OFF -DTARGET_ARCH=WINDOWS -B build
  1. Try to build "Hello S3" app (https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/build-cmake.html) in Visual Studio 2019 (linking and include files configured)

Possible Solution

The AWS documentation (Developer Guide, Getting Started -> Getting SDK from source -> Build on Windows) mentions an example of using Curl only as a dynamic library on Windows but it can also be used in the static version with some clarifications (for example someone uses all dependencies as static libraries).

To fix it you need to notify Сurl about its use in the static version: define the CURL_STATICLIB preprocessor directive when building AWS libraries (https://github.com/curl/curl/tree/master/winbuild#building-your-own-application-with-a-static-libcurl). I did it by setting flags CMAKE_C_FLAGS_INIT and CMAKE_CXX_FLAGS_INIT when executing the CMake command like this:

cmake -A Win32 -DCMAKE_INSTALL_PREFIX="C:/aws-sdk-cpp" -DBUILD_ONLY="s3" -DFORCE_CURL=ON -DCURL_INCLUDE_DIR="C:/curl/include" -DCURL_LIBRARY="C:/curl/lib/libcurl.lib" -DBUILD_SHARED_LIBS=OFF -DCPP_STANDARD=14 -DENABLE_TESTING=OFF -DTARGET_ARCH=WINDOWS -DCMAKE_C_FLAGS_INIT="/DCURL_STATICLIB" -DCMAKE_CXX_FLAGS_INIT="/DCURL_STATICLIB" -B build

Previously, it was enough to define a CURL_STATICLIB preprocessor directive at the application level - this does not work now.

Additional Information/Context

Curl version used
8.1.0

Also a similar topic has already been raised but for Linux: #1270

AWS CPP SDK version used

1.11.82

Compiler and Version used

MSVC 19.29.30148

Operating System and version

Windows 10 22H2 10.0.19045.2846

@Shempp Shempp added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels May 23, 2023
@yasminetalby
Copy link
Contributor

Hello @Shempp ,

Thank you very much for your submission.

From a first look, this doesn't seem like an issue with the AWS C++ SDK. It seems that the libraries are not being successfully linked.
The documentation you have linked mentioned that when building an application that uses the static libcurl library on Windows, you must define CURL_STATICLIB. Otherwise the linker will look for dynamic import symbols.

You have mentioned that "Previously, it was enough to define a CURL_STATICLIB preprocessor directive at the application level - this does not work now."

Could you specify any changes you have made that resulted in this change of behavior?

Have you attempted to add add_definitions(-DCURL_STATICLIB) to CMakeLists.txt?

Thank you very much for your time and collaboration.

Sincerely,

Yasmine

@yasminetalby yasminetalby removed the needs-triage This issue or PR still needs to be triaged. label May 23, 2023
@yasminetalby yasminetalby self-assigned this May 23, 2023
@yasminetalby yasminetalby added p3 This is a minor priority issue response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days. labels May 23, 2023
@Shempp
Copy link
Author

Shempp commented May 24, 2023

Hello @yasminetalby,
Thanks for the answer.

Could you specify any changes you have made that resulted in this change of behavior?

I am updating libraries in a project (I have no information on how they were buided before). In fact, this is not so important, this issue can be reproduced in the simplest example (more on that below).

Have you attempted to add add_definitions(-DCURL_STATICLIB) to CMakeLists.txt?

Yes.

From a first look, this doesn't seem like an issue with the AWS C++ SDK.

I would note the need to define the directive CURL_STATICLIB in the AWS documentation when building Windows with static Curl if the problem is confirmed.

It seems that the libraries are not being successfully linked.

Yes, the preprocessor directive CURL_STATICLIB is responsible for whether the symbols will be imported/exported or will be untouched for the Curl library (https://github.com/curl/curl/blob/master/include/curl/curl.h#L129).
However, if we have a compiled Curl and AWS, defining this directive in a project using these libraries will not help solve the problem (in any case, it did not help in my tests).

The simplest example of reproducing the problem (Note: I intentionally omit the details of linking necessary for static Curl, like OpenSSL linking, if there is one, etc.):
main.cpp

// https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/build-cmake.html

#include <aws/core/Aws.h>
#include <aws/core/utils/logging/LogLevel.h>
#include <aws/s3/S3Client.h>

#include <iostream>

using namespace Aws;

int main()
{
    //The Aws::SDKOptions struct contains SDK configuration options.
    //An instance of Aws::SDKOptions is passed to the Aws::InitAPI and 
    //Aws::ShutdownAPI methods.  The same instance should be sent to both methods.
    SDKOptions options;
    options.loggingOptions.logLevel = Utils::Logging::LogLevel::Debug;

    //The AWS SDK for C++ must be initialized by calling Aws::InitAPI.
    InitAPI(options);
    {
        S3::S3Client client;

        auto outcome = client.ListBuckets();
        if (outcome.IsSuccess()) {
            std::cout << "Found " << outcome.GetResult().GetBuckets().size() << " buckets\n";
            for (auto&& b : outcome.GetResult().GetBuckets()) {
                std::cout << b.GetName() << std::endl;
            }
        }
        else {
            std::cout << "Failed with error: " << outcome.GetError() << std::endl;
        }
    }

    //Before the application terminates, the SDK must be shut down. 
    ShutdownAPI(options);
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.3)
set(CMAKE_CXX_STANDARD 11)
project(AWS LANGUAGES CXX)

add_definitions(-DCURL_STATICLIB)

#Set the location of where Windows can find the installed libraries of the SDK.
if(MSVC)
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-auth\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-cal\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-common\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-compression\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-event-stream\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-checksums\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-http\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-io\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-mqtt\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-crt-cpp\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-s3\\cmake")
    list(APPEND CMAKE_PREFIX_PATH "C:\\aws-sdk-cpp\\lib\\aws-c-sdkutils\\cmake")
endif()

message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
set(BUILD_SHARED_LIBS OFF CACHE STRING "Link to shared libraries by default.")

#Load required services/packages: This basic example uses S3.
find_package(AWSSDK REQUIRED COMPONENTS s3)
add_executable(${PROJECT_NAME} "main.cpp")

set_compiler_flags(${PROJECT_NAME})
set_compiler_warnings(${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} ${AWSSDK_LINK_LIBRARIES})

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days. label May 25, 2023
@yasminetalby
Copy link
Contributor

Hello @Shempp ,

Thank you very much for providing the repro steps. I have discussed this issue as well as #1270 with the team and this would fall into the scope of the following feature request: #1888 which is still in progress. You can add a thumbs up to this to showcase your interest.

Thank you very much for your collaboration and for bringing this up to our attention.

Sincerely,

Yasmine

@yasminetalby yasminetalby added the Cmake Cmake related submissions label Sep 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. Cmake Cmake related submissions p3 This is a minor priority issue
Projects
None yet
Development

No branches or pull requests

2 participants