I have a shell script that takes a JSON file in and outputs a .h
file which one of my targets depends on. It would appear that CMake's add_custom_command
is what I need to accomplish this, but I can't get the header file to generate. I have tried just about every combination I could think of using the information from this post and this post.
Below is the simplest I could create to reproduce the issues I am encountering.
My project structure is as follows:
. ├── CMakeLists.txt ├── main.c └── res ├── generate.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"
}
}