rust-lang/git2-rs

Windows build does not link with Advapi32.lib

Closed this issue · 3 comments

I tried to use git2 in my build.rs script and encountered a series of errors:

liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_OpenProcessToken referenced in function current_user_sid␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_CheckTokenMembership referenced in function git_fs_path_owner_is␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_CopySid referenced in function sid_dup␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_EqualSid referenced in function git_fs_path_owner_is␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_GetLengthSid referenced in function sid_dup␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_GetTokenInformation referenced in function current_user_sid␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_IsValidSid referenced in function file_owner_sid␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_IsWellKnownSid referenced in function git_fs_path_owner_is␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-fs_path.o) : error LNK2019: unresolved external symbol __imp_GetNamedSecurityInfoW referenced in function file_owner_sid␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(43a19b30e9e69d8f-sysdir.o) : error LNK2019: unresolved external symbol __imp_RegCloseKey referenced in function lookup_registry_key␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(43a19b30e9e69d8f-sysdir.o) : error LNK2019: unresolved external symbol __imp_RegOpenKeyExW referenced in function lookup_registry_key␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(43a19b30e9e69d8f-sysdir.o) : error LNK2019: unresolved external symbol __imp_RegQueryValueExW referenced in function lookup_registry_key␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-rand.o) : error LNK2019: unresolved external symbol __imp_CryptAcquireContextA referenced in function getseed␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f5e66aefe9cd60e0-win32.o) : error LNK2001: unresolved external symbol __imp_CryptAcquireContextA␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-rand.o) : error LNK2019: unresolved external symbol __imp_CryptReleaseContext referenced in function getseed␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f5e66aefe9cd60e0-win32.o) : error LNK2001: unresolved external symbol __imp_CryptReleaseContext␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f6e81ea219c0b9f3-rand.o) : error LNK2019: unresolved external symbol __imp_CryptGenRandom referenced in function getseed␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f5e66aefe9cd60e0-win32.o) : error LNK2019: unresolved external symbol __imp_CryptGetHashParam referenced in function hash_cryptoapi_final␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f5e66aefe9cd60e0-win32.o) : error LNK2019: unresolved external symbol __imp_CryptCreateHash referenced in function hash_cryptoapi_init␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f5e66aefe9cd60e0-win32.o) : error LNK2019: unresolved external symbol __imp_CryptHashData referenced in function hash_cryptoapi_update␍
          liblibgit2_sys-13851f2c09f1f8ee.rlib(f5e66aefe9cd60e0-win32.o) : error LNK2019: unresolved external symbol __imp_CryptDestroyHash referenced in function hash_cryptoapi_init␍

Turn out libgit2 uses some WinAPI calls from Advapi32, like GetCurrentProcess in https://github.com/libgit2/libgit2/blob/21a351b0ed207d0871cb23e09c027d1ee42eae98/src/util/fs_path.c#L1832 (MSDN docs for this call https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocesstoken say that linkage with Advapi32.lib is required for the call to work).
The problem is that there is no linkage with Advapi32 in CMake scripts. Looks like Advapi32 should be added in here https://github.com/libgit2/libgit2/blob/21a351b0ed207d0871cb23e09c027d1ee42eae98/src/CMakeLists.txt#L125-L128
I created an issue for this in the libgit2 repo libgit2/libgit2#7053 Just wanted to let you know, so new release is published when someone fixes this issue.

Just for reference, that is the build.rs code which produced these errors:

use std::{env, fs, path::PathBuf};

use anyhow::{Context, Result};
use git2::{DescribeOptions, ErrorCode, Repository};

fn get_current_branch(repo: &Repository) -> Result<Option<String>> {
    // git branch --show-current
    let head = match repo.head() {
        Ok(head) => Some(head),
        Err(err) => match err.code() {
            ErrorCode::NotFound | ErrorCode::UnbornBranch => None,
            _ => return Err(err.into()),
        },
    };
    Ok(head.as_ref().and_then(|h| h.shorthand()).map(String::from))
}

fn rerun_if_git_ref_changed(repo: &Repository) -> Result<()> {
    let git_dir = repo.path();

    let head_path = git_dir.join("HEAD");
    if head_path.exists() {
        println!("cargo:rerun-if-changed={}", head_path.display());
    }

    if let Some(current_branch) = get_current_branch(repo)? {
        let git_current_branch_ref = git_dir.join("refs").join("heads").join(current_branch);
        if git_current_branch_ref.exists() {
            println!(
                "cargo:rerun-if-changed={}",
                git_current_branch_ref.display()
            );
        }
    }

    let tags_path = git_dir.join("refs").join("tags");
    if tags_path.exists() {
        println!("cargo:rerun-if-changed={}", tags_path.display());
    }

    Ok(())
}

fn git_describe_tags(repo: &Repository) -> Result<String> {
    // git describe --tags
    Ok(repo
        .describe(DescribeOptions::new().describe_tags())?
        .format(None)?)
}

fn git_rev_parse_commit_hash(repo: &Repository) -> Result<String> {
    // git rev-parse --short HEAD^{commit}
    let commit_hash = repo
        .revparse_ext("HEAD^{commit}")?
        .0
        .describe(DescribeOptions::new().show_commit_oid_as_fallback(true))?
        .format(None)?;
    Ok(commit_hash)
}

fn get_version() -> Result<String> {
    if let Ok(repo) = Repository::discover(".") {
        rerun_if_git_ref_changed(&repo)?;
        if let Ok(tag) = git_describe_tags(&repo) {
            return Ok(tag);
        }
        if let Ok(hash) = git_rev_parse_commit_hash(&repo) {
            return Ok(hash);
        }
    }
    Ok("undefined".to_owned())
}

fn main() -> Result<()> {
    let out_dir = PathBuf::from(env::var_os("OUT_DIR").context("OUT_DIR is set by cargo")?);
    fs::write(out_dir.join("version.txt"), get_version()?)?;
    Ok(())
}

This is a close rewrite of this code https://github.com/mullvad/mullvadvpn-app/blob/main/mullvad-version/build.rs So not only me could benefit from the fix to this issue.

Thanks for the report! I have opened a fix at #1143

Thanks for the fix! I haven't checked that you have recreated build script entirely, and not using corrosion to build via CMake)