Repository: aws/aws-sam-cli

Issue:
sam build includes absolute paths in Golang binaries
### Description:
<!-- Briefly describe the bug you are facing.-->
When you run ```sam build``` and ```sam package``` in two instances of the same projects with different absolute paths and upload to the same S3 bucket, the compiled binaries will be uploaded both times, even though the binaries are identical.
According to #2110 this has been fixed, but I can still reproduce the issue on Windows.

### Steps to reproduce:
<!-- Provide detailed steps to replicate the bug, including steps from third party tools (CDK, etc.) -->
1. Clone [this repository](https://github.com/suroh1994/sampackagesample) into a directory on your local Windows machine.
1. ```cd``` into the directory.
1. Run ```sam build```.
1. Run ```sam package --s3-bucket YOUR_BUCKETNAME```
1. Clone the same repository into a second directory on your local windows machine.
1. Copy the second directory into a third directory using ```xcopy seconddirectory thirddirectory /s /e```.
1. ```cd``` into the second directory.
1. Run ```sam build```.
1. Run ```sam package --s3-bucket YOUR_BUCKETNAME```
1. ```cd``` into the third directory.
1. Run ```sam build```.
1. Run ```sam package --s3-bucket YOUR_BUCKETNAME```


### Observed result:
<!-- Please provide command output with `--debug` flag set. -->
The calculated hashes change, when the parent directory changes. This results in the compiled binaries being re-uploaded for every directory, although no files have been modified.


### Expected result:
<!-- Describe what you expected. -->
Hashes should not depend on the parent directory. Compiled binaries should only be uploaded, when they have been modified.


### Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

1. OS: Windows 10 Pro Version 20H2 (Build 19042.1165)
2. `sam --version`: 1.31.0
3. AWS region: eu-central-1

### Further notes:
I can imagine this is also the cause for the issue #2872, where running ```sam package``` in an ephemeral container results in the files being uploaded every time.



Discussion:
I've played around with the source code and it seems the hashes are correct, but instead the compiled binaries are not identical. But I have not yet identified, why they differ.
I believe I have identified the issue. When I build my binaries using ```sam build```, the resulting binary is identical to ```go build```. But when I use ```go build -trimpath``` the binary is different, yet the binaries in both directories are now identical. I'm looking into what other metadata is stored in the binaries, that could let to the binaries differing between two CodeBuild runs.
I solved the issue successfully for both local builds and builds generated by CodeBuild. As my last post suggested, the issue came down to ```go build``` embedding absolute paths into the binary. So to resolve the issue I did the following:

To have ```sam build``` use the ```-trimpath``` flag, I setup makefiles for every Lambda function and added these lines to each function:
```
    Metadata:
      BuildMethod: makefile
```
Then I added a ```Makefile``` file to each directory listed as ```CodeUri``` with the following content:
```
build-Logical-Resource-Id:
	go build -trimpath -o "$(ARTIFACTS_DIR)/your-handler-name"
```
For more information on how to use a makefile, see the [documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html).
A complete example can be found in the [resolved branch](https://github.com/suroh1994/sampackagesample/tree/resolved) of my repo.

Going forward, it might be interesting to consider using the ```-trimpath``` by default. I do not know how important it is to keep the information in the binaries and which variant more commonly would lead to issues.
Updated title to reflect the found issue.
@suroh1994 Thanks for the info, it is very valuable. We will consider adding `-trimpath` by default if that avoid such issue
Any update on if trimpath can be included by default? My group is running into this issue atm. 
@jaglade This will be a welcome contribution to the `aws-lambda-builders` golang build workflow and we can make this feature opt-in (atleast at this point, I have not considered the ramifications of the change in behavior causing breaks).
@sriram-mv I have opened a [pull request](https://github.com/aws/aws-lambda-builders/pull/389) in aws-lambda-builders allowing this option to be passed in. 

Once this PR is reviewed and merged I believe this project can be updated [here](https://github.com/aws/aws-sam-cli/blob/develop/samcli/lib/build/app_builder.py#L715) to something along the lines of: 
```python
        _build_options: Dict = {
            "go": {
                "artifact_executable_name": handler,
                "trim_go_path": build_props.get("TrimGoPath", False),
            },
            "provided": {"build_logical_id": function_name},
            "nodejs": {"use_npm_ci": build_props.get("UseNpmCi", False)},
        }
```

I _believe_ this will allow SAM template users to define functions like the following:
```yaml
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functions/hello-world/
      Handler: main
      Runtime: go1.x
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get
    Metadata:
      BuildProperties:
        TrimGoPath: True
```
Which fixes the issue described above by @suroh1994 and @jaglade 

Resolving patch:
diff --git a/samcli/lib/build/app_builder.py b/samcli/lib/build/app_builder.py
--- a/samcli/lib/build/app_builder.py
+++ b/samcli/lib/build/app_builder.py
@@ -712,7 +712,10 @@ def _get_build_options(
             return normalized_build_props
 
         _build_options: Dict = {
-            "go": {"artifact_executable_name": handler},
+            "go": {
+                "artifact_executable_name": handler,
+                "trim_go_path": build_props.get("TrimGoPath", False),
+            },
             "provided": {"build_logical_id": function_name},
             "nodejs": {"use_npm_ci": build_props.get("UseNpmCi", False)},
         }


Test patch:
diff --git a/tests/unit/lib/build_module/test_app_builder.py b/tests/unit/lib/build_module/test_app_builder.py
--- a/tests/unit/lib/build_module/test_app_builder.py
+++ b/tests/unit/lib/build_module/test_app_builder.py
@@ -1906,15 +1906,31 @@ def test_invalid_metadata_cases(self, metadata, expected_output):
 
     @parameterized.expand(
         [
-            ("go", "", {"artifact_executable_name": "app.handler"}),
-            ("python", "", None),
-            ("nodejs", "npm", {"use_npm_ci": True}),
-            ("esbuild", "npm-esbuild", {"entry_points": ["app"], "use_npm_ci": True}),
-            ("provided", "", {"build_logical_id": "Function"}),
+            ("go", "", {"TrimGoPath": True}, {"artifact_executable_name": "app.handler", "trim_go_path": True}),
+            ("python", "", {}, None),
+            ("nodejs", "npm", {"UseNpmCi": True}, {"use_npm_ci": True}),
+            ("esbuild", "npm-esbuild", {"UseNpmCi": True}, {"entry_points": ["app"], "use_npm_ci": True}),
+            ("provided", "", {}, {"build_logical_id": "Function"}),
         ]
     )
-    def test_get_options_various_languages_dependency_managers(self, language, dependency_manager, expected_options):
-        build_properties = {"UseNpmCi": True}
+    def test_get_options_various_languages_dependency_managers(
+        self, language, dependency_manager, build_properties, expected_options
+    ):
+        metadata = {"BuildProperties": build_properties}
+        options = ApplicationBuilder._get_build_options(
+            "Function", language, "app.handler", dependency_manager, metadata
+        )
+        self.assertEqual(options, expected_options)
+
+    @parameterized.expand(
+        [
+            ("go", "", {}, {"artifact_executable_name": "app.handler", "trim_go_path": False}),
+            ("nodejs", "npm", {}, {"use_npm_ci": False}),
+        ]
+    )
+    def test_get_default_options_various_languages_dependency_managers(
+        self, language, dependency_manager, build_properties, expected_options
+    ):
         metadata = {"BuildProperties": build_properties}
         options = ApplicationBuilder._get_build_options(
             "Function", language, "app.handler", dependency_manager, metadata