Repository: conda/conda-build

Issue:
conda-build 3.17 failing to build go-based packages
This issue is to pickup the parts of #3287 that did not get addressed, see:
  - `vault` issue: https://github.com/conda/conda-build/issues/3287#issuecomment-443922743
  - `ptvsd` issue: https://github.com/conda/conda-build/issues/3287#issuecomment-443953991
  - `go-bootstrap` issue: https://github.com/conda/conda-build/issues/3287#issuecomment-443965104
  - `git-lfs` issue: https://github.com/conda-forge/git-lfs-feedstock/pull/16

### Actual Behavior
Conda-build 3.17 fails to build packages that do not have dynamic linked libraries, e.g. `go`, `vault`, etc. 
<!-- What actually happens? -->

### Expected Behavior
This behavior does not happen on conda-build 3.16 as can be seen when one pins conda-build to 3.16 within the conda-forge ci-scripts, see:
  - `git-lfs`: 
https://github.com/conda-forge/git-lfs-feedstock/pull/16/commits/2b5cb52fed265f4f37462e59a08b2ee89c384867
  - `vault`: 
https://github.com/conda-forge/vault-feedstock/pull/24/commits/6c4a10de48bbcf997edf401772df2946b19ae592
  - `go`: 
https://github.com/conda-forge/go-feedstock/pull/34/commits/9499072cbb18b24e5adc331b9cdcccbb1b5e6e63

### Steps to Reproduce
Build the packages above using conda-build 3.17. 

cc: @isuruf, @jakirkham 


Discussion:
Thanks for keeping this issue alive.  #3287 was originally about LIEF errors on Windows which #3288 addressed but the issues reported with other platforms also need to be fixed.

Is this specific to packages which use go or are packages containing C and C++ code also effected?   The `ptvsd` package does not appear to use go and is failing, although with a different error `AttributeError: 'NoneType' object has no attribute 'replace'` than the go packages, `AttributeError: '_pylief.ELF.Binary' object has no attribute 'soname'`
It sounds like anything that was statically linked. Though I could be mistaken.
The packages built with go definitely have the problem as I have been patching the conda-forge recipes and referencing this issue.

The ptvsd issue is outside of my scope and was reported earlier by @isuruf, I wanted to copy the problem back here for completeness. Looking back at it,  I should have split the issue into two, one handling the 'soname' issue and the other 'replace'. 

I will try to rebuild some c/c++ packages that I have access and report back.
Here are the easy steps to reproduce the error:

```bash
# Create and activate environment with the go compiler and conda-build 3.17
conda create -y -n issue-3292 go conda-build=3.17
conda activate issue-3292

# Compile hello world in Go
echo 'package main; import "fmt"; func main() { fmt.Printf("Hello, World!\n"); }' > hello.go
go build hello.go

# Reproduce Error
python -c 'from conda_build.os_utils.liefldd import get_uniqueness_key; get_uniqueness_key("hello")'
```
Are there issues with static libraries as well?
I only found a negative example in conda-forge/hcephes-feedstock#13, so I don't know yet.
A basic 'hello.c' does not cause the problem either as we should expect.
Did you already inspect the libraries produced by `ptvsd`? Was there anything unusual about them?
Not yet, that might take longer for me to debug since I am not familiar with ptvsd.
Maybe @dhirschfeld would be able to help. 😉

Resolving patch:
diff --git a/conda_build/os_utils/liefldd.py b/conda_build/os_utils/liefldd.py
--- a/conda_build/os_utils/liefldd.py
+++ b/conda_build/os_utils/liefldd.py
@@ -238,12 +238,10 @@ def get_uniqueness_key(file):
          and  # noqa
          (binary.type == lief.ELF.ELF_CLASS.CLASS32 or binary.type == lief.ELF.ELF_CLASS.CLASS64)):
         dynamic_entries = binary.dynamic_entries
-        for e in dynamic_entries:
-            result = [e.name for e in dynamic_entries if e.tag == lief.ELF.DYNAMIC_TAGS.SONAME]
-            if result:
-                return result[0]
-            return binary.name
-        return binary.soname
+        result = [e.name for e in dynamic_entries if e.tag == lief.ELF.DYNAMIC_TAGS.SONAME]
+        if result:
+            return result[0]
+        return binary.name
     return binary.name
 
 


Test patch:
diff --git a/tests/test-recipes/go-package/hello.go b/tests/test-recipes/go-package/hello.go
new file mode 100644
--- /dev/null
+++ b/tests/test-recipes/go-package/hello.go
@@ -0,0 +1,7 @@
+package main
+
+import "fmt"
+
+func main() {
+    fmt.Printf("Hello, World!\n")
+}
diff --git a/tests/test-recipes/go-package/meta.yaml b/tests/test-recipes/go-package/meta.yaml
new file mode 100644
--- /dev/null
+++ b/tests/test-recipes/go-package/meta.yaml
@@ -0,0 +1,27 @@
+package:
+  name: go-hello
+  version: 1.0.0
+
+build:
+  number: 0
+  script:
+    - pushd ${RECIPE_DIR}  # [not win]
+    - mkdir $PREFIX/bin    # [not win]
+    - pushd %RECIPE_DIR%          # [win]
+    - mkdir %LIBRARY_PREFIX%/bin  # [win]
+
+    - go build hello.go
+
+    - mv hello ${PREFIX}/bin/go-hello  # [not win]
+    - mv hello.exe %LIBRARY_PREFIX%/bin/go-hello.exe  # [win]
+
+requirements:
+  build:
+    - {{ compiler('go') }}
+
+test:
+  commands:
+    - go-hello
+
+about:
+  summary: Tests that go-packages still compile correctly
diff --git a/tests/test_api_build_go_package.py b/tests/test_api_build_go_package.py
new file mode 100644
--- /dev/null
+++ b/tests/test_api_build_go_package.py
@@ -0,0 +1,20 @@
+import os
+import pytest
+
+from conda_build import api
+
+from .utils import thisdir
+
+@pytest.fixture()
+def recipe():
+    return os.path.join(thisdir, 'test-recipes', 'go-package')
+
+def test_recipe_build(recipe, testing_config, testing_workdir, monkeypatch):
+    # These variables are defined solely for testing purposes,
+    # so they can be checked within build scripts
+    testing_config.activate = True
+    monkeypatch.setenv("CONDA_TEST_VAR", "conda_test")
+    monkeypatch.setenv("CONDA_TEST_VAR_2", "conda_test_2")
+    api.build(recipe, config=testing_config)
+
+