aws/aws-lambda-builders

sam build with Gradle packages unnecessary JARs.

shearn89 opened this issue · 3 comments

Description:

Possibly duplicate of #138, not sure.

I have a SAM project that uses Gradle, and I want to use a layer for my libraries (it's Java). Running gradle build correctly produces the right zip files, one of 32MB (my dependencies) and one of 109K (my lambda):

❯ gradle build

BUILD SUCCESSFUL in 1s
8 actionable tasks: 8 up-to-date
❯ ll myFunction/build/distributions/myFunction.zip
-rw-r--r--  1 ajshearn  staff   109K  2 Mar 14:08 myFunction/build/distributions/myFunction.zip
❯ ll layers/build/distributions/layers.zip
-rw-r--r--  1 ajshearn  staff    32M  2 Mar 14:08 layers/build/distributions/layers.zip

When I run sam build, it bundles all the libraries into my main function folder:

❯ rm -rf .aws-sam; sam build
Test the latest build changes for Java runtime 'SAM_CLI_BETA_MAVEN_SCOPE_AND_LAYER=1 sam build'. These changes will replace the existing flow on 1st of April 2022. Check https://github.com/aws/aws-sam-cli/issues/3639 for more information.
Building layer 'libs'
Running JavaGradleWorkflow:GradleBuild
Running JavaGradleWorkflow:JavaGradleCopyArtifacts
Building codeuri: /Users/ajshearn/repos/myLambda/nodeFunctions runtime: nodejs14.x metadata: {} architecture: arm64 functions: ['connectTriggerFunction']
package.json file not found. Continuing the build without dependencies.
Running NodejsNpmBuilder:CopySource
Building codeuri: /Users/ajshearn/repos/myLambda/myFunction runtime: java11 metadata: {} architecture: arm64 functions: ['myFunction']
Running JavaGradleWorkflow:GradleBuild
Running JavaGradleWorkflow:JavaGradleCopyArtifacts

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided

❯ du -sh .aws-sam/build/*
4.0K	.aws-sam/build/connectTriggerFunction
 36M	.aws-sam/build/libs
 36M	.aws-sam/build/processVoicePrintFunction
4.0K	.aws-sam/build/template.yaml

Steps to reproduce the issue:

  1. Clone this repo, which is pretty much sam init with the required gradle and template.yml modifications to add the layers.
  2. Check the README for the commands

Observed result:
JAR files packaged into main function zip even though they don't need to be.

Expected result:
Layers packaged correctly resulting in a "skinny" function zip.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)
M1 Macbook Pro with MacOS 12.2.1, SAM CLI version 1.40.1. Java 11 (Coretto). Gradle 7.4.

I found a workaround, which is tracked in the workaround branch in the linked repo.

I had to change the build method to makefile and then create and copy the files myself:

❯ git diff main
diff --git a/HelloWorldFunction/Makefile b/HelloWorldFunction/Makefile
new file mode 100644
index 0000000..e2a98f3
--- /dev/null
+++ b/HelloWorldFunction/Makefile
@@ -0,0 +1,5 @@
+.PHONY: build-HelloWorldFunction
+
+build-HelloWorldFunction:
+       gradle build
+       unzip -d $(ARTIFACTS_DIR)/ ./build/libs/HelloWorldFunction*.jar
diff --git a/template.yaml b/template.yaml
index 403565b..9c902cb 100644
--- a/template.yaml
+++ b/template.yaml
@@ -31,6 +31,8 @@ Resources:
           Properties:
             Path: /hello
             Method: get
+    Metadata:
+      BuildMethod: makefile
   libs:
     Type: AWS::Serverless::LayerVersion
     Properties:

But I do now get:

❯ tree .aws-sam
.aws-sam
├── build
│   ├── HelloWorldFunction
│   │   ├── META-INF
│   │   │   └── MANIFEST.MF
│   │   └── helloworld
│   │       └── App.class
│   ├── libs
│   │   └── java
│   │       ├── META-INF
│   │       │   └── MANIFEST.MF
│   │       └── lib
│   │           ├── aws-lambda-java-core-1.2.1.jar
│   │           ├── aws-lambda-java-events-3.11.0.jar
│   │           └── joda-time-2.6.jar
│   └── template.yaml
└── build.toml

8 directories, 8 files
jfuss commented

@shearn89 Unfortunately this is by design (https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/java_gradle/DESIGN.md has more details) and partially due to Layers not being a build-able target (I don't think Layers was even a thing when we launch sam build).

I am not sure how we can unwind this and still get what we are getting today. So I think what you called out as a workaround is actually the solution here. Makefile will give you the ability to escape out of our "canned" builders and therefore more power. Maybe there is a better way to handle this and open to hear thoughts (if you have any).

I do think this is a duplicate of #138 or at least #138 would also solve this.

I would prefer to push conversations into #138 so we can keep everything in one place (best we can) but let me know if you feel differently.

Hi @jfuss - ah, okay, no worries. I'm happy to mark this as closed as the workaround doesn't bother me too much. I'll add a comment to #138 to say I found a workaround so that it's easy to find for future search engine users. Thanks!