Continuing on here from results of bug submittal at http://public.kitware.com/Bug/view.php?id=14705 I will try to post whatever necessary bits from that here in hopes of making this cohesive discussion.
The bug report example has two CMakeLists.txt files: external_project/CMakeLists.txt referred to here as TOP and external_project/some_external_project/CMakeLists.txt referred to here as SUB, sets some CMAKE_C*_FLAGS (not using CACHE FORCE). TOP ExternalProject_Adds SUB and tries to set CMAKE_C*_FLAGS* and friends vars by using -DVAR_NAME:VAR_TYPE="VAR_VALUE" with VAR_TYPE as INTERNAL in hopes of FORCING subproject vars, which IMHO should not be this difficult. >From Bug Report Brad responds with: "FORCE tells set() to overwrite an existing non-INTERNAL cache entry and ignore whatever the user may have manually configured. An INTERNAL cache entry means it belongs to the project and should not be edited by the user manually." Yes force will overwrite and existing non-INTERNAL cache entry. I am passing the values as INTERNAL so why is a non forced value overriding it in the subproject? There are various CMAKE_* variables some are specified as INTERNAL such as *maybe* *CMAKE_<LANG>_COMPILER_ABI*: An internal variable subject to change. *CMAKE_<LANG>_PLATFORM_ID*: An internal variable subject to change. *CMAKE_INTERNAL_PLATFORM_ABI*: An internal variable subject to change. as I am not *sure* if internal == INTERNAL but not CMAKE_C*_FLAGS* and friends. At least that's my probably incorrect understanding. >From Bug Report Brad also responds with: "The code in your ExternalProject_Add call correctly sets the cache entry values for the build tree of the inner project. However, as I explained in 0014705:0034966 <http://public.kitware.com/Bug/view.php?id=14705#c34966>the code in your inner-project's CMakeLists.txt hides those values by setting normal variables of the same name. Therefore the cache values are not visible and are ignored regardless of their type or value. This is explained in the documentation linked in 0014705:0034968<http://public.kitware.com/Bug/view.php?id=14705#c34968> ." Document Brad referred to is: http://cmake.org/gitweb?p=cmake.git;a=blob;f=Help/manual/cmake-language.7.rst;hb=1b395813#l393 This document does not state any persistence a variable should have when terms INTERNAL or FORCE are used. From my reading documentation "INTERNAL implies FORCE". So while the document has a wonderful discussion on variables it says nothing as to how variables persist or can be overridden. If it is explained there I certainly do not see where. I almost wonder if the wrong link was posted in his reply. Yes the inner project does specify the values. However should passing in the variable type as INTERNAL imply FORCE and override the internal setting of the subproject as INTERNAL implies FORCE? Clearly it does not, but should it? I really wish I could get a direct answer to this simple question. It's as though the documentation implies a certain functionality, but CMake does not operate this way. The referenced document makes no reference to FORCE or INTERNAL. If this is the holy grail of CMake internal operation then shouldn't it? The document references a persistent cache, but I do not glean from this how it promptly ignores types as he states such as INTERNAL. I don't see or understand how it is explained here and I am probably thick headed on this and just not seeing it. It appears to expalin some of the internal workings of the language, but not how external interfaces affect it such as -D at the command prompt or when using ExternalProject_Add. This document is "aware" of -D option (Paragraph beginning "To support legacy CMake code"), but does not reference how it is interpreted and how variables are ignored or stored in the CACHE. I also enjoy reading the grammar definition for CMake in order to determine how CMake should work. I had never see this doc before this post. It also looks as though it refrences CMake 3.0 so maybe 3.0 will have a better gramar parser? Not sure how this document helps me in 2.8 if this is gramar spec for 3.0, but likely backwards compatible? This doc may need section such as "ExternalProject_Add and Command Line Scope CMake promptly ignores all attempts you the take to set or force variables in project if variables are set in project even if said variables are not CACHE FORCE in sub project. Thinking about using -DVAR_NAME:INTERNAL="VAR_VALUE" thinking that INTERNAL implies FORCE... don't bother CMake will ignore that too. What's FORCE mean?... certainly not what you think. Ha Ha programmer jokes on you :-)!" Or something to that effect :-) These variables in the sub project are set, but are not forced so should not be setting of these variables be overridden by parent project when -DCMAKE_C_FLAGS_DEBUG:INTERNAL="/MDd /Z7 /Od" is specified to ExternalProject_Add. Or maybe a better question is what should I expect from specifying INTERNAL as clearly it is not what I expect from reading the documentation... really any documentation so far. Also above document referenced following doument which was also no help. http://www.cmake.org/cmake/help/git-master/manual/cmake-variables.7.html >From documentation http://www.cmake.org/cmake/help/v2.8.12/cmake.html: <snip> INTERNAL = No GUI entry (used for persistent variables). If <type> is INTERNAL, the cache variable is marked as internal, and will not be shown to the user in tools like cmake-gui. This is intended for values that should be persisted in the cache, but which users should not normally change. INTERNAL implies FORCE. <end snip> Now either: 1) Above statement is a lie 2) It is correct and INTERNAL does not work in all use cases of CMake including ExternalProject_Add and and the command prompt using -D option. 3) It is correct and CMake has a bug or is not correctly implemented for all use cases. >From Command prompt calling into the subproject(SUB above): c:\projects\CMakeTesting\external_project_test\some_external_project\build> del *.* && cmake -DCMAKE_C_FLAGS_DEBUG="=====SOME_OTHER_VARIABLE =====" ..\ CMAKE_CXX_FLAGS_INIT=/DWIN32 /D_WINDOWS /W3 /Zm1000 /EHsc /GR Following line for CXX DEBUG should contain /MDd CMAKE_CXX_FLAGS_DEBUG=/D_DEBUG /MTd /Zi /Ob0 /Od /Gm CMAKE_CXX_FLAGS_DEBUG_INIT=/D_DEBUG /MTd /Zi /Ob0 /Od CMAKE_C_FLAGS_DEBUG=CHILD_PROJECT_DEBUG CMAKE_C_FLAGS_DEBUG_INIT=/D_DEBUG /MTd /Zi /Ob0 /Od CMAKE_C_FLAGS_RELEASE=CHILD_PROJECT_RELEASE SOME_VAR=ChildProjectSomeValue ANOTHER_VAR= -- Configuring done -- Generating done -- Build files have been written to: C:/projects/CMakeTesting/external_project_test/some_external_project/build So CMAKE_C_FLAGS_DEBUG is not changed to "=====SOME_OTHER_VARIABLE=====" and remains CHILD_PROJECT_DEBUG. I have slightly modified my version of the example I posted to bug report and changed flags to a simple string argument. So CMake appears to promptly ignore -DVAR_NAME=VAL_VALUE if set in sub project which I guess is normal. Lets add -LA to opts see what happens, but still not specify INTERNAL: c:\projects\CMakeTesting\external_project_test\some_external_project\build> del *.* && cmake -LA -DCMAKE_C_FLAGS_DEBUG="=====SOME_OTHER_VARIABLE =====" ..\ CMAKE_CXX_FLAGS_INIT=/DWIN32 /D_WINDOWS /W3 /Zm1000 /EHsc /GR Following line for CXX DEBUG should contain /MDd CMAKE_CXX_FLAGS_DEBUG=/D_DEBUG /MTd /Zi /Ob0 /Od /Gm CMAKE_CXX_FLAGS_DEBUG_INIT=/D_DEBUG /MTd /Zi /Ob0 /Od CMAKE_C_FLAGS_DEBUG=CHILD_PROJECT_DEBUG CMAKE_C_FLAGS_DEBUG_INIT=/D_DEBUG /MTd /Zi /Ob0 /Od CMAKE_C_FLAGS_RELEASE=CHILD_PROJECT_RELEASE SOME_VAR=ChildProjectSomeValue ANOTHER_VAR= -- Configuring done -- Generating done -- Build files have been written to: C:/projects/CMakeTesting/external_project_test/some_external_project/build -- Cache values CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4 CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 /GR /EHsc CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uu id.lib comdlg32.lib advapi32.lib CMAKE_C_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 CMAKE_C_FLAGS_DEBUG:STRING======SOME_OTHER_VARIABLE ===== CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid .lib comdlg32.lib advapi32.lib CMAKE_EXE_LINKER_FLAGS:STRING= /machine:X86 CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/Project CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe CMAKE_MAKE_PROGRAM:FILEPATH=C:/PROGRA~2/MICROS~4.0/Common7/IDE/devenv.com CMAKE_MODULE_LINKER_FLAGS:STRING= /machine:X86 CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL CMAKE_RC_COMPILER:FILEPATH=rc CMAKE_RC_FLAGS:STRING= CMAKE_SHARED_LINKER_FLAGS:STRING= /machine:X86 CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL CMAKE_SKIP_INSTALL_RPATH:BOOL=NO CMAKE_SKIP_RPATH:BOOL=NO CMAKE_STATIC_LINKER_FLAGS:STRING= CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= CMAKE_USE_RELATIVE_PATHS:BOOL=OFF CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE EXECUTABLE_OUTPUT_PATH:PATH= LIBRARY_OUTPUT_PATH:PATH= Ok so there's a lot of goop there, but the important bits are the line CMAKE_C_FLAGS_DEBUG=CHILD_PROJECT_DEBUG before the line -- Configuring done and the line CMAKE_C_FLAGS_DEBUG:STRING======SOME_OTHER_VARIABLE ===== Which means CMake sees it and promplty ignores it in subproject. Why this is standard operating procedure I am not sure, but I am familiar with it operating this way. Hey I know maybe we can pass it in as INTERNAL as that implies FORCE. Which I understand to mean FORCE in the CACHE. c:\projects\CMakeTesting\external_project_test\some_external_project\build>cmake -LA -DCMAKE_C_FLAGS_DEBUG:INTERNAL="=== ==SOME_OTHER_VARIABLE =====" ..\ CMAKE_CXX_FLAGS_INIT=/DWIN32 /D_WINDOWS /W3 /Zm1000 /EHsc /GR Following line for CXX DEBUG should contain /MDd CMAKE_CXX_FLAGS_DEBUG=/D_DEBUG /MTd /Zi /Ob0 /Od /Gm CMAKE_CXX_FLAGS_DEBUG_INIT=/D_DEBUG /MTd /Zi /Ob0 /Od CMAKE_C_FLAGS_DEBUG=CHILD_PROJECT_DEBUG CMAKE_C_FLAGS_DEBUG_INIT=/D_DEBUG /MTd /Zi /Ob0 /Od CMAKE_C_FLAGS_RELEASE=CHILD_PROJECT_RELEASE SOME_VAR=ChildProjectSomeValue ANOTHER_VAR= -- Configuring done -- Generating done -- Build files have been written to: C:/projects/CMakeTesting/external_project_test/some_external_project/build -- Cache values CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4 CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 /GR /EHsc CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uu id.lib comdlg32.lib advapi32.lib CMAKE_C_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid .lib comdlg32.lib advapi32.lib CMAKE_EXE_LINKER_FLAGS:STRING= /machine:X86 CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/Project CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe CMAKE_MAKE_PROGRAM:FILEPATH=C:/PROGRA~2/MICROS~4.0/Common7/IDE/devenv.com CMAKE_MODULE_LINKER_FLAGS:STRING= /machine:X86 CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL CMAKE_RC_COMPILER:FILEPATH=rc CMAKE_RC_FLAGS:STRING= CMAKE_SHARED_LINKER_FLAGS:STRING= /machine:X86 CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL CMAKE_SKIP_INSTALL_RPATH:BOOL=NO CMAKE_SKIP_RPATH:BOOL=NO CMAKE_STATIC_LINKER_FLAGS:STRING= CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= CMAKE_USE_RELATIVE_PATHS:BOOL=OFF CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE EXECUTABLE_OUTPUT_PATH:PATH= LIBRARY_OUTPUT_PATH:PATH= So the line following line is still unchanged CMAKE_C_FLAGS_RELEASE=CHILD_PROJECT_RELEASE before the line -- Configuring done and the line CMAKE_C_FLAGS_DEBUG:STRING======SOME_OTHER_VARIABLE ===== has disappeared whch it should. So it ran away and hid and still did nothing. Clearly did not FORCE. INTERNAL implies RUN AWAY HIDE DO NOTHING when used from external interfaces such as command prompt and ExternalProject_Add at least from my experience. I am sure I have all this wrong.
-- 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: http://www.cmake.org/mailman/listinfo/cmake
