cmake,将外部程序的结果作为预处理器定义传递
cmake, pass result of external program as preprocessor definitions
我是 cmake 的新手,所以如果我把事情搞砸了请纠正我,这应该使用 cmake 以外的其他方法来解决。
我有 main_program
,需要在构建阶段以 bindata 的形式指定多个其他 subprograms
。现在我通过 运行ning
构建它
cmake -DBINDATA1="\xde\xad..." -DBINDATA2="\xbe\xef" -DBINDATA3="..."
在代码中我将它们用作:
// main_program.cpp
int main() {
#ifdef BINDATA1
perform_action1(BINDATA1);
#endif
#ifdef BINDATA2
perform_action2(BINDATA2);
#endif
[...]
这是相当不干净的方法,因为任何时候我要更改其中之一 subprograms
我必须从中生成 bindata 并将其传递给 cmake 命令。
我想做的是有一个项目结构:
/
-> main_program
-> subprograms
-> subprogram1
-> subprogram2
-> subprogram3
当我 运行 cmake 时,我想
- 编译每个
subprograms
- 通过 运行ning
generate_bindata
程序在它们上面 从它们中的每一个生成 shellcode
- 构建
main_program
从第 2 步传递 bindatas
and when I run cmake, I would like to
- compile each of subprograms
- generate shellcode from each of them, by running generate_shellcode program on them
- build main_program passing shellcodes from step 2
那我们就开始吧。让我们先写一个简短的脚本来生成一个 header:
#!/bin/sh
# ./custom_script.sh
# TODO: Find out proper quoting and add `"` is necessarily. Ie. details.
# Prefer to use actual real variables like `static const char *shellcode[3]`
# instead of raw macro defines.
cat > "" <<EOF
#define SHELLCODE1 $(cat "")
#define SHELLCODE2 $(cat "")
#define SHELLCODE3 $(cat "")
EOF
为了便于移植,请在cmake 中编写此脚本。此脚本将在构建阶段 运行 生成编译所需的 header。然后,“模型依赖关系”——找出究竟是什么依赖于什么。然后在cmake中写入:
add_executable(subprogram1 sources.c...)
add_executable(subprogram2 sources.c...)
add_executable(subprogram3 sources.c...)
for(i IN ITEMS 1 2 3)
add_custom_target(
COMMENT Generate shellcode${i}.txt with the content of shellcode
# TODO: redirection in COMMAND should be removed, or the command
# should be wrapped in `sh -c ...`.
COMMAND $<TARGET_FILE:subprogram${i}> | generate_shellcode > ${CMAKE_CURRENT_BINARY_DIR}/shellcode${i}.txt
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shellcode${i}.txt
DEPENDS $<TARGET_FILE:subprogram${i}> generate_shellcode
)
endfor()
add_custom_command(
COMMENT Generate shellcodes.h from shellcode1.txt shellcode2.txt and shellcode3.txt
COMMAND sh custom_script.sh
${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h
${CMAKE_CURRENT_BINARY_DIR}/shellcode1.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode2.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode3.txt
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/shellcode1.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode2.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode3.txt
)
# Then compile the final executable
add_executable(main main.c ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h)
# Don't forget to add includes!
target_include_directories(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
# or you may add dependency to a single file instead of target
# Like below only to a single shellcodeswrapper.c file only
# This should help build parallelization.
set_source_files_properties(main.c OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h)
# Or you may add a target for shelcodes header file and depend on it
add_custom_target(shellcodes DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h)
add_executable(main main.c)
target_include_directories(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(main shellcodes)
然后是你的主文件:
#include <shellcodes.h> // compiler will find it in BINARY_DIR
int main() {
perform_action1(SHELLCODE1);
perform_action2(SHELLCODE2);
}
为了避免每次都重新编译所有源文件,我建议写一个包装器:
// shellcodewrapper.c
#include <shellcodes.h>
// preserve memory by not duplicating code in each TU
static const char shellcode1[] = SHELLCODE1;
// only this file will be recompiled when SHELLCODE changes
const char *get_shellcode1(void) {
return shellcode1;
}
// shellcodewrapper.h
const char *get_shellcode1(void);
// main.c
#include <shellcodewrapper.h>
int main() {
perform_action1(get_shellcode1());
perform_action2(get_shellcode2());
}
这样当您更改“SHELLCODE”生成器时,只会编译 shellcodewrapper.c
,从而实现超快的编译时间。
注意依赖关系是如何传输的以及它是如何工作的——我在 BINARY_DIR
中使用 files 将结果从一个命令传输到另一个命令,然后这些 files 跟踪更改的内容并在链下方传输依赖项。跟踪 DEPENDS
中的依赖项和 add_custom_command
中的 OUTPUT
并且 cmake 将以正确的顺序正确编译。
我是 cmake 的新手,所以如果我把事情搞砸了请纠正我,这应该使用 cmake 以外的其他方法来解决。
我有 main_program
,需要在构建阶段以 bindata 的形式指定多个其他 subprograms
。现在我通过 运行ning
cmake -DBINDATA1="\xde\xad..." -DBINDATA2="\xbe\xef" -DBINDATA3="..."
在代码中我将它们用作:
// main_program.cpp
int main() {
#ifdef BINDATA1
perform_action1(BINDATA1);
#endif
#ifdef BINDATA2
perform_action2(BINDATA2);
#endif
[...]
这是相当不干净的方法,因为任何时候我要更改其中之一 subprograms
我必须从中生成 bindata 并将其传递给 cmake 命令。
我想做的是有一个项目结构:
/
-> main_program
-> subprograms
-> subprogram1
-> subprogram2
-> subprogram3
当我 运行 cmake 时,我想
- 编译每个
subprograms
- 通过 运行ning
generate_bindata
程序在它们上面 从它们中的每一个生成 shellcode
- 构建
main_program
从第 2 步传递 bindatas
and when I run cmake, I would like to
- compile each of subprograms
- generate shellcode from each of them, by running generate_shellcode program on them
- build main_program passing shellcodes from step 2
那我们就开始吧。让我们先写一个简短的脚本来生成一个 header:
#!/bin/sh
# ./custom_script.sh
# TODO: Find out proper quoting and add `"` is necessarily. Ie. details.
# Prefer to use actual real variables like `static const char *shellcode[3]`
# instead of raw macro defines.
cat > "" <<EOF
#define SHELLCODE1 $(cat "")
#define SHELLCODE2 $(cat "")
#define SHELLCODE3 $(cat "")
EOF
为了便于移植,请在cmake 中编写此脚本。此脚本将在构建阶段 运行 生成编译所需的 header。然后,“模型依赖关系”——找出究竟是什么依赖于什么。然后在cmake中写入:
add_executable(subprogram1 sources.c...)
add_executable(subprogram2 sources.c...)
add_executable(subprogram3 sources.c...)
for(i IN ITEMS 1 2 3)
add_custom_target(
COMMENT Generate shellcode${i}.txt with the content of shellcode
# TODO: redirection in COMMAND should be removed, or the command
# should be wrapped in `sh -c ...`.
COMMAND $<TARGET_FILE:subprogram${i}> | generate_shellcode > ${CMAKE_CURRENT_BINARY_DIR}/shellcode${i}.txt
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shellcode${i}.txt
DEPENDS $<TARGET_FILE:subprogram${i}> generate_shellcode
)
endfor()
add_custom_command(
COMMENT Generate shellcodes.h from shellcode1.txt shellcode2.txt and shellcode3.txt
COMMAND sh custom_script.sh
${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h
${CMAKE_CURRENT_BINARY_DIR}/shellcode1.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode2.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode3.txt
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/shellcode1.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode2.txt
${CMAKE_CURRENT_BINARY_DIR}/shellcode3.txt
)
# Then compile the final executable
add_executable(main main.c ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h)
# Don't forget to add includes!
target_include_directories(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
# or you may add dependency to a single file instead of target
# Like below only to a single shellcodeswrapper.c file only
# This should help build parallelization.
set_source_files_properties(main.c OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h)
# Or you may add a target for shelcodes header file and depend on it
add_custom_target(shellcodes DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/shellcodes.h)
add_executable(main main.c)
target_include_directories(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(main shellcodes)
然后是你的主文件:
#include <shellcodes.h> // compiler will find it in BINARY_DIR
int main() {
perform_action1(SHELLCODE1);
perform_action2(SHELLCODE2);
}
为了避免每次都重新编译所有源文件,我建议写一个包装器:
// shellcodewrapper.c
#include <shellcodes.h>
// preserve memory by not duplicating code in each TU
static const char shellcode1[] = SHELLCODE1;
// only this file will be recompiled when SHELLCODE changes
const char *get_shellcode1(void) {
return shellcode1;
}
// shellcodewrapper.h
const char *get_shellcode1(void);
// main.c
#include <shellcodewrapper.h>
int main() {
perform_action1(get_shellcode1());
perform_action2(get_shellcode2());
}
这样当您更改“SHELLCODE”生成器时,只会编译 shellcodewrapper.c
,从而实现超快的编译时间。
注意依赖关系是如何传输的以及它是如何工作的——我在 BINARY_DIR
中使用 files 将结果从一个命令传输到另一个命令,然后这些 files 跟踪更改的内容并在链下方传输依赖项。跟踪 DEPENDS
中的依赖项和 add_custom_command
中的 OUTPUT
并且 cmake 将以正确的顺序正确编译。