When converting DocBook, pandoc can't find image - cmake

I'm writing documentation for a program and would like to include a screenshot. The CMakeLists.txt file, which is in the doc subdirectory, looks like this:
find_program(PANDOC pandoc)
if (PANDOC)
add_custom_command(OUTPUT perfecttin.pdf MAIN_DEPENDENCY perfecttin.xml COMMAND pandoc -f docbook -o perfecttin.pdf -V papersize=a4 --data-dir=${PROJECT_SOURCE_DIR}/doc ${PROJECT_SOURCE_DIR}/doc/perfecttin.xml)
add_custom_target(perfecttin-doc ALL DEPENDS perfecttin.pdf)
endif ()
The section of the DocBook file looks like this:
<section id="window">
<title>Main Window</title>
<mediaobject>
<imageobject>
<imagedata fileref="window1.png" format="PNG"/>
</imageobject>
</mediaobject>
</section>
window1.png is in the same directory as CMakeLists.txt and perfecttin.xml. I've tried it with and without --data-dir=${PROJECT_SOURCE_DIR}/doc, and I get the same error:
[pandoc warning] Could not find image `window1.png', skipping...
How do I tell pandoc where to look for the image?

The option to do this is --resource-path, but that is not available on the version of pandoc on Ubuntu Bionic. So to build the documentation on a newer version, but not break the entire build on an older version, I added code to check whether pandoc supports the option. Here is the working CMakeLists.txt:
find_program(PANDOC pandoc)
if (PANDOC)
execute_process(COMMAND ${PANDOC} "--resource-path=/" INPUT_FILE /dev/null ERROR_FILE /dev/null RESULT_VARIABLE pandoc_exit)
endif ()
if (PANDOC AND NOT pandoc_exit)
add_custom_command(OUTPUT perfecttin.pdf MAIN_DEPENDENCY perfecttin.xml COMMAND pandoc -f docbook -o perfecttin.pdf -V papersize=a4 --resource-path=${PROJECT_SOURCE_DIR}/doc ${PROJECT_SOURCE_DIR}/doc/perfecttin.xml)
add_custom_target(perfecttin-doc ALL DEPENDS perfecttin.pdf)
endif ()
if (PANDOC AND NOT pandoc_exit) sounds backward, but the exit code for success is 0, which CMake takes as false, while the code for error is 2, which it takes as true.

Related

cmake incorrectly escapes bison target option

Take this minimized example
Critical place:
bison_target(parser
numgrammar.y
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
COMPILE_FLAGS "--defines=${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh")
Then please create some folder with space inside name like:
> mkdir "test folder" && cd "test folder"
> cmake ${ADVGRAMMAR}
> make VERBOSE=1
You will see something like:
> /usr/bin/bison --defines=/mnt/c/research/test folder/advgrammar/build/numgrammar.tab.hh -d -o ....
You see the problem: space in "test folder" not escaped.
Ok, now lets try to escape:
bison_target(parser
numgrammar.y
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
COMPILE_FLAGS "--defines=\"${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh\"")
You will see:
/usr/bin/bison --defines=\"/mnt/c/research/test folder/advgrammar/build/numgrammar.tab.hh\" -d -o ....
Now cmake added wrong escape mark for quotes.
Of course no problem if cmake in some neutral-named folder without spaces, but I want any folder.
I tried to google really hard. I tried string with CONFIGURE, I tried generator expressions, I tried this and that and everything and looks like I can't get behavior I want.
I want simply this:
/usr/bin/bison --defines="/mnt/c/research/test folder/advgrammar/build/numgrammar.tab.hh" -d -o ....
Of course I can do it with my own custom target. But I want this with bison_target.
Really need cmake experts help. Any ideas appreciated.
This is because the bison_target macro calls1 separate_arguments on the value of the COMPILE_FLAGS without using the new form that respects native shell rules (it just blindly replaces spaces with semicolons).
Unfortunately, the macro doesn't give you a chance to inject flags in a more modern way, either, so the best I could come up with was to use the variable_watch command to hack at the internals of bison_target, at least until this bug is fixed.
Here's a full example:
cmake_minimum_required(VERSION 3.22)
project(test)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
# Hack around FindBISON's incorrect use of separate_arguments
if (CMAKE_VERSION VERSION_LESS 3.24)
function(patch_flags variable access value ip stack)
set(invalid "${CMAKE_CURRENT_BINARY_DIR}")
separate_arguments(invalid)
string(REPLACE "${invalid}" "${CMAKE_CURRENT_BINARY_DIR}" "${variable}" "${value}")
set("${variable}" "${${variable}}" PARENT_SCOPE)
endfunction()
variable_watch(BISON_TARGET_cmdopt patch_flags)
endif ()
flex_target(scanner
numgrammar.l
"${CMAKE_CURRENT_BINARY_DIR}/lexer.cc"
)
bison_target(
parser
numgrammar.y
"${CMAKE_CURRENT_BINARY_DIR}/parser.cc"
COMPILE_FLAGS "--defines=${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh"
)
add_flex_bison_dependency(scanner parser)
add_executable(
numgrammar
driver.cc
${BISON_parser_OUTPUTS}
${FLEX_scanner_OUTPUTS}
)
And here's a shell interaction:
$ cmake -G Ninja -S . -B "build with space"
$ cmake --build "build with space" -- -nv # n = dry-run, v = verbose
[1/6] cd "/home/alex/test/build with space" && /usr/bin/bison "--defines=/home/alex/test/build with space/numgrammar.tab.hh" -d -o "/home/alex/test/build with space/parser.cc" /home/alex/test/numgrammar.y
[2/6] cd "/home/alex/test/build with space" && /usr/bin/flex "-o/home/alex/test/build with space/lexer.cc" /home/alex/test/numgrammar.l
[3/6] /usr/bin/c++ -MD -MT CMakeFiles/numgrammar.dir/driver.cc.o -MF CMakeFiles/numgrammar.dir/driver.cc.o.d -o CMakeFiles/numgrammar.dir/driver.cc.o -c /home/alex/test/driver.cc
[4/6] /usr/bin/c++ -MD -MT CMakeFiles/numgrammar.dir/parser.cc.o -MF CMakeFiles/numgrammar.dir/parser.cc.o.d -o CMakeFiles/numgrammar.dir/parser.cc.o -c '/home/alex/test/build with space/parser.cc'
[5/6] /usr/bin/c++ -MD -MT CMakeFiles/numgrammar.dir/lexer.cc.o -MF CMakeFiles/numgrammar.dir/lexer.cc.o.d -o CMakeFiles/numgrammar.dir/lexer.cc.o -c '/home/alex/test/build with space/lexer.cc'
[6/6] : && /usr/bin/c++ CMakeFiles/numgrammar.dir/driver.cc.o CMakeFiles/numgrammar.dir/parser.cc.o CMakeFiles/numgrammar.dir/lexer.cc.o -o numgrammar && :
As you can see the bison rule correctly quotes the spaces.
... /usr/bin/bison "--defines=/home/alex/test/build with space/numgrammar.tab.hh" ...
1. See https://github.com/Kitware/CMake/blob/6b6bdcbb64e1aa2ddac4f09a0807553f5684165a/Modules/FindBISON.cmake#L131 and https://github.com/Kitware/CMake/blob/6b6bdcbb64e1aa2ddac4f09a0807553f5684165a/Modules/FindBISON.cmake#L249
Just in case: there is an option DEFINES_FILE in the bison_target macro. As for me it looks like more portable. You can use it instead of COMPILE_FLAGS.
bison_target(parser
numgrammar.y
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
## COMPILE_FLAGS "--defines=${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh")
DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh
)
It works fine at least on Catalina.
$ cmake -G Ninja -S . -B "build with spaces"
$ cmake --build "build with spaces" -- -nv
[1/6] cd /Users/tonnyred/td && /usr/local/opt/bison/bin/bison "--defines=/Users/tonnyred/td/build with spaces/numgrammar.tab.hh" -o "/Users/tonnyred/td/build with spaces/parser.cc" numgrammar.y
[2/6] cd /Users/tonnyred/td && /usr/local/opt/flex/bin/flex "-o/Users/tonnyred/td/build with spaces/lexer.cc" numgrammar.l
...

How can I generalize a custom command into a generic-make-rule-like construct?

In this question:
How can I build a fatbin file using CMake?
we saw how to formulate a pair of add_custom_command() and add_custom_target() commands, for building a .fatbin file out of a .cu file:
add_custom_command(
OUTPUT my_src.fatbin
COMMAND ${CMAKE_CUDA_COMPILER} -fatbin -o foo.fatbin
"${CMAKE_CURRENT_SOURCE_DIR}/my_src.cu"
MAIN_DEPENDENCY my_src.cu
)
add_custom_target(dummy ALL DEPENDS my_src.fatbin)
. The details of what these files are and how they are used is immaterial to this question (I hope); what I would like to do is generalize these two specific commands so that I don't just build my_src.fatbin from my_src.cu, but so that I can easily build any .cu file I specify into a .fatbin file. Essentially, the equivalent of Make's:
$(OBJDIR)/%.fatbin : $(SRCDIR)/%.cu
$(CUDA_COMPILER) $(CUDA_CPP_FLAGS) -fatbin -o $# $<
What's the appropriate idiom for doing that?
Perhaps a function is the right approach. Something like this? :
function(add_fatbin target_basename source_file)
# TODO: Should I check target_basename isn't a full path?
set(target_filename "${target_basename}.fatbin")
add_custom_command(
OUTPUT "${target_filename}"
COMMAND ${CMAKE_CUDA_COMPILER} -fatbin -o "${target_filename}"
"${source_file}"
MAIN_DEPENDENCY "${source_file}"
)
add_custom_target("${target_basename}_fatbin_tgt" ALL DEPENDS "${target_filename}")
endfunction()

How do I get CMake to check for TeXLive in Pandoc?

In PerfectTIN (https://github.com/phma/perfecttin), I build the documentation with this CMakeLists file:
find_program(PANDOC pandoc)
if (PANDOC)
execute_process(COMMAND ${PANDOC} "--resource-path=/" INPUT_FILE /dev/null ERROR_FILE /dev/null RESULT_VARIABLE pandoc_exit)
endif ()
if (PANDOC AND NOT pandoc_exit)
add_custom_command(OUTPUT perfecttin.pdf MAIN_DEPENDENCY perfecttin.xml COMMAND pandoc -f docbook -o perfecttin.pdf -V papersize=a4 -V margin-left=15mm -V margin-right=15mm -V margin-top=15mm -V margin-bottom=20mm --resource-path=${PROJECT_SOURCE_DIR}/doc ${PROJECT_SOURCE_DIR}/doc/perfecttin.xml)
add_custom_command(OUTPUT fileformat.pdf MAIN_DEPENDENCY fileformat.xml COMMAND pandoc -f docbook -o fileformat.pdf -V papersize=a4 -V margin-left=15mm -V margin-right=15mm -V margin-top=15mm -V margin-bottom=20mm --resource-path=${PROJECT_SOURCE_DIR}/doc ${PROJECT_SOURCE_DIR}/doc/fileformat.xml)
add_custom_target(perfecttin-doc ALL DEPENDS perfecttin.pdf fileformat.pdf)
install(FILES ${PROJECT_BINARY_DIR}/doc/fileformat.pdf ${PROJECT_BINARY_DIR}/doc/perfecttin.pdf DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/perfecttin)
endif ()
If Pandoc is absent, it doesn't build the documentation. If Pandoc and TeXLive are both present, it builds the documentation. But if Pandoc is present but TeXLive is not, the build fails. How can I check that Pandoc has what it needs before trying to build the documentation?
I tried "--resource-path=/ -f docbook -o /dev/zero"; it didn't fix it.
The program Pandoc uses is pdflatex (which is in the texlive-latex-base package in Ubuntu). So I added a search for pdflatex to CMakeLists.txt:
find_program(PANDOC pandoc)
find_program(PDFLATEX pdflatex)
if (PANDOC AND PDFLATEX)
execute_process(COMMAND ${PANDOC} "--resource-path=/" INPUT_FILE /dev/null ERROR_FILE /dev/null RESULT_VARIABLE pandoc_exit)
endif ()
if (PANDOC AND PDFLATEX AND NOT pandoc_exit)
add_custom_command(OUTPUT perfecttin.pdf MAIN_DEPENDENCY perfecttin.xml COMMAND pandoc -f docbook -o perfecttin.pdf -V papersize=a4 -V margin-left=15mm -V margin-right=15mm -V margin-top=15mm -V margin-bottom=20mm --resource-path=${PROJECT_SOURCE_DIR}/doc ${PROJECT_SOURCE_DIR}/doc/perfecttin.xml)
add_custom_command(OUTPUT fileformat.pdf MAIN_DEPENDENCY fileformat.xml COMMAND pandoc -f docbook -o fileformat.pdf -V papersize=a4 -V margin-left=15mm -V margin-right=15mm -V margin-top=15mm -V margin-bottom=20mm --resource-path=${PROJECT_SOURCE_DIR}/doc ${PROJECT_SOURCE_DIR}/doc/fileformat.xml)
add_custom_target(perfecttin-doc ALL DEPENDS perfecttin.pdf fileformat.pdf)
install(FILES ${PROJECT_BINARY_DIR}/doc/fileformat.pdf ${PROJECT_BINARY_DIR}/doc/perfecttin.pdf DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/perfecttin)
endif ()

wxWidgets library build garbled file name in linker

On attempting to build wxWidgets 3.1.0 libraries, I am getting this error
ar: gcc_mswu\moolib_fontmap.o: No such file or directory
A file does exists with a slightly different spelling
Directory of C:\Users\James\code\wxwidgets-3.1.0\build\msw\gcc_mswu
2017-01-05 02:01 PM 98,886 monolib_fontmap.o
It looks like a typo in the makefile, or like a letter is missed reading the makefile. Is that possible?
Except: if I redirect the console output to a file and open in an editor , the correct spelling shows up:
So the correct command is going to the linker, but the linker is looking for a garbled filename!
Here is the complete recipe for what I am doing:
Download wxWidgets source code from https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.0/wxWidgets-3.1.0.7z
Unpack to a folder. On my system, I use C:\Users\James\code\wxwidgets-3.1.0
Open a command window.
cd to the code::blocks mingw folder. On my system this is C:\Program Files (x86)\CodeBlocks16\MinGW
Type mingwvars.bat
cd to wxwidgets folder. On my system C:\Users\James\code\wxwidgets-3.1.0
cd to ./build/msw
Type mingw32-make SHELL=CMD.exe -j4 -f makefile.gcc BUILD=release UNICODE=1 SHARED=0 MONOLITHIC=1
This seems to be the same problem as the one mentioned in the wiki. Apparently there is a bug in mingw32-make with very long command lines which makes it (sometimes?) eat characters in them...
Yes. Applying the recipe in the link you posted fixed the problem. Here are the details:
modify makefile.gcc as following:
From:
ifeq ($(MONOLITHIC),1)
ifeq ($(SHARED),0)
$(LIBDIRNAME)\libwx$(PORTNAME)$(WXUNIVNAME)$(WX_RELEASE_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR).a: $(MONOLIB_OBJECTS)
if exist $# del $#
ar rcu $# $(MONOLIB_OBJECTS)
ranlib $#
endif
endif
Replace second occurence of $(MONOLIB_OBJECTS) with gcc_mswu\monolib*.o:
ifeq ($(MONOLITHIC),1)
ifeq ($(SHARED),0)
$(LIBDIRNAME)\libwx$(PORTNAME)$(WXUNIVNAME)$(WX_RELEASE_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR).a: $(MONOLIB_OBJECTS)
if exist $# del $#
ar rcu $# gcc_mswu\\monolib*.o
ranlib $#
endif
endif

Use Fortify sourceanalyzer with CMake

I have a Makefile generated by CMake. The following path to CMake executable is set in the Makefile:
CMAKE_COMMAND = /home/xyz/opt/cmake/cmake-3.1.1/bin/cmake
How can I integrate Fortify sourceanalyzer with it and run scans?
I had the same challenge but solved it by running it like this:
sourceanalyzer -b project_ID -clean
Go to your build directory and perform make clean or remove all contents including the Makefile
Run cmake by changing CC and CXX variables:
CC="sourceanalyzer -b project_ID gcc" CXX="sourceanalyzer -b project_ID g++" cmake ..
Run make and fortify should be translating files while compilers do their job.
Run sourceanalyzer -b project_ID -scan -f results.fpr
Hope it helps.
I was tasked with integrating our CMake build system with HP Fortify SCA and came across this Thread that gave some insights but lacked specifics as related to HP Fortify so I thought I would share my implementation.
I created a fortify_tools directory at the same level as the source directory. Inside the fortify_tools are a toolchain file and fortify_cc, fortify_cxx, and fortify_ar scripts that will be set as the cmake_compilers via the toolchain file.
fortify_cc
#!/bin/bash
sourceanalyzer -b <PROJECT_ID> gcc $#
fortify_cxx
#!/bin/bash
sourceanalyzer -b <PROJECT_ID> g++ $#
fortify_ar
#!/bin/bash
sourceanalyzer -b <PROJECT_ID> ar $#
NOTE: insert your project name in place of PROJECT_ID
Setting cmake to use the scripts is accomplished in a toolchain file.
fortify_linux_toolchain.cmake
INCLUDE (CMakeForceCompiler)
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
#specify the compilers
SET(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/fortify_tools/fortify_cc)
SET(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/fortify_tools/fortify_cxx)
SET(CMAKE_AR_COMPILER ${CMAKE_SOURCE_DIR}/fortify_tools/fortify_ar)
To generate makefiles using the toolchain file
ccmake -DCMAKE_TOOLCHAIN_FILE=../fortify_tools/foritfy_linux_toolchain.cmake ../
configure and generate your makefiles and build your project.
Once the project is built from within the build directory generate a fortify report by
sourceanalyzer -Xmx2400M -debug -verbose -b <PROJECT_ID> -scan -f <PROJECT_ID>.fpr
I understand the last step is outside of CMake but I am pretty confident a cmake_custom_command can be created to perform the scan step as a post build action.
Finally, this is just the linux implementation but the concept scales well to Windows by creating the necessary batch files and windows specific toolchain file
Fortify doesn't support CMake, I received confirmation from Fortify support team.
This answer is late, but might help someone. This is actually easy to fix - you simply need to run cmake inside sourceanalyzer as well. Make a simple build script that calls cmake and then make, and use sourceanalyzer on that instead. I am using fortify 4.21.
Our old Fortify script for building hand-created Makefiles used a build command that looked like this:
$SOURCEANALYZER $MEMORY $LAUNCHERSWITCHES -b $BUILDID make -f Makefile -j12
I was able to get it working for a project that had been converted to CMake by replacing the above line with this, inspired by a couple of the other answers here:
CC="$SOURCEANALYZER $MEMORY $LAUNCHERSWITCHES -b $BUILDID gcc" \
CXX="$SOURCEANALYZER $MEMORY $LAUNCHERSWITCHES -b $BUILDID g++" \
AR="$SOURCEANALYZER $MEMORY $LAUNCHERSWITCHES -b $BUILDID ar" \
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ..
make -f Makefile -j12 VERBOSE=1
This is with cmake 2.8.12.2 on Linux.
Below is the script i use for my example project to generate HP Fortify report for Android JNI C/C++ Code.
#!/bin/sh
# Configure NDK version and CMake version
NDK_VERSION=21.0.6113669
CMAKE_VERSION=3.10.2
CMAKE_VERSION_PATH=$CMAKE_VERSION.4988404
PROJECTID="JNI_EXAMPLE"
REPORT_NAME=$PROJECTID"_$(date +'%Y%m%d_%H:%M:%S')"
WORKING_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
BUILD_HOME=${WORKING_DIR}/../hpfortify_build
FPR="$BUILD_HOME/$REPORT_NAME.fpr"
# Following exports need to be configured according to host machine.
export ANDROID_SDK_HOME=/Library/Android/sdk
export ANDROID_CMAKE_HOME=$ANDROID_SDK_HOME/cmake/$CMAKE_VERSION_PATH/bin
export ANDROID_NDK_HOME=$ANDROID_SDK_HOME/ndk/$NDK_VERSION
# E.g. JniExample/app/hpfortify/build/CMakeFiles/3.10.2
export CMAKE_FILES_PATH=${BUILD_HOME}/CMakeFiles/$CMAKE_VERSION
export HPFORTIFY_HOME="/Applications/Fortify/Fortify_SCA_and_Apps_20.1.0/bin"
export PATH=$PATH:$ANDROID_SDK_HOME:$ANDROID_NDK_HOME:$ANDROID_CMAKE_HOME:$HPFORTIFY_HOME
echo "[========Start Android JNI C/C++ HP Fortify scanning========]"
echo "[========Build Dir: $BUILD_HOME========]"
echo "[========HP Fortify report path: $FPR========]"
function create_build_folder {
rm -rf $BUILD_HOME
mkdir $BUILD_HOME
}
# The standalone cmake build command can be found from below file.
# JniExample/app/.cxx/cmake/release/x86/build_command.txt
# This file is generated after running command
# `➜ JniExample git:(master) ✗ ./gradlew :app:externalNativeBuildRelease`
function configure_cmake_files {
cd $BUILD_HOME
$ANDROID_CMAKE_HOME/cmake -H$BUILD_HOME/. \
-DCMAKE_CXX_FLAGS=-std=c++11 -frtti -fexceptions \
-DCMAKE_FIND_ROOT_PATH=$BUILD_HOME/.cxx/cmake/release/prefab/x86/prefab \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_SDK_HOME/ndk/$NDK_VERSION/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=x86 \
-DANDROID_NDK=$ANDROID_SDK_HOME/ndk/$NDK_VERSION \
-DANDROID_PLATFORM=android-16 \
-DCMAKE_ANDROID_ARCH_ABI=x86 \
-DCMAKE_ANDROID_NDK=$ANDROID_SDK_HOME/ndk/$NDK_VERSION \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$BUILD_HOME/intermediates/cmake/release/obj/x86 \
-DCMAKE_MAKE_PROGRAM=$ANDROID_SDK_HOME/cmake/$CMAKE_VERSION_PATH/bin/ninja \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=16 \
-B$BUILD_HOME/.cxx/cmake/release/x86 \
-GNinja ..
}
function build {
cmake --build .
}
function cleanup {
rm -rf $BUILD_HOME/CMakeFiles/native-lib.dir
rm -rf $FPR
$HPFORTIFY_HOME/sourceanalyzer -clean
}
function replace_compiler_paths {
FORTIFY_TOOLS_PATH="$WORKING_DIR"
CLANG_PATH="$ANDROID_SDK_HOME/ndk/$NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang"
CLANGXX_PATH="$ANDROID_SDK_HOME/ndk/$NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++"
HPFORTIFY_CCPATH="$FORTIFY_TOOLS_PATH/fortify_cc"
HPFORTIFY_CXXPATH="$FORTIFY_TOOLS_PATH/fortify_cxx"\"
sed -i '' 's+'$CLANG_PATH'+'$HPFORTIFY_CCPATH'+g' $CMAKE_FILES_PATH/CMakeCCompiler.cmake
sed -i '' 's+'$CLANG_PATH.*[^")"]'+'$HPFORTIFY_CXXPATH'+g' $CMAKE_FILES_PATH/CMakeCXXCompiler.cmake
}
function scan {
$HPFORTIFY_HOME/sourceanalyzer -b $PROJECTID -scan -f $FPR
# copy the file to $WORKING_DIR
cp $FPR $WORKING_DIR
}
create_build_folder
configure_cmake_files
echo "[========Compile C/C++ using normal compiler ========"]
build
echo "[========Replace the compiler with HP Fortify analyser wrapper compilers ========"]
replace_compiler_paths
echo "[========Clean up the build intermediates and the older build ID and fpr file ========"]
cleanup
echo "[========Recompile C/C++ using HP Fortify analyser wrapper compilers ========"]
build
echo "[========Scan the compiled files and generate final report ========"]
scan
echo "[========Change directory to original working dir ========"]
cd $WORKING_DIR
Need to configure below vars before using it. For my case, I use NDK 21 and CMake 3.10.2 and my project ID is "JNI_EXAMPLE"
# Configure NDK version and CMake version
NDK_VERSION=21.0.6113669
CMAKE_VERSION=3.10.2
CMAKE_VERSION_PATH=$CMAKE_VERSION.4988404
PROJECTID="JNI_EXAMPLE"
# Following exports need to be configured according to host machine.
export ANDROID_SDK_HOME=/Library/Android/sdk
export ANDROID_NDK_HOME=$ANDROID_SDK_HOME/ndk/$NDK_VERSION
export HPFORTIFY_HOME="/Applications/Fortify/Fortify_SCA_and_Apps_20.1.0/bin"
Here is a more detailed explanation: Using HP Fortify to Scan Android JNI C/C++ Code
On recent version of CMake one can use:
CMAKE_<LANG>_COMPILER_LAUNCHER='sourceanalyzer;-b;<PROJECT_ID>'
You can add other arguments (like -Xmx2G for instance), semicolon separated, as mentioned on cmake documentation
You need to check if you don't use the compiler launcher for another tool like ccache. We can probably use both with
CCACHE_PREFIX='.../sourceanalyzer -b ID'
Here is what I've used in CMake project:
project(myFortifiedProject LANGUAGES CXX)
set(CMAKE_CXX_COMPILER_LAUNCHER ${FORTIFY_TOOL} -b ${PROJECT_NAME})
So when running cmake (assuming sourceanalyzer is on the path):
cmake <other args> -DFORTIFY_TOOL=sourceanalyzer
So the normal build command works:
make myFortifiedProject
And you can finally collect results with:
sourceanalyzer -b myFortifiedProject -scan