Skip to content
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

[<liblzma>] <add LZMA_API_STATIC in lzma.h for linking static build of liblzma> #43803

Open
alwendya opened this issue Feb 12, 2025 · 3 comments
Assignees
Labels
requires:repro The issue is not currently repro-able

Comments

@alwendya
Copy link

alwendya commented Feb 12, 2025

Is your feature request related to a problem? Please describe.

I had problem using liblzma in static inside my program with the triplet x64-windows-static-md.
If I look inside lzma.h main header, it says

"#define LZMA_API_STATIC in your application if you want to link against static liblzma"

I defined LZMA_API_STATIC before including lzma.h but I got linking error telling it doesn't find any function.
In details it is looking for lzma function with the prefix __imp_ (for example __imp_lzma_stream_encoder_mt for lzma_stream_encoder_mt function) but since I'm in static mode, it shouldn't.

I looked further in lzma.h header and there is no usage of the LZMA_API_STATIC flag.

I looked in the original lzma.h file from liblzma github repository and inside their files, they use the static flag for LZMA_API_IMPORT.

VCPGK lzma.h extract :

#ifndef LZMA_API_IMPORT
#  if !1 && defined(_WIN32) && !defined(__GNUC__)
#    define LZMA_API_IMPORT __declspec(dllimport)
#  else
#    define LZMA_API_IMPORT
#  endif
#endif

Original lzma.h extract :

#ifndef LZMA_API_IMPORT
#  if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
#    define LZMA_API_IMPORT __declspec(dllimport)
#  else
#    define LZMA_API_IMPORT
#  endif
#endif

I switched LZMA_API_IMPORT from original lzma.h and now it works

Proposed solution

Replace !1 by !defined(LZMA_API_STATIC) in lzma.h

VCPGK lzma.h extract :

#ifndef LZMA_API_IMPORT
#  if !1 && defined(_WIN32) && !defined(__GNUC__)
#    define LZMA_API_IMPORT __declspec(dllimport)
#  else
#    define LZMA_API_IMPORT
#  endif
#endif

Original lzma.h extract :

#ifndef LZMA_API_IMPORT
#  if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
#    define LZMA_API_IMPORT __declspec(dllimport)
#  else
#    define LZMA_API_IMPORT
#  endif
#endif

Describe alternatives you've considered

No response

Additional context

No response

@alwendya alwendya added the category:port-feature The issue is with a library, which is requesting new capabilities that didn’t exist label Feb 12, 2025
@Mengna-Li Mengna-Li added requires:repro The issue is not currently repro-able and removed category:port-feature The issue is with a library, which is requesting new capabilities that didn’t exist labels Feb 13, 2025
@Mengna-Li
Copy link
Contributor

Mengna-Li commented Feb 13, 2025

@alwendya I did not encounter any errors when testing the usage on x64-windows-static and x64-windows-static-md. Can you provide a simple example?

@alwendya
Copy link
Author

Thanks @Mengna-Li ,
I build liblzma this way :
vcpkg install liblzma --triplet x64-windows-static-md
I link it under my program (Qt Application compiled with MSVC 2022 ) and run this function

#define LZMA_API_STATIC
#include <lzma.h>

...

bool MainWindow::LZMA_Stream_MT_Compress(const QByteArray& inputFileData,
                                         QByteArray&       outputFileData,
                                         int32_t           compressionLevel,
                                         int32_t           threads)
{
    if (inputFileData.size() == 0) { return false; }

    lzma_mt mt    = {};
    mt.flags      = 0;
    mt.threads    = (threads == -1) ? QThread::idealThreadCount() : threads;
    mt.block_size = 0;
    mt.timeout    = 0;
    mt.preset     = (compressionLevel == -1) ? LZMA_PRESET_DEFAULT : compressionLevel;
    mt.check      = LZMA_CHECK_CRC64;

    lzma_stream strm = LZMA_STREAM_INIT;
    lzma_ret    ret  = lzma_stream_encoder_mt(&strm, &mt);
    if (ret != LZMA_OK) { return false; }

    QByteArray inputBuffer;
    QByteArray outputBuffer(65536, 0); // 64KB buffer

    int64_t Pos = 0;
    while (Pos != inputFileData.size()) {
        inputBuffer    = inputFileData.mid(Pos,
                                        (inputFileData.size() - Pos < 65536)
                                               ? inputFileData.size() - Pos
                                               : 65536);
        Pos           += inputBuffer.size();
        strm.next_in   = reinterpret_cast<const uint8_t*>(inputBuffer.data());
        strm.avail_in  = inputBuffer.size();
        do {
            strm.next_out  = reinterpret_cast<uint8_t*>(outputBuffer.data());
            strm.avail_out = outputBuffer.size();

            ret = lzma_code(&strm, LZMA_RUN);
            if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
                lzma_end(&strm);
                return false;
            }
            outputFileData.append(outputBuffer.mid(0, outputBuffer.size() - strm.avail_out));
        } while (strm.avail_out == 0);
    }
    // Finish compression stream
    strm.next_in  = nullptr;
    strm.avail_in = 0;

    do {
        strm.next_out  = reinterpret_cast<uint8_t*>(outputBuffer.data());
        strm.avail_out = outputBuffer.size();

        ret = lzma_code(&strm, LZMA_FINISH);
        if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
            lzma_end(&strm);
            return false;
        }
        outputFileData.append(outputBuffer.mid(0, outputBuffer.size() - strm.avail_out));
    } while (strm.avail_out == 0);
    lzma_end(&strm);
    return true;
}

When I try to run this function, I get linker error searching from all function with __imp_ like __imp_lzma_code, __imp_lzma_end, etc...
the lzma.h LZMA_API_IMPORT preprocessor works like it's still a DLL and the way for me to make it work was to replace !1 by !defined(LZMA_API_STATIC) like I describeb it in my OP.
When I set that in place, my function works without problem. When I switch back to !1, I get the linker error.

@Neumann-A
Copy link
Contributor

@Mengna-Li API defines need to be burned in for MSBuild consumers or other builds which don't use CMake or pkg-config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
requires:repro The issue is not currently repro-able
Projects
None yet
Development

No branches or pull requests

3 participants