【问题标题】:CMake generate C header via shell scriptCMake 通过 shell 脚本生成 C 头文件
【发布时间】:2013-02-11 02:17:34
【问题描述】:

我有一个 shell 脚本,它接收一个 JSON 文件并输出一个 .h 文件,这是我的一个目标所依赖的。看起来 CMake 的 add_custom_command 是我需要完成的,但我无法生成头文件。使用this postthis post 中的信息,我已经尝试了几乎所有我能想到的组合。

下面是我可以创建的最简单的方法来重现我遇到的问题。

我的项目结构如下:

. ├── CMakeLists.txt ├── main.c └── 资源 ├── 生成.sh └── input.json

CMakeLists.txt


cmake_minimum_required(VERSION 2.8)
project(test)

set(TEST_DATA_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test_data.h)
add_custom_command(
    OUTPUT ${TEST_DATA_OUTPUT}
    COMMAND res/generate.sh h res/input.json ${TEST_DATA_OUTPUT}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMENT "Generates the header file containing the JSON data."
)

# add the binary tree to the search path for include files so we
# will fine the generated files
include_directories(${CMAKE_CURRENT_BINARY_DIR})

set(SRCS main.c)
add_executable(test ${SRCS})

main.c


#include <stdio.h>

#include "test_data.h"

int main(int argc, char** argv)
{
    printf("%s\n", TEST_DATA);
    return 0;
}

res/generate.sh


#!/bin/sh
#
# Converts the JSON to a C header file to be used as a resource file.

print_usage()
{
cat << EOF
USAGE:
    $0 h INPUT

DESCRIPTION:
    Outputs JSON data to another format.

EOF
}

to_h()
{
cat << EOF
#ifndef TEST_DATA_H
#define TEST_DATA_H

static const char* TEST_DATA =
"$(cat "$1" | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/"\n"/g')";

#endif // TEST_DATA_H
EOF
}

case "$1" in
h)
    if [ $# -eq 3 ] ; then
        to_h "$2" > "$3"
    elif [ $# -eq 2 ] ; then
        to_h "$2"
    else
        echo "no input file specified" 1>&2
    fi
    ;;
*)
    print_usage
    ;;
esac

exit 0

res/input.json


{
    "1": {
        "attr1": "value1",
        "attr2": "value2"
    },
    "2": {
        "attr1": "value1",
        "attr2": "value2"
    }
}

【问题讨论】:

  • 在源代码外构建中,此命令将失败,您的第一个链接提供了解决方案。否则,请阅读和/或提供构建日志以了解构建过程尝试运行您的自定义命令时实际发生的情况。
  • 依赖generated.h的目标是什么?你能告诉我们你的目标吗? add_custom_command 只会在您尝试构建它或依赖它的东西时执行。

标签: c cmake build-automation


【解决方案1】:

这是一个示例 CMakeLists.txt,它使用 Ragel 读取输入文件 (nstrip.rl),生成输出文件 (nstrip.c),并将输出文件编译/链接到二进制文件。

set(RAGEL_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/nstrip.c)

add_executable(
  nstrip
    ${RAGEL_OUTPUT}
  )
set_target_properties(
  nstrip
  PROPERTIES
    COMPILE_FLAGS -std=c99
  )

find_program(RAGEL ragel)
add_custom_command(
  OUTPUT             ${RAGEL_OUTPUT}
  COMMAND            ${RAGEL} -G2 -o ${RAGEL_OUTPUT} nstrip.rl
  DEPENDS            nstrip.rl
  WORKING_DIRECTORY  ${CMAKE_CURRENT_SOURCE_DIR}
  COMMENT            "Ragel: Generating Statemachine"
  VERBATIM
  )

注意事项:

  • 使用DEPENDS,该命令仅在依赖项实际更改时才会执行。
  • 这是为源外构建准备的,因为它将生成的文件放在CMAKE_CURRENT_BINARY_DIR(即build树中的目录对应于上述CMakeLists.txt的位置source 树中),并将其用作可执行文件的输入。
  • 同样,它还执行命令,并将WORKING_DIRECTORY 设置为上述CMakeLists.txt 所在的位置,因此您可以使用相对路径引用源文件(此处为nstrip.rl)(您也可以以其他方式执行此操作周围)。

对于您的情况,您需要告诉 CMake 在哪里可以找到标头:

# assuming you generate into the build tree
include_directories("${CMAKE_CURRENT_BINARY_DIR}")`

此外,如果生成的可执行文件是位于源代码树中而不是 $PATH 上的脚本,请忽略 find_program,只需将脚本添加到 DEPENDS。每当您更改输入文件(json)脚本本身时,CMake 都会自动触发头文件的重建。

【讨论】:

    【解决方案2】:

    现在我已经获得了更多使用 CMake 的经验,我回来看看我是否可以让它工作。下面显示了需要更改的 2 行。

    diff --git a/CMakeLists.txt b/CMakeLists.txt
    index 6aa2ac6..5d80124 100644
    --- a/CMakeLists.txt
    +++ b/CMakeLists.txt
    @@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 2.8)
     project(test)
    
     set(TEST_DATA_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test_data.h)
    -add_custom_command(
    -    OUTPUT ${TEST_DATA_OUTPUT}
    +add_custom_target(generate
         COMMAND res/generate.sh h res/input.json ${TEST_DATA_OUTPUT}
         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
         COMMENT "Generates the header file containing the JSON data."
    @@ -15,3 +14,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
    
     set(SRCS main.c)
     add_executable(test ${SRCS})
    +add_dependencies(test generate)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-10
      • 2016-02-06
      • 1970-01-01
      相关资源
      最近更新 更多