使用 GNU make 将 java 内部类文件包含到 JAR 中

发布于 2025-01-08 01:31:03 字数 862 浏览 0 评论 0原文

我有一个java项目,它使用GNU make来编译源文件并创建一个JAR。引入嵌套枚举后,将创建一个新文件 main_classname$inner_classname.class

我在将此文件包含在 JAR 中时遇到问题。

下面是我的 Makefile 的相关部分:

JARNAME=Project.jar

CLASSES=\
   Main.class \
   Main$$Inner.class

这是 Makefile 包含的 targets 文件的摘录:

$(JARNAME): $(CLASSES)
   jar cvf $(JARNAME) $(CLASSES)

内部类不会添加到 JAR 中,因为 shell 在之后扩展了字符串美元符号。

我尝试在 $$ 前面放一个反斜杠,即 Main\$$Inner.class,但提出抱怨:

make:*没有规则来创建目标Main\$Inner.class',需要 通过Project.jar'。停止。

另一种方法是尝试以下更改,以便转义美元,但无济于事:

ESCAPED_CLASSES=$(patsubst %$$,%\$$,$(CLASSES))
$(JARNAME): $(CLASSES)
   jar cvf $(JARNAME) $(ESCAPED_CLASSES)

可以采取什么措施来克服此问题,尤其是在不将特殊情况硬编码到 targets 文件中的情况下?

I have a java project which uses GNU make to compile the source files and also create a JAR. After I introduced a nested enum, a new file main_classname$inner_classname.class is getting created.

I am having trouble including this file in the JAR.

Below is the relevant portion of my Makefile:

JARNAME=Project.jar

CLASSES=\
   Main.class \
   Main$Inner.class

And this is an excerpt from the targets file that is included by the Makefile:

$(JARNAME): $(CLASSES)
   jar cvf $(JARNAME) $(CLASSES)

The inner class doesn't get added to the JAR because the shell expands the string after the dollar sign.

I tried putting a back-slash in front of $$, i.e. Main\$$Inner.class, but make complains:

make: * No rule to make target Main\$Inner.class', needed
by
Project.jar'. Stop.

Another approach was to try the following change so that the dollar is escaped, but to no avail:

ESCAPED_CLASSES=$(patsubst %$,%\$,$(CLASSES))
$(JARNAME): $(CLASSES)
   jar cvf $(JARNAME) $(ESCAPED_CLASSES)

What can be done to overcome this problem, especially without hard-coding special cases to the targets file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁吢 2025-01-15 01:31:04

(未经测试)

如果您不能只对所有类文件使用通配符来获取文件名,但需要显式命名它,则需要告诉 Make 您的美元符号美元符号!

这是在 Make 中通过使用另一个美元符号转义来完成的。来自 http://www.gnu.org/software/make/手册/make.html#规则语法

因为美元符号用于开始进行变量引用,如果
您确实希望在目标或先决条件中出现美元符号,您必须
写入其中两个“$$”(请参阅​​如何使用变量)。如果你有
启用了二次扩展(请参阅二次扩展)并且您想要一个
先决条件列表中的文字美元符号,您必须实际编写
四个美元符号('$$$$')。

在这种情况下,您需要两个真正的美元符号。据此,它意味着 Makefile 中的四个甚至个美元符号。

(untested)

If you cannot just use a wildcard for all class files to get the file names but need to name it explicitly, you need to tell Make that your dollars signs are dollar signs!

This is in Make done by escaping with another dollar sign. From http://www.gnu.org/software/make/manual/make.html#Rule-Syntax

Because dollar signs are used to start make variable references, if
you really want a dollar sign in a target or prerequisite you must
write two of them, ‘$$’ (see How to Use Variables). If you have
enabled secondary expansion (see Secondary Expansion) and you want a
literal dollar sign in the prerequisites list, you must actually write
four dollar signs (‘$$$$’).

In this case you want two real dollar signs. According to this it means either four or even eight dollar signs in the Makefile.

无边思念无边月 2025-01-15 01:31:04

你就快到了。我使用 $(subst $$,\$$,$(CLASSES)) 并将美元加倍(就像你所做的那样)。

这个 GNU makefile 对我有用:

JAR     =       /usr/bin/jar
CLASSES = org/apache/commons/csv/CSVParser$Token.class

executable: poo.jar

poo.jar:      $(CLASSES)
    $(JAR) cvf $@ $(subst $,\$,$(CLASSES))

You were almost there. I use $(subst $$,\$$,$(CLASSES)) and double up the dollars (as you did).

This GNU makefile works for me:

JAR     =       /usr/bin/jar
CLASSES = org/apache/commons/csv/CSVParser$Token.class

executable: poo.jar

poo.jar:      $(CLASSES)
    $(JAR) cvf $@ $(subst $,\$,$(CLASSES))
零時差 2025-01-15 01:31:04

您使用 $(patsubst) 的想法似乎是合理的,但我认为您的调用方式不正确。您是否尝试过:

ESCAPED_CLASSES := $(patsubst $,\$,$(CLASSES))

另请注意,您应该使用 := 而不是 = ,否则您将浪费大量时间重新评估 $(patsubst)< /code> 每次 $(ESCAPED_CLASSES) 展开时。

Your idea to use $(patsubst) appears to be sound, but I think you're calling it incorrectly. Have you tried:

ESCAPED_CLASSES := $(patsubst $,\$,$(CLASSES))

Note also that you should be using := instead of = or you'll waste lots of time re-evaluating the $(patsubst) every time $(ESCAPED_CLASSES) is expanded.

云巢 2025-01-15 01:31:04

这就是我最终解决问题的方法,尽管我希望有更好的答案。或者也许我应该停止在 Java 项目中使用 make

我在 Makefile 中定义了一个新变量,现在的样子是这样的:

JARNAME=Project.jar

CLASSES=\
   Main.class\
   Main$Inner.class

ESCAPED_CLASSES=\
   Main.class\
   Main\$Inner.class

因为 ESCAPED_CLASSES 可能不一定由所有使用的 Makefile 定义targets 文件,我按以下方式处理此问题,以便将规则保留在 targets 文件中通用:

ESCAPED_CLASSES ?= $(CLASSES)

$(JARNAME): $(CLASSES)
   jar cvf $(JARNAME) $(ESCAPED_CLASSES)

?= 将确保进行分配仅当变量尚未定义时 - 描述条件变量赋值运算符的 GNU make 手册

This is how I finally solved the problem, though I hope there exists a better answer. Or may be I should stop using make for Java projects.

I defined a new variable in the Makefile and this is how it looks now:

JARNAME=Project.jar

CLASSES=\
   Main.class\
   Main$Inner.class

ESCAPED_CLASSES=\
   Main.class\
   Main\$Inner.class

Because ESCAPED_CLASSES may not be necessarily defined by all the Makefiles that use targets file, I handled this in the following way so as to keep rules in targets file generic:

ESCAPED_CLASSES ?= $(CLASSES)

$(JARNAME): $(CLASSES)
   jar cvf $(JARNAME) $(ESCAPED_CLASSES)

?= will make sure that assignment takes place only if the variable is not already defined - GNU make manual describing conditional variable assignment operator

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文