野牛目标的CMake自定义命令

bnlyeluc  于 2023-10-20  发布在  其他
关注(0)|答案(4)|浏览(148)

我正在尝试将一个旧的Autotools项目转换为CMake。在其中一个Makefile中,有一些使用lex和yacc的规则。我发现CMake有bison_targetflex_target。但是在Makefile中有一个sed规则来编辑生成的文件。以下是Makefile.am

docdir = @SIS_DOCDIR@
AM_CPPFLAGS = -DSIS -I../include
AM_YFLAGS = -d

BUILT_SOURCES = readlib.c readlib.h readliblex.c
CLEANFILES = $(BUILT_SOURCES)

noinst_LIBRARIES = libgenlib.a
libgenlib_a_SOURCES = aoi.c com_genlib.c comb.c comb.h count.c genlib.c \
    genlib.h genlib_int.h io.c nand.c permute.c sptree.c sptree.h \
    readlib.y readliblex.l
dist_doc_DATA = genlib.doc

readlib.h: readlib.c
readlib.c readlib.h: readlib.y
    $(YACC) $(YFLAGS) $(AM_YFLAGS) $<
    sed 's/yy/GENLIB_yy/g' y.tab.c > readlib.c
    sed 's/yy/GENLIB_yy/g' y.tab.h > readlib.h
    $(RM) y.tab.c y.tab.h
readliblex.c: readliblex.l readlib.h
    $(LEX) $(LFLAGS) $(AM_LFLAGS) $<
    sed 's/yy/GENLIB_yy/g' lex.yy.c > readliblex.c
    $(RM) lex.yy.c

我是这样翻译的:

set(CMAKE_C_FLAGS -DSIS)
add_library(genlib STATIC
        aoi.c
        com_genlib.c
        comb.c
        count.c
        genlib.c
        io.c
        nand.c
        permute.c
        sptree.c

        readlib.y
        readliblex.l
        )
find_package(BISON)
find_package(FLEX)
bison_target(readlib readlib.y -d)
add_custom_command(TARGET readlib POST_BUILD
        COMMAND sed 's/yy/GENLIB_yy/g' y.tab.c > readlib.c
        COMMAND sed 's/yy/GENLIB_yy/g' y.tab.h > readlib.h
        COMMAND rm -f y.tab.c y.tab.h
        )
flex_target(readliblex readliblex.l lex.yy.c)
add_custom_command(TARGET readliblex POST_BUILD
        COMMAND sed 's/yy/GENLIB_yy/g' lex.yy.c > readliblex.c
        COMMAND rm -f lex.yy.c
        )

问题是CMake没有将readlibreadliblex视为目标:

CMake Error at sis/genlib/CMakeLists.txt:28 (add_custom_command):
  No TARGET 'readlib' has been created in this directory.

CMake Error at sis/genlib/CMakeLists.txt:34 (add_custom_command):
  No TARGET 'readliblex' has been created in this directory.

我哪里错了?

jei2mxaa

jei2mxaa1#

bison_target并不创建CMake target。它只是add_custom_command()调用其中的 OUTPUT 文件,列在BISON_<name>_OUTPUT变量中。

kcugc4gi

kcugc4gi2#

鉴于bison_target没有创建目标,我最终使用了不同的解决方案:

set(CMAKE_C_FLAGS -DSIS)

find_package(BISON REQUIRED)
find_package(FLEX REQUIRED)

set(BISON_OUTPUT ${CMAKE_SOURCE_DIR}/sis/genlib/readlib.c)
if (BISON_FOUND)
    add_custom_command(
            OUTPUT ${BISON_OUTPUT}
            COMMAND ${BISON_EXECUTABLE}
            --output=${BISON_OUTPUT}
            -d
            ${CMAKE_SOURCE_DIR}/sis/genlib/readlib.y
            COMMENT "Generating readlib.c"
    )
endif ()

set(FLEX_OUTPUT ${CMAKE_SOURCE_DIR}/sis/genlib/readliblex.c)
if (FLEX_FOUND)
    add_custom_command(
            OUTPUT ${FLEX_OUTPUT}
            COMMAND ${FLEX_EXECUTABLE}
            --outfile=${FLEX_OUTPUT}
            ${CMAKE_SOURCE_DIR}/sis/genlib/readliblex.l
            COMMENT "Generating readliblex.c"
    )
endif ()

add_library(genlib STATIC
        aoi.c
        com_genlib.c
        comb.c
        count.c
        genlib.c
        io.c
        nand.c
        permute.c
        sptree.c
        ${BISON_OUTPUT}
        ${FLEX_OUTPUT}
        )
add_custom_command(TARGET genlib POST_BUILD
        COMMAND sed -i 's/yy/GENLIB_yy/g' ${CMAKE_SOURCE_DIR}/sis/genlib/readlib.c
        COMMAND sed -i 's/yy/GENLIB_yy/g' ${CMAKE_SOURCE_DIR}/sis/genlib/readlib.h
        COMMAND sed -i 's/yy/GENLIB_yy/g' ${CMAKE_SOURCE_DIR}/sis/genlib/readliblex.c
        )
hvvq6cgz

hvvq6cgz3#

与其更改生成的源代码来替换'yy'前缀,不如告诉野牛在生成代码时使用前缀:
对于2.6之前的野牛:

bison --name_prefix=GENLIB_yy

对于2.6之后的野牛:

bison -Dapi.prefix=GENLIB_yy
6tdlim6h

6tdlim6h4#

还有另一个选项可以使用add_custom_target()和其他CMake脚本。

add_library(genlib STATIC
  aoi.c
  com_genlib.c
  comb.c
  count.c
  genlib.c
  io.c
  nand.c
  permute.c
  sptree.c
  ${BISON_readlib_OUTPUTS}
)

find_package(BISON)

bison_target(readlib readlib.y COMPILE_FLAGS -d)

add_custom_target(
  patchReadlibFiles
  COMMAND ${CMAKE_COMMAND} -P "${CMAKE_SOURCE_DIR}/cmake/modules/Foo/patch_readlib_file.cmake"
  DEPENDS ${BISON_readlib_OUTPUTS}
)

add_dependencies(genlib patchReadlibFiles)

patch_readlib_file.cmake脚本的内容:

message(STATUS "Patching readlib.c")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/readlib.c" file_contents)
string(REPLACE "yy" "GENLIB_yy" file_contents "${file_contents}")
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/readlib.c" "${file_contents}")

message(STATUS "Patching readlib.h")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/readlib.h" file_contents)
string(REPLACE "yy" "GENLIB_yy" file_contents "${file_contents}")
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/readlib.h" "${file_contents}")

这样,patchReadlibFiles目标依赖于野牛执行,并且它将在构建genlib目标之前运行。

相关问题