1

我有一个 shell 脚本,它接收一个 JSON 文件并输出一个.h我的目标之一所依赖的文件。看来 CMakeadd_custom_command是我完成此任务所需的,但我无法生成头文件。我已经尝试了几乎所有我能想到的使用这篇文章这篇文章中的信息的组合。

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

我的项目结构如下:

.
├── 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})

主程序


#include <stdio.h>

#include "test_data.h"

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

资源/生成.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"
    }
}
4

2 回答 2

0

这是一个示例 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
  )

笔记:

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

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

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

此外,如果生成的可执行文件是位于源代码树而$PATH不是. 每当您更改输入文件 (json)脚本本身时,CMake 都会自动触发头文件的重建。find_programDEPENDS

于 2013-02-11T12:38:45.773 回答
0

现在我已经获得了更多的 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)
于 2014-08-14T01:51:46.387 回答