I have a situation where I've created a custom command to generate .cpp
files to be compiled (in my case running bison/flex).
I'm using CMake 3.13.4
However, I have to compile this code in two different ways for two
different targets. I am seeing the Visual Studio generator re-running
bison/flex once for each of these targets, which is (a) not necessary
and (b) causes my builds to fail since it often happens that the second
run can't replace the output files (due to Windows' annoying habit of
locking files that are open).
I have a custom command like this:
add_custom_command(OUTPUT
${OUT_DIR}/MyParser.tab.cpp
${OUT_DIR}/MyParser.tab.hpp
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUT_DIR}
COMMAND ${BISON} -d -o ${OUT_DIR}/MyParser.tab.cpp MyParser.y
DEPENDS MyParser.y
COMMENT "Building MyParser parser")
set(MyParserOutput
${OUT_DIR}/MyParser.tab.cpp
${OUT_DIR}/MyParser.tab.hpp)
add_custom_target(MyGenParser DEPENDS ${MyParserOutput})
Then I have two different libraries, both depending on this:
add_library(OneLib STATIC ${MyParserOutput} ...)
target_compile_definitions(OneLib PRIVATE -DONELIB)
target_include_directories(OneLib PRIVATE ${OUT_DIR})
add_dependencies(OneLib MyGenparser)
add_library(TwoLib STATIC ${MyParserOutput} ...)
target_compile_definitions(TwoLib PRIVATE -DTWOLIB)
target_include_directories(TwoLib PRIVATE ${OUT_DIR})
add_dependencies(TwoLib MyGenparser)
On Linux and MacOS, this works fine. However on Windows with Visual
Studio I see the custom target being run twice, once for each library:
18:27:10 21>PrepareForBuild:
18:27:10 Creating directory "OneLib.dir\RelWithDebInfo\".
18:27:10 Creating directory "OneLib.dir\RelWithDebInfo\OneLib.tlog\".
18:27:10 InitializeBuildStatus:
18:27:10 Creating
"OneLib.dir\RelWithDebInfo\OneLib.tlog\unsuccessfulbuild" because
"AlwaysCreate" was specified.
18:27:10 ComputeCustomBuildOutput:
18:27:10 Creating directory "D:\builds\src\".
18:27:10 CustomBuild:
18:27:10 Building MyParser parser
Then again later:
18:27:20 69>PrepareForBuild:
18:27:20 Creating directory "TwoLib.dir\RelWithDebInfo\".
18:27:20 Creating directory "TwoLib.dir\RelWithDebInfo\TwoLib.tlog\".
18:27:20 InitializeBuildStatus:
18:27:20 Creating
"TwoLib.dir\RelWithDebInfo\TwoLib.tlog\unsuccessfulbuild" because
"AlwaysCreate" was specified.
18:27:20 CustomBuild:
18:27:20 Building MyParser parser
See how this second one is re-building the parser; then this fails
because the output file is locked by Windows (in use by the compiler):
18:27:21 69>CustomBuild:
18:27:21 bison.exe: could not create D:/builds/src/MyParser.tab.cpp
18:27:25 69>C:\Program Files (x86)\Microsoft Visual
Studio\2017\Professional\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(209,5):
error MSB6006: "cmd.exe" exited with code 1. [D:\builds\TwoLib.vcxproj]
How can I get CMake to only run the bison command one time, then use
the output for two different libraries?
--
Powered by www.kitware.com
Please keep messages on-topic and check the CMake FAQ at:
http://www.cmake.org/Wiki/CMake_FAQ
Kitware offers various services to support the CMake community. For more
information on each offering, please visit:
CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Follow this link to subscribe/unsubscribe:
https://cmake.org/mailman/listinfo/cmake