[CMake] Fwd: Problem finding DLLS to use with tests

aaron.meadows at thomsonreuters.com aaron.meadows at thomsonreuters.com
Fri Feb 3 10:42:40 EST 2012


Catching up on old threads here..

I've gone with Approach 4 below.  It was somewhat difficult to achieve, but I have it working fairly well now.  Let me share what I've done:  (We are mainly a visual studio shop, so this is geared toward a multi-config generator)

First off, I'm not using add_test(), I'm using UnitTest++ with projects which add executables and have post build events that run them.  I should probably explore add_test() as an alternative to the post build events, but it's hard to find time to fix something that's working.

Each of my find_package() scripts (we have various libraries as dependencies, all of which we maintain in an internal repo) which have dynamic libraries call a function WriteExtraFiles(), which writes path setting statements into files under subdirectories for each configuration type.

Each of the UnitTest projects calls a function to setup the post build event.  Part of the command it writes includes calling the script file for setting up the path.  For Visual Studio, we use $(ConfigurationName) as part of the path so that it will expand to the correct script.


Some of the hurdles to this approach were as follows:
  * Needed to be able to have the post build event execute an arbitrary number of commands passed to the function.  Since there is no way to have add_custom_command() take an arbitrary number of COMMAND statements, I write a file into the CMAKE_CURRENT_BINARY_DIR containing the add_custom_command(), then include() it at the end of the function.

  * Needed to be able to iterate across all configuration types (and we had some extras), so had to guarantee that was all fixed up ahead of time.  Additionally, I needed to be sure that the right configurations were marked debug.  The global property DEBUG_CONFIGURATIONS was not populated by default (which might make sense..) so I had to do that.


I think that about sums it up.  Hopefully that's useful to someone.  If you think there's a better way to handle this, I'm happy to discuss it!

Aaron Meadows


-----Original Message-----
From: cmake-bounces at cmake.org [mailto:cmake-bounces at cmake.org] On Behalf Of QbProg
Sent: Sunday, June 26, 2011 3:40 PM
To: aaron.meadows at i.com
Cc: cmake at cmake.org
Subject: Re: [CMake] Fwd: Problem finding DLLS to use with tests

I was writing exactly about this, then found this email.
Let me elaborate the problem a bit more, since what we need really is a best pratice.

Suppose you have a project with multiple libraries and a test project.
The problem is that generated DLLs are not on PATH, so the exe will not find it. Usually the binaries are put in the build folder in separate directories, so the test executable won't find these if you run it directly.

I see three possible solutions:
- Put the binaries , in the build folder, under the same output directory. This can be done by changing the appropriate CMAKE_ setting.
- Run the tests from the installation directory. This requires that you do an INSTALL before running the tests
- Do a post-build step to copy the binaries and the tests somewhere.
Something like an INSTALL phase, but related only to test data (so , for instance , you won't have to copy source/configuration files)
- Change the path to let the exe find all the DLLs

Approach 1 will change the build folder default behavoir, and you still to find a way to copy there the possible external dependencies.
Approach 2 is probably non really appropriate since the INSTALL phase may do many things other than copying binaries Approach 3 requires a custom setup step, but will possibly allow this.
Also, instead of a post build step, this can be done as a pre-build TEST step (I don't know if it is possible) Approach 4 may be really hard to achieve.

So, what is the best pratice to solve this problem, if there's one?
How should be ctest configured?

Also, while solving this, I faced another problem: if we use external libs (say TCL or Qt), is there a standard way to copy the BINARIES of these libs (found using find_package) where we want (i.e. the test binary folder).

Thank you in advance for any hint!
QbProg

2011/6/23  <aaron.meadows at thomsonreuters.com>:
> So, you are manually running your tests, for example, the 'test_julian.exe'
> or 'testcpp.exe'?  Running them from a command prompt gives you that 
> same error about the application has failed to start?  And the name of 
> the dll's exactly match?  And you have tried copying the .dll into the 
> same directory and running it manually?
>
>
>
> You can use Dependency Walker to run a program and debug the issues it 
> has with DLL.  Some versions of Visual Studio come with a version of 
> it. You can run depends.exe from a visual studio command prompt and 
> pass it the executable.  If you don't have it, you can get it from 
> http://www.dependencywalker.com/.  You can profile and executable by 
> hitting
> F7 (I usually checkmark all the options to on) and it will tell you 
> all about what it is doing to bootstrap you exe, including where it fails.
> Usually, this will give you a better idea of what happened, where it 
> looked for the DLL, and why it rejected ones that seemed like they 
> should have worked.  In particular, it might be finding that DLL fine, 
> but the DLL is returning 0 from DllMain() and failing to be loaded.
>
>
>
> Hope that helps!
>
>
>
> Aaron C. Meadows
>
> From: cmake-bounces at cmake.org [mailto:cmake-bounces at cmake.org] On 
> Behalf Of Stephen Torri
> Sent: Thursday, June 23, 2011 1:19 PM
> To: cmake at cmake.org
> Subject: [CMake] Fwd: Problem finding DLLS to use with tests
>
>
>
> On Thu, Jun 23, 2011 at 11:37 AM, <aaron.meadows at thomsonreuters.com> wrote:
>
> Can you post your CMakeLists.txt?  Did you get different errors for 
> each of the 3 solutions you tried, or were they all the same error?  
> What was the exception code?
>
>
>
> I got the same error. I did not receive a exception throw when I ran 
> the testing code via Visual Studio. I got a message that said:
>
>
>
> "The application has failed to start because 
> boost_unit_test_framework-vc100-mt-gd-1_46_1.dll was not found. 
> Reinstalling the application may fix the problem".
>
>
>
> It looks like I either need to copy the boost dlls I use to my test 
> directory or somehow add the boost directory to the PATH environment 
> variable.
>
>
>
> ---------- Master CMakeLists.txt ------------
>
> cmake_minimum_required ( VERSION 2.8 )
>
> SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/")
>
> PROJECT(myproject)
>
> SET ( ${PROJECT_NAME}_MAJOR_VERSION 0 ) SET ( 
> ${PROJECT_NAME}_MINOR_VERSION 5 ) SET ( ${PROJECT_NAME}_PATCH_LEVEL 0 
> )
>
> SET(BOOST_ROOT "C:/Program Files (x86)/boost/boost_1_46_1" CACHE PATH 
> "Installation directory for boost")
>
> #-----------------------------------------------------
> #                   DEBUG
> #-----------------------------------------------------
> OPTION(DEBUG_TLE_PARSER "Enable debugging of TLE parser." OFF)
> IF(DEBUG_TLE_PARSER)
>   SET (DEBUG_PARSER 1)
> ENDIF(DEBUG_TLE_PARSER)
>
> #-----------------------------------------------------
> #            Unix Configuration
> #-----------------------------------------------------
> IF(UNIX)
>
>   SET(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for
> executables")
>   SET(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for 
> libraries")
>   SET(INSTALL_INC_DIR include CACHE PATH "Installation directory for
> headers")
>   SET(INSTALL_DATA_DIR shared/${PROJECT_NAME} CACHE PATH "Installation 
> directory for data files")
>
>   #-----------------------------------------------------
>   #                 FLAGS
>   #----------------------------------------------------
>   IF(CMAKE_BUILD_TYPE MATCHES Release)
>     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -ansi
> -pedantic")
>   ENDIF(CMAKE_BUILD_TYPE MATCHES Release)
>   IF(CMAKE_BUILD_TYPE MATCHES Debug)
>     SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -Wall 
> -Werror -ansi -pedantic")
>   ENDIF(CMAKE_BUILD_TYPE MATCHES Debug)
>
>   OPTION(BUILD_SHARED_LIBS "Build shared libraries." ON)
>
>   IF(DEBUG_TLE_PARSER)
>     SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} 
> -DDEBUG_PARSER")
>   ENDIF(DEBUG_TLE_PARSER)
>
> ENDIF(UNIX)
>
> set(myproject_SRC_DIR ${CMAKE_SOURCE_DIR}/myproject)
>
> #-----------------------------------------------------
> #                 SHARED / STATIC
> #-----------------------------------------------------
>
> # Allow the developer to select if Dynamic or Static libraries are 
> built OPTION(BUILD_SHARED_LIBS "Build shared libraries." OFF)
>
> # Set the LIB_TYPE variable to STATIC
> SET (LIB_TYPE STATIC)
> IF (BUILD_SHARED_LIBS)
>   # User wants to build Dynamic Libraries, so change the LIB_TYPE 
> variable to CMake keyword 'SHARED'
>   SET (LIB_TYPE SHARED)
>   IF(WIN32)
>     SET (BUILD_SHARED_WIN32 1)
>   ENDIF(WIN32)
> ENDIF (BUILD_SHARED_LIBS)
>
> CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/myproject/config.h.in
> ${CMAKE_CURRENT_SOURCE_DIR}/myproject/config.h)
>
> #-----------------------------------------------------
> #                   TESTING
> #-----------------------------------------------------
>
> ENABLE_TESTING()
>
> add_custom_target ( check COMMAND ${CMAKE_CTEST_COMMAND} )
>
> SUBDIRS(Testing/units)
> SUBDIRS(Testing/myproject)
>
> #-----------------------------------------------------
> #                 FIND PACKAGES
> #-----------------------------------------------------
> IF(WIN32)
>    SET(Boost_USE_STATIC_LIBS ON)
>    SET(Boost_USE_MULTITHREADED ON)
> ENDIF(WIN32)
>
> SET(Boost_ADDITIONAL_VERSIONS "1.46" "1.44" "1.44.0" ) 
> FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options thread 
> unit_test_framework filesystem system)
>
> #-----------------------------------------------------
> #                   CPACK
> #-----------------------------------------------------
>
> #-----------------------------
> #   CPACK DESCRIPTION INFORMATION
> #-----------------------------
>
> IF(CMAKE_BUILD_TYPE MATCHES Release)
> SET(CPACK_PACKAGE_NAME "myproject")
> SET(CPACK_PACKAGE_INSTALL_DIRECTORY "myproject") 
> ENDIF(CMAKE_BUILD_TYPE MATCHES Release)
>
> IF(CMAKE_BUILD_TYPE MATCHES Debug)
> SET(CPACK_PACKAGE_NAME "myproject_debug") 
> SET(CPACK_PACKAGE_INSTALL_DIRECTORY "myproject debug") 
> ENDIF(CMAKE_BUILD_TYPE MATCHES Debug)
>
> SET(CPACK_PACKAGE_VENDOR "Self")
> SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "myproject is an implementation 
> of the myproject satellite model for use in the DTCS project") 
> SET(CPACK_PACKAGE_DESCRIPTION_FILE 
> "${CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt")
> SET(CPACK_RESOURCE_FILE_LICENSE 
> "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt")
> SET(CPACK_PACKAGE_VERSION_MAJOR ${myproject_MAJOR_VERSION}) 
> SET(CPACK_PACKAGE_VERSION_MINOR ${myproject_MINOR_VERSION}) 
> SET(CPACK_PACKAGE_VERSION_PATCH ${myproject_PATCH_LEVEL})
>
> #-----------------------------------------------------
> #                 DOCUMENTATION
> #-----------------------------------------------------
> find_package ( Doxygen )
> IF(DOXYGEN)
>    ADD_SUBDIRECTORY(documentation)
> ELSE(DOXYGEN)
>    MESSAGE(STATUS "WARNING: Doxygen not found - API documentation not
> created")
> ENDIF(DOXYGEN)
>
> SET ( INSTALLED_HEADERS
>      myproject/constants.hpp
>   myproject/dll_defines.hpp
>      myproject/exception.hpp
>      myproject/file_error.hpp
>      myproject/interface.hpp
>      myproject/missing_file_error.hpp
>   myproject/exception.hpp
>      myproject/parsing_error.hpp )
>
>
>
> SET ( INSTALLED_UNIT_HEADERS
>      myproject/units/coordinates.hpp
>   myproject/units/day.hpp
>   myproject/units/invalid_day_exception.hpp
>   myproject/units/invalid_hour_exception.hpp
>   myproject/units/invalid_month_exception.hpp
>   myproject/units/invalid_year_exception.hpp
>      myproject/units/julian.hpp
>   myproject/units/minute.hpp
>   myproject/units/month.hpp
>   myproject/units/second.hpp
>   myproject/units/time.hpp
>      myproject/units/value_array.hpp
>      myproject/units/vector.hpp
>   myproject/units/year.hpp )
>
>
>
> SET ( HEADERS
>   ${INSTALLED_HEADERS}
>   ${INSTALLED_UNIT_HEADERS}
>      myproject/interface_impl.hpp
>      myproject/model_map.hpp
>      myproject/model_map.inl
>      myproject/satellite_model.hpp
>   myproject/parsers/bstar_compose.hpp
>   myproject/parsers/degree_to_radians_convert.hpp
>   myproject/parsers/derivative_compose.hpp
>   myproject/parsers/eccentricity_compose.hpp
>   myproject/parsers/error_handler.hpp
>   myproject/parsers/mean_motion_compose.hpp
>   myproject/parsers/myproject_entry_compose.hpp
>   myproject/parsers/tle_parser.hpp
>   myproject/parsers/ureal11_policy.hpp
>      myproject/model/near_earth_orbit.hpp
>      myproject/model/near_earth_orbit.inl
>      myproject/model/myproject.hpp
>      myproject/model/myproject.inl
>      myproject/model/myproject_orbit_data.hpp
>      myproject/model/myproject_orbit_data.inl
>      myproject/units/tle.hpp
>      myproject/world_geodetic_system/gravitational_constant_t.hpp
>      myproject/world_geodetic_system/old_wsg72_constant_type.hpp
>      myproject/world_geodetic_system/no_constants_type.hpp
>      myproject/world_geodetic_system/j2_constant_type.hpp
>      myproject/world_geodetic_system/j2j3_constant_type.hpp
>      myproject/world_geodetic_system/wsg72_constant_type.hpp
>      myproject/world_geodetic_system/wsg84_constant_type.hpp )
>
>
>
> SET ( SOURCE
>     myproject/interface.cpp
>     myproject/model/near_earth_orbit.cpp
>     myproject/model/myproject.cpp
>     myproject/model/myproject_orbit_data.cpp
>  myproject/units/day.cpp
>  myproject/units/hour.cpp
>     myproject/units/julian.cpp
>  myproject/units/minute.cpp
>  myproject/units/month.cpp
>  myproject/units/second.cpp
>     myproject/units/tle.cpp
>  myproject/units/value_array.cpp
>  myproject/units/vector.cpp
>  myproject/units/year.cpp
>     myproject/world_geodetic_system/old_wsg72_constant_type.cpp
>     myproject/world_geodetic_system/no_constants_type.cpp
>     myproject/world_geodetic_system/J2_constant_type.cpp
>     myproject/world_geodetic_system/J2J3_constant_type.cpp
>     myproject/world_geodetic_system/wsg72_constant_type.cpp
>     myproject/world_geodetic_system/wsg84_constant_type.cpp )
>
> #SET ( CSHARP_SOURCE
> #  csharp/myproject_wrap.cxx )
> #
> #FILE ( GLOB CSHARP_FILES "csharp/*.cs" )
>
> #-----------------------------------------------------
> #                   LINKING
> #-----------------------------------------------------
>
> include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}
> ${myproject_SRC_DIR})
>
> LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
>
> add_library ( myproject ${LIB_TYPE} ${SOURCE} ${HEADERS} )
>
> IF(UNIX)
> target_link_libraries ( myproject stdc++ )
> ENDIF(UNIX)
>
> #add_library ( myproject_csharp ${CSHARP_SOURCE} )
>
> add_executable(testcpp myproject/testcpp.cpp ) add_executable(validate 
> myproject/validate.cpp )
>
> IF(UNIX)
> target_link_libraries (validate ${Boost_LIBRARIES} myproject pthread ) 
> target_link_libraries (testcpp ${Boost_LIBRARIES} myproject pthread )
> ELSE(WIN32)
> target_link_libraries (validate ${Boost_LIBRARIES} myproject ) 
> target_link_libraries (testcpp ${Boost_LIBRARIES} myproject )
> ENDIF(UNIX)
>
>
>
> #-----------------------------------------------------
> #                   INSTALL
> #-----------------------------------------------------
> INSTALL(TARGETS myproject DESTINATION lib COMPONENT libraries) 
> INSTALL(FILES ${INSTALLED_HEADERS} DESTINATION include/${PROJECT_NAME} 
> COMPONENT devel) INSTALL(FILES ${INSTALLED_UNIT_HEADERS} DESTINATION 
> include/${PROJECT_NAME}/units COMPONENT devel) #INSTALL(TARGETS 
> myproject_csharp DESTINATION lib COMPONENT csharp) #INSTALL(FILES 
> ${CSHARP_FILES} DESTINATION include/${PROJECT_NAME}/csharp COMPONENT 
> csharp)
>
> IF(UNIX)
>   INSTALL(FILES Findmyproject.cmake DESTINATION share/module)
> ENDIF(UNIX)
>
>
>
> #-----------------------------
> #  INSTALLATION INFORMATION
> #-----------------------------
> #SET(CPACK_COMPONENTS_ALL libraries devel docs csharp) 
> SET(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") 
> SET(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "Dynamic library used to 
> build programs with myproject Interface") 
> SET(CPACK_COMPONENT_DEVEL_DISPLAY_NAME "C++ Headers") 
> SET(CPACK_COMPONENT_DEVEL_DESCRIPTION "C++ header files for use with 
> myproject Interface") SET(CPACK_COMPONENT_DEVEL_DEPENDS libraries) 
> SET(CPACK_COMPONENT_DOCS_DISPLAY_NAME "C++ API Documentation") 
> SET(CPACK_COMPONENT_DOCS_DESCRIPTION "C++ API HTML files describing 
> the API for myproject Interface") 
> #SET(CPACK_COMPONENT_CSHARP_DISPLAY_NAME "C# API files") 
> #SET(CPACK_COMPONENT_CSHARP_DESCRIPTION "C# API files describing the 
> API for myproject Interface") SET(CPACK_COMPONENT_LIBRARIES_GROUP 
> "Runtime") SET(CPACK_COMPONENT_DEVEL_GROUP "Development") 
> SET(CPACK_COMPONENT_DOCS_GROUP "Development") 
> #SET(CPACK_COMPONENT_CSHARP_GROUP "Development") 
> SET(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "All of the tools 
> necessary to develop against the SMT Interface")
>
>
>
> #-----------------------------
> #  INSTALLATION TYPES
> #-----------------------------
> SET(CPACK_ALL_INSTALL_TYPES Full Runtime Developer) 
> SET(CPACK_COMPONENT_LIBRARIES_INSTALL_TYPES Full Developer Runtime) 
> SET(CPACK_COMPONENT_DEVEL_INSTALL_TYPES Full Developer) 
> SET(CPACK_COMPONENT_DOCS_INSTALL_TYPES Full Developer) 
> #SET(CPACK_COMPONENT_CSHARP_INSTALL_TYPES Full Developer)
>
> IF (WIN32)
>   SET(CPACK_PACKAGE_ICON 
> "${CMAKE_CURRENT_SOURCE_DIR}\\\\InstallIcon.bmp")
>   SET(CPACK_NSIS_MODIFY_PATH ON)
>   SET(CPACK_GENERATOR "NSIS")
> ELSE (UNIX)
>   SET(CPACK_GENERATOR "RPM")
> ENDIF(WIN32)
>
> # Always include this last.
> INCLUDE(CPack)
>
>
>
> --------- test CMakeLists.txt -------------
>
> add_executable ( test_julian EXCLUDE_FROM_ALL test_julian.cpp ) 
> add_test ( test_julian test_julian ) add_dependencies ( check 
> test_julian ) target_link_libraries ( test_julian ${Boost_LIBRARIES} 
> myproject )
>
>
>
> add_executable ( test_valuearray EXCLUDE_FROM_ALL test_valuearray.cpp 
> ) add_test ( test_valuearray test_valuearray ) add_dependencies ( 
> check test_valuearray ) target_link_libraries ( test_valuearray 
> ${Boost_LIBRARIES} myproject )
>
>
>
> add_executable ( test_vector EXCLUDE_FROM_ALL test_vector.cpp ) 
> add_test ( test_vector test_vector ) add_dependencies ( check 
> test_vector ) target_link_libraries ( test_vector ${Boost_LIBRARIES} 
> myproject )
>
>
>
>
>
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at 
> http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the CMake FAQ at:
> http://www.cmake.org/Wiki/CMake_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.cmake.org/mailman/listinfo/cmake
>
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Follow this link to subscribe/unsubscribe:
http://www.cmake.org/mailman/listinfo/cmake

This email was sent to you by Thomson Reuters, the global news and information company. Any views expressed in this message are those of the individual sender, except where the sender specifically states them to be the views of Thomson Reuters.


More information about the CMake mailing list