生成的 C 文件和 autotools
A generated C file and autotools
在基于 autoools 的构建中,我想用生成的 C 文件替换版本控制的 C 文件。
这个虚拟的,你好世界示例的作品:
#!/bin/sh -ex
cat > configure.ac <<EOF
AC_INIT([hello], [0.01])
AC_PREREQ([2.68])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.11])
AC_CONFIG_FILES([Makefile])
AC_PROG_CC
AC_OUTPUT
EOF
cat > autogen.sh <<EOF
touch NEWS README AUTHORS ChangeLog COPYING
autoreconf -i
EOF
chmod +x autogen.sh
printf "
bin_PROGRAMS = hello
hello_SOURCES = hello.c
hello.c: generate
\t./generate
" > Makefile.am
cat > hello.c <<EOF
#include <stdio.h>
int main()
{
puts("hello world");
return 0;
}
EOF
cat > generate <<EOF0
#!/bin/sh
cat > hello.c <<EOF
#include <stdio.h>
int main()
{
puts("HELLO WORLD");
return 0;
}
EOF
EOF0
chmod +x generate
./autogen.sh
./configure
make -j$(nproc)
除非它阻止我进行树外构建,例如:
mkdir B
cd B
../configure
make
我通常可以在基于 autotools 的包中执行此操作。
我怎样才能生成 C 文件,以便树外构建继续工作?
重要的是要记住 make
对目录了解不多;在大多数情况下,一切都是一个字符串。这并不总是那么明显,但是当您尝试编写可以处理源外构建的构建系统时,它往往会真正困扰您。
您提供了一个构建规则,其中 hello.c
取决于您的 generate
脚本,这在原则上是可以的。 Make
甚至可以在源代码外构建中正确处理依赖项处理,在源目录中找到 generate
脚本。但是构建规则 explicitly 运行s ./generate
中的配方在执行外源构建时不存在。此外,依赖关系和构建规则之间存在脱节:'generate' 与 './generate' 不同。
主要有两种选择:
在您的构建规则中,仅依靠自动 make
变量(例如 $<
)来引用依赖项。当 make
执行源外构建时,它会使用可行的路径初始化自动变量。
通过显式路径引用源目录中的文件。
要单独使用选项 (1),您需要解决在(可能)不在路径中时如何 运行 generate
脚本的问题。您可以通过 shell 间接地 运行 来做到这一点。在这种情况下你想要的 make 规则是
hello.c: generate
$(SHELL) $<
这应该适用于源内或源外构建。 $(SHELL)
make 变量应由 Autotools 提供。
另一方面,要使用选项 (2),您可能会依赖 $(srcdir)
或 $(top_srcdir)
:
# Note that the dependency name will always contain a '/':
hello.c: $(srcdir)/generate
$<
(您也可以在构建配方中使用路径命名生成脚本,但通常最好避免重复。)$(srcdir)
和 $(top_srcdir)
变量也由自动工具。前者指的是源码树中与我们当前构建的build-tree目录对应的目录;后者指的是包含 configure
脚本的源代码树目录。
在这两者中,本着外源构建的精神,我给 (1) 的评分更高一些,但实际上并没有太大区别。
在基于 autoools 的构建中,我想用生成的 C 文件替换版本控制的 C 文件。
这个虚拟的,你好世界示例的作品:
#!/bin/sh -ex
cat > configure.ac <<EOF
AC_INIT([hello], [0.01])
AC_PREREQ([2.68])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.11])
AC_CONFIG_FILES([Makefile])
AC_PROG_CC
AC_OUTPUT
EOF
cat > autogen.sh <<EOF
touch NEWS README AUTHORS ChangeLog COPYING
autoreconf -i
EOF
chmod +x autogen.sh
printf "
bin_PROGRAMS = hello
hello_SOURCES = hello.c
hello.c: generate
\t./generate
" > Makefile.am
cat > hello.c <<EOF
#include <stdio.h>
int main()
{
puts("hello world");
return 0;
}
EOF
cat > generate <<EOF0
#!/bin/sh
cat > hello.c <<EOF
#include <stdio.h>
int main()
{
puts("HELLO WORLD");
return 0;
}
EOF
EOF0
chmod +x generate
./autogen.sh
./configure
make -j$(nproc)
除非它阻止我进行树外构建,例如:
mkdir B
cd B
../configure
make
我通常可以在基于 autotools 的包中执行此操作。 我怎样才能生成 C 文件,以便树外构建继续工作?
重要的是要记住 make
对目录了解不多;在大多数情况下,一切都是一个字符串。这并不总是那么明显,但是当您尝试编写可以处理源外构建的构建系统时,它往往会真正困扰您。
您提供了一个构建规则,其中 hello.c
取决于您的 generate
脚本,这在原则上是可以的。 Make
甚至可以在源代码外构建中正确处理依赖项处理,在源目录中找到 generate
脚本。但是构建规则 explicitly 运行s ./generate
中的配方在执行外源构建时不存在。此外,依赖关系和构建规则之间存在脱节:'generate' 与 './generate' 不同。
主要有两种选择:
在您的构建规则中,仅依靠自动
make
变量(例如$<
)来引用依赖项。当make
执行源外构建时,它会使用可行的路径初始化自动变量。通过显式路径引用源目录中的文件。
要单独使用选项 (1),您需要解决在(可能)不在路径中时如何 运行 generate
脚本的问题。您可以通过 shell 间接地 运行 来做到这一点。在这种情况下你想要的 make 规则是
hello.c: generate
$(SHELL) $<
这应该适用于源内或源外构建。 $(SHELL)
make 变量应由 Autotools 提供。
另一方面,要使用选项 (2),您可能会依赖 $(srcdir)
或 $(top_srcdir)
:
# Note that the dependency name will always contain a '/':
hello.c: $(srcdir)/generate
$<
(您也可以在构建配方中使用路径命名生成脚本,但通常最好避免重复。)$(srcdir)
和 $(top_srcdir)
变量也由自动工具。前者指的是源码树中与我们当前构建的build-tree目录对应的目录;后者指的是包含 configure
脚本的源代码树目录。
在这两者中,本着外源构建的精神,我给 (1) 的评分更高一些,但实际上并没有太大区别。