我有一个shell脚本,它接受一个JSON文件并输出一个.h
文件,我的一个目标依赖于该文件。似乎CMake的add_custom_command
是我需要完成的,但是我无法生成头文件。我已经尝试过使用this post和this post中的信息考虑的所有组合。
以下是我可以创建的最简单的方法来重现我遇到的问题。
我的项目结构如下:
. ├── CMakeLists.txt ├── main.c └── res ├── generate.sh └── input.json
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;
}
#!/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
{
"1": {
"attr1": "value1",
"attr2": "value2"
},
"2": {
"attr1": "value1",
"attr2": "value2"
}
}
答案 0 :(得分: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
)
注意:
DEPENDS
该命令仅在依赖项实际更改时执行。CMAKE_CURRENT_BINARY_DIR
中(即 build 树中的目录对应于上述CMakeLists的位置) source 树中的.txt),并将其用作可执行文件的输入。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将自动触发标头的重建。
答案 1 :(得分: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)